در حال ویرایش پودمان:Navbox

هشدار: شما وارد نشده‌اید. نشانی آی‌پی شما برای عموم قابل مشاهده خواهد بود اگر هر تغییری ایجاد کنید. اگر وارد شوید یا یک حساب کاربری بسازید، ویرایش‌هایتان به نام کاربری‌تان نسبت داده خواهد شد، همراه با مزایای دیگر.

این ویرایش را می‌توان خنثی کرد. لطفاً تفاوت زیر را بررسی کنید تا تأیید کنید که این چیزی است که می‌خواهید انجام دهید، سپس تغییرات زیر را ذخیره کنید تا خنثی‌سازی ویرایش را به پایان ببرید.

نسخهٔ فعلی متن شما
خط ۱: خط ۱:
require('strict')
--
-- This module will implement {{Navbox}}
--
 
local p = {}
local p = {}
local cfg = mw.loadData('Module:Navbox/configuration')
local inArray = require("Module:TableTools").inArray
local numConv = require('Module:Numeral converter').convert
local getArgs -- lazily initialized
local hiding_templatestyles = {}


-- global passthrough variables
local HtmlBuilder = require('Module:HtmlBuilder')
local passthrough = {
local Navbar = require('Module:Navbar')
[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,
argHash=true
}


-- helper functions
local args
local andnum = function(s, n) return string.format(cfg.arg[s .. '_and_num'], n) end
local frame
local isblank = function(v) return (v or '') == '' end
local tableRowAdded = false
local border
local listnums = {}


local function concatstrings(s)
function trim(s)
local r = table.concat(s, '')
    return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
if r:match('^%s*$') then return nil end
return r
end
end


local function concatstyles(s)
function addTableRow(tbl)
local r = ''
    -- If any other rows have already been added, then we add a 2px gutter row.
for _, v in ipairs(s) do
    if tableRowAdded then
v = mw.text.trim(v, "%s;")
        tbl
if not isblank(v) then r = r .. v .. ';' end
            .tag('tr')
end
                .css('height', '2px')
if isblank(r) then return nil end
                .tag('td')
return r
    end
end
 
    tableRowAdded = true


local function getSubgroup(args, listnum, listText, prefix)
    return tbl.tag('tr')
local subArgs = {
[cfg.arg.border] = cfg.keyword.border_subgroup,
[cfg.arg.navbar] = cfg.keyword.navbar_plain,
argHash = 0
}
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
subArgs.argHash = subArgs.argHash + (v and #v or 0)
end
end
end
return hasSubArgs and p._navbox(subArgs) or listText
end
end


-- Main functions
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)
--
-- Return wikitext with markers replaced for odd/even striping.
--   Title row
-- Child (subgroup) navboxes are flagged with a category that is removed
--
-- by parent navboxes. The result is that the category shows all pages
function renderTitleRow(tbl)
-- where a child navbox is not contained in a parent navbox.
    if not args.title then return end
local orphanCat = cfg.category.orphan
if border == cfg.keyword.border_subgroup and args[cfg.arg.orphan] ~= cfg.keyword.orphan_yes then
-- No change; striping occurs in outermost navbox.
return wikitext .. orphanCat
end
local first, second = cfg.class.navbox_odd_part, cfg.class.navbox_even_part
if args[cfg.arg.evenodd] then
if args[cfg.arg.evenodd] == cfg.keyword.evenodd_swap then
first, second = second, first
else
first = args[cfg.arg.evenodd]
second = first
end
end
local changer
if first == second then
changer = first
else
local index = 0
changer = function (code)
if code == '0' then
-- Current occurrence is for a group before a nested table.
-- Set it to first as a valid although pointless class.
-- The next occurrence will be the first row after a title
-- in a subgroup and will also be first.
index = 0
return first
end
index = index + 1
return index % 2 == 1 and first or second
end
end
local regex = orphanCat:gsub('([%[%]])', '%%%1')
return (wikitext:gsub(regex, ''):gsub(cfg.marker.regex, changer)) -- () omits gsub count
end


local function processItem(item, nowrapitems)
    local titleRow = addTableRow(tbl)
if item:sub(1, 2) == '{|' then
-- Applying nowrap to lines in a table does not make sense.
-- Add newlines to compensate for trim of x in |parm=x in a template.
return '\n' .. item .. '\n'
end
if nowrapitems == cfg.keyword.nowrapitems_yes then
local lines = {}
for line in (item .. '\n'):gmatch('([^\n]*)\n') do
local prefix, content = line:match('^([*:;#]+)%s*(.*)')
if prefix and not content:match(cfg.pattern.nowrap) then
line = string.format(cfg.nowrap_item, prefix, content)
end
table.insert(lines, line)
end
item = table.concat(lines, '\n')
end
if item:match('^[*:;#]') then
return '\n' .. item .. '\n'
end
return item
end


local function has_navbar()
    if args.titlegroup then
return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off
        titleRow
and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain
            .tag('th')
and (
                .attr('scope', 'row')
args[cfg.arg.name]
                .addClass('navbox-group')
or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '')
                .addClass(args.titlegroupclass)
~= cfg.pattern.navbox
                .cssText(args.basestyle)
)
                .cssText(args.groupstyle)
end
                .cssText(args.titlegroupstyle)
                .wikitext(args.titlegroup)
    end


-- extract text color from css, which is the only permitted inline CSS for the navbar
    local titleCell = titleRow.tag('th').attr('scope', 'col')
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


local function renderNavBar(titleCell)
    if args.titlegroup then
if has_navbar() then
        titleCell
local navbar = require('Module:Navbar')._navbar
            .css('border-left', '2px solid #fdfdfd')
titleCell:wikitext(navbar{
            .css('width', '100%')
[cfg.navbar.name] = args[cfg.arg.name],
    end
[cfg.navbar.mini] = 1,
[cfg.navbar.fontstyle] = extract_color(
(args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '')
)
})
end


end
    local titleColspan = 2
    if args.imageleft then titleColspan = titleColspan + 1 end
    if args.image then titleColspan = titleColspan + 1 end
    if args.titlegroup then titleColspan = titleColspan - 1 end


local function renderTitleRow(tbl)
    titleCell
if not args[cfg.arg.title] then return end
        .cssText(args.basestyle)
        .cssText(args.titlestyle)
        .addClass('navbox-title')
        .attr('colspan', titleColspan)


local titleRow = tbl:tag('tr')
    renderNavBar(titleCell)


local titleCell = titleRow:tag('th'):attr('scope', 'col')
    titleCell
        .tag('div')
            .addClass(args.titleclass)
            .css('font-size', '110%')
            .newline()
            .wikitext(args.title)
end


local titleColspan = 2
function renderNavBar(titleCell)
if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end
    -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
if args[cfg.arg.image] then titleColspan = titleColspan + 1 end
    -- or right to keep the title centered.
    local spacerSide = nil


titleCell
    if args.navbar == 'off' then
:cssText(args[cfg.arg.basestyle])
        -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
:cssText(args[cfg.arg.titlestyle])
        -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
:addClass(cfg.class.navbox_title)
        if args.state == 'plain' then spacerSide = 'right' end
:attr('colspan', titleColspan)
    elseif args.navbar == 'plain' or args.navbar == 'off' or (not args.name and (border == 'subgroup' or border == 'child' or border == 'none')) then
        -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
        if args.state ~= 'plain' then spacerSide = 'left' end
    else
        -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
        -- to balance out the width of the navbar.
        if args.state == 'plain' then spacerSide = 'right' end


renderNavBar(titleCell)
        titleCell.wikitext(Navbar.navbar({
            args.name,
            mini = 1,
            fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
        }))
    end


titleCell
    -- Render the spacer div.
:tag('div')
    --            .css('float', spacerSide)
-- id for aria-labelledby attribute
    if spacerSide then
:attr('id', mw.uri.anchorEncode(args[cfg.arg.title]) .. args.argHash)
        titleCell
:addClass(args[cfg.arg.titleclass])
            .tag('span')
:css('font-size', '114%')
   
:css('margin', '0 4em')
                .css('float', 'right')
:wikitext(processItem(args[cfg.arg.title]))
                .css('width', '6em')
end
                .wikitext(' ')
    end
end


local function getAboveBelowColspan()
local ret = 2
if args[cfg.arg.imageleft] then ret = ret + 1 end
if args[cfg.arg.image] then ret = ret + 1 end
return ret
end


local function renderAboveRow(tbl)
--
if not args[cfg.arg.above] then return end
--  Above/Below rows
--
function renderAboveRow(tbl)
    if not args.above then return end


tbl:tag('tr')
    addTableRow(tbl)
:tag('td')
        .tag('td')
:addClass(cfg.class.navbox_abovebelow)
            .addClass('navbox-abovebelow')
:addClass(args[cfg.arg.aboveclass])
            .addClass(args.aboveclass)
:cssText(args[cfg.arg.basestyle])
            .cssText(args.basestyle)
:cssText(args[cfg.arg.abovestyle])
            .cssText(args.abovestyle)
:attr('colspan', getAboveBelowColspan())
            .attr('colspan', getAboveBelowColspan())
:tag('div')
            .tag('div')
-- id for aria-labelledby attribute, if no title
                .newline()
:attr('id', (not args[cfg.arg.title]) and
                .wikitext(args.above)
(mw.uri.anchorEncode(args[cfg.arg.above]) .. args.argHash)
end
or nil)
:wikitext(processItem(args[cfg.arg.above], args[cfg.arg.nowrapitems]))
end


local function renderBelowRow(tbl)
function renderBelowRow(tbl)
if not args[cfg.arg.below] then return end
    if not args.below then return end


tbl:tag('tr')
    addTableRow(tbl)
:tag('td')
        .tag('td')
:addClass(cfg.class.navbox_abovebelow)
            .addClass('navbox-abovebelow')
:addClass(args[cfg.arg.belowclass])
            .addClass(args.belowclass)
:cssText(args[cfg.arg.basestyle])
            .cssText(args.basestyle)
:cssText(args[cfg.arg.belowstyle])
            .cssText(args.belowstyle)
:attr('colspan', getAboveBelowColspan())
            .attr('colspan', getAboveBelowColspan())
:tag('div')
            .tag('div')
:wikitext(processItem(args[cfg.arg.below], args[cfg.arg.nowrapitems]))
                .newline()
end
                .wikitext(args.below)
end


local function renderListRow(tbl, index, listnum, listnums_size)
function getAboveBelowColspan()
local row = tbl:tag('tr')
    local ret = 2
    if args.imageleft then ret = ret + 1 end
    if args.image then ret = ret + 1 end
    return ret
end


if index == 1 and args[cfg.arg.imageleft] then
row
:tag('td')
:addClass(cfg.class.noviewer)
:addClass(cfg.class.navbox_image)
:addClass(args[cfg.arg.imageclass])
:css('width', '1px')              -- Minimize width
:css('padding', '0 2px 0 0')
:cssText(args[cfg.arg.imageleftstyle])
:attr('rowspan', listnums_size)
:tag('div')
:wikitext(processItem(args[cfg.arg.imageleft]))
end


local group_and_num = andnum('group', listnum)
--
local groupstyle_and_num = andnum('groupstyle', listnum)
--  List rows
if args[group_and_num] then
--
local groupCell = row:tag('th')
function renderListRow(tbl, listnum)
    local row = addTableRow(tbl)


-- id for aria-labelledby attribute, if lone group with no title or above
    if listnum == 1 and args.imageleft then
if listnum == 1 and not (args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group2]) then
        row
groupCell
            .tag('td')
:attr('id', mw.uri.anchorEncode(args[cfg.arg.group1]) .. args.argHash)
                .addClass('navbox-image')
end
                .addClass(args.imageclass)
                .css('width', '0%')
                .css('padding', '0px 2px 0px 0px')
                .cssText(args.imageleftstyle)
                .attr('rowspan', 2 * #listnums - 1)
                .tag('div')
                    .newline()
                    .wikitext(args.imageleft)
    end


groupCell
    if args['group' .. listnum] then
:attr('scope', 'row')
        local groupCell = row.tag('th')
:addClass(cfg.class.navbox_group)
:addClass(args[cfg.arg.groupclass])
:cssText(args[cfg.arg.basestyle])
-- If groupwidth not specified, minimize width
:css('width', args[cfg.arg.groupwidth] or '1%')


groupCell
        groupCell
:cssText(args[cfg.arg.groupstyle])
              .attr('scope', 'row')
:cssText(args[groupstyle_and_num])
              .addClass('navbox-group')
:wikitext(args[group_and_num])
              .addClass(args.groupclass)
end
              .cssText(args.basestyle)


local listCell = row:tag('td')
        if args.groupwidth then
            groupCell.css('width', args.groupwidth)
        end


if args[group_and_num] then
        groupCell
listCell
            .cssText(args.groupstyle)
:addClass(cfg.class.navbox_list_with_group)
            .cssText(args['group' .. listnum .. 'style'])
else
            .wikitext(args['group' .. listnum])
listCell:attr('colspan', 2)
    end
end


if not args[cfg.arg.groupwidth] then
    local listCell = row.tag('td')
listCell:css('width', '100%')
end


local rowstyle  -- usually nil so cssText(rowstyle) usually adds nothing
    if args['group' .. listnum] then
if index % 2 == 1 then
        listCell
rowstyle = args[cfg.arg.oddstyle]
            .css('text-align', 'left')
else
            .css('border-left-width', '2px')
rowstyle = args[cfg.arg.evenstyle]
            .css('border-left-style', 'solid')
end
    else
        listCell.attr('colspan', 2)
    end


local list_and_num = andnum('list', listnum)
    if not args.groupwidth then
local listText = inArray(cfg.keyword.subgroups, args[list_and_num])
        listCell.css('width', '100%')
and getSubgroup(args, listnum, args[list_and_num]) or args[list_and_num]
    end


local oddEven = cfg.marker.oddeven
    local isOdd = (listnum % 2) == 1
if listText:sub(1, 12) == '</div><table' then
    local rowstyle = args.evenstyle
-- Assume list text is for a subgroup navbox so no automatic striping for this row.
    if isOdd then rowstyle = args.oddstyle end
oddEven = listText:find(cfg.pattern.navbox_title) and cfg.marker.restart or cfg.class.navbox_odd_part
end


local liststyle_and_num = andnum('liststyle', listnum)
    local evenOdd
local listclass_and_num = andnum('listclass', listnum)
    if args.evenodd == 'swap' then
listCell
        if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
:css('padding', '0')
    else
:cssText(args[cfg.arg.liststyle])
        if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
:cssText(rowstyle)
    end
:cssText(args[liststyle_and_num])
:addClass(cfg.class.navbox_list)
:addClass(cfg.class.navbox_part .. oddEven)
:addClass(args[cfg.arg.listclass])
:addClass(args[listclass_and_num])
:tag('div')
:css('padding',
(index == 1 and args[cfg.arg.list1padding]) or args[cfg.arg.listpadding] or '0 0.25em'
)
:wikitext(processItem(listText, args[cfg.arg.nowrapitems]))


if index == 1 and args[cfg.arg.image] then
    listCell
row
        .css('padding', '0px')
:tag('td')
        .cssText(args.liststyle)
:addClass(cfg.class.noviewer)
        .cssText(rowstyle)
:addClass(cfg.class.navbox_image)
        .cssText(args['list' .. listnum .. 'style'])
:addClass(args[cfg.arg.imageclass])
        .addClass('navbox-list')
:css('width', '1px')               -- Minimize width
        .addClass('navbox-' .. evenOdd)
:css('padding', '0 0 0 2px')
        .addClass(args.listclass)
:cssText(args[cfg.arg.imagestyle])
        .tag('div')
:attr('rowspan', listnums_size)
            .css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
:tag('div')
            .newline()
:wikitext(processItem(args[cfg.arg.image]))
            .wikitext(args['list' .. listnum])
end
end


local function has_list_class(htmlclass)
    if listnum == 1 and args.image then
local patterns = {
        row
'^' .. htmlclass .. '$',
            .tag('td')
'%s' .. htmlclass .. '$',
                .addClass('navbox-image')
'^' .. htmlclass .. '%s',
                .addClass(args.imageclass)
'%s' .. htmlclass .. '%s'
                .css('width', '0%')
}
                .css('padding', '0px 0px 0px 2px')
                .cssText(args.imagestyle)
                .attr('rowspan', 2 * #listnums - 1)
                .tag('div')
                    .newline()
                    .wikitext(args.image)
    end
end


for arg, _ in pairs(args) do
if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then
for _, pattern in ipairs(patterns) do
if mw.ustring.find(args[arg] or '', pattern) then
return true
end
end
end
end
return false
end


-- there are a lot of list classes in the wild, so we add their TemplateStyles
--
local function add_list_styles()
--  Tracking categories
local frame = mw.getCurrentFrame()
--
local function add_list_templatestyles(htmlclass, templatestyles)
function renderTrackingCategories(builder)
if has_list_class(htmlclass) then
    local frame = mw.getCurrentFrame()
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
else
return ''
end
end


local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles)
    if not frame then return end
local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles)


-- a second workaround for [[phab:T303378]]
    local s = frame:preprocess('{{#ifeq:{{NAMESPACE}}|{{ns:10}}|1|0}}{{SUBPAGENAME}}')
-- when that issue is fixed, we can actually use has_navbar not to emit the
    if mw.ustring.sub(s, 1, 1) == '0' then return end -- not in template space
-- tag here if we want
    local subpage = mw.ustring.lower(mw.ustring.sub(s, 2))
if has_navbar() and hlist_styles == '' then
    if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
hlist_styles = frame:extensionTag{
name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
}
end


-- hlist -> plainlist is best-effort to preserve old Common.css ordering.
    for i, cat in ipairs(getTrackingCategories()) do
-- this ordering is not a guarantee because most navboxes will emit only
        builder.wikitext('')
-- one of these classes [hlist_note]
    end
return hlist_styles .. plainlist_styles
end
end


local function needsHorizontalLists(border)
function getTrackingCategories()
if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then
    local cats = {}
return false
    if needsHorizontalLists() then table.insert(cats, 'Navigational boxes without horizontal lists') end
end
    if hasBackgroundColors() then table.insert(cats, 'Navboxes using background colours') end
return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist)
    return cats
end
end


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


local function hasBorders()
    local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle,
    for i, cls in ipairs(listClasses) do
cfg.arg.abovestyle, cfg.arg.belowstyle}) do
        if args.listclass == cls or args.bodyclass == cls then
if tostring(args[key]):find('border', 1, true) then
            return false
return true
        end
end
    end
end
return false
end


local function isIllegible()
    return true
local styleratio = require('Module:Color contrast')._styleratio
end
for key, style in pairs(args) do
if tostring(key):match(cfg.pattern.style) then
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
return true
end
end
end
return false
end


local function getTrackingCategories(border)
function hasBackgroundColors()
local cats = {}
    return args.titlestyle or args.groupstyle
if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) end
end
if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end
if isIllegible() then table.insert(cats, cfg.category.illegible) end
if hasBorders() then table.insert(cats, cfg.category.borders) end
return cats
end


local function renderTrackingCategories(builder, border)
local title = mw.title.getCurrentTitle()
if title.namespace ~= 10 then return end -- not in template space
local subpage = title.subpageText
if subpage == cfg.keyword.subpage_doc or subpage == cfg.keyword.subpage_sandbox
or subpage == cfg.keyword.subpage_testcases then return end


for _, cat in ipairs(getTrackingCategories(border)) do
--
builder:wikitext('[[Category:' .. cat .. ']]')
--  Main navbox tables
end
--
end
function renderMainTable()
    local tbl = HtmlBuilder.create('table')
        .attr('cellspacing', 0)
        .addClass('nowraplinks')
        .addClass(args.bodyclass)


local function renderMainTable(border, listnums)
    if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
local tbl = mw.html.create('table')
        tbl
:addClass(cfg.class.nowraplinks)
            .addClass('collapsible')
:addClass(args[cfg.arg.bodyclass])
            .addClass(args.state or 'autocollapse')
    end


local state = args[cfg.arg.state]
    tbl.css('border-spacing', 0)
if args[cfg.arg.title] and state ~= cfg.keyword.state_plain and state ~= cfg.keyword.state_off then
    if border == 'subgroup' or border == 'child' or border == 'none' then
if state == cfg.keyword.state_collapsed then
        tbl
state = cfg.class.collapsed
            .addClass('navbox-subgroup')
end
            .cssText(args.bodystyle)
tbl
            .cssText(args.style)
:addClass(cfg.class.collapsible)
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
:addClass(state or cfg.class.autocollapse)
        tbl
end
            .addClass('navbox-inner')
            .css('background', 'transparent')
            .css('color', 'inherit')
    end
    tbl.cssText(args.innerstyle)


tbl:css('border-spacing', 0)
    renderTitleRow(tbl)
if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then
    renderAboveRow(tbl)
tbl
    for i, listnum in ipairs(listnums) do
:addClass(cfg.class.navbox_subgroup)
        renderListRow(tbl, listnum)
:cssText(args[cfg.arg.bodystyle])
    end
:cssText(args[cfg.arg.style])
    renderBelowRow(tbl)
else  -- regular navbox - bodystyle and style will be applied to the wrapper table
tbl
:addClass(cfg.class.navbox_inner)
:css('background', 'transparent')
:css('color', 'inherit')
end
tbl:cssText(args[cfg.arg.innerstyle])


renderTitleRow(tbl)
    return tbl
renderAboveRow(tbl)
end
local listnums_size = #listnums
for i, listnum in ipairs(listnums) do
renderListRow(tbl, i, listnum, listnums_size)
end
renderBelowRow(tbl)


return tbl
function p._navbox(navboxArgs)
end
    args = navboxArgs


local function add_navbox_styles(hiding_templatestyles)
    for k, v in pairs(args) do
local frame = mw.getCurrentFrame()
        local listnum = ('' .. k):match('^list(%d+)$')
-- This is a lambda so that it doesn't need the frame as a parameter
        if listnum then table.insert(listnums, tonumber(listnum)) end
local function add_user_styles(templatestyles)
    end
if not isblank(templatestyles) then
    table.sort(listnums)
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
end
return ''
end


-- get templatestyles. load base from config so that Lua only needs to do
    border = trim(args.border or args[1] or '')
-- the work once of parser tag expansion
local base_templatestyles = cfg.templatestyles
local templatestyles = add_user_styles(args[cfg.arg.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
    -- render the main body of the navbox
-- more elegantly. Instead of combinatorial rules, this ends up being linear
    local tbl = renderMainTable()
-- number of CSS rules.
return mw.html.create('div')
:addClass(cfg.class.navbox_styles)
:wikitext(
add_list_styles() .. -- see [hlist_note] applied to 'before base_templatestyles'
base_templatestyles ..
templatestyles ..
child_templatestyles ..
table.concat(hiding_templatestyles)
)
:done()
end


-- work around [[phab:T303378]]
    -- render the appropriate wrapper around the navbox, depending on the border param
-- for each arg: find all the templatestyles strip markers, insert them into a
    local res = HtmlBuilder.create()
-- table. then remove all templatestyles markers from the arg
    if border == 'none' then
local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
        res.node(tbl)
local argHash = 0
    elseif border == 'subgroup' or border == 'child' then
for k, arg in pairs(args) do
        -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
if type(arg) == 'string' then
        -- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
for marker in string.gfind(arg, strip_marker_pattern) do
        -- padding being applied, and at the end add a <div> to balance out the parent's </div>
table.insert(hiding_templatestyles, marker)
        res
end
            .tag('/div', {unclosed = true})
argHash = argHash + #arg
                .done()
args[k] = string.gsub(arg, strip_marker_pattern, '')
            .node(tbl)
end
            .tag('div', {unclosed = true})
end
    else
        res
if not args.argHash then args.argHash = argHash end
            .tag('table')
                .attr('cellspacing', 0)
                .addClass('navbox')
                .css('border-spacing', 0)
                .cssText(args.bodystyle)
                .cssText(args.style)
                .tag('tr')
                    .tag('td')
                        .css('padding', '2px')
                        .node(tbl)
    end


local listnums = {}
    renderTrackingCategories(res)


for k, _ in pairs(args) do
    return tostring(res)
if type(k) == 'string' then
end
local listnum = k:match(cfg.pattern.listnum)
if listnum and args[andnum('list', tonumber(listnum))] then
table.insert(listnums, tonumber(listnum))
end
end
end
table.sort(listnums)


local border = mw.text.trim(args[cfg.arg.border] or args[1] or '')
function p.navbox(frame)
if border == cfg.keyword.border_child then
    -- ParserFunctions considers the empty string to be false, so to preserve the previous
border = cfg.keyword.border_subgroup
    -- behavior of {{navbox}}, change any empty arguments to nil, so Lua will consider
end
    -- them false too.
    local args = {}
    local parent_args = frame:getParent().args;


-- render the main body of the navbox
    -- Out of order parsing bug.
local tbl = renderMainTable(border, listnums)
    local temp;
 
    temp = parent_args.title;
local res = mw.html.create()
    temp = parent_args.above;
-- render the appropriate wrapper for the navbox, based on the border param
    for i = 1, 20 do
 
        temp = parent_args["group" .. tostring(i)];
if border == cfg.keyword.border_none then
        temp = parent_args["list" .. tostring(i)];
res:node(add_navbox_styles(hiding_templatestyles))
    end
local nav = res:tag('div')
    temp = parent_args.below;
:attr('role', 'navigation')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args[cfg.arg.title] or args[cfg.arg.above] or (args[cfg.arg.group1]
and not args[cfg.arg.group2]) then
nav:attr(
'aria-labelledby',
mw.uri.anchorEncode(
args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
) .. args.argHash
)
else
nav:attr('aria-label', cfg.aria_label)
end
elseif border == cfg.keyword.border_subgroup then
-- 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
:wikitext('</div>')
:node(tbl)
:wikitext('<div>')
else
res:node(add_navbox_styles(hiding_templatestyles))
local nav = res:tag('div')
:attr('role', 'navigation')
:addClass(cfg.class.navbox)
:addClass(args[cfg.arg.navboxclass])
:cssText(args[cfg.arg.bodystyle])
:cssText(args[cfg.arg.style])
:css('padding', '3px')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args[cfg.arg.title] or args[cfg.arg.above]
or (args[cfg.arg.group1] and not args[cfg.arg.group2]) then
nav:attr(
'aria-labelledby',
mw.uri.anchorEncode(
args[cfg.arg.title] or args[cfg.arg.above] or args[cfg.arg.group1]
) .. args.argHash
)
else
nav:attr('aria-label', cfg.aria_label .. args.argHash)
end
end
 
if (args[cfg.arg.nocat] or cfg.keyword.nocat_false):lower() == cfg.keyword.nocat_false then
renderTrackingCategories(res, border)
end
return striped(tostring(res), border)
end --p._navbox
 
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],
argHash = pargs.argHash
})
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 --p._withCollapsibleGroups
 
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('&nbsp;&nbsp;&nbsp;')
: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.category.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 --p._withColumns
 
-- 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 _ = 0
_ = _ + (args[prefix .. cfg.arg.title] and #args[prefix .. cfg.arg.title] or 0)
_ = _ + (args[prefix .. cfg.arg.above] and #args[prefix .. cfg.arg.above] or 0)
-- 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)] and #args[prefix .. andnum('group', i)] or 0)
if inArray(cfg.keyword.subgroups, args[prefix .. andnum('list', i)]) then
for _, v in ipairs(cfg.arg.subgroups_and_num) do
readArgs(args, prefix .. string.format(v, i) .. "_")
end
readArgs(args, prefix .. andnum('col', i) .. "_")
end
end
_ = _ + (args[prefix .. cfg.arg.below] and #args[prefix .. cfg.arg.below] or 0)
return _
end
 
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
local args = getArgs(frame, {wrappers = {cfg.pattern[boxtype or 'navbox']}})
args.argHash = readArgs(args, "")
args.type = args.type or cfg.keyword[boxtype]
 
-- افزودن پارامترهای فارسی:
local function aliasParam(original, aliases)
for _, alias in ipairs(aliases) do
if args[original] == nil and args[alias] ~= nil then
args[original] = args[alias]
end
end
end
 
--  پارامترهای فارسی پایه:
aliasParam('title', {'عنوان'})
aliasParam('above', {'بالا'})
aliasParam('below', {'پایین'})
aliasParam('image', {'تصویر'})
aliasParam('imageright', {'تصویر راست'})
aliasParam('name', {'نام'})
aliasParam('state', {'حالت'})
aliasParam('navbar', {'سرپیوند'})
aliasParam('border', {'حاشیه', 'اطراف'})
aliasParam('groupwidth', {'عرض گروه'})
aliasParam('style', {'سبک', 'سبک بدنه'})
aliasParam('imagestyle', {'سبک تصویر'})
aliasParam('imagerightstyle', {'سبک تصویر راست'})
aliasParam('titlestyle', {'سبک عنوان'})
aliasParam('basestyle', {'سبک پایه'})
aliasParam('abovestyle', {'سبک بالا'})
aliasParam('belowstyle', {'سبک پایین'})
aliasParam('groupstyle', {'سبک گروه'})
aliasParam('liststyle', {'سبک فهرست'})
aliasParam('evenstyle', {'سبک زوج'})
aliasParam('oddstyle', {'سبک فرد'})
aliasParam('evenodd', {'زوج فرد'})
aliasParam('listpadding', {'فاصله فهرست'})
aliasParam('bodyclass', {'کلاس بدنه'})
aliasParam('listclass', {'کلاس فهرست'})
aliasParam('belowclass', {'کلاس پایین'})
 
-- گروه‌ها و فهرست‌ها:
for i = 1, 40 do
aliasParam('group' .. i, {'گروه' .. numConv('fa', i)})
aliasParam('list' .. i, {'فهرست' .. numConv('fa', i)})
aliasParam('group' .. i .. 'style', {'سبک گروه' .. numConv('fa', i)})
aliasParam('list' .. i .. 'style', {'سبک فهرست' .. numConv('fa', i)})
end
 
-- فهرست و گروه پیش‌فرض:
aliasParam('group1', {'گروه'})
aliasParam('list1', {'فهرست'})
 
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)
    for k, v in pairs(parent_args) do
return p.navbox(frame, 'with_columns')
        if v ~= '' then
            args[k] = v
        end
    end
    return p._navbox(args)
end
end


return p
return p
لطفاً توجه داشته باشید که همهٔ مشارکت‌ها در ویکی حج منتشرشده تحت Creative Commons Attribution-NonCommercial-ShareAlike در نظر گرفته‌می‌شوند (برای جزئیات بیش‌تر ویکی حج:حق تکثیر را ببینید). اگر نمی‌خواهید نوشته‌هایتان بی‌رحمانه ویرایش و توزیع شوند؛ بنابراین، آنها را اینجا ارائه نکنید.
شما همچنین به ما تعهد می‌کنید که خودتان این را نوشته‌اید یا آن را از یک منبع با مالکیت عمومی یا مشابه آزاد آن برداشته‌اید (برای جزئیات بیش‌تر ویکی حج:حق تکثیر را ببینید). کارهای دارای حق تکثیر را بدون اجازه ارائه نکنید!
لغو راهنمای ویرایش (در پنجرهٔ تازه باز می‌شود)

الگوی به‌کاررفته در این صفحه: