imported>Χ No edit summary |
(No difference)
|
Latest revision as of 09:40, 17 September 2018
Documentation for this module may be created at Module:Sandbox/Χ/InfoboxMaker/doc
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, "[[Category:" .. name .. "]]")
else
table.insert(categories, "[[Category:" .. name .. "|" .. key .. "]]")
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