Module:Navbox with collapsible groups: Difference between revisions
Nazarzadeh (talk | contribs) m (1 revision imported) |
(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 |
Revision as of 23:36, 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