Jump to content

Module:Gallery

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Arthurfragoso (talk | contribs) at 03:06, 2 February 2025 (Refactored argument parsing and gallery building algorithm. There should be no visible difference to existing articles but it provides greater flexibility for future editors using arguments and improves the module's extensibility. Ping me if you find any abnormality, or revert the changes.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

-- This module implements {{gallery}} by wrapping the <gallery> core extension tag.

local p = {}

local templatestyles = 'Module:Gallery/styles.css'
local yesno = require('Module:Yesno')

local function trim(s)
	return mw.ustring.gsub(mw.ustring.gsub(s or '', '%s', ' '), '^%s*(.-)%s*$', '%1')
end

local function isImage(file)
    local file = trim(file):lower() -- Case insensitive check
    -- Check if it starts with "File:", "Image:", or "Media:" or ends with a file extension of 3 to 4 characters
    if file:match("^(file:|image:|media:).+") or
       file:match("%.%w%w%w%w?$") then
        return true
    end
    return false
end

local tracking, preview

local function checkarg(k,v)
	if k and type(k) == 'string' then
		if k == 'align' or k == 'state' or k == 'style' or k == 'title' or
			k == 'width' or k == 'height' or k == 'whitebg' or
			k == 'mode' or k == 'footer' or k == 'perrow' or k == 'noborder' or
			k:match('^alt%d+$') or k:match('^%d+$') then
			-- valid
		elseif k == 'captionstyle' then
			if not v:match('^text%-align%s*:%s*center[;%s]*$') then
				table.insert(tracking, '[[Category:Pages using gallery with the captionstyle parameter]]')
			end
		else
			-- invalid
			local vlen = mw.ustring.len(k)
			k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25)
			k = mw.ustring.gsub(k, '[^%w%-_ ]', '?')
			table.insert(tracking, '[[Category:Pages using gallery with unknown parameters|' .. k .. ']]')
			table.insert(preview, '"' .. k .. '"')
		end
	end
end

function p.gallery(frame)
	-- If called via #invoke, use the args passed into the invoking template.
	-- Otherwise, for testing purposes, assume args are being passed directly in.
	local origArgs = (type(frame.getParent) == 'function') and frame:getParent().args or frame

    -- ParserFunctions considers the empty string to be false, so to preserve the previous
    -- behavior of {{gallery}}, change any empty arguments to nil, so Lua will consider
    -- them false too.
    local args = {}
    tracking, preview = {}, {}
    for k, v in pairs(origArgs) do
    	if v ~= '' then
    		args[k] = v
    		checkarg(k,v)
    	end
	end
	
	if (args.mode or '') == 'packed' and (args.align or '') == '' then
		args.align = 'center'
	end

	if (args.align or '') == 'centre' then
		args.align = 'center'
	end

	local tbl = mw.html.create('div')
	tbl:addClass('mod-gallery')

	if args.state then
		tbl
			:addClass('mod-gallery-collapsible')
			:addClass('collapsible')
			:addClass(args.state)
	end
	
	if args.style then
		tbl:cssText(args.style)
	else
		tbl:addClass('mod-gallery-default')
	end
	
	if args.align then
		tbl:addClass('mod-gallery-' .. args.align:lower())
	end

	if args.title then
		tbl:tag('div')
			:addClass('title')
				:tag('div')
					:wikitext(args.title)
	end
	
	local gargs = {}
	gargs['class'] = 'nochecker' .. (args.noborder and '' or ' bordered-images')
	gargs['widths'] = tonumber(args.width) or 180
	gargs['heights'] = tonumber(args.height) or 180
	gargs['style'] = args.captionstyle
	gargs['perrow'] = args.perrow
	gargs['mode'] = args.mode
	if yesno(args.whitebg or 'yes') then
		gargs['class'] = gargs['class'] .. ' whitebg'
	end
	
	local virtualgallery = {}
	local gallery = {}
	
	local imageCount = 0
	
	for i = 1, #args do
	    local currentfield = trim(args[i]) or ''
	
	    if currentfield == '' then
	        -- Skip empty fields
	    elseif isImage(currentfield) then
	        imageCount = imageCount + 1
	        virtualgallery[imageCount] = { currentfield }
	    elseif imageCount > 0 and virtualgallery[imageCount][2] == nil then
	    	-- In case of multiple captions, use the first and ignore the laters
	        virtualgallery[imageCount][2] = currentfield
	    end
	end

	-- Run through virtualgallery and builds gallery
	for n = 1, #virtualgallery do
	    local img = virtualgallery[n][1]
	    local caption = virtualgallery[n][2] or ''
	    local alt = trim(args['alt' .. n] or '')
	    
	    table.insert(gallery, img .. 
	    	(alt ~= '' and ('|alt=' .. alt) or '') ..
	    	(caption ~= '' and ('|' .. caption) or ''))
	end
	
	tbl:tag('div')
		:addClass('main')
		:tag('div')
			:wikitext(
				frame:extensionTag{ name = 'gallery', content = '\n' .. table.concat(gallery,'\n'), args = gargs}
				)

	if args.footer then
		tbl:tag('div')
			:addClass('footer')
				:tag('div')
					:wikitext(args.footer)
	end

	local trackstr = (#tracking > 0) and table.concat(tracking, '') or ''
	if #preview > 0 then
		trackstr = require('Module:If preview')._warning({
			'Unknown parameters ' .. table.concat(preview, '; ') .. '.'
		}) .. trackstr
	end
	
	return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} } .. tostring(tbl) .. trackstr
end

return p