Module:Navbox and Module:Navbox/sandbox: Difference between pages
Appearance
(Difference between pages)
Content deleted Content added
Read prefixed title, above, and below |
Restored revision 1249008661 by Dabao qian (talk) |
||
Line 1: | Line 1: | ||
require('strict') |
require('strict') |
||
local p = {} |
local p = {} |
||
local cfg = mw.loadData('Module:Navbox/configuration') |
local cfg = mw.loadData('Module:Navbox/configuration/sandbox') |
||
local inArray = require("Module:TableTools").inArray |
local inArray = require("Module:TableTools").inArray |
||
local getArgs -- lazily initialized |
local getArgs -- lazily initialized |
||
local format = string.format |
|||
-- global passthrough variables |
|||
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.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.title]=true,[cfg.arg.titleclass]=true,[cfg.arg.titlestyle]=true, |
|||
} |
|||
-- 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, prefix) |
|||
local subArgs = { |
|||
[cfg.arg.border] = cfg.keyword.border_subgroup, |
|||
[cfg.arg.navbar] = cfg.keyword.navbar_plain |
|||
} |
|||
local hasSubArgs = false |
|||
local subgroups_and_num = prefix and {prefix} or cfg.arg.subgroups_and_num |
|||
for k, v in pairs(args) do |
|||
k = tostring(k) |
|||
for _, w in ipairs(subgroups_and_num) do |
|||
w = string.format(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 |
|||
function p._navbox(args) |
function p._navbox(args) |
||
if args.type == cfg.keyword.with_collapsible_groups then |
|||
return p._withCollapsibleGroups(args) |
|||
elseif args.type == cfg.keyword.with_columns then |
|||
return p._withColumns(args) |
|||
end |
|||
local function striped(wikitext, border) |
local function striped(wikitext, border) |
||
-- Return wikitext with markers replaced for odd/even striping. |
-- Return wikitext with markers replaced for odd/even striping. |
||
Line 47: | Line 109: | ||
return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count |
return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count |
||
end |
end |
||
local function processItem(item, nowrapitems) |
local function processItem(item, nowrapitems) |
||
if item:sub(1, 2) == '{|' then |
if item:sub(1, 2) == '{|' then |
||
Line 59: | Line 121: | ||
local prefix, content = line:match('^([*:;#]+)%s*(.*)') |
local prefix, content = line:match('^([*:;#]+)%s*(.*)') |
||
if prefix and not content:match(cfg.pattern.nowrap) then |
if prefix and not content:match(cfg.pattern.nowrap) then |
||
line = format(cfg.nowrap_item, prefix, content) |
line = string.format(cfg.nowrap_item, prefix, content) |
||
end |
end |
||
table.insert(lines, line) |
table.insert(lines, line) |
||
Line 70: | Line 132: | ||
return item |
return item |
||
end |
end |
||
local function has_navbar() |
local function has_navbar() |
||
return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off |
return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off |
||
Line 80: | Line 142: | ||
) |
) |
||
end |
end |
||
-- extract text color from css, which is the only permitted inline CSS for the navbar |
-- extract text color from css, which is the only permitted inline CSS for the navbar |
||
local function extract_color(css_str) |
local function extract_color(css_str) |
||
Line 87: | Line 149: | ||
return mw.ustring.match(';' .. css_str .. ';', '.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;') or nil |
return mw.ustring.match(';' .. css_str .. ';', '.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;') or nil |
||
end |
end |
||
local function renderNavBar(titleCell) |
local function renderNavBar(titleCell) |
||
if has_navbar() then |
if has_navbar() then |
||
local navbar = require('Module:Navbar')._navbar |
local navbar = require('Module:Navbar/sandbox')._navbar |
||
titleCell:wikitext(navbar{ |
titleCell:wikitext(navbar{ |
||
[cfg.navbar.name] = args[cfg.arg.name], |
[cfg.navbar.name] = args[cfg.arg.name], |
||
Line 99: | Line 161: | ||
}) |
}) |
||
end |
end |
||
end |
end |
||
local function renderTitleRow(tbl) |
local function renderTitleRow(tbl) |
||
if not args[cfg.arg.title] then return end |
if not args[cfg.arg.title] then return end |
||
local titleRow = tbl:tag('tr') |
local titleRow = tbl:tag('tr') |
||
local titleCell = titleRow:tag('th'):attr('scope', 'col') |
local titleCell = titleRow:tag('th'):attr('scope', 'col') |
||
local titleColspan = 2 |
local titleColspan = 2 |
||
if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end |
if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end |
||
if args[cfg.arg.image] then titleColspan = titleColspan + 1 end |
if args[cfg.arg.image] then titleColspan = titleColspan + 1 end |
||
titleCell |
titleCell |
||
:cssText(args[cfg.arg.basestyle]) |
:cssText(args[cfg.arg.basestyle]) |
||
Line 118: | Line 180: | ||
:addClass(cfg.class.navbox_title) |
:addClass(cfg.class.navbox_title) |
||
:attr('colspan', titleColspan) |
:attr('colspan', titleColspan) |
||
renderNavBar(titleCell) |
renderNavBar(titleCell) |
||
titleCell |
titleCell |
||
:tag('div') |
:tag('div') |
||
Line 130: | Line 192: | ||
:wikitext(processItem(args[cfg.arg.title])) |
:wikitext(processItem(args[cfg.arg.title])) |
||
end |
end |
||
local function getAboveBelowColspan() |
local function getAboveBelowColspan() |
||
local ret = 2 |
local ret = 2 |
||
Line 137: | Line 199: | ||
return ret |
return ret |
||
end |
end |
||
local function renderAboveRow(tbl) |
local function renderAboveRow(tbl) |
||
if not args[cfg.arg.above] then return end |
if not args[cfg.arg.above] then return end |
||
tbl:tag('tr') |
tbl:tag('tr') |
||
:tag('td') |
:tag('td') |
||
Line 153: | Line 215: | ||
:wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems])) |
:wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems])) |
||
end |
end |
||
local function renderBelowRow(tbl) |
local function renderBelowRow(tbl) |
||
if not args[cfg.arg.below] then return end |
if not args[cfg.arg.below] then return end |
||
tbl:tag('tr') |
tbl:tag('tr') |
||
:tag('td') |
:tag('td') |
||
Line 167: | Line 229: | ||
:wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems])) |
:wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems])) |
||
end |
end |
||
local function renderListRow(tbl, index, listnum, listnums_size) |
local function renderListRow(tbl, index, listnum, listnums_size) |
||
local row = tbl:tag('tr') |
local row = tbl:tag('tr') |
||
if index == 1 and args[cfg.arg.imageleft] then |
if index == 1 and args[cfg.arg.imageleft] then |
||
row |
row |
||
Line 184: | Line 246: | ||
:wikitext(processItem(args[cfg.arg.imageleft])) |
:wikitext(processItem(args[cfg.arg.imageleft])) |
||
end |
end |
||
local group_and_num = |
local group_and_num = andnum('group', listnum) |
||
local groupstyle_and_num = |
local groupstyle_and_num = andnum('groupstyle', listnum) |
||
if args[group_and_num] then |
if args[group_and_num] then |
||
local groupCell = row:tag('th') |
local groupCell = row:tag('th') |
||
-- id for aria-labelledby attribute, if lone group with no title or above |
-- id for aria-labelledby attribute, if lone group with no title or above |
||
if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then |
if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then |
||
Line 195: | Line 257: | ||
:attr('id', mw.uri.anchorEncode(args[cfg.arg.group1])) |
:attr('id', mw.uri.anchorEncode(args[cfg.arg.group1])) |
||
end |
end |
||
groupCell |
groupCell |
||
:attr('scope', 'row') |
:attr('scope', 'row') |
||
Line 203: | Line 265: | ||
-- If groupwidth not specified, minimize width |
-- If groupwidth not specified, minimize width |
||
:css('width', args[cfg.arg.groupwidth] or '1%') |
:css('width', args[cfg.arg.groupwidth] or '1%') |
||
groupCell |
groupCell |
||
:cssText(args[cfg.arg.groupstyle]) |
:cssText(args[cfg.arg.groupstyle]) |
||
Line 209: | Line 271: | ||
:wikitext(args[group_and_num]) |
:wikitext(args[group_and_num]) |
||
end |
end |
||
local listCell = row:tag('td') |
local listCell = row:tag('td') |
||
if args[group_and_num] then |
if args[group_and_num] then |
||
listCell |
listCell |
||
Line 218: | Line 280: | ||
listCell:attr('colspan', 2) |
listCell:attr('colspan', 2) |
||
end |
end |
||
if not args[cfg.arg.groupwidth] then |
if not args[cfg.arg.groupwidth] then |
||
listCell:css('width', '100%') |
listCell:css('width', '100%') |
||
end |
end |
||
local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing |
local rowstyle -- usually nil so cssText(rowstyle) usually adds nothing |
||
if index % 2 == 1 then |
if index % 2 == 1 then |
||
Line 229: | Line 291: | ||
rowstyle = args[cfg.arg.evenstyle] |
rowstyle = args[cfg.arg.evenstyle] |
||
end |
end |
||
local list_and_num = |
local list_and_num = andnum('list', listnum) |
||
local listText = args[list_and_num] |
local listText = inArray(cfg.keyword.subgroups, args[list_and_num]) |
||
and getSubgroup(args, listnum, args[list_and_num]) or args[list_and_num] |
|||
if inArray(cfg.keyword.subgroups, listText) then |
|||
local childArgs = { |
|||
[cfg.arg.border] = cfg.keyword.border_subgroup, |
|||
[cfg.arg.navbar] = cfg.keyword.navbar_plain |
|||
} |
|||
local hasChildArgs = 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 |
|||
childArgs[k:sub(#w + 1)] = v |
|||
hasChildArgs = true |
|||
end |
|||
end |
|||
end |
|||
listText = hasChildArgs and p._navbox(childArgs) or listText |
|||
end |
|||
local oddEven = cfg.marker.oddeven |
local oddEven = cfg.marker.oddeven |
||
if listText:sub(1, 12) == '</div><table' then |
if listText:sub(1, 12) == '</div><table' then |
||
Line 257: | Line 301: | ||
oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part |
oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part |
||
end |
end |
||
local liststyle_and_num = |
local liststyle_and_num = andnum('liststyle', listnum) |
||
local listclass_and_num = |
local listclass_and_num = andnum('listclass', listnum) |
||
listCell |
listCell |
||
:css('padding', '0') |
:css('padding', '0') |
||
Line 274: | Line 318: | ||
) |
) |
||
:wikitext(processItem(listText, args[cfg.arg.nowrapitems])) |
:wikitext(processItem(listText, args[cfg.arg.nowrapitems])) |
||
if index == 1 and args[cfg.arg.image] then |
if index == 1 and args[cfg.arg.image] then |
||
row |
row |
||
Line 289: | Line 333: | ||
end |
end |
||
end |
end |
||
local function has_list_class(htmlclass) |
local function has_list_class(htmlclass) |
||
local patterns = { |
local patterns = { |
||
Line 297: | Line 341: | ||
'%s' .. htmlclass .. '%s' |
'%s' .. htmlclass .. '%s' |
||
} |
} |
||
for arg, _ in pairs(args) do |
for arg, _ in pairs(args) do |
||
if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then |
if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then |
||
Line 309: | Line 353: | ||
return false |
return false |
||
end |
end |
||
-- there are a lot of list classes in the wild, so we add their TemplateStyles |
-- there are a lot of list classes in the wild, so we add their TemplateStyles |
||
local function add_list_styles() |
local function add_list_styles() |
||
Line 322: | Line 366: | ||
end |
end |
||
end |
end |
||
local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles) |
local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles) |
||
local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles) |
local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles) |
||
-- a second workaround for [[phab:T303378]] |
-- a second workaround for [[phab:T303378]] |
||
-- when that issue is fixed, we can actually use has_navbar not to emit the |
-- when that issue is fixed, we can actually use has_navbar not to emit the |
||
Line 334: | Line 378: | ||
} |
} |
||
end |
end |
||
-- hlist -> plainlist is best-effort to preserve old Common.css ordering. |
-- hlist -> plainlist is best-effort to preserve old Common.css ordering. |
||
-- this ordering is not a guarantee because most navboxes will emit only |
-- this ordering is not a guarantee because most navboxes will emit only |
||
Line 340: | Line 384: | ||
return hlist_styles .. plainlist_styles |
return hlist_styles .. plainlist_styles |
||
end |
end |
||
local function needsHorizontalLists(border) |
local function needsHorizontalLists(border) |
||
if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then |
if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then |
||
Line 347: | Line 391: | ||
return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist) |
return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist) |
||
end |
end |
||
local function hasBackgroundColors() |
local function hasBackgroundColors() |
||
for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle, |
for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle, |
||
Line 357: | Line 401: | ||
return false |
return false |
||
end |
end |
||
local function hasBorders() |
local function hasBorders() |
||
for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle, |
for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle, |
||
Line 367: | Line 411: | ||
return false |
return false |
||
end |
end |
||
local function isIllegible() |
local function isIllegible() |
||
local styleratio = require('Module:Color contrast')._styleratio |
local styleratio = require('Module:Color contrast')._styleratio |
||
Line 379: | Line 423: | ||
return false |
return false |
||
end |
end |
||
local function getTrackingCategories(border) |
local function getTrackingCategories(border) |
||
local cats = {} |
local cats = {} |
||
Line 388: | Line 432: | ||
return cats |
return cats |
||
end |
end |
||
local function renderTrackingCategories(builder, border) |
local function renderTrackingCategories(builder, border) |
||
local title = mw.title.getCurrentTitle() |
local title = mw.title.getCurrentTitle() |
||
Line 395: | Line 439: | ||
if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox |
if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox |
||
or subpage == cfg.keyword.subpage_testcases then return end |
or subpage == cfg.keyword.subpage_testcases then return end |
||
for _, cat in ipairs(getTrackingCategories(border)) do |
for _, cat in ipairs(getTrackingCategories(border)) do |
||
builder:wikitext('[[Category:' .. cat .. ']]') |
builder:wikitext('[[Category:' .. cat .. ']]') |
||
end |
end |
||
end |
end |
||
local function renderMainTable(border, listnums) |
local function renderMainTable(border, listnums) |
||
local tbl = mw.html.create('table') |
local tbl = mw.html.create('table') |
||
:addClass(cfg.class.nowraplinks) |
:addClass(cfg.class.nowraplinks) |
||
:addClass(args[cfg.arg.bodyclass]) |
:addClass(args[cfg.arg.bodyclass]) |
||
local state = args[cfg.arg.state] |
local state = args[cfg.arg.state] |
||
if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then |
if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then |
||
Line 415: | Line 459: | ||
:addClass(state or cfg.class.autocollapse) |
:addClass(state or cfg.class.autocollapse) |
||
end |
end |
||
tbl:css('border-spacing', 0) |
tbl:css('border-spacing', 0) |
||
if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then |
if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then |
||
Line 429: | Line 473: | ||
end |
end |
||
tbl:cssText(args[cfg.arg.innerstyle]) |
tbl:cssText(args[cfg.arg.innerstyle]) |
||
renderTitleRow(tbl) |
renderTitleRow(tbl) |
||
renderAboveRow(tbl) |
renderAboveRow(tbl) |
||
Line 437: | Line 481: | ||
end |
end |
||
renderBelowRow(tbl) |
renderBelowRow(tbl) |
||
return tbl |
return tbl |
||
end |
end |
||
local function add_navbox_styles(hiding_templatestyles) |
local function add_navbox_styles(hiding_templatestyles) |
||
local frame = mw.getCurrentFrame() |
local frame = mw.getCurrentFrame() |
||
-- This is a lambda so that it doesn't need the frame as a parameter |
-- This is a lambda so that it doesn't need the frame as a parameter |
||
local function add_user_styles(templatestyles) |
local function add_user_styles(templatestyles) |
||
if |
if not isblank(templatestyles) then |
||
return frame:extensionTag{ |
return frame:extensionTag{ |
||
name = 'templatestyles', args = { src = templatestyles } |
name = 'templatestyles', args = { src = templatestyles } |
||
Line 452: | Line 496: | ||
return '' |
return '' |
||
end |
end |
||
-- get templatestyles. load base from config so that Lua only needs to do |
-- get templatestyles. load base from config so that Lua only needs to do |
||
-- the work once of parser tag expansion |
-- the work once of parser tag expansion |
||
Line 458: | Line 502: | ||
local templatestyles = add_user_styles(args[cfg.arg.templatestyles]) |
local templatestyles = add_user_styles(args[cfg.arg.templatestyles]) |
||
local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles]) |
local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles]) |
||
-- The 'navbox-styles' div exists to wrap the styles to work around T200206 |
-- The 'navbox-styles' div exists to wrap the styles to work around T200206 |
||
-- more elegantly. Instead of combinatorial rules, this ends up being linear |
-- more elegantly. Instead of combinatorial rules, this ends up being linear |
||
Line 473: | Line 517: | ||
:done() |
:done() |
||
end |
end |
||
-- work around [[phab:T303378]] |
-- work around [[phab:T303378]] |
||
-- for each arg: find all the templatestyles strip markers, insert them into a |
-- for each arg: find all the templatestyles strip markers, insert them into a |
||
Line 490: | Line 534: | ||
return templatestyles_markers |
return templatestyles_markers |
||
end |
end |
||
local hiding_templatestyles = move_hiding_templatestyles(args) |
local hiding_templatestyles = move_hiding_templatestyles(args) |
||
local listnums = {} |
local listnums = {} |
||
for k, _ in pairs(args) do |
for k, _ in pairs(args) do |
||
if type(k) == 'string' then |
if type(k) == 'string' then |
||
Line 567: | Line 611: | ||
end |
end |
||
function p. |
function p._withCollapsibleGroups(pargs) |
||
-- table for args passed to navbox |
|||
local targs = {} |
|||
-- process args |
|||
local passthroughLocal = { |
|||
[cfg.arg.bodystyle] = true, |
|||
[cfg.arg.border] = true, |
|||
[cfg.arg.style] = true, |
|||
} |
|||
for k,v in pairs(pargs) do |
|||
if k and type(k) == 'string' then |
|||
if passthrough[k] or passthroughLocal[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 |
|||
function p._withColumns(pargs) |
|||
-- table for args passed to navbox |
|||
local targs = {} |
|||
-- tables of column numbers |
|||
local colheadernums = {} |
|||
local colnums = {} |
|||
local colfooternums = {} |
|||
-- process args |
|||
local passthroughLocal = { |
|||
[cfg.arg.evenstyle]=true, |
|||
[cfg.arg.groupstyle]=true, |
|||
[cfg.arg.liststyle]=true, |
|||
[cfg.arg.oddstyle]=true, |
|||
[cfg.arg.state]=true, |
|||
} |
|||
for k,v in pairs(pargs) do |
|||
if passthrough[k] or passthroughLocal[k] then |
|||
targs[k] = v |
|||
elseif type(k) == 'string' then |
|||
if k:match(cfg.pattern.listnum) then |
|||
local n = k:match(cfg.pattern.listnum) |
|||
targs[andnum('liststyle', n + 2)] = pargs[andnum('liststyle', n)] |
|||
targs[andnum('group', n + 2)] = pargs[andnum('group', n)] |
|||
targs[andnum('groupstyle', n + 2)] = pargs[andnum('groupstyle', n)] |
|||
if v and inArray(cfg.keyword.subgroups, v) then |
|||
targs[andnum('list', n + 2)] = getSubgroup(pargs, n, v) |
|||
else |
|||
targs[andnum('list', n + 2)] = v |
|||
end |
|||
elseif (k:match(cfg.pattern.colheadernum) and v ~= '') then |
|||
table.insert(colheadernums, tonumber(k:match(cfg.pattern.colheadernum))) |
|||
elseif (k:match(cfg.pattern.colnum) and v ~= '') then |
|||
table.insert(colnums, tonumber(k:match(cfg.pattern.colnum))) |
|||
elseif (k:match(cfg.pattern.colfooternum) and v ~= '') then |
|||
table.insert(colfooternums, tonumber(k:match(cfg.pattern.colfooternum))) |
|||
end |
|||
end |
|||
end |
|||
table.sort(colheadernums) |
|||
table.sort(colnums) |
|||
table.sort(colfooternums) |
|||
-- HTML table for list1 |
|||
local coltable = mw.html.create( 'table' ):addClass('navbox-columns-table') |
|||
local row, col |
|||
local tablestyle = ( (#colheadernums > 0) or (not isblank(pargs[cfg.arg.fullwidth])) ) |
|||
and 'width:100%' |
|||
or 'width:auto; margin-left:auto; margin-right:auto' |
|||
coltable:cssText(concatstyles({ |
|||
'border-spacing: 0px; text-align:left', |
|||
tablestyle, |
|||
pargs[cfg.arg.coltablestyle] or '' |
|||
})) |
|||
--- Header row --- |
|||
if (#colheadernums > 0) then |
|||
row = coltable:tag('tr') |
|||
for k, n in ipairs(colheadernums) do |
|||
col = row:tag('td'):addClass('navbox-abovebelow') |
|||
col:cssText(concatstyles({ |
|||
(k > 1) and 'border-left:2px solid #fdfdfd' or '', |
|||
'font-weight:bold', |
|||
pargs[cfg.arg.colheaderstyle] or '', |
|||
pargs[andnum('colheaderstyle', n)] or '' |
|||
})) |
|||
col:attr('colspan', tonumber(pargs[andnum('colheadercolspan', n)])) |
|||
col:wikitext(pargs[andnum('colheader', n)]) |
|||
end |
|||
end |
|||
--- Main columns --- |
|||
row = coltable:tag('tr'):css('vertical-align', 'top') |
|||
for k, n in ipairs(colnums) do |
|||
if k == 1 and isblank(pargs[andnum('colheader', 1)]) |
|||
and isblank(pargs[andnum('colfooter', 1)]) |
|||
and isblank(pargs[cfg.arg.fullwidth]) then |
|||
local nopad = inArray( |
|||
{'off', '0', '0em', '0px'}, |
|||
mw.ustring.gsub(pargs[cfg.arg.padding] or '', '[;%%]', '')) |
|||
if not nopad then |
|||
row:tag('td'):wikitext(' ') |
|||
:css('width', (pargs[cfg.arg.padding] or '5em')) |
|||
end |
|||
end |
|||
col = row:tag('td'):addClass('navbox-list') |
|||
col:cssText(concatstyles({ |
|||
(k > 1) and 'border-left:2px solid #fdfdfd' or '', |
|||
'padding:0px', |
|||
pargs[cfg.arg.colstyle] or '', |
|||
((n%2 == 0) and pargs[cfg.arg.evencolstyle] or pargs[cfg.arg.oddcolstyle]) or '', |
|||
pargs[andnum('colstyle', n)] or '', |
|||
'width:' .. (pargs[andnum('colwidth', n)] or pargs[cfg.arg.colwidth] or '10em') |
|||
})) |
|||
local wt = pargs[andnum('col', n)] |
|||
if wt and inArray(cfg.keyword.subgroups, wt) then |
|||
wt = getSubgroup(pargs, n, wt, cfg.arg.col_and_num) |
|||
end |
|||
col:tag('div'):newline():wikitext(wt):newline() |
|||
end |
|||
--- Footer row --- |
|||
if (#colfooternums > 0) then |
|||
row = coltable:tag('tr') |
|||
for k, n in ipairs(colfooternums) do |
|||
col = row:tag('td'):addClass('navbox-abovebelow') |
|||
col:cssText(concatstyles({ |
|||
(k > 1) and 'border-left:2px solid #fdfdfd' or '', |
|||
'font-weight:bold', |
|||
pargs[cfg.arg.colfooterstyle] or '', |
|||
pargs[andnum('colfooterstyle', n)] or '' |
|||
})) |
|||
col:attr('colspan', tonumber(pargs[andnum('colfootercolspan', n)])) |
|||
col:wikitext(pargs[andnum('colfooter', n)]) |
|||
end |
|||
end |
|||
-- assign table to list1 |
|||
targs[andnum('list', 1)] = tostring(coltable) |
|||
if isblank(pargs[andnum('colheader', 1)]) |
|||
and isblank(pargs[andnum('col', 1)]) |
|||
and isblank(pargs[andnum('colfooter', 1)]) then |
|||
targs[andnum('list', 1)] = targs[andnum('list', 1)] .. |
|||
'[[' .. cfg.pattern.without_first_col .. ']]' |
|||
end |
|||
-- Other parameters |
|||
targs[cfg.arg.border] = pargs[cfg.arg.border] or pargs[1] |
|||
targs[cfg.arg.evenodd] = (not isblank(pargs[cfg.arg.evenodd])) and pargs[cfg.arg.evenodd] or nil |
|||
targs[cfg.arg.list1padding] = '0px' |
|||
targs[andnum('liststyle', 1)] = 'background:transparent;color:inherit;' |
|||
targs[cfg.arg.style] = concatstyles({pargs[cfg.arg.style], pargs[cfg.arg.bodystyle]}) |
|||
targs[cfg.arg.tracking] = 'no' |
|||
return p._navbox(targs) |
|||
end |
|||
-- Template entry points |
|||
function p.navbox (frame, boxtype) |
|||
local function readArgs(args, prefix) |
local function readArgs(args, prefix) |
||
-- Read the arguments in the order they'll be output in, to make references |
-- Read the arguments in the order they'll be output in, to make references |
||
Line 577: | Line 850: | ||
-- iterator approach won't work here |
-- iterator approach won't work here |
||
for i = 1, 20 do |
for i = 1, 20 do |
||
_ = args[prefix .. |
_ = args[prefix .. andnum('group', i)] |
||
if inArray(cfg.keyword.subgroups, args[prefix .. |
if inArray(cfg.keyword.subgroups, args[prefix .. andnum('list', i)]) then |
||
for _, v in ipairs(cfg. |
for _, v in ipairs(cfg.arg.subgroups_and_num) do |
||
readArgs(args, prefix .. v |
readArgs(args, prefix .. string.format(v, i) .. "_") |
||
end |
end |
||
readArgs(args, prefix .. andnum('col', i) .. "_") |
|||
end |
end |
||
end |
end |
||
Line 590: | Line 864: | ||
getArgs = require('Module:Arguments').getArgs |
getArgs = require('Module:Arguments').getArgs |
||
end |
end |
||
local args = getArgs(frame, {wrappers = {cfg.pattern |
local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}}) |
||
readArgs(args, "") |
readArgs(args, "") |
||
args.type = args.type or cfg.keyword[boxtype] |
|||
return p._navbox(args) |
|||
return p['_navbox'](args) |
|||
end |
|||
p[cfg.keyword.with_collapsible_groups] = function (frame) |
|||
return p.navbox(frame, 'with_collapsible_groups') |
|||
end |
|||
p[cfg.keyword.with_columns] = function (frame) |
|||
return p.navbox(frame, 'with_columns') |
|||
end |
end |
||