无编辑摘要
无编辑摘要
 
第5行: 第5行:
local p = {}
local p = {}


local navbar = require('Module:Navbar')._navbar
local getArgs -- lazily initialized
local getArgs -- lazily initialized


第14行: 第13行:
local RESTART_MARKER = '\127_ODDEVEN0_\127'
local RESTART_MARKER = '\127_ODDEVEN0_\127'
local REGEX_MARKER = '\127_ODDEVEN(%d?)_\127'
local REGEX_MARKER = '\127_ODDEVEN(%d?)_\127'
local lists = {
plainlist_t = {
patterns = {
'^plainlist$',
'%splainlist$',
'^plainlist%s',
'%splainlist%s'
},
found = false,
styles = 'Plainlist/styles.css'
},
hlist_t = {
patterns = {
'^hlist$',
'%shlist$',
'^hlist%s',
'%shlist%s'
},
found = false,
styles = 'Hlist/styles.css'
}
}
local function has_list_class(args_to_check)
for _, list in pairs(lists) do
if not list.found then
for _, arg in pairs(args_to_check) do
for _, pattern in ipairs(list.patterns) do
if mw.ustring.find(arg or '', pattern) then
list.found = true
break
end
end
if list.found then break end
end
end
end
end


local function striped(wikitext)
local function striped(wikitext)
第20行: 第58行:
-- by parent navboxes. The result is that the category shows all pages
-- by parent navboxes. The result is that the category shows all pages
-- where a child navbox is not contained in a parent navbox.
-- where a child navbox is not contained in a parent navbox.
local orphanCat = '[[Category:Navbox orphans]]'
local orphanCat = '[[Category:孤立的子导航框]]'
if border == 'subgroup' and args.orphan ~= 'yes' then
if border == 'subgroup' and args.orphan ~= 'yes' then
-- No change; striping occurs in outermost navbox.
-- No change; striping occurs in outermost navbox.
第56行: 第94行:
end
end


local function processItem(item, nowrapitems)
local function addNewline(s)
if item:sub(1, 2) == '{|' then
if s:match('^[*:;#]') or s:match('^{|') then
-- Applying nowrap to lines in a table does not make sense.
return '\n' .. s ..'\n'
-- Add newlines to compensate for trim of x in |parm=x in a template.
else
return '\n' .. item ..'\n'
return s
end
end
if nowrapitems == 'yes' then
end
local lines = {}
 
for line in (item .. '\n'):gmatch('([^\n]*)\n') do
local function has_collapsible_toggle()
local prefix, content = line:match('^([*:;#]+)%s*(.*)')
return args.state ~= 'off'
if prefix and not content:match('^<span class="nowrap">') then
and args.state ~= 'plain'
line = prefix .. '<span class="nowrap">' .. content .. '</span>'
end
end
 
table.insert(lines, line)
local function has_navbar()
end
return args.navbar ~= 'off'
item = table.concat(lines, '\n')
and args.navbar ~= 'plain'
end
and (
if item:match('^[*:;#]') then
args.name
return '\n' .. item ..'\n'
or (
end
mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '')
return item
~= 'Template:Navbox' and
mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '')
~= 'Template:Navbox subgroup'
)
)
end
 
-- extract text color from css, which is the only permitted inline CSS for the navbar
local function extract_color(css_str)
-- return nil because navbar takes its argument into mw.html which handles
-- nil gracefully, removing the associated style attribute
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 args.navbar ~= 'off' and args.navbar ~= 'plain' and not (not args.name and mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '') == 'Template:Navbox') then
if has_navbar() then
local navbar = require('Module:Navbar')._navbar
titleCell:wikitext(navbar{
titleCell:wikitext(navbar{
args.name,
args.name,
mini = 1,
mini = 1,
fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;box-shadow:none;padding:0;'
fontstyle = extract_color(
(args.basestyle or '') .. ';' .. (args.titlestyle or '')
)
})
})
end
end
第96行: 第148行:
local function renderTitleRow(tbl)
local function renderTitleRow(tbl)
if not args.title then return end
if not args.title then return end
has_list_class({args.titleclass})


local titleRow = tbl:tag('tr')
local titleRow = tbl:tag('tr')
if args.titlegroup then
titleRow
:tag('th')
:attr('scope', 'row')
:addClass('navbox-group')
:addClass(args.titlegroupclass)
:cssText(args.basestyle)
:cssText(args.groupstyle)
:cssText(args.titlegroupstyle)
:wikitext(args.titlegroup)
end


local titleCell = titleRow:tag('th'):attr('scope', 'col')
local titleCell = titleRow:tag('th'):attr('scope', 'col')


if args.titlegroup then
if has_collapsible_toggle() then
titleCell
titleCell
:css('border-left', '2px solid #fdfdfd')
:addClass('collapsible-title')
:css('width', '100%')
end
end


第122行: 第163行:
if args.imageleft then titleColspan = titleColspan + 1 end
if args.imageleft then titleColspan = titleColspan + 1 end
if args.image then titleColspan = titleColspan + 1 end
if args.image then titleColspan = titleColspan + 1 end
if args.titlegroup then titleColspan = titleColspan - 1 end


titleCell
titleCell
第137行: 第177行:
:attr('id', mw.uri.anchorEncode(args.title))
:attr('id', mw.uri.anchorEncode(args.title))
:addClass(args.titleclass)
:addClass(args.titleclass)
:css('font-size', '114%')
:css('font-size', '110%')
:css('margin', '0 4em')
:css('margin', '0 5em')
:wikitext(processItem(args.title))
:wikitext(addNewline(args.title))
end
end


第155行: 第195行:
local function renderAboveRow(tbl)
local function renderAboveRow(tbl)
if not args.above then return end
if not args.above then return end
has_list_class({ args.aboveclass })


tbl:tag('tr')
tbl:tag('tr')
第165行: 第207行:
:tag('div')
:tag('div')
-- id for aria-labelledby attribute, if no title
-- id for aria-labelledby attribute, if no title
:attr('id', args.title and nil or mw.uri.anchorEncode(args.above))
:attr('id', (not args.title) and mw.uri.anchorEncode(args.above) or nil)
:wikitext(processItem(args.above, args.nowrapitems))
:wikitext(addNewline(args.above))
end
end


local function renderBelowRow(tbl)
local function renderBelowRow(tbl)
if not args.below then return end
if not args.below then return end
has_list_class({ args.belowclass })


tbl:tag('tr')
tbl:tag('tr')
第180行: 第224行:
:attr('colspan', getAboveBelowColspan())
:attr('colspan', getAboveBelowColspan())
:tag('div')
:tag('div')
:wikitext(processItem(args.below, args.nowrapitems))
:wikitext(addNewline(args.below))
end
end


第186行: 第230行:
--  List rows
--  List rows
--
--
local function renderListRow(tbl, index, listnum)
local function renderListRow(tbl, listnum)
local row = tbl:tag('tr')
local row = tbl:tag('tr')


if index == 1 and args.imageleft then
if listnum == 1 and args.imageleft then
has_list_class({ args.imageclass })
 
row
row
:tag('td')
:tag('td')
第200行: 第246行:
:attr('rowspan', #listnums)
:attr('rowspan', #listnums)
:tag('div')
:tag('div')
:wikitext(processItem(args.imageleft))
:wikitext(addNewline(args.imageleft))
end
end


if args['group' .. listnum] then
if args['group' .. listnum] then
has_list_class({ args.groupclass })
local groupCell = row:tag('th')
local groupCell = row:tag('th')


第224行: 第272行:
:wikitext(args['group' .. listnum])
:wikitext(args['group' .. listnum])
end
end
has_list_class({ args.listclass, args['list' .. listnum .. 'class'] })


local listCell = row:tag('td')
local listCell = row:tag('td')
第229行: 第279行:
if args['group' .. listnum] then
if args['group' .. listnum] then
listCell
listCell
:css('text-align', 'left')
:addClass('navbox-list-with-group')
:css('border-left-width', '2px')
:css('border-left-style', 'solid')
else
else
listCell:attr('colspan', 2)
listCell:attr('colspan', 2)
第241行: 第289行:


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 listnum % 2 == 1 then
rowstyle = args.oddstyle
rowstyle = args.oddstyle
else
else
第251行: 第299行:
if listText:sub(1, 12) == '</div><table' then
if listText:sub(1, 12) == '</div><table' then
-- Assume list text is for a subgroup navbox so no automatic striping for this row.
-- Assume list text is for a subgroup navbox so no automatic striping for this row.
oddEven = listText:find('<th[^>]*"navbox%-title"') and RESTART_MARKER or 'odd'
oddEven = listText:find('<th[^>]*["? ?]navbox%-title"') and RESTART_MARKER or 'odd'
end
end
listCell
listCell
第263行: 第311行:
:addClass(args['list' .. listnum .. 'class'])
:addClass(args['list' .. listnum .. 'class'])
:tag('div')
:tag('div')
:css('padding', (index == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
:css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
:wikitext(processItem(listText, args.nowrapitems))
:wikitext(addNewline(listText))
 
if listnum == 1 and args.image then
has_list_class({ args.imageclass })


if index == 1 and args.image then
row
row
:tag('td')
:tag('td')
第277行: 第327行:
:attr('rowspan', #listnums)
:attr('rowspan', #listnums)
:tag('div')
:tag('div')
:wikitext(processItem(args.image))
:wikitext(addNewline(args.image))
end
end
end
end


--
--
第290行: 第339行:
return false
return false
end
end
local listClasses = {
 
['plainlist'] = true, ['hlist'] = true, ['hlist hnum'] = true,
return not lists.hlist_t.found and not lists.plainlist_t.found
['hlist hwrap'] = true, ['hlist vcard'] = true, ['vcard hlist'] = true,
['hlist vevent'] = true,
}
return not (listClasses[args.listclass] or listClasses[args.bodyclass])
end
end


第306行: 第351行:
end
end


local function hasBorders()
local function argNameAndRealTitleAreDifferent()
for _, key in ipairs({'groupstyle', 'basestyle', 'abovestyle', 'belowstyle'}) do
if border == 'subgroup' or args.tracking == 'no' then
if tostring(args[key]):find('border', 1, true) then
return false
return true
end
end
end
end


local function isIllegible()
if has_navbar() and args.name ~= mw.title.getCurrentTitle().text then
local styleratio = require('Module:Color contrast')._styleratio
return true
end


for key, style in pairs(args) do
if tostring(key):match("style$") then
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
return true
end
end
end
return false
return false
end
end
第329行: 第365行:
local function getTrackingCategories()
local function getTrackingCategories()
local cats = {}
local cats = {}
if needsHorizontalLists() then table.insert(cats, 'Navigational boxes without horizontal lists') end
if needsHorizontalLists() then table.insert(cats, '没有使用水平列表的导航框') end
if hasBackgroundColors() then table.insert(cats, 'Navboxes using background colours') end
if hasBackgroundColors() then table.insert(cats, '使用背景颜色的导航框') end
if isIllegible() then table.insert(cats, 'Potentially illegible navboxes') end
if argNameAndRealTitleAreDifferent() then table.insert(cats, 'name參數和實際不同的導航框') end
if hasBorders() then table.insert(cats, 'Navboxes using borders') end
return cats
return cats
end
end
第345行: 第380行:
builder:wikitext('[[Category:' .. cat .. ']]')
builder:wikitext('[[Category:' .. cat .. ']]')
end
end
end
--
-- Load the templatestyles for the navbox
--
local function loadTemplateStyles(hiding_templatestyles)
local frame = mw.getCurrentFrame()
local hlist_templatestyles = ''
if lists.hlist_t.found then
hlist_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = lists.hlist_t.styles }
}
end
-- a second workaround for [[phab:T303378]]
-- when that issue is fixed, we can actually use has_navbar not to emit the
-- tag here if we want
if has_navbar() and hlist_templatestyles == '' then
hlist_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = lists.hlist_t.styles }
}
end
local plainlist_templatestyles = ''
if lists.plainlist_t.found then
plainlist_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = lists.plainlist_t.styles }
}
end
local base_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' }
}
local templatestyles = ''
if args['templatestyles'] then
templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['templatestyles'] }
}
end
local child_templatestyles = ''
if args['child templatestyles'] then
child_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['child templatestyles'] }
}
end
return mw.html.create('div')
:addClass('navbox-styles')
:wikitext(
-- hlist -> plainlist -> base is best-effort to preserve old Common.css ordering.
-- this ordering is not a guarantee because the rows of interest invoking
-- each class may not be on a specific page
hlist_templatestyles ..
plainlist_templatestyles ..
base_templatestyles ..
templatestyles ..
child_templatestyles ..
table.concat(hiding_templatestyles)
)
:done()
end
-- work around [[phab:T303378]]
-- for each arg: find all the templatestyles strip markers, insert them into a
-- table. then remove all templatestyles markers from the arg
local function move_hiding_templatestyles(args)
local gfind = string.gfind
local gsub = string.gsub
local templatestyles_markers = {}
local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
for k, arg in pairs(args) do
for marker in gfind(arg, strip_marker_pattern) do
table.insert(templatestyles_markers, marker)
end
args[k] = gsub(arg, strip_marker_pattern, '')
end
return templatestyles_markers
end
end


第355行: 第470行:
:addClass(args.bodyclass)
:addClass(args.bodyclass)


if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
has_list_class({ args.bodyclass })
 
if args.title and has_collapsible_toggle() then
if args.state == 'collapsed' then args.state = 'mw-collapsed' end
if args.state == 'collapsed' then args.state = 'mw-collapsed' end
tbl
tbl
第379行: 第496行:
renderAboveRow(tbl)
renderAboveRow(tbl)
for i, listnum in ipairs(listnums) do
for i, listnum in ipairs(listnums) do
renderListRow(tbl, i, listnum)
renderListRow(tbl, listnum)
end
end
renderBelowRow(tbl)
renderBelowRow(tbl)
第388行: 第505行:
function p._navbox(navboxArgs)
function p._navbox(navboxArgs)
args = navboxArgs
args = navboxArgs
local hiding_templatestyles = move_hiding_templatestyles(args)
listnums = {}
listnums = {}


for k, _ in pairs(args) do
for k, v in pairs(args) do
if type(k) == 'string' then
local listnum = ('' .. k):match('^list(%d+)$')
local listnum = k:match('^list(%d+)$')
if listnum then table.insert(listnums, tonumber(listnum)) end
if listnum then table.insert(listnums, tonumber(listnum)) end
end
end
end
table.sort(listnums)
table.sort(listnums)
第409行: 第525行:
local res = mw.html.create()
local res = mw.html.create()
if border == 'none' then
if border == 'none' then
res:node(loadTemplateStyles(hiding_templatestyles))
local nav = res:tag('div')
local nav = res:tag('div')
:attr('role', 'navigation')
:attr('role', 'navigation')
第423行: 第540行:
-- padding being applied, and at the end add a <div> to balance out the parent's </div>
-- padding being applied, and at the end add a <div> to balance out the parent's </div>
res
res
:wikitext('</div>')
:wikitext('</div>') -- mw.html 未支持 unclosed
:node(tbl)
:node(tbl)
:wikitext('<div>')
:wikitext('<div>') -- mw.html 未支持 unclosed
else
else
res:node(loadTemplateStyles(hiding_templatestyles))
has_list_class({ args.navboxclass })
local nav = res:tag('div')
local nav = res:tag('div')
:attr('role', 'navigation')
:attr('role', 'navigation')
第453行: 第574行:
getArgs = require('Module:Arguments').getArgs
getArgs = require('Module:Arguments').getArgs
end
end
args = getArgs(frame, {wrappers = {'Template:Navbox'}})
args = getArgs(frame, {wrappers = {'Template:Navbox', 'Template:Navbox subgroup'}})
if frame.args.border then
-- This allows Template:Navbox_subgroup to use {{#invoke:Navbox|navbox|border=...}}.
args.border = frame.args.border
end


-- Read the arguments in the order they'll be output in, to make references number in the right order.
-- Read the arguments in the order they'll be output in, to make references number in the right order.
第459行: 第584行:
_ = args.title
_ = args.title
_ = args.above
_ = args.above
for i = 1, 20 do
for i = 1, 35 do
_ = args["group" .. tostring(i)]
_ = args["group" .. tostring(i)]
_ = args["list" .. tostring(i)]
_ = args["list" .. tostring(i)]