Module:Navbox with collapsible groups: Difference between revisions
Jump to navigation
Jump to search
>MusikAnimal m Protected "Module:Navbox with collapsible groups": High-risk Lua module ([Edit=Require template editor access] (indefinite) [Move=Require template editor access] (indefinite)) |
>Ahecht pseudo-ternary operator doesn't work with "and nil" |
||
Line 1: | Line 1: | ||
-- This module implements {{Navbox with collapsible groups}} | -- This module implements {{Navbox with collapsible groups}} | ||
local | |||
local Navbox = | require('strict') | ||
local p = {} | |||
local parentCfg = mw.loadData('Module:Navbox/configuration') | |||
local thisCfg = mw.loadData('Module:Navbox with collapsible groups/configuration') | |||
local cfg = {} | |||
for k, v in pairs(thisCfg) do | |||
if type(v) == 'table' then | |||
cfg[k] = {} | |||
if type(parentCfg[k]) == 'table' then | |||
for kk, vv in pairs(parentCfg[k]) do cfg[k][kk] = vv end | |||
end | |||
for kk, vv in pairs(v) do cfg[k][kk] = vv end | |||
end | |||
end | |||
local inArray = require("Module:TableTools").inArray | |||
local getArgs -- lazily initialized | |||
-- helper functions | -- helper functions | ||
local andnum = function(s, n) return string.format(cfg.arg[s..'_and_num'], n) end | |||
local isblank = function(v) return (v or '') == '' end | |||
local function concatstrings(s) | local function concatstrings(s) | ||
local r = table.concat(s, '') | local r = table.concat(s, '') | ||
if r:match('^%s*$') then | if r:match('^%s*$') then return nil end | ||
return r | return r | ||
end | end | ||
local function concatstyles(s) | local function concatstyles(s) | ||
local r = | local r = '' | ||
for _, v in ipairs(s) do | |||
v = mw.text.trim(v, "%s;") | |||
if not isblank(v) then r = r .. v .. ';' end | |||
end | end | ||
if r | if isblank(r) then return nil end | ||
return r | return r | ||
end | end | ||
local function getSubgroup(args, listnum, listText) | |||
local subArgs = { | |||
[cfg.arg.border] = cfg.keyword.border_subgroup, | |||
[cfg.arg.navbar] = cfg.keyword.navbar_plain | |||
} | |||
local hasSubArgs = false | |||
for k, v in pairs(args) do | |||
k = tostring(k) | |||
for _, w in ipairs(cfg.keyword.subgroups) do | |||
w = w .. listnum .. "_" | |||
if (#k > #w) and (k:sub(1, #w) == w) then | |||
subArgs[k:sub(#w + 1)] = v | |||
hasSubArgs = true | |||
end | |||
end | |||
end | |||
return hasSubArgs and p._navbox(subArgs) or listText | |||
end | |||
-- Main functions | |||
p._navbox = require('Module:Navbox')._navbox | |||
function | function p._withCollapsibleGroups(pargs) | ||
-- table for args passed to navbox | -- table for args passed to navbox | ||
local targs = {} | local targs = {} | ||
Line 25: | Line 67: | ||
-- process args | -- process args | ||
local passthrough = { | local passthrough = { | ||
[ | [cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true, | ||
[ | [cfg.arg.basestyle]=true, | ||
[ | [cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true, | ||
[ | [cfg.arg.bodyclass]=true,[cfg.arg.bodystyle]=true, | ||
[cfg.arg.border]=true, | |||
[ | [cfg.arg.groupclass]=true, | ||
[ | [cfg.arg.image]=true,[cfg.arg.imageclass]=true,[cfg.arg.imagestyle]=true, | ||
[cfg.arg.imageleft]=true,[cfg.arg.imageleftstyle]=true, | |||
[cfg.arg.listclass]=true, | |||
[cfg.arg.name]=true, | |||
[cfg.arg.navbar]=true, | |||
[cfg.arg.state]=true, | |||
[cfg.arg.style]=true, | |||
[cfg.arg.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true | |||
} | } | ||
for k,v in pairs(pargs) do | for k,v in pairs(pargs) do | ||
Line 38: | Line 86: | ||
if passthrough[k] then | if passthrough[k] then | ||
targs[k] = v | targs[k] = v | ||
elseif (k:match( | elseif (k:match(cfg.pattern.num)) then | ||
local n = k:match(cfg.pattern.num) | |||
local | local list_and_num = andnum('list', n) | ||
if (targs[ | if ((k:match(cfg.pattern.listnum) or k:match(cfg.pattern.contentnum)) | ||
and targs[list_and_num] == nil | |||
targs[ | and pargs[andnum('group', n)] == nil | ||
and pargs[andnum('sect', n)] == nil | |||
and pargs[andnum('section', n)] == nil) then | |||
targs[list_and_num] = concatstrings({ | |||
pargs[list_and_num] or '', | |||
pargs[andnum('content', n)] or '' | |||
}) | |||
if (targs[list_and_num] and inArray(cfg.keyword.subgroups, targs[list_and_num])) then | |||
local titlestyle = concatstyles( | targs[list_and_num] = getSubgroup(pargs, n, targs[list_and_num]) | ||
end | |||
elseif ((k:match(cfg.pattern.groupnum) or k:match(cfg.pattern.sectnum) or k:match(cfg.pattern.sectionnum)) | |||
and targs[list_and_num] == nil) then | |||
local liststyle = concatstyles( | local titlestyle = concatstyles({ | ||
pargs[cfg.arg.groupstyle] or '', | |||
pargs[cfg.arg.secttitlestyle] or '', | |||
pargs[andnum('groupstyle', n)] or '', | |||
local title = concatstrings( | pargs[andnum('sectiontitlestyle', n)] or '' | ||
}) | |||
local liststyle = concatstyles({ | |||
pargs[cfg.arg.liststyle] or '', | |||
local list = concatstrings( | pargs[cfg.arg.contentstyle] or '', | ||
pargs[andnum('liststyle', n)] or '', | |||
pargs[andnum('contentstyle', n)] or '' | |||
local | }) | ||
and | local title = concatstrings({ | ||
pargs[andnum('group', n)] or '', | |||
pargs[andnum('sect', n)] or '', | |||
pargs[andnum('section', n)] or '' | |||
}) | |||
local list = concatstrings({ | |||
pargs[list_and_num] or '', | |||
pargs[andnum('content', n)] or '' | |||
}) | |||
if list and inArray(cfg.keyword.subgroups, list) then | |||
list = getSubgroup(pargs, n, list) | |||
end | |||
local abbr_and_num = andnum('abbr', n) | |||
local state = (pargs[abbr_and_num] and pargs[abbr_and_num] == pargs[cfg.arg.selected]) | |||
and cfg.keyword.state_uncollapsed | |||
or (pargs[andnum('state', n)] or cfg.keyword.state_collapsed) | |||
targs[ | targs[list_and_num] =p._navbox({ | ||
cfg.keyword.border_child, | |||
basestyle = pargs[ | [cfg.arg.navbar] = cfg.keyword.navbar_plain, | ||
title = title, titlestyle = titlestyle, | [cfg.arg.state] = state, | ||
[cfg.arg.basestyle] = pargs[cfg.arg.basestyle], | |||
listclass = pargs[' | [cfg.arg.title] = title, | ||
image = pargs['image' | [cfg.arg.titlestyle] = titlestyle, | ||
imageleft = pargs['imageleft' | [andnum('list', 1)] = list, | ||
listpadding = pargs[ | [cfg.arg.liststyle] = liststyle, | ||
[cfg.arg.listclass] = pargs[andnum('listclass', n)], | |||
[cfg.arg.image] = pargs[andnum('image', n)], | |||
[cfg.arg.imageleft] = pargs[andnum('imageleft', n)], | |||
[cfg.arg.listpadding] = pargs[cfg.arg.listpadding] | |||
}) | |||
end | end | ||
end | end | ||
Line 83: | Line 151: | ||
end | end | ||
-- ordering of style and bodystyle | -- ordering of style and bodystyle | ||
targs[ | targs[cfg.arg.style] = concatstyles({targs[cfg.arg.style] or '', targs[cfg.arg.bodystyle] or ''}) | ||
targs[ | targs[cfg.arg.bodystyle] = nil | ||
-- child or subgroup | -- child or subgroup | ||
if targs[ | if targs[cfg.arg.border] == nil then targs[cfg.arg.border] = pargs[1] end | ||
return | return p._navbox(targs) | ||
end | end | ||
function | -- Template entry points | ||
local | function p.navbox (frame, boxtype) | ||
local function readArgs(args, prefix) | |||
-- Read the arguments in the order they'll be output in, to make references | |||
-- number in the right order. | |||
local _ | |||
_ = args[prefix .. cfg.arg.title] | |||
_ = args[prefix .. cfg.arg.above] | |||
-- Limit this to 20 as covering 'most' cases (that's a SWAG) and because | |||
-- iterator approach won't work here | |||
for i = 1, 20 do | |||
_ = args[prefix .. andnum('group', i)] | |||
if inArray(cfg.keyword.subgroups, args[prefix .. andnum('list', i)]) then | |||
for _, v in ipairs(cfg.keyword.subgroups) do | |||
readArgs(args, prefix .. v .. i .. "_") | |||
end | |||
end | |||
end | |||
_ = args[prefix .. cfg.arg.below] | |||
end | |||
if not getArgs then | |||
getArgs = require('Module:Arguments').getArgs | |||
end | end | ||
_ | local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}}) | ||
readArgs(args, "") | |||
return p['_'..(boxtype or 'navbox')](args) | |||
end | |||
return | p['with collapsible groups'] = function (frame) | ||
return p.navbox(frame, 'withCollapsibleGroups') | |||
end | end | ||
local q = {} | |||
q._navbox = p._withCollapsibleGroups | |||
q.navbox = p['with collapsible groups'] | |||
return q | return q |
Latest revision as of 15:06, 17 September 2024
Documentation for this module may be created at Module:Navbox with collapsible groups/doc
-- This module implements {{Navbox with collapsible groups}}
require('strict')
local p = {}
local parentCfg = mw.loadData('Module:Navbox/configuration')
local thisCfg = mw.loadData('Module:Navbox with collapsible groups/configuration')
local cfg = {}
for k, v in pairs(thisCfg) do
if type(v) == 'table' then
cfg[k] = {}
if type(parentCfg[k]) == 'table' then
for kk, vv in pairs(parentCfg[k]) do cfg[k][kk] = vv end
end
for kk, vv in pairs(v) do cfg[k][kk] = vv end
end
end
local inArray = require("Module:TableTools").inArray
local getArgs -- lazily initialized
-- helper functions
local andnum = function(s, n) return string.format(cfg.arg[s..'_and_num'], n) end
local isblank = function(v) return (v or '') == '' end
local function concatstrings(s)
local r = table.concat(s, '')
if r:match('^%s*$') then return nil end
return r
end
local function concatstyles(s)
local r = ''
for _, v in ipairs(s) do
v = mw.text.trim(v, "%s;")
if not isblank(v) then r = r .. v .. ';' end
end
if isblank(r) then return nil end
return r
end
local function getSubgroup(args, listnum, listText)
local subArgs = {
[cfg.arg.border] = cfg.keyword.border_subgroup,
[cfg.arg.navbar] = cfg.keyword.navbar_plain
}
local hasSubArgs = false
for k, v in pairs(args) do
k = tostring(k)
for _, w in ipairs(cfg.keyword.subgroups) do
w = w .. listnum .. "_"
if (#k > #w) and (k:sub(1, #w) == w) then
subArgs[k:sub(#w + 1)] = v
hasSubArgs = true
end
end
end
return hasSubArgs and p._navbox(subArgs) or listText
end
-- Main functions
p._navbox = require('Module:Navbox')._navbox
function p._withCollapsibleGroups(pargs)
-- table for args passed to navbox
local targs = {}
-- process args
local passthrough = {
[cfg.arg.above]=true,[cfg.arg.aboveclass]=true,[cfg.arg.abovestyle]=true,
[cfg.arg.basestyle]=true,
[cfg.arg.below]=true,[cfg.arg.belowclass]=true,[cfg.arg.belowstyle]=true,
[cfg.arg.bodyclass]=true,[cfg.arg.bodystyle]=true,
[cfg.arg.border]=true,
[cfg.arg.groupclass]=true,
[cfg.arg.image]=true,[cfg.arg.imageclass]=true,[cfg.arg.imagestyle]=true,
[cfg.arg.imageleft]=true,[cfg.arg.imageleftstyle]=true,
[cfg.arg.listclass]=true,
[cfg.arg.name]=true,
[cfg.arg.navbar]=true,
[cfg.arg.state]=true,
[cfg.arg.style]=true,
[cfg.arg.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true
}
for k,v in pairs(pargs) do
if k and type(k) == 'string' then
if passthrough[k] then
targs[k] = v
elseif (k:match(cfg.pattern.num)) then
local n = k:match(cfg.pattern.num)
local list_and_num = andnum('list', n)
if ((k:match(cfg.pattern.listnum) or k:match(cfg.pattern.contentnum))
and targs[list_and_num] == nil
and pargs[andnum('group', n)] == nil
and pargs[andnum('sect', n)] == nil
and pargs[andnum('section', n)] == nil) then
targs[list_and_num] = concatstrings({
pargs[list_and_num] or '',
pargs[andnum('content', n)] or ''
})
if (targs[list_and_num] and inArray(cfg.keyword.subgroups, targs[list_and_num])) then
targs[list_and_num] = getSubgroup(pargs, n, targs[list_and_num])
end
elseif ((k:match(cfg.pattern.groupnum) or k:match(cfg.pattern.sectnum) or k:match(cfg.pattern.sectionnum))
and targs[list_and_num] == nil) then
local titlestyle = concatstyles({
pargs[cfg.arg.groupstyle] or '',
pargs[cfg.arg.secttitlestyle] or '',
pargs[andnum('groupstyle', n)] or '',
pargs[andnum('sectiontitlestyle', n)] or ''
})
local liststyle = concatstyles({
pargs[cfg.arg.liststyle] or '',
pargs[cfg.arg.contentstyle] or '',
pargs[andnum('liststyle', n)] or '',
pargs[andnum('contentstyle', n)] or ''
})
local title = concatstrings({
pargs[andnum('group', n)] or '',
pargs[andnum('sect', n)] or '',
pargs[andnum('section', n)] or ''
})
local list = concatstrings({
pargs[list_and_num] or '',
pargs[andnum('content', n)] or ''
})
if list and inArray(cfg.keyword.subgroups, list) then
list = getSubgroup(pargs, n, list)
end
local abbr_and_num = andnum('abbr', n)
local state = (pargs[abbr_and_num] and pargs[abbr_and_num] == pargs[cfg.arg.selected])
and cfg.keyword.state_uncollapsed
or (pargs[andnum('state', n)] or cfg.keyword.state_collapsed)
targs[list_and_num] =p._navbox({
cfg.keyword.border_child,
[cfg.arg.navbar] = cfg.keyword.navbar_plain,
[cfg.arg.state] = state,
[cfg.arg.basestyle] = pargs[cfg.arg.basestyle],
[cfg.arg.title] = title,
[cfg.arg.titlestyle] = titlestyle,
[andnum('list', 1)] = list,
[cfg.arg.liststyle] = liststyle,
[cfg.arg.listclass] = pargs[andnum('listclass', n)],
[cfg.arg.image] = pargs[andnum('image', n)],
[cfg.arg.imageleft] = pargs[andnum('imageleft', n)],
[cfg.arg.listpadding] = pargs[cfg.arg.listpadding]
})
end
end
end
end
-- ordering of style and bodystyle
targs[cfg.arg.style] = concatstyles({targs[cfg.arg.style] or '', targs[cfg.arg.bodystyle] or ''})
targs[cfg.arg.bodystyle] = nil
-- child or subgroup
if targs[cfg.arg.border] == nil then targs[cfg.arg.border] = pargs[1] end
return p._navbox(targs)
end
-- Template entry points
function p.navbox (frame, boxtype)
local function readArgs(args, prefix)
-- Read the arguments in the order they'll be output in, to make references
-- number in the right order.
local _
_ = args[prefix .. cfg.arg.title]
_ = args[prefix .. cfg.arg.above]
-- Limit this to 20 as covering 'most' cases (that's a SWAG) and because
-- iterator approach won't work here
for i = 1, 20 do
_ = args[prefix .. andnum('group', i)]
if inArray(cfg.keyword.subgroups, args[prefix .. andnum('list', i)]) then
for _, v in ipairs(cfg.keyword.subgroups) do
readArgs(args, prefix .. v .. i .. "_")
end
end
end
_ = args[prefix .. cfg.arg.below]
end
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}})
readArgs(args, "")
return p['_'..(boxtype or 'navbox')](args)
end
p['with collapsible groups'] = function (frame)
return p.navbox(frame, 'withCollapsibleGroups')
end
local q = {}
q._navbox = p._withCollapsibleGroups
q.navbox = p['with collapsible groups']
return q