Module:Sandbox/Χ/InfoboxMaker

local ga = require('Module:Arguments').getArgs local tt = require('Module:TableTools') local ib = require('Module:Infobox').infobox local ii = require('Module:InfoboxImage').InfoboxImage

local origArgs			-- Args received from the the initalizing module. local ibArgs    = {}	-- Args sent to Module:Infobox local categories = {}	-- Categories appended to the Infobox local counter = { row = 1, subheader = 1, image = 1, } local params = { global = { 'child',		-- properties 'subbox', 'name', 'italic title', 'decat', 'bodyclass',	-- classes 'titleclass', 'aboveclass', 'subheaderclass', 'imageclass', 'headerclass', 'belowclass', 'bodystyle',	-- styles 'titlestyle', 'abovestyle', 'subheaderstyle', 'captionstyle', 'imagestyle', 'headerstyle', 'labelstyle', 'datastyle', 'belowstyle', },	row = { 'header', 'label', 'data', 'class', 'rowclass', 'rowstyle', 'rowcellstyle', 'dataid', 'labelid', 'headerid', 'rowid', },	subheader = { 'subheader', 'subheaderrowclass', 'subheaderstyle', },	image = { 'image', 'size', 'maxsize', 'sizedefault', 'alt', 'border', 'suppressplaceholder', 'imagerowclass', 'caption', }, }

local functions = { ['or'] =	function (x) if type(x) ~= table then return x end for _, v in pairs(x) do						if not isEmpty(v) then return v end end end, ['ul'] =	function (x) if type(x) ~= table then return x end local l = mw.html.create('ul') for _, v in pairs(x) do						if not isEmpty(v) then l:tag('li'):wikitext(v) end end return l				end, ['ol'] =	function (x) if type(x) ~= table then return x end local l = mw.html.create('ol') for _, v in pairs(x) do						if not isEmpty(v) then l:tag('li'):wikitext(v) end end return l				end, ___ =		function (x) return type(x) == 'table' and x[1] or x end } setmetatable(functions, {__index = function (t) return t.___ end})

--[[

--- Helper functions ---

--]]

-- -- Checks whether x is nil, empty or false -- local function isEmpty(x) return x == nil or x == '' or x == false or (type(x) == 'table' and tt.size(x) == 0) end

-- -- Transforms x into a table -- function totable(x) return type(x) == 'table' and x or {x} end

-- -- Replaces one or multiple arguments with their associated value in origArgs. -- There is an optional "n" suffix, intended to be a number. -- local function argToVal(args, n)	n = n and tostring(n) or "" if type(args) == 'table' then if n == '1' then for i, v in pairs(args) do args[i] = origArgs[v .. '1'] or origArgs[v] end else for i, v in pairs(args) do args[i] = origArgst[v .. n]			end end elseif type(args) == 'string' then if n == '1' then args = origArgs[args .. '1'] or origArgs[args] else args = origArgs[args .. n]		end end return args end

-- -- Used to build "repeated" things. -- Filters out values and arguments using their indices. -- function filter(args, params, valIndex, argIndex) local newArgs = {} for _, param in ipairs(params) do local paramArg = args[param .. "Arg"] local paramVal = args[param] local default if type(paramVal) ~= 'table' then default = paramVal paramVal = {} end newArgs[param] = paramVal[valIndex] or argToVal(paramArg, argIndex) or default newArgs[param .. "Func"] = args[param .. "Func"] end return newArgs end

-- -- Sets up unique elements like title, above, below, etc. -- local function uniqueElement(prefix, args) if type(args) ~= 'table' then ibArgs[prefix] = args or ibArgs[prefix] else ibArgs[prefix]           = args[prefix] or ibArgs[prefix] ibArgs[prefix .. 'class'] = args.class or args[prefix .. 'class'] or ibArgs[prefix .. 'class'] ibArgs[prefix .. 'style'] = args.style or args[prefix .. 'style'] or ibArgs[prefix .. 'style'] end end

-- -- Sets up incremental elements like images, subheader, and data rows -- Optional n parameter. -- function addElement(elem, args, n)	local i	if n == nil then i = tostring(counter[elem]) counter[elem] = counter[elem] + 1 else i = tostring(n) end for _, param in ipairs(params[elem]) do local func = args[param .. "Func"] if type(func) ~= 'function' then func = functions[func] end local value = args[param] or argToVal(args[param .. "Arg"]) ibArgs[param .. i] = pcall(function func(value) end) and func(value) or value end end

--[[

--- Member functions ---

--]] local p = {}

function p.initialize(args) -- Modules using InfoboxMaker must first initialize it with a set of args. origArgs = args end

-- -- Global styling and class assignments -- function p.setup(args) for _, param in ipairs(params.global) do		ibArgs[param] = args[param] end end

function p.title(args) uniqueElement('title', args) end function p.above(args) uniqueElement('above', args) end function p.below(args) uniqueElement('below', args) end

-- -- Adds a single subheader -- function p.addSubheader(args) uniqueElement('subheader', {class=args.class or args.subheaderclass}) addElement('subheader', args) end

-- -- Adds a single image and caption -- function p.addImage(args) uniqueElement('image', {		class=args.class or args.imageclass,		style=args.style or args.imagestyle,	}) local imgArgs = {} local i = tostring(counter.image) counter.image = counter.image + 1 for _, param in ipairs(params.image) do local func = args[param .. "Func"] if type(func) ~= 'function' then func = functions[func] end local value = args[param] or argToVal(args[param .. "Arg"]) imgArgs[param] = pcall(function func(value) end) and func(value) or value end ibArgs['image' .. i]        = ii{args=imgArgs} ibArgs['imagerowclass' .. i] = imgArgs.imagerowclass ibArgs['caption' .. i]      = imgArgs.caption end

-- -- Adds a single category -- function p.addCategory(catArgs) local name = catArgs.name or "" local key = catArgs.key  or "" if not isEmpty(name) then if isEmpty(key) then table.insert(categories, "") else table.insert(categories, "") end end end

-- -- Adds a single row -- function p.addRow(rowArgs, n)	local i	if n == nil then i = tostring(counter.row) counter.row = counter.row + 1 else i = tostring(n) end for _, param in ipairs(params.row) do local func = rowArgs[param .. "Func"] if type(func) ~= 'function' then func = functions[func] end local value = rowArgs[param] or argToVal(rowArgs[param .. "Arg"]) ibArgs[param .. i] = pcall(function func(value) end) and func(value) or value end if ibArgs["header" .. i] or ibArgs["data" .. i] then return true else return false end end

-- -- Adds multiple rows. Useful for numbered parameters. -- function p.addRepeatedRow(rowArgs) local added = false -- First, determine how many rows will be needed local n = {} local m = 0 for _, param in ipairs(params.row) do		-- Number of paramArgs local paramArg = totable(rowArgs[param .. "Arg"]) for _, prefix in pairs(paramArg) do			for _, v in ipairs(tt.affixNums(origArgs, prefix)) do				table.insert(n, v)			end end -- Number of paramVals local paramVal = totable(rowArgs[param]) m = math.max(m, #paramVal) end if isEmpty(n) then for i=1,m do table.insert(n, i) end else n = tt.removeDuplicates(n) table.sort(n) end -- Second, actually generate the rows if not isEmpty(n) then for i, j in ipairs(n) do			local newRowArgs = filter(rowArgs, params.row, i, j)			added = p.addRow(newRowArgs) or added end end return added end

-- -- Adds a set of rows. The "first" row is added only if the rest is not empty. --  Individual rows can actually be sections, repeated rows, or single rows. --  First row must be a single row. -- function p.addSection(sectionArgs) local rows = sectionArgs.rows or {} local first = sectionArgs[1]  or {} local added = false local h = counter.row counter.row = counter.row + 1 for _, row in ipairs(rows) do		if    row.mode == 'section' then added = p.addSection(row) or added elseif row.mode == 'repeated'  then added = p.addRepeatedRow(row)   or added else added = p.addRow(row)    or added end end if added then p.addRow(first, h)	end return added end

-- -- Adds multiple sections sharing the same definition. -- Useful with numbered parameters. -- Only single rows are accepted. -- function p.addRepeatedSection(sectionArgs) local rows = sectionArgs.rows or {} local first = sectionArgs[1]  or {} local added = false local added_row = false local h	-- First, determine how many rows will be needed local n = {} local m = 0 for _, rowArgs in ipairs(rows) do		for _, param in ipairs(params.row) do			-- Number of paramArgs local paramArg = totable(rowArgs[param .. "Arg"]) for _, prefix in pairs(paramArg) do				for _, v in ipairs(tt.affixNums(origArgs, prefix)) do					table.insert(n, v)				end end -- Number of paramVals local paramVal = totable(rowArgs[param]) m = math.max(m, #paramVal) end end if isEmpty(n) then for i=1,m do table.insert(n, i) end else n = tt.removeDuplicates(n) table.sort(n) end -- Second, actually generate the rows if not isEmpty(n) then for i, j in ipairs(n) do			added_row = false h = counter.row counter.row = counter.row + 1 for _, rowArgs in ipairs(rows) do				local newRowArgs = filter(rowArgs, params.row, i, j)				added_row = p.addRow(newRowArgs) or added end if added_row then local newFirst = filter(first, params.row, i, j)				added = p.addRow(newFirst, h) or added_row or added end end end return added end

-- -- Generate the infobox! Append categories if any. -- function p.makeInfobox return ib(ibArgs) .. mw.text.listToText(categories, , ) end

return p