has_rows = true
has_list_class({ imageArgs.rowclass, imageArgs.class })  
local row = root:tag('tr')
row:addClass(imageArgs.rowclass)  
local dataCell = row:tag('td')
dataCell
:attr('colspan', '2')
:addClass('infobox-image')
:addClass(imageArgs.class)
:cssText(imageArgs.datastyle)
:wikitext(fixChildBoxes(imageArgs.data, 'td'))
else
table.insert(empty_row_categories, imageArgs.data or '')
end
end  
local function renderImages
if args.image then
args.image1 = args.image
end
if args.caption then
args.caption1 = args.caption
end
local imagenums = getArgNums('image')
for k, num in ipairs(imagenums) do
local caption = args['caption' .. tostring(num)]
local data = mw.html.create:wikitext(args['image' .. tostring(num)])
if caption then
data
:tag('div')
:addClass('infobox-caption')
-- @deprecated next; target .infobox-<name> .infobox-caption
:cssText(args.captionstyle)
:wikitext(caption)
end
addImageRow({
data = tostring(data),
-- @deprecated next; target .infobox-<name> .infobox-image
datastyle = args.imagestyle,
class = args.imageclass,
rowclass = args['imagerowclass' .. tostring(num)]
})
end
end  
-- When autoheaders are turned on, preprocesses the rows
local function preprocessRows
if not args.autoheaders then return end  
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
local lastheader
for k, num in ipairs(rownums) do
if args['header' .. tostring(num)] then
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
lastheader = num
elseif args['data' .. tostring(num)] and
args['data' .. tostring(num)]:gsub(
category_in_empty_row_pattern, ''
):match('^%S') then
local data = args['data' .. tostring(num)]
if data:gsub(category_in_empty_row_pattern, ''):match('%S') then
lastheader = nil
end
end
end
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
end  
-- Gets the union of the header and data argument numbers,
-- and renders them all in order
local function renderRows  
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
for k, num in ipairs(rownums) do
addRow({
header = args['header' .. tostring(num)],
label = args['label' .. tostring(num)],
data = args['data' .. tostring(num)],
datastyle = args.datastyle,
class = args['class' .. tostring(num)],
rowclass = args['rowclass' .. tostring(num)],
-- @deprecated next; target .infobox-<name> rowclass
rowstyle = args['rowstyle' .. tostring(num)],
rowcellstyle = args['rowcellstyle' .. tostring(num)]
})
end
end  
local function renderNavBar
if not args.name then return end  
has_rows = true
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('infobox-navbar')
:wikitext(require('Module:Navbar')._navbar{
args.name,
mini = 1,
})
end  
local function renderItalicTitle
local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
root:wikitext(require('Module:Italic title')._main({}))
end
end  
-- Categories in otherwise empty rows are collected in empty_row_categories.
-- This function adds them to the module output. It is not affected by
-- args.decat because this module should not prevent module-external categories
-- from rendering.
local function renderEmptyRowCategories
for _, s in ipairs(empty_row_categories) do
root:wikitext(s)
end
end  
-- Render tracking categories. args.decat == turns off tracking categories.
local function renderTrackingCategories
if args.decat == 'yes' then return end
if args.child == 'yes' then
if args.title then
root:wikitext(
''
end
elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle.namespace == 0 then
root:wikitext('')
end
end  
--[=[
Loads the templatestyles for the infobox.  
TODO: FINISH loading base templatestyles here rather than in
MediaWiki:Common.css. There are 4-5000 pages with 'raw' infobox tables.
See Mediawiki_talk:Common.css/to_do#Infobox and/or come help :).
When we do this we should clean up the inline CSS below too.
Will have to do some bizarre conversion category like with sidebar.  
]=]
local function loadTemplateStyles
local = mw.getCurrentFrame  
local hlist_templatestyles = ''
if lists.hlist_t.found then
hlist_templatestyles = :extensionTag{
name = 'templatestyles', args = { src = lists.hlist_t.styles }
}
end  
local plainlist_templatestyles = ''
if lists.plainlist_t.found then
plainlist_templatestyles = :extensionTag{
name = 'templatestyles', args = { src = lists.plainlist_t.styles }
}
end  
-- See function description
local base_templatestyles = :extensionTag{
name = 'templatestyles', args = { src = 'Module:Infobox/styles.css' }
}  
local templatestyles = ''
if args['templatestyles'] then
templatestyles = :extensionTag{
name = 'templatestyles', args = { src = args['templatestyles'] }
}
end  
local child_templatestyles = ''
if args['child templatestyles'] then
child_templatestyles = :extensionTag{
name = 'templatestyles', args = { src = args['child templatestyles'] }
}
end  
local grandchild_templatestyles = ''
if args['grandchild templatestyles'] then
grandchild_templatestyles = :extensionTag{
name = 'templatestyles', args = { src = args['grandchild templatestyles'] }
}
end  
return table.concat({
-- hlist -> plainlist -> base is best-effort to preserve old Common.css ordering.
-- this ordering is not a guarantee because the rows of interest invoking
-- each class may not be on a specific page
hlist_templatestyles,
plainlist_templatestyles,
base_templatestyles,
templatestyles,
child_templatestyles,
grandchild_templatestyles
})
end  
-- common functions between the child and non child cases
local function structure_infobox_common
renderSubheaders
renderImages
preprocessRows
renderRows
renderBelowRow
renderNavBar
renderItalicTitle
renderEmptyRowCategories
renderTrackingCategories
cleanInfobox
end  
-- Specify the overall layout of the infobox, with special settings if the
-- infobox is used as a 'child' inside another infobox.
local function _infobox
if args.child ~= 'yes' then
root = mw.html.create('table')  
root
:addClass(args.subbox == 'yes' and 'infobox-subbox' or 'infobox')
:addClass(args.bodyclass)
-- @deprecated next; target .infobox-<name>
:cssText(args.bodystyle)  
has_list_class({ args.bodyclass })  
renderTitle
renderAboveRow
else
root = mw.html.create  
root
:wikitext(args.title)
end
structure_infobox_common  
return loadTemplateStyles .. root
end  
-- If the argument exists and isn't blank, add it to the argument table.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
local function preprocessSingleArg(argName)
if origArgs[argName] and origArgs[argName] ~= '' then
args[argName] = origArgs[argName]
end
end  
-- Assign the parameters with the given prefixes to the args table, in order, in
-- batches of the step size specified. This is to prevent references etc. from
-- appearing in the wrong order. The prefixTable should be an array containing
-- tables, each of which has two possible fields, a "prefix" string and a
-- "depend" table. The function always parses parameters containing the "prefix"
-- string, but only parses parameters in the "depend" table if the prefix
-- parameter is present and non-blank.
local function preprocessArgs(prefixTable, step)
if type(prefixTable) ~= 'table' then
error("Non-table value detected for the prefix table", 2)
end
if type(step) ~= 'number' then
error("Invalid step value detected", 2)
end  
-- Get arguments without a number suffix, and check for bad input.
for i,v in ipairs(prefixTable) do
if type(v) ~= 'table' or type(v.prefix) ~= "string" or
(v.depend and type(v.depend) ~= 'table') then
error('Invalid input detected to preprocessArgs prefix table', 2)
end
preprocessSingleArg(v.prefix)
-- Only parse the depend parameter if the prefix parameter is present
-- and not blank.
if args[v.prefix] and v.depend then
for j, dependValue in ipairs(v.depend) do
if type(dependValue) ~= 'string' then
error('Invalid "depend" parameter value detected in preprocessArgs')
end