Module:Simple navbox
Jump to navigation
Jump to search
local p = {}
-- Utilities
local function isNotEmpty(v)
return v ~= nil and v ~= ''
end
local function lc(v)
return type(v) == 'string' and mw.ustring.lower(v) or v
end
local function getArg(args, ...)
for i = 1, select('#', ...) do
local k = select(i, ...)
if isNotEmpty(args[k]) then
return args[k]
end
end
return nil
end
-- Main entry point
function p.main(frame)
local args = frame:getParent().args
local out = {}
-- Stylesheets
table.insert(out, frame:extensionTag{ name = 'templatestyles', args = { src = 'Simple navbox/styles.css' } })
table.insert(out, frame:extensionTag{ name = 'templatestyles', args = { src = 'Hlist/styles.css' } })
if isNotEmpty(args.templatestyles) then
table.insert(out, frame:extensionTag{ name = 'templatestyles', args = { src = args.templatestyles } })
end
-- Collapse logic
local collapse = getArg(args, 'collapse', 'collapsible')
local collapsible = not (lc(collapse) == 'no')
local state = lc(args.state)
-- Outer image
local imageOuter = getArg(args, 'image-outer', 'imageouter')
-- Classes
local bodyclass = getArg(args, 'bodyclass', 'class') or ''
local classes = { 'simple-navbox', bodyclass, 'noprint' }
if collapsible then
table.insert(classes, 'NavFrame')
if state == 'collapsed' then
table.insert(classes, 'NavClosed')
end
else
if isNotEmpty(imageOuter) then
table.insert(classes, 'simple-outer')
end
end
-- Body style
local bodystyle = args.bodystyle or ''
table.insert(out, string.format(
'<div class="%s" style="%s">',
table.concat(classes, ' '), bodystyle
))
-- Outer image rendering (non-collapsible only)
if not collapsible and isNotEmpty(imageOuter) then
table.insert(out, string.format('<div class="simple-outer-image">%s</div>', imageOuter))
end
-- Header
local headerstyle = getArg(args, 'headerstyle', 'titlestyle') or ''
local headerClass = 'simple-header NavHead'
if isNotEmpty(headerstyle) then
headerClass = headerClass .. ' simple-header-modified'
end
local header = {}
if isNotEmpty(args.name) then
table.insert(header, frame:expandTemplate{ title = 'simple navbar', args = { args.name } })
end
table.insert(header, args.title or 'Default title: add a value for <code>title</code> in the template.')
table.insert(out, string.format(
'<div class="%s" style="%s">%s</div>',
headerClass, headerstyle, table.concat(header)
))
-- Nav content wrapper
table.insert(out, string.format(
'<div class="simple-navcontent NavContent" style="%s">',
args.navcontentstyle or ''
))
-- Above block
if isNotEmpty(args.above) then
table.insert(out, string.format(
'<div class="simple-group-above" style="%s">\n%s\n</div>',
args.abovestyle or '',
frame:preprocess(args.above)
))
end
-- Flex container
local imageAlign = getArg(args, 'image-align', 'imagealign')
local flex = 'display:flex; flex-flow:row;'
if lc(imageAlign) == 'left' then
flex = 'display:flex; flex-flow:row-reverse; justify-content:flex-end;'
end
table.insert(out, string.format(
'<div class="simple-content-container" style="%s %s">',
flex, args.containerstyle or ''
))
-- Left image
local imageLeft = getArg(args, 'image2', 'imageleft')
local imageValign = getArg(args, 'image-valign', 'imagevalign') or 'center'
if not isNotEmpty(imageOuter) and isNotEmpty(imageLeft) then
table.insert(out, string.format(
'<div class="simple-image" style="align-self:%s">%s</div>',
imageValign, imageLeft
))
end
-- Content
table.insert(out, string.format(
'<div class="simple-content %s" style="%s">',
args.listclass or '', args.contentstyle or ''
))
-- Grouped mode
if isNotEmpty(args.group1) then
local modified = isNotEmpty(args.groupstyle) or isNotEmpty(args.oddgroupstyle) or isNotEmpty(args.evengroupstyle)
local tableClass = 'simple-group-container'
if modified then
tableClass = tableClass .. ' simple-group-modified'
end
table.insert(out, string.format(
'<table class="%s" style="%s">',
tableClass, args.tablestyle or ''
))
-- Precompute odd/even styles to avoid repeated concatenation
local oddGStyle = (args.groupstyle or '') .. (isNotEmpty(args.oddgroupstyle) and ';' .. args.oddgroupstyle or '')
local evenGStyle = (args.groupstyle or '') .. (isNotEmpty(args.evengroupstyle) and ';' .. args.evengroupstyle or '')
local oddLStyle = (args.liststyle or '') .. (isNotEmpty(args.oddliststyle) and ';' .. args.oddliststyle or '')
local evenLStyle = (args.liststyle or '') .. (isNotEmpty(args.evenliststyle) and ';' .. args.evenliststyle or '')
-- Collect non-empty lists for batch preprocessing
local batchLists = {}
local groupIndices = {}
for i = 1, 50 do
local group = args['group' .. i]
local listContent = args['list' .. i] or ''
if isNotEmpty(group) then
table.insert(batchLists, listContent)
table.insert(groupIndices, i)
end
end
-- Batch preprocess
local preprocessedLists = {}
if #batchLists > 0 then
-- Concatenate with unique separator
local sep = '@@SIMPLE_SEPARATOR@@'
local concatenated = table.concat(batchLists, sep)
local processed = frame:preprocess(concatenated)
-- Split back
for part in mw.ustring.gmatch(processed, '(.-)' .. sep) do
table.insert(preprocessedLists, part)
end
-- Handle last item
if #preprocessedLists < #batchLists then
table.insert(preprocessedLists, mw.ustring.match(processed, '.*' .. sep .. '(.*)') or batchLists[#batchLists])
end
end
-- Output rows
for idx, i in ipairs(groupIndices) do
local group = args['group' .. i]
local listContent = preprocessedLists[idx] or ''
local odd = (i % 2 == 1)
local gstyle = odd and oddGStyle or evenGStyle
gstyle = gstyle .. ';' .. (args['group' .. i .. 'style'] or '')
local lstyle = odd and oddLStyle or evenLStyle
lstyle = lstyle .. ';' .. (args['list' .. i .. 'style'] or '')
table.insert(out, string.format(
'<tr class="simple-group-row" style="%s">' ..
'<td class="simple-group" style="%s">%s</td>' ..
'<td class="simple-list" style="%s">\n%s\n</td>' ..
'</tr>',
args.rowstyle or '',
gstyle,
group,
lstyle,
listContent
))
end
table.insert(out, '</table>')
else
-- List-only mode
local list = args.list or args.list1 or 'Error: <code>list</code> is empty!'
if isNotEmpty(list) then
list = frame:preprocess(list)
end
table.insert(out, string.format(
'<div class="simple-list simple-list-only" style="%s">\n%s\n</div>',
args.liststyle or '',
list
))
end
table.insert(out, '</div>') -- simple-content
-- Right image
if not isNotEmpty(imageOuter) and isNotEmpty(args.image) then
table.insert(out, string.format(
'<div class="simple-image" style="align-self:%s">%s</div>',
imageValign, args.image
))
end
table.insert(out, '</div>') -- container
-- Below block
if isNotEmpty(args.below) then
table.insert(out, string.format(
'<div class="simple-group-above simple-group-below" style="%s">\n%s\n</div>',
args.belowstyle or args.abovestyle or '',
frame:preprocess(args.below)
))
end
table.insert(out, '</div></div>')
return table.concat(out)
end
return p