Module:Simple navbox
Jump to navigation
Jump to search
local p = {}
local getArgs = require('Module:Arguments').getArgs
-- Utilities
local function lc(v)
return type(v) == 'string' and mw.ustring.lower(v) or v
end
local function hasBackground(s)
return type(s) == 'string' and (
s:find('background', 1, true) or
s:find('background%-color', 1, true)
)
end
local function hasColor(s)
if type(s) ~= 'string' then return false end
s = s:lower()
return s:match('^%s*color%s*:') or s:match('[;%s]color%s*:')
end
-- Main entry point
function p.main(frame)
local args = getArgs(frame) -- Uses Module:Arguments, trims, handles aliases
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 args.templatestyles then
table.insert(out, frame:extensionTag{ name = 'templatestyles', args = { src = args.templatestyles } })
end
-- Collapse logic
local collapse = lc(args.collapse or args.collapsible or '')
local state = lc(args.state or '')
local collapsible = state ~= 'plain' and collapse ~= 'no'
local allowOuterImages = not collapsible
local userSetOuterImage = args['image-outer'] or args.imageouter or args.imageouterleft or args['image-outer-right'] or args.imageouterright or args.imageouter2
if userSetOuterImage and collapsible then
mw.addWarning("<code>imageouter</code> type images will not be shown unless <code>|state = plain</code> or <code>|collapse = no</code>.")
end
-- Outer image args
local imageOuterLeft = allowOuterImages and (args['image-outer'] or args.imageouter or args.imageouterleft)
local imageOuterRight = allowOuterImages and (args['image-outer-right'] or args.imageouterright or args.imageouter2)
local hasOuterImages = imageOuterLeft or imageOuterRight
-- Inner images
local imageLeftArg = args.image2 or args.imageleft
local hasInnerImages = args.image or imageLeftArg
if hasOuterImages and hasInnerImages then
mw.addWarning("When <code>|state = plain</code> or <code>|collapse = no</code>, <code>image</code> ''or'' <code>imageouter</code> type images can be used, but ''not'' both.")
end
-- Classes
local bodyclass = args.bodyclass or args.class or ''
local classes = { 'simple-navbox', bodyclass, 'noprint' }
if collapsible then
table.insert(classes, 'NavFrame')
if state == 'collapsed' or state == 'closed' then
table.insert(classes, 'NavClosed')
elseif state == 'expanded' or state == 'uncollapsed' or state == 'open' then
table.insert(classes, 'NavOpen')
end
elseif hasOuterImages then
table.insert(classes, 'simple-outer')
end
-- Body style
local bodystyle = args.bodystyle or ''
table.insert(out, string.format('<div class="%s" style="%s">', table.concat(classes, ' '), bodystyle))
-- Outer left image
if imageOuterLeft then
table.insert(out, string.format('<div class="simple-outer-image">%s</div>', imageOuterLeft))
end
-- Header
local headerstyle = args.headerstyle or args.titlestyle or ''
local headerClass = 'simple-header NavHead'
if headerstyle ~= '' and hasColor(headerstyle) then
headerClass = headerClass .. ' simple-header-modified'
end
local header = {}
if 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 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 = lc(args['image-align'] or args.imagealign or '')
local flex = 'display:flex; flex-flow:row;'
if 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 inner image
local imageLeft = args.image2 or args.imageleft
local imageValign = args['image-valign'] or args.imagevalign or 'center'
if not hasOuterImages and 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 args.group1 then
local oddGStyle = (args.groupstyle or '') .. (args.oddgroupstyle and ';' .. args.oddgroupstyle or '')
local evenGStyle = (args.groupstyle or '') .. (args.evengroupstyle and ';' .. args.evengroupstyle or '')
local oddLStyle = (args.liststyle or '') .. (args.oddliststyle and ';' .. args.oddliststyle or '')
local evenLStyle = (args.liststyle or '') .. (args.evenliststyle and ';' .. args.evenliststyle or '')
local tableClass = 'simple-group-container' ..
((hasBackground(args.groupstyle) or hasBackground(args.oddgroupstyle) or hasBackground(args.evengroupstyle)) and ' simple-group-modified' or '') ..
((hasBackground(args.liststyle) or hasBackground(args.oddliststyle) or hasBackground(args.evenliststyle)) and ' simple-list-modified' or '')
if hasColor(oddGStyle) or hasColor(evenGStyle) then
tableClass = tableClass .. ' simple-group-inherit'
end
table.insert(out, string.format('<table class="%s" style="%s">', tableClass, args.tablestyle or ''))
local batchLists, groupIndices = {}, {}
for i = 1, 50 do
if args['group' .. i] then
table.insert(batchLists, args['list' .. i] or '')
table.insert(groupIndices, i)
end
end
local preprocessedLists = {}
if #batchLists > 0 then
local sep = '@@SIMPLE_SEPARATOR@@'
local concatenated = table.concat(batchLists, sep)
local processed = frame:preprocess(concatenated)
for part in mw.ustring.gmatch(processed, '(.-)' .. sep) do
table.insert(preprocessedLists, part)
end
if #preprocessedLists < #batchLists then
table.insert(preprocessedLists, mw.ustring.match(processed, '.*' .. sep .. '(.*)') or batchLists[#batchLists])
end
end
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) .. ';' .. (args['group' .. i .. 'style'] or '')
local lstyle = (odd and oddLStyle or evenLStyle) .. ';' .. (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
local list = args.list or args.list1 or 'Error: <code>list</code> is empty!'
if 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 inner image
if not hasOuterImages and 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 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>') -- close simple-navcontent
-- Outer right image
if imageOuterRight then
table.insert(out, string.format('<div class="simple-outer-imageright">%s</div>', imageOuterRight))
end
table.insert(out, '</div>') -- close outer simple-navbox
return table.concat(out)
end
return p