Module:User:Fenakhay/multiple images

Hello, you have come here looking for the meaning of the word Module:User:Fenakhay/multiple images. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:User:Fenakhay/multiple images, but we will also tell you about its etymology, its characteristics and you will know how to say Module:User:Fenakhay/multiple images in singular and plural. Everything you need to know about the word Module:User:Fenakhay/multiple images you have here. The definition of the word Module:User:Fenakhay/multiple images will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:User:Fenakhay/multiple images, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.


local p = {}

local patterns = {
	image_key = "^image(%d*)$",
	px_val = "^(-?%d+%.?%d*)?$",
	digits = "%d+",
	not_empty = "%S"
}

local file_dimensions_cache = {}

local function is_not_empty(s)
	return s and s:match(patterns.not_empty)
end

local function to_numeric(val)
	if type(val) == 'number' then
		return val
	end
	if type(val) ~= 'string' then
		return nil
	end
	local num_str = val:match(patterns.px_val) or val
	return tonumber(num_str)
end

local function get_file_dimensions(filename)
	if file_dimensions_cache then
		return file_dimensions_cache.width, file_dimensions_cache.height
	end

	local file = mw.title.new('File:' .. filename)
	local w, h = 0, 0
	if file and file.exists then
		w = file.width
		h = file.height
	end

	file_dimensions_cache = { width = w, height = h }
	return w, h
end

local function get_images_per_row(per_row_str, image_count)
	local per_row_counts = {}
	for num in mw.ustring.gmatch(per_row_str or "", patterns.digits) do
		table.insert(per_row_counts, tonumber(num))
	end

	if #per_row_counts == 0 then
		return { image_count }
	end

	local result_rows = {}
	local processed_count = 0
	local i = 1
	local last_row_count = per_row_counts

	while processed_count < image_count do
		local current_row_spec = per_row_counts or last_row_count
		local remaining = image_count - processed_count
		local row_count = math.min(current_row_spec, remaining)

		table.insert(result_rows, row_count)
		processed_count = processed_count + row_count
		last_row_count = row_count
		i = i + 1
	end

	return result_rows
end

function p.render(frame)
	local args = frame:getParent().args
	local has_autoscaled = false
	local has_manualscaled = false

	local images = {}
	for k, v in pairs(args) do
		local key = tostring(k)
		local num = key:match(patterns.image_key)
		if num and is_not_empty(v) then
			table.insert(images, {
				index = tonumber(num),
				file = v,
				caption = args,
				link = args,
				alt = args,
				width = to_numeric(args),
				height = to_numeric(args),
				thumbtime = args
			})
		end
	end

	if #images == 0 then
		return ""
	end

	table.sort(images, function(a, b) return a.index < b.index end)
	local image_count = #images

	local direction = args.direction or 'vertical'
	local per_row_str
	if direction == 'vertical' then
		per_row_str = '1'
	else
		per_row_str = args.perrow
	end

	local per_row_layout = get_images_per_row(per_row_str, image_count)
	local row_count = #per_row_layout

	local align = args.align or (args.border == 'infobox' and 'center' or 'right')
	local caption_align = args.caption_align or ''
	local total_width = to_numeric(args.total_width)
	local default_width = to_numeric(args.width) or 200
	local image_gap = to_numeric(args.image_gap) or 1
	image_gap = math.max(0, image_gap)

	local total_content_width = 0

	for i, img in ipairs(images) do
		if img.width and img.height then
			has_manualscaled = true
		else
			local w, h = get_file_dimensions(img.file)
			img.width = img.width or default_width
			img.native_width = w
			img.native_height = h
			has_autoscaled = true
		end
	end

	if total_width then
		if direction == 'vertical' then
			local available_width = total_width - 12
			for _, img in ipairs(images) do
				local aspect_ratio = 1.6
				if img.native_height and img.native_height > 0 then
					aspect_ratio = img.native_width / img.native_height
				elseif img.height and img.height > 0 then
					aspect_ratio = img.width / img.height
				end

				if aspect_ratio > 0 then
					img.width = available_width
					img.height = math.floor(available_width / aspect_ratio + 0.5)
				end
			end
		else
			local k = 1
			for r = 1, row_count do
				local row_img_count = per_row_layout
				local available_width = total_width - (row_img_count - 1) * image_gap - 12
				local aspect_ratio_sum = 0

				for i = k, k + row_img_count - 1 do
					local img = images
					if img then
						if img.native_height and img.native_height > 0 then
							img.aspect_ratio = img.native_width / img.native_height
						elseif img.height and img.height > 0 then
							img.aspect_ratio = img.width / img.height
						else
							img.aspect_ratio = 1.6
						end
						aspect_ratio_sum = aspect_ratio_sum + img.aspect_ratio
					end
				end

				if aspect_ratio_sum > 0 then
					local common_height = available_width / aspect_ratio_sum
					for i = k, k + row_img_count - 1 do
						local img = images
						if img then
							img.width = math.floor(img.aspect_ratio * common_height + 0.5)
							img.height = math.floor(common_height + 0.5)
						end
					end
				end
				k = k + row_img_count
			end
		end
	end

	local k = 1
	for r = 1, row_count do
		local row_width = 0
		local row_img_count = per_row_layout
		for i = k, k + row_img_count - 1 do
			local img = images
			if img then
				row_width = row_width + img.width
			end
		end
		row_width = row_width + (row_img_count - 1) * image_gap
		total_content_width = math.max(total_content_width, row_width)
		k = k + row_img_count
	end

	local root = mw.html.create('div')
	local thumbclass = { left = 'tleft', none = 'tnone', center = 'tnone', right = 'tright' }
	root
		:addClass('thumb tmulti')
		:addClass(thumbclass or 'tright')
		:css('background-color', args.background_color or nil)

	if align == 'center' then
		root:addClass('center')
	end

	local thumbinner = root:tag('div')
		:addClass('thumbinner multiimageinner')
		:css('width', (total_content_width + 8) .. 'px')
		:css('background-color', args.background_color or nil)

	if args.border == 'infobox' or args.border == 'none' then
		thumbinner:css('border', 'none')
	end

	if is_not_empty(args.header or args.title) then
		thumbinner:tag('div')
			:addClass('theader')
			:css('text-align', args.header_align or nil)
			:css('background-color', args.header_background or nil)
			:wikitext(args.header or args.title)
	end

	local image_idx = 1
	for r = 1, row_count do
		local row_div = thumbinner:tag('div'):addClass('trow')
		for c = 1, per_row_layout do
			if image_idx > image_count then break end
			local img = images

			local cell = row_div:tag('div')
				:addClass('tsingle')
				:css('width', (img.width + 2) .. 'px')
				:css('background-color', args.background_color or nil)

			if c < per_row_layout and image_gap > 0 then
				cell:css('margin-right', image_gap .. 'px')
			end

			local img_div = cell:tag('div')
				:addClass('thumbimage')
				:cssText(args.image_style or nil)

			local wikitext_parts = { '[[File:', img.file }

			local size_str
			if img.height and img.height > 0 then
				size_str = table.concat({ img.width, 'x', img.height, 'px' })
			else
				size_str = img.width .. 'px'
			end
			table.insert(wikitext_parts, '|' .. size_str)

			table.insert(wikitext_parts, '|alt=' .. (img.alt or ''))
			if img.link then table.insert(wikitext_parts, '|link=' .. img.link) end
			if img.thumbtime then table.insert(wikitext_parts, '|thumbtime=' .. img.thumbtime) end
			table.insert(wikitext_parts, ']]')
			img_div:wikitext(table.concat(wikitext_parts))

			if is_not_empty(img.caption) then
				cell:tag('div')
					:addClass('thumbcaption')
					:addClass(is_not_empty(caption_align) and ('text-align-' .. caption_align) or nil)
					:wikitext(img.caption)
			end
			image_idx = image_idx + 1
		end
	end

	if is_not_empty(args.footer) then
		thumbinner:tag('div')
			:addClass('thumbcaption')
			:css('text-align', args.footer_align or nil)
			:css('background-color', args.footer_background or nil)
			:wikitext(args.footer)
	end

	local output = {
		frame:extensionTag('templatestyles', nil, { src = 'multiple images/styles.css', wrapper = '.tmulti' }),
		tostring(root)
	}

	if has_autoscaled then
		table.insert(output, ']')
	end
	if has_manualscaled then
		table.insert(output, ']')
	end

	return table.concat(output)
end

return p