11.314
suntingan
dw>Uzume (strict) |
(←Membuat halaman berisi '-- -- This module implements {{Navbox}} -- local p = {} local navbar = require('Module:Navbar')._navbar local getArgs -- lazily initialized local args local border local listnums local ODD_EVEN_MARKER = '\127_ODDEVEN_\127' local RESTART_MARKER = '\127_ODDEVEN0_\127' local REGEX_MARKER = '\127_ODDEVEN(%d?)_\127' local function striped(wikitext) -- Return wikitext with markers replaced for odd/even striping. -- Child (subgroup) navboxes are flagged with a cat...') |
||
Baris 1: | Baris 1: | ||
-- | |||
-- This module implements {{Navbox}} | |||
-- | |||
local p = {} | local p = {} | ||
local navbar = require('Module:Navbar')._navbar | local navbar = require('Module:Navbar')._navbar | ||
local getArgs -- lazily initialized | local getArgs -- lazily initialized | ||
local args | local args | ||
local | local border | ||
local listnums | |||
local ODD_EVEN_MARKER = '\127_ODDEVEN_\127' | |||
local RESTART_MARKER = '\127_ODDEVEN0_\127' | |||
local REGEX_MARKER = '\127_ODDEVEN(%d?)_\127' | |||
local function striped(wikitext | local function striped(wikitext) | ||
-- Return wikitext with markers replaced for odd/even striping. | -- Return wikitext with markers replaced for odd/even striping. | ||
-- Child (subgroup) navboxes are flagged with a category that is removed | -- Child (subgroup) navboxes are flagged with a category that is removed | ||
-- 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 = | local orphanCat = '[[Kategori:Navbox yatim]]' | ||
if border == | if border == 'subgroup' and args.orphan ~= 'yes' then | ||
-- No change; striping occurs in outermost navbox. | -- No change; striping occurs in outermost navbox. | ||
return wikitext .. orphanCat | return wikitext .. orphanCat | ||
end | end | ||
local first, second = | local first, second = 'odd', 'even' | ||
if args | if args.evenodd then | ||
if args | if args.evenodd == 'swap' then | ||
first, second = second, first | first, second = second, first | ||
else | else | ||
first = args | first = args.evenodd | ||
second = first | second = first | ||
end | end | ||
Baris 45: | Baris 53: | ||
end | end | ||
local regex = orphanCat:gsub('([%[%]])', '%%%1') | local regex = orphanCat:gsub('([%[%]])', '%%%1') | ||
return (wikitext:gsub(regex, ''):gsub( | return (wikitext:gsub(regex, ''):gsub(REGEX_MARKER, changer)) -- () omits gsub count | ||
end | end | ||
Baris 54: | Baris 62: | ||
return '\n' .. item ..'\n' | return '\n' .. item ..'\n' | ||
end | end | ||
if nowrapitems == | if nowrapitems == 'yes' then | ||
local lines = {} | local lines = {} | ||
for line in (item .. '\n'):gmatch('([^\n]*)\n') do | for line in (item .. '\n'):gmatch('([^\n]*)\n') do | ||
local prefix, content = line:match('^([*:;#]+)%s*(.*)') | local prefix, content = line:match('^([*:;#]+)%s*(.*)') | ||
if prefix and not content:match( | if prefix and not content:match('^<span class="nowrap">') then | ||
line = | line = prefix .. '<span class="nowrap">' .. content .. '</span>' | ||
end | end | ||
table.insert(lines, line) | table.insert(lines, line) | ||
Baris 71: | Baris 79: | ||
end | end | ||
local function | 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 | |||
titleCell:wikitext(navbar{ | titleCell:wikitext(navbar{ | ||
args.name, | |||
mini = 1, | |||
fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;box-shadow:none;padding:0;' | |||
}) | }) | ||
end | end | ||
Baris 94: | Baris 91: | ||
end | end | ||
-- | |||
-- Title row | |||
-- | |||
local function renderTitleRow(tbl) | local function renderTitleRow(tbl) | ||
if not args | if not args.title then return end | ||
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 | |||
titleCell | |||
:css('border-left', '2px solid #fdfdfd') | |||
:css('width', '100%') | |||
end | |||
local titleColspan = 2 | local titleColspan = 2 | ||
if args | if args.imageleft then titleColspan = titleColspan + 1 end | ||
if args | if args.image then titleColspan = titleColspan + 1 end | ||
if args.titlegroup then titleColspan = titleColspan - 1 end | |||
titleCell | titleCell | ||
:cssText(args | :cssText(args.basestyle) | ||
:cssText(args | :cssText(args.titlestyle) | ||
:addClass( | :addClass('navbox-title') | ||
:attr('colspan', titleColspan) | :attr('colspan', titleColspan) | ||
Baris 116: | Baris 135: | ||
:tag('div') | :tag('div') | ||
-- id for aria-labelledby attribute | -- id for aria-labelledby attribute | ||
:attr('id', mw.uri.anchorEncode(args | :attr('id', mw.uri.anchorEncode(args.title)) | ||
:addClass(args | :addClass(args.titleclass) | ||
:css('font-size', '114%') | :css('font-size', '114%') | ||
:css('margin', '0 4em') | :css('margin', '0 4em') | ||
:wikitext(processItem(args | :wikitext(processItem(args.title)) | ||
end | end | ||
-- | |||
-- Above/Below rows | |||
-- | |||
local function getAboveBelowColspan() | local function getAboveBelowColspan() | ||
local ret = 2 | local ret = 2 | ||
if args | if args.imageleft then ret = ret + 1 end | ||
if args | if args.image then ret = ret + 1 end | ||
return ret | return ret | ||
end | end | ||
local function renderAboveRow(tbl) | local function renderAboveRow(tbl) | ||
if not args | if not args.above then return end | ||
tbl:tag('tr') | tbl:tag('tr') | ||
:tag('td') | :tag('td') | ||
:addClass( | :addClass('navbox-abovebelow') | ||
:addClass(args | :addClass(args.aboveclass) | ||
:cssText(args | :cssText(args.basestyle) | ||
:cssText(args | :cssText(args.abovestyle) | ||
:attr('colspan', getAboveBelowColspan()) | :attr('colspan', getAboveBelowColspan()) | ||
:tag('div') | :tag('div') | ||
-- id for aria-labelledby attribute, if no title | -- id for aria-labelledby attribute, if no title | ||
:attr('id', | :attr('id', args.title and nil or mw.uri.anchorEncode(args.above)) | ||
:wikitext(processItem(args | :wikitext(processItem(args.above, args.nowrapitems)) | ||
end | end | ||
local function renderBelowRow(tbl) | local function renderBelowRow(tbl) | ||
if not args | if not args.below then return end | ||
tbl:tag('tr') | tbl:tag('tr') | ||
:tag('td') | :tag('td') | ||
:addClass( | :addClass('navbox-abovebelow') | ||
:addClass(args | :addClass(args.belowclass) | ||
:cssText(args | :cssText(args.basestyle) | ||
:cssText(args | :cssText(args.belowstyle) | ||
:attr('colspan', getAboveBelowColspan()) | :attr('colspan', getAboveBelowColspan()) | ||
:tag('div') | :tag('div') | ||
:wikitext(processItem(args | :wikitext(processItem(args.below, args.nowrapitems)) | ||
end | end | ||
local function renderListRow(tbl, index, listnum | -- | ||
-- List rows | |||
-- | |||
local function renderListRow(tbl, index, listnum) | |||
local row = tbl:tag('tr') | local row = tbl:tag('tr') | ||
if index == 1 and args | if index == 1 and args.imageleft then | ||
row | row | ||
:tag('td') | :tag('td') | ||
:addClass( | :addClass('noviewer') | ||
:addClass( | :addClass('navbox-image') | ||
:addClass(args | :addClass(args.imageclass) | ||
:css('width', '1px') -- Minimize width | :css('width', '1px') -- Minimize width | ||
:css('padding', ' | :css('padding', '0px 2px 0px 0px') | ||
:cssText(args | :cssText(args.imageleftstyle) | ||
:attr('rowspan', | :attr('rowspan', #listnums) | ||
:tag('div') | :tag('div') | ||
:wikitext(processItem(args | :wikitext(processItem(args.imageleft)) | ||
end | end | ||
if args['group' .. listnum] 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 | if listnum == 1 and not (args.title or args.above or args.group2) then | ||
groupCell | groupCell | ||
:attr('id', mw.uri.anchorEncode(args | :attr('id', mw.uri.anchorEncode(args.group1)) | ||
end | end | ||
groupCell | groupCell | ||
:attr('scope', 'row') | :attr('scope', 'row') | ||
:addClass( | :addClass('navbox-group') | ||
:addClass(args | :addClass(args.groupclass) | ||
:cssText(args | :cssText(args.basestyle) | ||
:css('width', args.groupwidth or '1%') -- If groupwidth not specified, minimize width | |||
:css('width', args | |||
groupCell | groupCell | ||
:cssText(args | :cssText(args.groupstyle) | ||
:cssText(args[ | :cssText(args['group' .. listnum .. 'style']) | ||
:wikitext(args[ | :wikitext(args['group' .. listnum]) | ||
end | end | ||
local listCell = row:tag('td') | local listCell = row:tag('td') | ||
if args[ | if args['group' .. listnum] then | ||
listCell | listCell | ||
: | :css('text-align', 'left') | ||
:css('border-left-width', '2px') | |||
:css('border-left-style', 'solid') | |||
else | else | ||
listCell:attr('colspan', 2) | listCell:attr('colspan', 2) | ||
end | end | ||
if not args | if not args.groupwidth then | ||
listCell:css('width', '100%') | listCell:css('width', '100%') | ||
end | end | ||
Baris 217: | Baris 242: | ||
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 | ||
rowstyle = args | rowstyle = args.oddstyle | ||
else | else | ||
rowstyle = args | rowstyle = args.evenstyle | ||
end | end | ||
local | local listText = args['list' .. listnum] | ||
local oddEven = ODD_EVEN_MARKER | |||
local oddEven = | |||
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( | oddEven = listText:find('<th[^>]*"navbox%-title"') and RESTART_MARKER or 'odd' | ||
end | end | ||
listCell | listCell | ||
:css('padding', ' | :css('padding', '0px') | ||
:cssText(args | :cssText(args.liststyle) | ||
:cssText(rowstyle) | :cssText(rowstyle) | ||
:cssText(args[ | :cssText(args['list' .. listnum .. 'style']) | ||
:addClass( | :addClass('navbox-list') | ||
:addClass( | :addClass('navbox-' .. oddEven) | ||
:addClass(args | :addClass(args.listclass) | ||
:addClass(args[ | :addClass(args['list' .. listnum .. 'class']) | ||
:tag('div') | :tag('div') | ||
:css('padding', | :css('padding', (index == 1 and args.list1padding) or args.listpadding or '0em 0.25em') | ||
:wikitext(processItem(listText, args.nowrapitems)) | |||
:wikitext(processItem(listText, args | |||
if index == 1 and args | if index == 1 and args.image then | ||
row | row | ||
:tag('td') | :tag('td') | ||
:addClass( | :addClass('noviewer') | ||
:addClass( | :addClass('navbox-image') | ||
:addClass(args | :addClass(args.imageclass) | ||
:css('width', '1px') -- Minimize width | :css('width', '1px') -- Minimize width | ||
:css('padding', ' | :css('padding', '0px 0px 0px 2px') | ||
:cssText(args | :cssText(args.imagestyle) | ||
:attr('rowspan', | :attr('rowspan', #listnums) | ||
:tag('div') | :tag('div') | ||
:wikitext(processItem(args | :wikitext(processItem(args.image)) | ||
end | end | ||
end | end | ||
-- | -- | ||
-- Tracking categories | |||
-- | |||
local function needsHorizontalLists( | local function needsHorizontalLists() | ||
if border == | if border == 'subgroup' or args.tracking == 'no' then | ||
return false | return false | ||
end | end | ||
return not | local listClasses = { | ||
['plainlist'] = true, ['hlist'] = true, ['hlist hnum'] = true, | |||
['hlist hwrap'] = true, ['hlist vcard'] = true, ['vcard hlist'] = true, | |||
['hlist vevent'] = true, | |||
} | |||
return not (listClasses[args.listclass] or listClasses[args.bodyclass]) | |||
end | end | ||
local function hasBackgroundColors() | local function hasBackgroundColors() | ||
for _, key in ipairs({ | for _, key in ipairs({'titlestyle', 'groupstyle', 'basestyle', 'abovestyle', 'belowstyle'}) do | ||
if tostring(args[key]):find('background', 1, true) then | if tostring(args[key]):find('background', 1, true) then | ||
return true | return true | ||
end | end | ||
end | end | ||
end | end | ||
local function hasBorders() | local function hasBorders() | ||
for _, key in ipairs({ | for _, key in ipairs({'groupstyle', 'basestyle', 'abovestyle', 'belowstyle'}) do | ||
if tostring(args[key]):find('border', 1, true) then | if tostring(args[key]):find('border', 1, true) then | ||
return true | return true | ||
end | end | ||
end | end | ||
end | end | ||
local function isIllegible() | local function isIllegible() | ||
local styleratio = require('Module:Color contrast')._styleratio | local styleratio = require('Module:Color contrast')._styleratio | ||
for key, style in pairs(args) do | for key, style in pairs(args) do | ||
if tostring(key):match( | if tostring(key):match("style$") then | ||
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then | if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then | ||
return true | return true | ||
Baris 352: | Baris 327: | ||
end | end | ||
local function getTrackingCategories( | local function getTrackingCategories() | ||
local cats = {} | local cats = {} | ||
if needsHorizontalLists( | if needsHorizontalLists() then table.insert(cats, 'Navbox tanpa daftar horizontal') end | ||
if hasBackgroundColors() then table.insert(cats, | if hasBackgroundColors() then table.insert(cats, 'Navbox menggunakan warna latar belakang') end | ||
if isIllegible() then table.insert(cats, | if isIllegible() then table.insert(cats, 'Navbox berpotensi tidak terbaca') end | ||
if hasBorders() then table.insert(cats, | if hasBorders() then table.insert(cats, 'Navbox menggunakan border') end | ||
return cats | return cats | ||
end | end | ||
local function renderTrackingCategories(builder | local function renderTrackingCategories(builder) | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
if title.namespace ~= 10 then return end -- not in template space | if title.namespace ~= 10 then return end -- not in template space | ||
local subpage = title.subpageText | local subpage = title.subpageText | ||
if subpage == | if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end | ||
for _, cat in ipairs(getTrackingCategories( | for _, cat in ipairs(getTrackingCategories()) do | ||
builder:wikitext('[[Category:' .. cat .. ']]') | builder:wikitext('[[Category:' .. cat .. ']]') | ||
end | end | ||
end | end | ||
local function renderMainTable( | -- | ||
-- Main navbox tables | |||
-- | |||
local function renderMainTable() | |||
local tbl = mw.html.create('table') | local tbl = mw.html.create('table') | ||
:addClass( | :addClass('nowraplinks') | ||
:addClass(args | :addClass(args.bodyclass) | ||
if args.title and (args.state ~= 'plain' and args.state ~= 'off') then | |||
if args | if args.state == 'collapsed' then args.state = 'mw-collapsed' end | ||
if state == | |||
tbl | tbl | ||
:addClass( | :addClass('mw-collapsible') | ||
:addClass(state or | :addClass(args.state or 'autocollapse') | ||
end | end | ||
tbl:css('border-spacing', 0) | tbl:css('border-spacing', 0) | ||
if border == | if border == 'subgroup' or border == 'none' then | ||
tbl | tbl | ||
:addClass( | :addClass('navbox-subgroup') | ||
:cssText(args | :cssText(args.bodystyle) | ||
:cssText(args | :cssText(args.style) | ||
else -- regular navbox - bodystyle and style will be applied to the wrapper table | else -- regular navbox - bodystyle and style will be applied to the wrapper table | ||
tbl | tbl | ||
:addClass( | :addClass('navbox-inner') | ||
:css('background', 'transparent') | :css('background', 'transparent') | ||
:css('color', 'inherit') | :css('color', 'inherit') | ||
end | end | ||
tbl:cssText(args | tbl:cssText(args.innerstyle) | ||
renderTitleRow(tbl) | renderTitleRow(tbl) | ||
renderAboveRow(tbl) | renderAboveRow(tbl) | ||
for i, listnum in ipairs(listnums) do | for i, listnum in ipairs(listnums) do | ||
renderListRow(tbl, i, listnum | renderListRow(tbl, i, listnum) | ||
end | end | ||
renderBelowRow(tbl) | renderBelowRow(tbl) | ||
return tbl | return tbl | ||
end | end | ||
function p._navbox(navboxArgs) | function p._navbox(navboxArgs) | ||
args = navboxArgs | args = navboxArgs | ||
listnums = {} | |||
for k, _ in pairs(args) do | for k, _ in pairs(args) do | ||
if type(k) == 'string' then | if type(k) == 'string' then | ||
local listnum = k:match( | 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 | ||
Baris 476: | Baris 398: | ||
table.sort(listnums) | table.sort(listnums) | ||
border = mw.text.trim(args.border or args[1] or '') | |||
if border == | if border == 'child' then | ||
border = | border = 'subgroup' | ||
end | end | ||
-- render the main body of the navbox | -- render the main body of the navbox | ||
local tbl = renderMainTable( | local tbl = renderMainTable() | ||
-- render the appropriate wrapper around the navbox, depending on the border param | |||
local res = mw.html.create() | local res = mw.html.create() | ||
if border == 'none' then | |||
if border == | |||
local nav = res:tag('div') | local nav = res:tag('div') | ||
:attr('role', 'navigation') | :attr('role', 'navigation') | ||
:node(tbl) | :node(tbl) | ||
-- aria-labelledby title, otherwise above, otherwise lone group | -- aria-labelledby title, otherwise above, otherwise lone group | ||
if args | if args.title or args.above or (args.group1 and not args.group2) then | ||
nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title or args.above or args.group1)) | |||
nav:attr( | |||
else | else | ||
nav:attr('aria-label', | nav:attr('aria-label', 'Navbox') | ||
end | end | ||
elseif border == | elseif border == 'subgroup' then | ||
-- We assume that this navbox is being rendered in a list cell of a | -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is | ||
-- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the | |||
-- padding being applied, and at the end add a <div> to balance out the parent's </div> | |||
res | res | ||
:wikitext('</div>') | :wikitext('</div>') | ||
Baris 514: | Baris 427: | ||
:wikitext('<div>') | :wikitext('<div>') | ||
else | else | ||
local nav = res:tag('div') | local nav = res:tag('div') | ||
:attr('role', 'navigation') | :attr('role', 'navigation') | ||
:addClass( | :addClass('navbox') | ||
:addClass(args | :addClass(args.navboxclass) | ||
:cssText(args | :cssText(args.bodystyle) | ||
:cssText(args | :cssText(args.style) | ||
:css('padding', '3px') | :css('padding', '3px') | ||
:node(tbl) | :node(tbl) | ||
-- aria-labelledby title, otherwise above, otherwise lone group | -- aria-labelledby title, otherwise above, otherwise lone group | ||
if args | if args.title or args.above or (args.group1 and not args.group2) then | ||
nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title or args.above or args.group1)) | |||
nav:attr( | |||
else | else | ||
nav:attr('aria-label', | nav:attr('aria-label', 'Navbox') | ||
end | end | ||
end | end | ||
if (args | if (args.nocat or 'false'):lower() == 'false' then | ||
renderTrackingCategories(res | renderTrackingCategories(res) | ||
end | end | ||
return striped(tostring(res) | return striped(tostring(res)) | ||
end | end | ||
Baris 545: | Baris 453: | ||
getArgs = require('Module:Arguments').getArgs | getArgs = require('Module:Arguments').getArgs | ||
end | end | ||
args = getArgs(frame, {wrappers = { | args = getArgs(frame, {wrappers = {'Template:Navbox'}}) | ||
-- 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 number in the right order. | ||
local _ | local _ | ||
_ = args | _ = args.title | ||
_ = args | _ = args.above | ||
for i = 1, 20 do | for i = 1, 20 do | ||
_ = args[ | _ = args["group" .. tostring(i)] | ||
_ = args[ | _ = args["list" .. tostring(i)] | ||
end | end | ||
_ = args | _ = args.below | ||
return p._navbox(args) | return p._navbox(args) |