Documentation icon دستاویز [تخلیق]
-- Creates a slideshow gallery where the order is randomised. Intended for use on portal pages.
local p = {}
local excerptModule =  require('Module:Excerpt')
local randomModule = require('Module:Random')
local redirectModule = require('Module:Redirect')

function cleanupArgs(argsTable)
	local cleanArgs = {}
	for key, val in pairs(argsTable) do
		if type(val) == 'string' then
			val = val:match('^%s*(.-)%s*$')
			if val ~= '' then
				cleanArgs[key] = val
			end
		else
			cleanArgs[key] = val
		end
	end
	return cleanArgs
end

function normaliseCssMeasurement(input)
	local suffix = string.reverse(string.sub(string.reverse(input), 1, 2))
	if ( suffix == 'px' ) or ( suffix == 'em' ) or ( string.sub(suffix, 2, 2) == '%' ) then
		return input
	else
		return input .. 'px'
	end
end

function makeOutput(galleryLines, maxWidth)
	local randomiseArgs = {	['t'] = galleryLines }
	local randomisedLines = randomModule.main('array', randomiseArgs)
	local galleryContent = table.concat(randomisedLines, '\n')
	local output = '<div style="max-width:' .. normaliseCssMeasurement(maxWidth) .. '; margin:-4em auto;">{{#tag:gallery|' .. galleryContent  .. '|mode=slideshow}}</div>'
	return output
end

function makeGalleryLine(file, caption, credit)
	local title = mw.title.new(file, "File" )
	local creditLine = ( credit and '<p><span style="font-size:88%">' .. credit .. '</span>' or '' )
	return title.prefixedText .. '{{!}}' .. ( caption or '' ) .. creditLine
end

function makeGalleryLinesTable(args)
	local galleryLinesTable = {}
	local i = 1
	while args[i] do
		table.insert(galleryLinesTable, makeGalleryLine(args[i], args[i+1], args['credit' .. (i+1)/2]))
		i = i + 2
	end
	return galleryLinesTable 
end

function extractGalleryFiles(wikitext)
	local gallery = mw.ustring.match(wikitext, '<gallery.->%s*(.-)%s*</gallery>')
	if not gallery then
		return false
	end
	gallery = mw.ustring.gsub(gallery, '|', '{{!}}')
	return mw.text.split(gallery, '%c')
end

function extractRegularFiles(wikitext)
	local wikitext = mw.ustring.gsub(wikitext, '%]%]%[%[File:', ']]\n[[File:')
	local wikitext = mw.ustring.gsub(wikitext, '|thumb', '')
	local files = mw.text.split(wikitext, '%c')
	for k, v in pairs(files) do
		local f = mw.ustring.gsub(v, '|%s*thumb%s*([|%]])', '%1')
		f = mw.ustring.gsub(f, '|%s*left%s*([|%]])', '%1')
		f = mw.ustring.gsub(f, '|%s*right%s*([|%]])', '%1')
		f = mw.ustring.gsub(f, '|%s*center%s*([|%]])', '%1')
		f = mw.ustring.gsub(f, '|%s*upright%s*=?%s*.-([|%]])', '%1')
		f = mw.ustring.gsub(f, '|', '{{!}}')
		f = mw.ustring.gsub(f, '^%[%[(.*)%]%]$', '%1')
		files[k] = f
	end
	return files
end

function makeTranscludedGalleryLinesTables(args)
	local lines = {}
	local i = 1
	while args[i] do
		-- Get page content
		local content, pagename = excerptModule.getContent(args[i])
		if not pagename then
			return error('Cannot read a valid page for "' .. args[i] .. '"', 0)
		elseif not content then
			return error('No content found on page "' .. args[i] .. '"', 0)
		end
		if args['section'..i] then
			content = excerptModule.getsection(content, args['section'..i]) or ''
		end
		content = excerptModule.cleanupText(content)

		local galleryFiles = extractGalleryFiles(content)
		if galleryFiles then
			for _, f in pairs(galleryFiles) do
				table.insert(lines, f)
			end
		end

		local otherFiles = excerptModule.parse(content, {fileflags="1-100"}, true)
		if otherFiles then
			for _, f in pairs(extractRegularFiles(otherFiles)) do
				if f and f ~= '' and mw.ustring.sub(f, 1, 5) == 'File:' then
					table.insert(lines, f)
				end
			end
		end

		i = i + 1
	end
	return ( #lines > 0 ) and lines or error('No images found')
end

p._main = function(args, transclude)
	if not args[1] then
		return error(linked and 'No page specified' or 'No page specified', 0)
	end
	local lines = transclude and makeTranscludedGalleryLinesTables(args) or makeGalleryLinesTable(args)
	return makeOutput(lines, args.width or '100%')
end

p.main = function(frame)
	local parent = frame.getParent(frame)
	local parentArgs = parent.args
	local args = cleanupArgs(parentArgs)
	local output = p._main(args, false)
	return frame:preprocess(output)
end

p.transclude = function(frame)
	local parent = frame.getParent(frame)
	local parentArgs = parent.args
	local args = cleanupArgs(parentArgs)
	local output = p._main(args, true)
	return frame:preprocess(output)
end

return p