Module:Infobox
Documentation for this module may be created at Module:Infobox/doc
local p = {}
local args = {}
local origArgs = {}
local root
local empty_row_categories = {}
local category_in_empty_row_pattern = '%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]'
local has_rows = false
local yesno = require("Module:Yesno")
local lists = {
plainlist_t = {
patterns = {
'^plainlist$',
'%splainlist$',
'^plainlist%s',
'%splainlist%s'
},
found = false,
styles = 'Plainlist/styles.css'
},
hlist_t = {
patterns = {
'^hlist$',
'%shlist$',
'^hlist%s',
'%shlist%s'
},
found = false,
styles = 'Hlist/styles.css'
}
}
-- Detect list classes
local function has_list_class(args_to_check)
for _, list in pairs(lists) do
if not list.found then
for _, arg in pairs(args_to_check or {}) do
for _, pattern in ipairs(list.patterns) do
if arg and mw.ustring.find(arg, pattern) then
list.found = true
break
end
end
if list.found then break end
end
end
end
end
-- Fix nested child boxes
local function fixChildBoxes(sval, tt)
if not sval or sval == '' then return sval end
local marker = '<span class="special_infobox_marker">'
local s = sval
-- move categories and templatestyles inside rows safely
local last
repeat
last = s
s = mw.ustring.gsub(
s,
'(</[Tt][Rr]%s*>%s*)(%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*%]%])',
'%2%1'
)
s = mw.ustring.gsub(
s,
'(</[Tt][Rr]%s*>%s*)(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)',
'%2%1'
)
until s == last
return s
end
-- Clean empty tables
local function cleanInfobox()
root = tostring(root or '')
if not has_rows then
root = mw.ustring.gsub(root, '<table[^<>]*>%s*</table>', '')
end
end
-- Union helper
local function union(t1, t2)
local vals = {}
local out = {}
for _, v in pairs(t1 or {}) do vals[v] = true end
for _, v in pairs(t2 or {}) do vals[v] = true end
for k in pairs(vals) do
table.insert(out, k)
end
return out
end
-- Get argument numbers
local function getArgNums(prefix)
local nums = {}
for k in pairs(args) do
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
table.sort(nums)
return nums
end
-- Add row
local function addRow(rowArgs)
if rowArgs.header then
has_rows = true
root:tag('tr')
:tag('th')
:attr('colspan', '2')
:addClass('infobox-header')
:wikitext(fixChildBoxes(rowArgs.header, 'th'))
else
if rowArgs.data and rowArgs.data ~= '' then
has_rows = true
local tr = root:tag('tr')
if rowArgs.label then
tr:tag('th')
:attr('scope', 'row')
:addClass('infobox-label')
:wikitext(rowArgs.label)
end
local td = tr:tag('td')
:attr('colspan', rowArgs.label and nil or '2')
:addClass('infobox-data')
:wikitext(fixChildBoxes(rowArgs.data, 'td'))
else
table.insert(empty_row_categories, rowArgs.data or '')
end
end
end
local function renderTitle()
if not args.title then return end
root:tag('caption')
:addClass('infobox-title')
:wikitext(args.title)
has_rows = true
end
local function renderRows()
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
for _, num in ipairs(rownums) do
addRow({
header = args['header' .. num],
label = args['label' .. num],
data = args['data' .. num]
})
end
end
local function structure()
renderTitle()
renderRows()
cleanInfobox()
end
local function _infobox()
root = mw.html.create('table')
:addClass('infobox')
structure()
return root
end
local function preprocessSingleArg(name)
if origArgs[name] and origArgs[name] ~= '' then
args[name] = origArgs[name]
end
end
local function parseDataParameters()
for k, v in pairs(origArgs) do
if v ~= '' then
args[k] = v
end
end
end
function p.infobox(frame)
origArgs = frame:getParent().args
parseDataParameters()
return tostring(_infobox())
end
return p