require('strict')localp={}localcfg=mw.loadData('Module:Navbox/configuration')localinArray=require("Module:TableTools").inArraylocalgetArgs-- lazily initializedlocalhiding_templatestyles={}-- global passthrough variableslocalpassthrough={[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 functionslocalandnum=function(s,n)returnstring.format(cfg.arg[s..'_and_num'],n)endlocalisblank=function(v)return(vor'')==''endlocalfunctionconcatstrings(s)localr=table.concat(s,'')ifr:match('^%s*$')thenreturnnilendreturnrendlocalfunctionconcatstyles(s)localr=''for_,vinipairs(s)dov=mw.text.trim(v,"%s;")ifnotisblank(v)thenr=r..v..';'endendifisblank(r)thenreturnnilendreturnrendlocalfunctiongetSubgroup(args,listnum,listText,prefix)localsubArgs={[cfg.arg.border]=cfg.keyword.border_subgroup,[cfg.arg.navbar]=cfg.keyword.navbar_plain,argHash=0}localhasSubArgs=falselocalsubgroups_and_num=prefixand{prefix}orcfg.arg.subgroups_and_numfork,vinpairs(args)dok=tostring(k)for_,winipairs(subgroups_and_num)dow=string.format(w,listnum).."_"if(#k>#w)and(k:sub(1,#w)==w)thensubArgs[k:sub(#w+1)]=vhasSubArgs=truesubArgs.argHash=subArgs.argHash+(vand#vor0)endendendreturnhasSubArgsandp._navbox(subArgs)orlistTextend-- Main functionsfunctionp._navbox(args)ifargs.type==cfg.keyword.with_collapsible_groupsthenreturnp._withCollapsibleGroups(args)elseifargs.type==cfg.keyword.with_columnsthenreturnp._withColumns(args)endlocalfunctionstriped(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.localorphanCat=cfg.category.orphanifborder==cfg.keyword.border_subgroupandargs[cfg.arg.orphan]~=cfg.keyword.orphan_yesthen-- No change; striping occurs in outermost navbox.returnwikitext..orphanCatendlocalfirst,second=cfg.class.navbox_odd_part,cfg.class.navbox_even_partifargs[cfg.arg.evenodd]thenifargs[cfg.arg.evenodd]==cfg.keyword.evenodd_swapthenfirst,second=second,firstelsefirst=args[cfg.arg.evenodd]second=firstendendlocalchangeriffirst==secondthenchanger=firstelselocalindex=0changer=function(code)ifcode=='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=0returnfirstendindex=index+1returnindex%2==1andfirstorsecondendendlocalregex=orphanCat:gsub('([%[%]])','%%%1')return(wikitext:gsub(regex,''):gsub(cfg.marker.regex,changer))-- () omits gsub countendlocalfunctionprocessItem(item,nowrapitems)ifitem: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'endifnowrapitems==cfg.keyword.nowrapitems_yesthenlocallines={}forlinein(item..'\n'):gmatch('([^\n]*)\n')dolocalprefix,content=line:match('^([*:;#]+)%s*(.*)')ifprefixandnotcontent:match(cfg.pattern.nowrap)thenline=string.format(cfg.nowrap_item,prefix,content)endtable.insert(lines,line)enditem=table.concat(lines,'\n')endifitem:match('^[*:;#]')thenreturn'\n'..item..'\n'endreturnitemendlocalfunctionhas_navbar()returnargs[cfg.arg.navbar]~=cfg.keyword.navbar_offandargs[cfg.arg.navbar]~=cfg.keyword.navbar_plainand(args[cfg.arg.name]ormw.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 navbarlocalfunctionextract_color(css_str)-- return nil because navbar takes its argument into mw.html which handles-- nil gracefully, removing the associated style attributereturnmw.ustring.match(';'..css_str..';','.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;')ornilendlocalfunctionrenderNavBar(titleCell)ifhas_navbar()thenlocalnavbar=require('Module:Navbar')._navbartitleCell: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''))})endendlocalfunctionrenderTitleRow(tbl)ifnotargs[cfg.arg.title]thenreturnendlocaltitleRow=tbl:tag('tr')localtitleCell=titleRow:tag('th'):attr('scope','col')localtitleColspan=2ifargs[cfg.arg.imageleft]thentitleColspan=titleColspan+1endifargs[cfg.arg.image]thentitleColspan=titleColspan+1endtitleCell: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])..args.argHash):addClass(args[cfg.arg.titleclass]):css('font-size','114%'):css('margin','0 4em'):wikitext(processItem(args[cfg.arg.title]))endlocalfunctiongetAboveBelowColspan()localret=2ifargs[cfg.arg.imageleft]thenret=ret+1endifargs[cfg.arg.image]thenret=ret+1endreturnretendlocalfunctionrenderAboveRow(tbl)ifnotargs[cfg.arg.above]thenreturnendtbl: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',(notargs[cfg.arg.title])and(mw.uri.anchorEncode(args[cfg.arg.above])..args.argHash)ornil):wikitext(processItem(args[cfg.arg.above],args[cfg.arg.nowrapitems]))endlocalfunctionrenderBelowRow(tbl)ifnotargs[cfg.arg.below]thenreturnendtbl: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]))endlocalfunctionrenderListRow(tbl,index,listnum,listnums_size)localrow=tbl:tag('tr')ifindex==1andargs[cfg.arg.imageleft]thenrow: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]))endlocalgroup_and_num=andnum('group',listnum)localgroupstyle_and_num=andnum('groupstyle',listnum)ifargs[group_and_num]thenlocalgroupCell=row:tag('th')-- id for aria-labelledby attribute, if lone group with no title or aboveiflistnum==1andnot(args[cfg.arg.title]orargs[cfg.arg.above]orargs[cfg.arg.group2])thengroupCell:attr('id',mw.uri.anchorEncode(args[cfg.arg.group1])..args.argHash)endgroupCell: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])endlocallistCell=row:tag('td')ifargs[group_and_num]thenlistCell:addClass(cfg.class.navbox_list_with_group)elselistCell:attr('colspan',2)endifnotargs[cfg.arg.groupwidth]thenlistCell:css('width','100%')endlocalrowstyle-- usually nil so cssText(rowstyle) usually adds nothingifindex%2==1thenrowstyle=args[cfg.arg.oddstyle]elserowstyle=args[cfg.arg.evenstyle]endlocallist_and_num=andnum('list',listnum)locallistText=inArray(cfg.keyword.subgroups,args[list_and_num])andgetSubgroup(args,listnum,args[list_and_num])orargs[list_and_num]localoddEven=cfg.marker.oddeveniflistText: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)andcfg.marker.restartorcfg.class.navbox_odd_partendlocalliststyle_and_num=andnum('liststyle',listnum)locallistclass_and_num=andnum('listclass',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==1andargs[cfg.arg.list1padding])orargs[cfg.arg.listpadding]or'0 0.25em'):wikitext(processItem(listText,args[cfg.arg.nowrapitems]))ifindex==1andargs[cfg.arg.image]thenrow: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]))endendlocalfunctionhas_list_class(htmlclass)localpatterns={'^'..htmlclass..'$','%s'..htmlclass..'$','^'..htmlclass..'%s','%s'..htmlclass..'%s'}forarg,_inpairs(args)doiftype(arg)=='string'andmw.ustring.find(arg,cfg.pattern.class)thenfor_,patterninipairs(patterns)doifmw.ustring.find(args[arg]or'',pattern)thenreturntrueendendendendreturnfalseend-- there are a lot of list classes in the wild, so we add their TemplateStyleslocalfunctionadd_list_styles()localframe=mw.getCurrentFrame()localfunctionadd_list_templatestyles(htmlclass,templatestyles)ifhas_list_class(htmlclass)thenreturnframe:extensionTag{name='templatestyles',args={src=templatestyles}}elsereturn''endendlocalhlist_styles=add_list_templatestyles('hlist',cfg.hlist_templatestyles)localplainlist_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 wantifhas_navbar()andhlist_styles==''thenhlist_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]returnhlist_styles..plainlist_stylesendlocalfunctionneedsHorizontalLists(border)ifborder==cfg.keyword.border_subgrouporargs[cfg.arg.tracking]==cfg.keyword.tracking_nothenreturnfalseendreturnnothas_list_class(cfg.pattern.hlist)andnothas_list_class(cfg.pattern.plainlist)endlocalfunctionhasBackgroundColors()for_,keyinipairs({cfg.arg.titlestyle,cfg.arg.groupstyle,cfg.arg.basestyle,cfg.arg.abovestyle,cfg.arg.belowstyle})doiftostring(args[key]):find('background',1,true)thenreturntrueendendreturnfalseendlocalfunctionhasBorders()for_,keyinipairs({cfg.arg.groupstyle,cfg.arg.basestyle,cfg.arg.abovestyle,cfg.arg.belowstyle})doiftostring(args[key]):find('border',1,true)thenreturntrueendendreturnfalseendlocalfunctionisIllegible()localstyleratio=require('Module:Color contrast')._styleratioforkey,styleinpairs(args)doiftostring(key):match(cfg.pattern.style)thenifstyleratio{mw.text.unstripNoWiki(style)}<4.5thenreturntrueendendendreturnfalseendlocalfunctiongetTrackingCategories(border)localcats={}ifneedsHorizontalLists(border)thentable.insert(cats,cfg.category.horizontal_lists)endifhasBackgroundColors()thentable.insert(cats,cfg.category.background_colors)endifisIllegible()thentable.insert(cats,cfg.category.illegible)endifhasBorders()thentable.insert(cats,cfg.category.borders)endreturncatsendlocalfunctionrenderTrackingCategories(builder,border)localtitle=mw.title.getCurrentTitle()iftitle.namespace~=10thenreturnend-- not in template spacelocalsubpage=title.subpageTextifsubpage==cfg.keyword.subpage_docorsubpage==cfg.keyword.subpage_sandboxorsubpage==cfg.keyword.subpage_testcasesthenreturnendfor_,catinipairs(getTrackingCategories(border))dobuilder:wikitext('[[Category:'..cat..']]')endendlocalfunctionrenderMainTable(border,listnums)localtbl=mw.html.create('table'):addClass(cfg.class.nowraplinks):addClass(args[cfg.arg.bodyclass])localstate=args[cfg.arg.state]ifargs[cfg.arg.title]andstate~=cfg.keyword.state_plainandstate~=cfg.keyword.state_offthenifstate==cfg.keyword.state_collapsedthenstate=cfg.class.collapsedendtbl:addClass(cfg.class.collapsible):addClass(stateorcfg.class.autocollapse)endtbl:css('border-spacing',0)ifborder==cfg.keyword.border_subgrouporborder==cfg.keyword.border_nonethentbl: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 tabletbl:addClass(cfg.class.navbox_inner):css('background','transparent'):css('color','inherit')endtbl:cssText(args[cfg.arg.innerstyle])renderTitleRow(tbl)renderAboveRow(tbl)locallistnums_size=#listnumsfori,listnuminipairs(listnums)dorenderListRow(tbl,i,listnum,listnums_size)endrenderBelowRow(tbl)returntblendlocalfunctionadd_navbox_styles(hiding_templatestyles)localframe=mw.getCurrentFrame()-- This is a lambda so that it doesn't need the frame as a parameterlocalfunctionadd_user_styles(templatestyles)ifnotisblank(templatestyles)thenreturnframe:extensionTag{name='templatestyles',args={src=templatestyles}}endreturn''end-- get templatestyles. load base from config so that Lua only needs to do-- the work once of parser tag expansionlocalbase_templatestyles=cfg.templatestyleslocaltemplatestyles=add_user_styles(args[cfg.arg.templatestyles])localchild_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.returnmw.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 arglocalstrip_marker_pattern='(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'localargHash=0fork,arginpairs(args)doiftype(arg)=='string'thenformarkerinstring.gfind(arg,strip_marker_pattern)dotable.insert(hiding_templatestyles,marker)endargHash=argHash+#argargs[k]=string.gsub(arg,strip_marker_pattern,'')endendifnotargs.argHashthenargs.argHash=argHashendlocallistnums={}fork,_inpairs(args)doiftype(k)=='string'thenlocallistnum=k:match(cfg.pattern.listnum)iflistnumandargs[andnum('list',tonumber(listnum))]thentable.insert(listnums,tonumber(listnum))endendendtable.sort(listnums)localborder=mw.text.trim(args[cfg.arg.border]orargs[1]or'')ifborder==cfg.keyword.border_childthenborder=cfg.keyword.border_subgroupend-- render the main body of the navboxlocaltbl=renderMainTable(border,listnums)localres=mw.html.create()-- render the appropriate wrapper for the navbox, based on the border paramifborder==cfg.keyword.border_nonethenres:node(add_navbox_styles(hiding_templatestyles))localnav=res:tag('div'):attr('role','navigation'):node(tbl)-- aria-labelledby title, otherwise above, otherwise lone groupifargs[cfg.arg.title]orargs[cfg.arg.above]or(args[cfg.arg.group1]andnotargs[cfg.arg.group2])thennav:attr('aria-labelledby',mw.uri.anchorEncode(args[cfg.arg.title]orargs[cfg.arg.above]orargs[cfg.arg.group1])..args.argHash)elsenav:attr('aria-label',cfg.aria_label)endelseifborder==cfg.keyword.border_subgroupthen-- 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>')elseres:node(add_navbox_styles(hiding_templatestyles))localnav=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 groupifargs[cfg.arg.title]orargs[cfg.arg.above]or(args[cfg.arg.group1]andnotargs[cfg.arg.group2])thennav:attr('aria-labelledby',mw.uri.anchorEncode(args[cfg.arg.title]orargs[cfg.arg.above]orargs[cfg.arg.group1])..args.argHash)elsenav:attr('aria-label',cfg.aria_label..args.argHash)endendif(args[cfg.arg.nocat]orcfg.keyword.nocat_false):lower()==cfg.keyword.nocat_falsethenrenderTrackingCategories(res,border)endreturnstriped(tostring(res),border)end--p._navboxfunctionp._withCollapsibleGroups(pargs)-- table for args passed to navboxlocaltargs={}-- process argslocalpassthroughLocal={[cfg.arg.bodystyle]=true,[cfg.arg.border]=true,[cfg.arg.style]=true,}fork,vinpairs(pargs)doifkandtype(k)=='string'thenifpassthrough[k]orpassthroughLocal[k]thentargs[k]=velseif(k:match(cfg.pattern.num))thenlocaln=k:match(cfg.pattern.num)locallist_and_num=andnum('list',n)if((k:match(cfg.pattern.listnum)ork:match(cfg.pattern.contentnum))andtargs[list_and_num]==nilandpargs[andnum('group',n)]==nilandpargs[andnum('sect',n)]==nilandpargs[andnum('section',n)]==nil)thentargs[list_and_num]=concatstrings({pargs[list_and_num]or'',pargs[andnum('content',n)]or''})if(targs[list_and_num]andinArray(cfg.keyword.subgroups,targs[list_and_num]))thentargs[list_and_num]=getSubgroup(pargs,n,targs[list_and_num])endelseif((k:match(cfg.pattern.groupnum)ork:match(cfg.pattern.sectnum)ork:match(cfg.pattern.sectionnum))andtargs[list_and_num]==nil)thenlocaltitlestyle=concatstyles({pargs[cfg.arg.groupstyle]or'',pargs[cfg.arg.secttitlestyle]or'',pargs[andnum('groupstyle',n)]or'',pargs[andnum('sectiontitlestyle',n)]or''})localliststyle=concatstyles({pargs[cfg.arg.liststyle]or'',pargs[cfg.arg.contentstyle]or'',pargs[andnum('liststyle',n)]or'',pargs[andnum('contentstyle',n)]or''})localtitle=concatstrings({pargs[andnum('group',n)]or'',pargs[andnum('sect',n)]or'',pargs[andnum('section',n)]or''})locallist=concatstrings({pargs[list_and_num]or'',pargs[andnum('content',n)]or''})iflistandinArray(cfg.keyword.subgroups,list)thenlist=getSubgroup(pargs,n,list)endlocalabbr_and_num=andnum('abbr',n)localstate=(pargs[abbr_and_num]andpargs[abbr_and_num]==pargs[cfg.arg.selected])andcfg.keyword.state_uncollapsedor(pargs[andnum('state',n)]orcfg.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})endendendend-- ordering of style and bodystyletargs[cfg.arg.style]=concatstyles({targs[cfg.arg.style]or'',targs[cfg.arg.bodystyle]or''})targs[cfg.arg.bodystyle]=nil-- child or subgroupiftargs[cfg.arg.border]==nilthentargs[cfg.arg.border]=pargs[1]endreturnp._navbox(targs)end--p._withCollapsibleGroupsfunctionp._withColumns(pargs)-- table for args passed to navboxlocaltargs={}-- tables of column numberslocalcolheadernums={}localcolnums={}localcolfooternums={}-- process argslocalpassthroughLocal={[cfg.arg.evenstyle]=true,[cfg.arg.groupstyle]=true,[cfg.arg.liststyle]=true,[cfg.arg.oddstyle]=true,[cfg.arg.state]=true,}fork,vinpairs(pargs)doifpassthrough[k]orpassthroughLocal[k]thentargs[k]=velseiftype(k)=='string'thenifk:match(cfg.pattern.listnum)thenlocaln=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)]ifvandinArray(cfg.keyword.subgroups,v)thentargs[andnum('list',n+2)]=getSubgroup(pargs,n,v)elsetargs[andnum('list',n+2)]=vendelseif(k:match(cfg.pattern.colheadernum)andv~='')thentable.insert(colheadernums,tonumber(k:match(cfg.pattern.colheadernum)))elseif(k:match(cfg.pattern.colnum)andv~='')thentable.insert(colnums,tonumber(k:match(cfg.pattern.colnum)))elseif(k:match(cfg.pattern.colfooternum)andv~='')thentable.insert(colfooternums,tonumber(k:match(cfg.pattern.colfooternum)))endendendtable.sort(colheadernums)table.sort(colnums)table.sort(colfooternums)-- HTML table for list1localcoltable=mw.html.create('table'):addClass('navbox-columns-table')localrow,collocaltablestyle=((#colheadernums>0)or(notisblank(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)thenrow=coltable:tag('tr')fork,ninipairs(colheadernums)docol=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)])endend--- Main columns ---row=coltable:tag('tr'):css('vertical-align','top')fork,ninipairs(colnums)doifk==1andisblank(pargs[andnum('colheader',1)])andisblank(pargs[andnum('colfooter',1)])andisblank(pargs[cfg.arg.fullwidth])thenlocalnopad=inArray({'off','0','0em','0px'},mw.ustring.gsub(pargs[cfg.arg.padding]or'','[;%%]',''))ifnotnopadthenrow:tag('td'):wikitext(' '):css('width',(pargs[cfg.arg.padding]or'5em'))endendcol=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)andpargs[cfg.arg.evencolstyle]orpargs[cfg.arg.oddcolstyle])or'',pargs[andnum('colstyle',n)]or'','width:'..(pargs[andnum('colwidth',n)]orpargs[cfg.arg.colwidth]or'10em')}))localwt=pargs[andnum('col',n)]ifwtandinArray(cfg.keyword.subgroups,wt)thenwt=getSubgroup(pargs,n,wt,cfg.arg.col_and_num)endcol:tag('div'):newline():wikitext(wt):newline()end--- Footer row ---if(#colfooternums>0)thenrow=coltable:tag('tr')fork,ninipairs(colfooternums)docol=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)])endend-- assign table to list1targs[andnum('list',1)]=tostring(coltable)ifisblank(pargs[andnum('colheader',1)])andisblank(pargs[andnum('col',1)])andisblank(pargs[andnum('colfooter',1)])thentargs[andnum('list',1)]=targs[andnum('list',1)]..cfg.category.without_first_colend-- Other parameterstargs[cfg.arg.border]=pargs[cfg.arg.border]orpargs[1]targs[cfg.arg.evenodd]=(notisblank(pargs[cfg.arg.evenodd]))andpargs[cfg.arg.evenodd]orniltargs[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'returnp._navbox(targs)end--p._withColumns-- Template entry pointsfunctionp.navbox(frame,boxtype)localfunctionreadArgs(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]or0)_=_+(args[prefix..cfg.arg.above]and#args[prefix..cfg.arg.above]or0)-- Limit this to 20 as covering 'most' cases (that's a SWAG) and because-- iterator approach won't work herefori=1,20do_=_+(args[prefix..andnum('group',i)]and#args[prefix..andnum('group',i)]or0)ifinArray(cfg.keyword.subgroups,args[prefix..andnum('list',i)])thenfor_,vinipairs(cfg.arg.subgroups_and_num)doreadArgs(args,prefix..string.format(v,i).."_")endreadArgs(args,prefix..andnum('col',i).."_")endend_=_+(args[prefix..cfg.arg.below]and#args[prefix..cfg.arg.below]or0)return_endifnotgetArgsthengetArgs=require('Module:Arguments').getArgsendlocalargs=getArgs(frame,{wrappers={cfg.pattern[boxtypeor'navbox']}})args.argHash=readArgs(args,"")args.type=args.typeorcfg.keyword[boxtype]returnp['_navbox'](args)endp[cfg.keyword.with_collapsible_groups]=function(frame)returnp.navbox(frame,'with_collapsible_groups')endp[cfg.keyword.with_columns]=function(frame)returnp.navbox(frame,'with_columns')endreturnp