Module:InfoboxLite
Jump to navigation
Jump to search
Module:InfoboxLite
A lightweight variant of Module:Infobox for infoboxes that don't need the full feature set. Identical interface but with the following removed:
- TemplateStyles loading
child/subboxsupportautoheaders- Navbar
- Italic title
These were removed because there are currently no use cases for them on the wiki, and calling them 150~ times on content-heavy pages (such as Research) was causing Lua CPU timeouts.
Row limit
Numbered parameters (data, header, label, image, subheader) are capped at 10. If a parameter beyond this limit is detected (e.g. |data11=), a visible error row is rendered inside the infobox. Use Module:Infobox directly if you genuinely need more than 10 rows.
Usage
Use Template:InfoboxLite in place of Template:Infobox. All parameters are identical.
local p = {}
local MAX_ROWS = 10
local category_in_empty_row_pattern = '%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]'
local function fixChildBoxes(sval, tt)
local function notempty(s) return s and s:match('%S') end
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
-- Move templatestyles and categories inside table rows
local slast = ''
while slast ~= s do
slast = 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')
end
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker)
if s:match(marker) then
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '')
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1')
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1')
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1')
end
if s:match(marker) then
local subcells = mw.text.split(s, marker)
s = ''
for k = 1, #subcells do
if k == 1 then
s = s .. subcells[k] .. '</' .. tt .. '></tr>'
elseif k == #subcells then
local rowstyle = ' style="display:none"'
if notempty(subcells[k]) then rowstyle = '' end
s = s .. '<tr' .. rowstyle .. '><' .. tt .. ' colspan=2>\n' .. subcells[k]
elseif notempty(subcells[k]) then
if (k % 2) == 0 then
s = s .. subcells[k]
else
s = s .. '<tr><' .. tt .. ' colspan=2>\n' ..
subcells[k] .. '</' .. tt .. '></tr>'
end
end
end
end
-- Newline fix for PHP parser (phab:T191516)
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:])', '\n%1')
s = mw.ustring.gsub(s, '^(%{%|)', '\n%1')
return s
else
return sval
end
end
-- ---------------------------------------------------------------------------
-- Render helpers
-- ---------------------------------------------------------------------------
local function renderErrorRow(root, message)
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('infobox-data')
:cssText('color: red; font-weight: bold;')
:wikitext('<span class="error">⚠ InfoboxLite error: ' .. message .. '</span>')
end
local function renderAboveRow(root, args)
if not args.above then return end
root
:tag('tr')
:tag('th')
:attr('colspan', '2')
:addClass('infobox-above')
:addClass(args.aboveclass)
:cssText(args.abovestyle)
:wikitext(fixChildBoxes(args.above, 'th'))
end
local function renderSubheaders(root, args)
-- Alias bare |subheader= to |subheader1=
if args.subheader and not args.subheader1 then
args.subheader1 = args.subheader
end
for i = 1, MAX_ROWS do
local val = args['subheader' .. i]
if val and val:gsub(category_in_empty_row_pattern, ''):match('^%S') then
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('infobox-subheader')
:addClass(args.subheaderclass)
:cssText(args.subheaderstyle)
:cssText(args['subheaderstyle' .. i])
:wikitext(fixChildBoxes(val, 'td'))
end
end
-- Visible error if subheader11+ detected
if args['subheader' .. (MAX_ROWS + 1)] then
renderErrorRow(root, '|subheader' .. (MAX_ROWS + 1) .. '= exceeds the maximum of ' .. MAX_ROWS .. ' subheaders.')
end
end
local function renderImages(root, args)
if args.image and not args.image1 then
args.image1 = args.image
end
if args.caption and not args.caption1 then
args.caption1 = args.caption
end
for i = 1, MAX_ROWS do
local img = args['image' .. i]
if img and img:gsub(category_in_empty_row_pattern, ''):match('^%S') then
local data = mw.html.create()
data:wikitext(img)
local caption = args['caption' .. i]
if caption then
data:tag('div')
:addClass('infobox-caption')
:cssText(args.captionstyle)
:wikitext(caption)
end
root
:tag('tr')
:addClass(args['imagerowclass' .. i])
:tag('td')
:attr('colspan', '2')
:addClass('infobox-image')
:addClass(args.imageclass)
:cssText(args.imagestyle)
:wikitext(fixChildBoxes(tostring(data), 'td'))
end
end
-- Visible error if image11+ detected
if args['image' .. (MAX_ROWS + 1)] then
renderErrorRow(root, '|image' .. (MAX_ROWS + 1) .. '= exceeds the maximum of ' .. MAX_ROWS .. ' images.')
end
end
local function renderRows(root, args, empty_row_categories)
for i = 1, MAX_ROWS do
local header = args['header' .. i]
local data = args['data' .. i]
local label = args['label' .. i]
if header and header ~= '_BLANK_' then
root
:tag('tr')
:addClass(args['rowclass' .. i])
:cssText(args['rowstyle' .. i])
:tag('th')
:attr('colspan', '2')
:addClass('infobox-header')
:addClass(args.headerclass)
:cssText(args.headerstyle)
:cssText(args['rowcellstyle' .. i])
:wikitext(fixChildBoxes(header, 'th'))
elseif data and data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
local row = root:tag('tr')
row:addClass(args['rowclass' .. i])
row:cssText(args['rowstyle' .. i])
if label then
row
:tag('th')
:attr('scope', 'row')
:addClass('infobox-label')
:cssText(args.labelstyle)
:cssText(args['rowcellstyle' .. i])
:wikitext(label)
:done()
end
local dataCell = row:tag('td')
dataCell
:attr('colspan', not label and '2' or nil)
:addClass(not label and 'infobox-full-data' or 'infobox-data')
:addClass(args['class' .. i])
:cssText(args.datastyle)
:cssText(args['rowcellstyle' .. i])
:wikitext(fixChildBoxes(data, 'td'))
else
table.insert(empty_row_categories, data or '')
end
end
-- Visible error if row 11+ detected
if args['data' .. (MAX_ROWS + 1)] or args['header' .. (MAX_ROWS + 1)] then
renderErrorRow(root, '|data/' .. 'header' .. (MAX_ROWS + 1) .. '= exceeds the maximum of ' .. MAX_ROWS .. ' rows.')
end
end
local function renderBelowRow(root, args)
if not args.below then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('infobox-below')
:addClass(args.belowclass)
:cssText(args.belowstyle)
:wikitext(fixChildBoxes(args.below, 'td'))
end
local function renderEmptyRowCategories(root, empty_row_categories)
for _, s in ipairs(empty_row_categories) do
root:wikitext(s)
end
end
-- ---------------------------------------------------------------------------
-- Main entry point
-- ---------------------------------------------------------------------------
local function _infobox(origArgs)
-- Normalise: treat blank args as nil, consistent with ParserFunctions
local args = {}
for k, v in pairs(origArgs) do
v = mw.text.trim(v)
if v ~= '' then args[k] = v end
end
local empty_row_categories = {}
local root = mw.html.create('table')
root
:addClass('infobox')
:addClass(args.bodyclass)
:cssText(args.bodystyle)
if args.title then
root
:tag('caption')
:addClass('infobox-title')
:addClass(args.titleclass)
:cssText(args.titlestyle)
:wikitext(args.title)
end
renderAboveRow(root, args)
renderSubheaders(root, args)
renderImages(root, args)
renderRows(root, args, empty_row_categories)
renderBelowRow(root, args)
renderEmptyRowCategories(root, empty_row_categories)
return tostring(root)
end
function p.infobox(frame)
local origArgs
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
else
origArgs = frame
end
return _infobox(origArgs)
end
-- For calling via #invoke within a template (args passed directly, not via parent)
function p.infoboxTemplate(frame)
return _infobox(frame.args)
end
return p