Modulo:Immagine multipla

Modulo che implementa i template {{Immagine multipla}}, {{Doppia immagine}}, {{Doppia immagine verticale}} e {{Tripla immagine}}.


--=====================================================
-- Implementazione del  [[template:Immagine multipla]]
-- Importato e modificato da 
-- https://en.wiki.x.io/w/index.php?title=Module:Multiple_image&oldid=706647916
--=====================================================

local p = {}

--=====================================================
-- Generazione del codice una singola cella contenente
-- un'immagine
--=====================================================
local function renderImageCell(image, width, height, link, alt, caption, textalign, istyle)
	local root = mw.html.create('')
	
	local altstr = '|alt=' .. (alt or '')
	local linkstr = link and ('|link=' .. link) or ''
	local widthstr = '|' .. tostring(width) .. 'px'
	
	local imagediv = root:tag('div')
	imagediv:addClass('thumbimage')
	imagediv:cssText(istyle)
	if height then
		imagediv:css('height', tostring(height) .. 'px')
		imagediv:css('overflow', 'hidden')
	end
	imagediv:wikitext('[[file:' .. image .. widthstr .. linkstr .. altstr .. ']]')
	if caption then
		local captiondiv = root:tag('div')
		captiondiv:addClass('thumbcaption')
		captiondiv:css('clear', 'left')
		if textalign then
			captiondiv:css('text-align', textalign)
		end
		captiondiv:wikitext(caption)
	end
	return tostring(root)
end

--=====================================================
-- Ritorna una tabella che contiene il numero di immagini
-- per ogni riga.
-- pstr deve essere una stringa di numeri separati da qualunque
-- 
--=====================================================
local function getPerRow(pstr, ic)
	-- split string into array using any non-digit as a dilimiter
	local pr = mw.text.split(pstr or '', '[^%d][^%d]*')
	-- if split failed, assume a single row
	if (#pr < 1) then
		pr = {tostring(ic)}
	end
	-- convert the array of strings to an array of numbers,
	-- adding any implied/missing numbers at the end of the array
	local r = 1
	local thisrow = tonumber(pr[1] or ic) or ic
	local prownum = {}
	while( ic > 0 ) do
		prownum[r] = thisrow
		ic = ic - thisrow
		r = r + 1
		-- use the previous if the next is missing and 
		-- make sure we don't overstep the number of images
		thisrow = math.min(tonumber(pr[r] or thisrow) or ic, ic)
	end
	return prownum
end

--=====================================================
-- Ritorna le dimensioni dell'immagine (larghezza x altezza)
-- Se queste non sono passate dai parametri tenta di recuperarle
-- dalle informazioni del file immagine, altrimenti ricade su
-- una larghezza pari a 200 e un'altezza pari alla larghezza
--=====================================================

local function get_dimensions(w, h, name)
	local wr = w and tonumber(w)
	local hr = h and tonumber(h)
	if not(wr and hr) then
		local page = mw.title.new(name, 'Media')
		if not wr then 
			wr = page.file and page.file.width
		end
		if not hr then
			hr = page.file and page.file.height
		end
	end
	wr = wr or 200
	hr = hr or wr
	return wr, hr
end

-- Return a sorted array of the index of the parameter immagine1 .. immagine(n)
-- passed to the template. Index could be not consecutive but the gap between
-- different index must be five or less
local function getImageNumbers(args)
	local imagenumbers = {}
	local istart = 1
	local iend = 10
	local istep = 5
	while true do
		local found = false
		for i=istart, iend do
			if args['immagine' .. tostring(i)] then
				imagenumbers[#imagenumbers+1] = i
				found = true
			end
		end
		if found then 
			istart = iend + 1
			iend = iend + istep
		else
			break
		end
	end
	table.sort(imagenumbers)
	return imagenumbers
end

-- La funzione effettiva di creazione della galleria
function p._render(args)

	local width = (args['larghezza'] and tonumber(args['larghezza'])) or 200
	local dir = args['direzione']
	local align = args['allinea']
	local capalign = args['allinea didascalia'] --NEW
	local totalwidth = (args['larghezza totale'] and tonumber(args['larghezza totale'])) or 0
	local imgstyle = args['stile immagine']
	local header =  args['titolo']
	local footer = args['sotto']
	local perrow = nil
	local thumbclass = {
		["left"] = 'tleft',
		["none"] = 'tnone',
		["center"] = 'tnone',
		["centre"] = 'tnone',
		["right"] = 'tright',
		["sinistra"] = 'tleft',
		["nessuna"] = 'tnone',
		["centro"] = 'tnone',
		["destra"] = 'tright'
	}

	-- find all the nonempty images
	local imagenumbers = getImageNumbers(args)
	local imagecount = #imagenumbers
	if imagecount == 0 then
		return ''
	end
	
	-- create an array with the number of images per row
	if dir == 'verticale' or dir == 'vertical' then
		perrow = getPerRow('1', imagecount)
	else
		perrow = getPerRow(args['per riga'], imagecount)
	end
	
	-- compute the number of rows
	local rowcount = #perrow

	-- store the image widths and compute row widths and maximum row width
	local widths = {}
	local widthmax = 0
	local widthsum = {}
	local heights = {}
	local k = 0
	for r=1,rowcount do
		widthsum[r] = 0
		for c=1,perrow[r] do
			k = k + 1
			if k <= imagecount then
				local w = args['larghezza' .. imagenumbers[k]]
				if totalwidth > 0 then
					local h = args['altezza' .. imagenumbers[k]]
					widths[k], heights[k] = get_dimensions(w, h, args['immagine' .. imagenumbers[k]]) 
				else	
					widths[k] =  (w and tonumber(w)) or width
				end
				widthsum[r] = widthsum[r] + widths[k]
			end
		end
		widthmax = math.max(widthmax, widthsum[r])
	end

	-- if total_width has been specified, rescale the image widths
	if totalwidth > 0 then
		widthmax = 0
		local k = 0
		for r=1,rowcount do
			local koffset = k
			local tw = totalwidth - 4 * (perrow[r] - 1) - 12
			local ar = {}
			local arsum = 0
			for j=1,perrow[r] do
				k = k + 1
				if k<= imagecount then
					if (heights[k] > 0) then
						ar[j] = widths[k]/heights[k]
					else
						ar[j] = widths[k]/100
					end
					arsum = arsum + ar[j]
				end
			end
			local ht = tw/arsum
			local ws = 0
			k = koffset
			for j=1,perrow[r] do
				k = k + 1
				if k<= imagecount then
					local i = imagenumbers[k]
					widths[k] = math.floor(ar[j]*ht + 0.5)
					ws = ws + widths[k]
					if heights[k] then
						heights[k] = math.floor(ht)
					end
				end
			end
			widthsum[r] = ws
			widthmax = math.max(widthmax, widthsum[r])
		end
	end	

	-- start building the array of images, if there are images
	if imagecount > 0 then
		-- compute width of outer div
		local bodywidth = 0
		for r=1,rowcount do
			local bw = widthsum[r] + 4 * (perrow[r] - 1) + 2
			bodywidth = math.max(bodywidth, bw)
		end
		-- The body has a min-width of 100, which needs to be taken into account on specific widths
		bodywidth = math.max( 100, bodywidth);

		-- crea il div esterno per la galleria di immagini
		local root = mw.html.create('div')
		root:addClass('thumb')
		root:addClass(thumbclass[align] or 'tright')
		-- crea il div interno
		local div = root:tag('div')
		div:addClass('thumbinner')
		div:css('width', tostring(bodywidth+2) .. 'px')
			:css('flex-direction', 'row')
		if align == 'center' or align == 'centre' or align == 'centro' then
			div:css('margin', '0 auto')
		end
		-- aggiunge il titolo
		if header then
			div:tag('div')
				:css('clear', 'both')
				:css('text-align', args['allinea titolo'] or 'center')
				:css('background-color', args['sfondo titolo'])
				:wikitext(header)
		end
		-- loop through the images
		local k = 0
		for r=1,rowcount do
			for j=1,perrow[r] do
				k = k + 1
				if k <= imagecount then
					local imagediv = div:tag('div')
					imagediv:addClass('tsingle')
					if dir ~= 'vertical' then
						imagediv:css('float', 'left')
					end
					imagediv:css('margin', '1px')
					local i = imagenumbers[k]
					local img = args['immagine' .. i]
					local w = widths[k]
					imagediv:css('width', tostring(2 + w) .. 'px')
						--:css('max-width', tostring(2 + w) .. 'px')
						:css('padding-left', '0px')
						:css('padding-right', '0px')
					imagediv:wikitext(renderImageCell(img, w, heights[k], 
						args['collegamento' .. i], args['alt' .. i],
						args['didascalia' .. i], capalign, imgstyle))
				end
			end
			-- add a clearing div
			div:tag('div'):css('clear', 'left')
		end
		-- add the footer
		if footer then
			div:tag('div')
				:addClass('thumbcaption')
				:css('clear', 'left')
				:css('text-align', args['allinea sotto'] or 'left')
				:css('background-color', args['sfondo sotto'])
            	:wikitext(footer)
		end
		return tostring(root)
	end
	return ''
end

--interfaccia verso il template immagine multipla
function p.render( frame )
	local getArgs = require('Module:Arguments').getArgs
	--local pargs = getArgs(frame, {parentOnly=true})
	local args = getArgs(frame)
	return p._render( args )
end
 
--interfaccia verso template più specifici ({{Doppia immagine}}, {{tripla immagine}}...)
function p.render_frame( frame )
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame, {frameOnly=true})
	return p._render( args )
end

return p