Jump to content
 







Main menu
   


Navigation  



Main page
Contents
Current events
Random article
About Wikipedia
Contact us
Donate
 




Contribute  



Help
Learn to edit
Community portal
Recent changes
Upload file
 








Search  

































Create account

Log in
 









Create account
 Log in
 




Pages for logged out editors learn more  



Contributions
Talk
 



















Contents

   



(Top)
 


1 Tracking/maintenance categories  














Module:Navbox






Afrikaans
Alemannisch
Алтай тил

Anarâškielâ
Аԥсшәа
العربية
Aragonés
Արեւմտահայերէն

Asturianu
Авар
Azərbaycanca
تۆرکجه
Basa Bali

Banjar
 / Bân-lâm-gú
Basa Banyumasan
Башҡортса
Беларуская
Беларуская (тарашкевіца)

Bikol Central
Български
Bosanski
Буряад
Català
Чӑвашла
Cebuano
Čeština
Chamoru
ChiShona
ChiTumbuka
Corsu
Cymraeg
Dansk
الدارجة
Deutsch
Ελληνικά
Эрзянь
Español
Euskara
فارسی
Fiji Hindi
Føroyskt
Français
Frysk
Gaeilge
Gàidhlig
Galego
ГӀалгӀай

گیلکی

  / Gõychi Konknni
/Hak-kâ-ngî

Hausa
Hawaiʻi
Հայերեն
ि
Bahasa Hulontalo
Ido
Ilokano
Bahasa Indonesia
Interlingua
Interlingue
Ирон
Íslenska
Italiano
עברית
Jawa


Қазақша
Kernowek
Kiswahili
Kurdî
Ladin
Лакку

Latgaļu
Latviešu
Lëtzebuergesch
Лезги
Lietuvių
Li Niha
Ligure
Magyar
Madhurâ
ि
Македонски

Malti
Māori

مصرى

مازِرونی
Bahasa Melayu
Minangkabau
 / Mìng-dĕ̤ng-nḡ
Mirandés
Мокшень
Монгол

Nederlands

 

Napulitano
Нохчийн
Norsk bokmål
Norsk nynorsk
Novial
Occitan
Олык марий
ି
Oʻzbekcha / ўзбекча

Pangasinan
پنجابی

Patois
Перем коми

Tok Pisin
Polski
Português
Qaraqalpaqsha
Qırımtatarca
Română
Rumantsch
Русиньскый
Русский
Саха тыла
Sakizaya


سرائیکی
Scots
Sicilianu

Simple English
سنڌي
Slovenčina
Slovenščina
Soomaaliga
کوردی
Српски / srpski
Srpskohrvatski / српскохрватски
Suomi
Svenska
Tagalog
ி
Taqbaylit
Tarandíne
Татарча / tatarça
 
Tetun


Тоҷикӣ
Türkçe
Türkmençe
Тыва дыл
Удмурт
Українська
اردو
Vahcuengh
Vèneto
Tiếng Vit
Volapük

Winaray

Yorùbá

Zazaki

 

Edit links
 









Module
Talk
 

















Read
View source
View history
 








Tools
   


Actions  



Read
View source
View history
 




General  



What links here
Related changes
Upload file
Special pages
Permanent link
Page information
Get shortened URL
Download QR code
Wikidata item
 




Print/export  



Download as PDF
Printable version
 




In other projects  



Wikimedia Commons
MediaWiki
Meta-Wiki
Wikimedia Outreach
Multilingual Wikisource
Wikispecies
Wikibooks
Wikidata
Wikifunctions
Wikimania
Wikisource
Wikiversity
 
















Appearance
   

 





Permanently protected module

From Wikipedia, the free encyclopedia
 


This module implements the {{Navbox}} template. Please see the template page for usage instructions.

Tracking/maintenance categories

require('strict')
local p = {}
local navbar = require('Module:Navbar')._navbar
local cfg = mw.loadData('Module:Navbox/configuration')
local getArgs -- lazily initialized
local args
local format = string.format

local function striped(wikitext, border)
 -- Return wikitext with markers replaced for odd/even striping.
 -- Child (subgroup) navboxes are flagged with a category that is removed
 -- by parent navboxes. The result is that the category shows all pages
 -- where a child navbox is not contained in a parent navbox.
 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)
 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 = 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()
 return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off
  and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain
  and (
   args[cfg.arg.name]
   or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '')
    ~= cfg.pattern.navbox
  )
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

local function renderNavBar(titleCell)
 if has_navbar() then
  titleCell:wikitext(navbar{
   [cfg.navbar.name] = args[cfg.arg.name],
   [cfg.navbar.mini] = 1,
   [cfg.navbar.fontstyle] = extract_color(
    (args[cfg.arg.basestyle] or '') .. ';' .. (args[cfg.arg.titlestyle] or '')
   )
  })
 end

end

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

 local titleRow = tbl:tag('tr')

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

 local titleColspan = 2
 if args[cfg.arg.imageleft] then titleColspan = titleColspan + 1 end
 if args[cfg.arg.image] then titleColspan = titleColspan + 1 end

 titleCell
  :cssText(args[cfg.arg.basestyle])
  :cssText(args[cfg.arg.titlestyle])
  :addClass(cfg.class.navbox_title)
  :attr('colspan', titleColspan)

 renderNavBar(titleCell)

 titleCell
  :tag('div')
   -- id for aria-labelledby attribute
   :attr('id', mw.uri.anchorEncode(args[cfg.arg.title]))
   :addClass(args[cfg.arg.titleclass])
   :css('font-size', '114%')
   :css('margin', '0 4em')
   :wikitext(processItem(args[cfg.arg.title]))
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

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

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

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

local function renderListRow(tbl, index, listnum, listnums_size)
 local row = tbl:tag('tr')

 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 = format(cfg.arg.group_and_num, listnum)
 local groupstyle_and_num = format(cfg.arg.groupstyle_and_num, listnum)
 if args[group_and_num] then
  local groupCell = row:tag('th')

  -- 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
   groupCell
    :attr('id', mw.uri.anchorEncode(args[cfg.arg.group1]))
  end

  groupCell
   :attr('scope', 'row')
   :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
   :cssText(args[cfg.arg.groupstyle])
   :cssText(args[groupstyle_and_num])
   :wikitext(args[group_and_num])
 end

 local listCell = row:tag('td')

 if args[group_and_num] then
  listCell
   :addClass(cfg.class.navbox_list_with_group)
 else
  listCell:attr('colspan', 2)
 end

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

 local rowstyle  -- usually nil so cssText(rowstyle) usually adds nothing
 if index % 2 == 1 then
  rowstyle = args[cfg.arg.oddstyle]
 else
  rowstyle = args[cfg.arg.evenstyle]
 end

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

 local liststyle_and_num = format(cfg.arg.liststyle_and_num, listnum)
 local listclass_and_num = format(cfg.arg.listclass_and_num, listnum)
 listCell
  :css('padding', '0')
  :cssText(args[cfg.arg.liststyle])
  :cssText(rowstyle)
  :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
  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 0 0 2px')
    :cssText(args[cfg.arg.imagestyle])
    :attr('rowspan', listnums_size)
    :tag('div')
     :wikitext(processItem(args[cfg.arg.image]))
 end
end

local function has_list_class(htmlclass)
 local patterns = {
  '^' .. htmlclass .. '$',
  '%s' .. htmlclass .. '$',
  '^' .. htmlclass .. '%s',
  '%s' .. htmlclass .. '%s'
 }
 
 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()
 local frame = mw.getCurrentFrame()
 local function add_list_templatestyles(htmlclass, templatestyles)
  if has_list_class(htmlclass) then
   return frame:extensionTag{
    name = 'templatestyles', args = { src = templatestyles }
   }
  else
   return ''
  end
 end
 
 local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles)
 local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles)
 
 -- 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_styles == '' then
  hlist_styles = frame:extensionTag{
   name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
  }
 end
 
 -- hlist -> plainlist is best-effort to preserve old Common.css ordering.
 -- this ordering is not a guarantee because most navboxes will emit only
 -- one of these classes [hlist_note]
 return hlist_styles .. plainlist_styles
end

local function needsHorizontalLists(border)
 if border == cfg.keyword.border_subgroup or args[cfg.arg.tracking] == cfg.keyword.tracking_no then
  return false
 end
 return not has_list_class(cfg.pattern.hlist) and not has_list_class(cfg.pattern.plainlist)
end

local function hasBackgroundColors()
 for _, key in ipairs({cfg.arg.titlestyle, cfg.arg.groupstyle,
  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()
 for _, key in ipairs({cfg.arg.groupstyle, cfg.arg.basestyle,
  cfg.arg.abovestyle, cfg.arg.belowstyle}) do
  if tostring(args[key]):find('border', 1, true) then
   return true
  end
 end
 return false
end

local function isIllegible()
 local styleratio = require('Module:Color contrast')._styleratio
 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)
 local cats = {}
 if needsHorizontalLists(border) then table.insert(cats, cfg.category.horizontal_lists) 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 .. ']]')
 end
end

local function renderMainTable(border, listnums)
 local tbl = mw.html.create('table')
  :addClass(cfg.class.nowraplinks)
  :addClass(args[cfg.arg.bodyclass])

 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 state == cfg.keyword.state_collapsed then
   state = cfg.class.collapsed
  end
  tbl
   :addClass(cfg.class.collapsible)
   :addClass(state or cfg.class.autocollapse)
 end

 tbl:css('border-spacing', 0)
 if border == cfg.keyword.border_subgroup or border == cfg.keyword.border_none then
  tbl
   :addClass(cfg.class.navbox_subgroup)
   :cssText(args[cfg.arg.bodystyle])
   :cssText(args[cfg.arg.style])
 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)
 renderAboveRow(tbl)
 local listnums_size = #listnums
 for i, listnum in ipairs(listnums) do
  renderListRow(tbl, i, listnum, listnums_size)
 end
 renderBelowRow(tbl)

 return tbl
end

local function add_navbox_styles(hiding_templatestyles)
 local frame = mw.getCurrentFrame()
 -- This is a lambda so that it doesn't need the frame as a parameter
 local function add_user_styles(templatestyles)
  if templatestyles and templatestyles ~= '' then
   return frame:extensionTag{
    name = 'templatestyles', args = { src = templatestyles }
   }
  end
  return ''
 end

 -- get templatestyles. load base from config so that Lua only needs to do
 -- 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
 -- more elegantly. Instead of combinatorial rules, this ends up being linear
 -- 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]]
-- 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

function p._navbox(navboxArgs)
 args = navboxArgs
 local hiding_templatestyles = move_hiding_templatestyles(args)
 local listnums = {}

 for k, _ in pairs(args) do
  if type(k) == 'string' then
   local listnum = k:match(cfg.pattern.listnum)
   if 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 '')
 if border == cfg.keyword.border_child then
  border = cfg.keyword.border_subgroup
 end

 -- render the main body of the navbox
 local tbl = renderMainTable(border, listnums)

 local res = mw.html.create()
 -- render the appropriate wrapper for the navbox, based on the border param

 if border == cfg.keyword.border_none then
  res:node(add_navbox_styles(hiding_templatestyles))
  local nav = res:tag('div')
   :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]
    )
   )
  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])
   )
  else
   nav:attr('aria-label', cfg.aria_label)
  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

function p.navbox(frame)
 if not getArgs then
  getArgs = require('Module:Arguments').getArgs
 end
 args = getArgs(frame, {wrappers = {cfg.pattern.navbox}})

 -- Read the arguments in the order they'll be output in, to make references
 -- number in the right order.
 local _
 _ = args[cfg.arg.title]
 _ = args[cfg.arg.above]
 -- Limit this to 20 as covering 'most' cases (that's a SWAG) and because
 -- iterator approach won't work here
 for i = 1, 20 do
  _ = args[format(cfg.arg.group_and_num, i)]
  _ = args[format(cfg.arg.list_and_num, i)]
 end
 _ = args[cfg.arg.below]

 return p._navbox(args)
end

return p

Retrieved from "https://en.wikipedia.org/w/index.php?title=Module:Navbox&oldid=1224348842"

Categories: 
Modules subject to page protection
Templates using TemplateStyles
Modules that add a tracking category
Modules that check for strip markers
Hidden category: 
Wikipedia template-protected modules
 



This page was last edited on 17 May 2024, at 21:07 (UTC).

Text is available under the Creative Commons Attribution-ShareAlike License 4.0; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy. Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc., a non-profit organization.



Privacy policy

About Wikipedia

Disclaimers

Contact Wikipedia

Code of Conduct

Developers

Statistics

Cookie statement

Mobile view



Wikimedia Foundation
Powered by MediaWiki