Модуль:Navbox

-- lua port of [[Template:Navbox]]-- by DennouNeko-- == Helper functions ==--[[ libraries ]]localcommon=require("Module:Common")localstyle=require("Module:Styles")localcolors=style.main_colorsifmw.text==nilthenmw.text=require("Module:MW.text")end--[[ Retrieve a full list of 'list#', 'list#style', 'group#' and 'group#style' arguments as a table of objects with 'index', 'list', 'liststyle', 'group' and 'groupstyle' fields, where 'index' is the number in 'list#' argument name. Only 'list' and 'index' are always defined. Elements that weren't specified will be empty. If 'list#' wasn't defined, rest of elements for that given index will be ignored. Key of argument matches the number in arguments name. ]]localfunctionscan_lists(frame)localidx={}locallist={}localgroup={}localliststyle={}localgroupstyle={}localret={}locals,e,tfork,vinframe:argumentPairs()do-- accept only parameters without leading zeross,e,t=string.find(k,'^group([1-9]%d*)style$')ifs~=nilthengroupstyle[tonumber(t)]=vends,e,t=string.find(k,'^list([1-9]%d*)style$')ifs~=nilthenliststyle[tonumber(t)]=vends,e,t=string.find(k,'^group([1-9]%d*)$')ifs~=nilthengroup[tonumber(t)]=vends,e,t=string.find(k,'^list([1-9]%d*)$')ifs~=nilthenlist[tonumber(t)]=vidx[#idx+1]=tonumber(t)endendtable.sort(idx)fork,vinpairs(idx)dolocaltmp={}tmp['index']=vtmp['list']=list[v]ifcommon.isset(group[v])thentmp['group']=group[v]endifcommon.isset(liststyle[v])thentmp['liststyle']=liststyle[v]endifcommon.isset(groupstyle[v])thentmp['groupstyle']=groupstyle[v]endret[#ret+1]=tmpendreturnretend-- == Functions generating the document elements ==--[[ Generates the beginning of box, based on specified 'ttype' and 'border'. ]]localfunctionstart_box(frame,border,ttype)localret={}ifborder=="subgroup"orborder=="child"then-- since we're in a cell of parent navbox, we have to close its <div> elementret[#ret+1]='</div>'elseifborder=="none"then-- nothing to doelse-- new, independent navbox - create a frame around itret[#ret+1]='<table class="navbox'ifcommon.isset(frame.args['bodyclass'])thenret[#ret+1]=" "..frame.args['bodyclass']endret[#ret+1]='" cellspacing="0" style="'ifcommon.isset(colors[ttype])thenret[#ret+1]='background:'..colors[ttype]['background']..';'end-- ret[#ret+1] = 'border:1px solid #aaa; padding:1px;width:100%;vertical-align:middle;margin:auto;clear:both;font-size:88%;text-align:center;'style.add(ret,frame.args['bodystyle'])style.add(ret,frame.args['style'])ret[#ret+1]='"><tr><td style="padding: 2px;">'end-- The actual navbox table starts hereret[#ret+1]='<table cellspacing="0" class="nowraplinks'ifcommon.isset(frame.args['title'])andframe.args['state']~="plain"andframe.args['state']~="off"then--TODO: If there is support for collapsible and autocollapse, swap comments here--ret[#ret+1] = ' collapsible 'ret[#ret+1]=' mw-collapsible 'ifcommon.isset(frame.args['state'])thenret[#ret+1]=frame.args['state']else--ret[#ret+1] = 'autocollapse'ret[#ret+1]='mw-collapsed'endendifborder=="subgroup"orborder=="child"orborder=="none"thenret[#ret+1]=' navbox-subgroup" style="'ifcommon.isset(colors[ttype])thentable.insert(ret,'background:'..colors[ttype]['background']..';')end-- ret[#ret+1] = 'margin:auto;clear:both;font-size:88%;text-align:center;width:100%;vertical-align:middle;'ret[#ret+1]='width: 100%;'style.add(ret,frame.args['bodystyle'])style.add(ret,frame.args['style'])ret[#ret+1]='">'elseret[#ret+1]='" style="width:100%;background:transparent;color:inherit;">'endreturntable.concat(ret)end--[[ Finalizes the box, based on specified 'ttype' and 'border' ]]localfunctionend_box(frame,border,ttype)localret={""}ret[#ret+1]='</table>'ifborder=="subgroup"orborder=="child"then-- open a <div>, since we closed one when starting this child navboxret[#ret+1]='<div>'elseifborder=="none"then-- nothing to doelse-- close the table we started as a frameret[#ret+1]='</td></tr></table>'endreturntable.concat(ret)end--[[ Generates the title row: 'v(iew) • d(iscuss) • e(dit)' + title + '[Expand]'/'[Collapse]' buttons. ]]localfunctionbuild_title(frame,border,ttype)localret={""}ifnotcommon.isset(frame.args['title'])thenreturn''endtable.insert(ret,'<tr>')ifcommon.isset(frame.args['titlegroup'])then-- in case that there's a group for titleret[#ret+1]='<td class="navbox-group" style="'ifcommon.isset(colors[ttype])thenret[#ret+1]='background:'..colors[ttype]['group']..';'endret[#ret+1]='padding-left:1em;padding-right:1em;white-space:nowrap;text-align:right;'style.add(ret,frame.args['basestyle'])style.add(ret,frame.args['groupstyle'])style.add(ret,frame.args['titlegroupstyle'])ret[#ret+1]='">\n'ret[#ret+1]=frame.args['titlegroup']ret[#ret+1]='</td>'ret[#ret+1]='<th style="border-left:2px solid 'ret[#ret+1]=common.cv(common.isset(colors[ttype]),colors[ttype]['background'],'#fdfdfd')ret[#ret+1]=';width:100%;'else-- no group for titletable.insert(ret,'<th style="')endifcommon.isset(colors[ttype])thenret[#ret+1]='background:'..colors[ttype]['title']..';'endret[#ret+1]='text-align:center;'style.add(ret,frame.args['basestyle'])style.add(ret,frame.args['titlestyle'])ret[#ret+1]='"'-- calculate the colspan for titlelocalcs=2-- 2 because each list element with group occupies 2 columnsifcommon.isset(frame.args['imageleft'])thencs=cs+1endifcommon.isset(frame.args['image'])thencs=cs+1endifcommon.isset(frame.args['titlegroup'])thencs=cs-1end-- if there was a titlegroup, it occupies one cell alreadyret[#ret+1]=' colspan = "'..cs..'"'ret[#ret+1]=' class="navbox-title">'-- add navbars and/or padding when neededifframe.args['navbar']=="plain"orframe.args['navbar']=="off"orborder=="subgroup"orborder=="child"orborder=="none"thenifframe.args['navbar']=="off"thenifframe.args['state']=="plain"thenret[#ret+1]='<div style="float:right;width:6em;">&nbsp;</div>'endelseifframe.args['state']~="plain"thenret[#ret+1]='<div style="float:left; width:6em;text-align:left;">&nbsp;</div>'endendelseifframe.args['state']=="plain"thenret[#ret+1]='<div style="float:right;width:6em;">&nbsp;</div>'endret[#ret+1]='<div style="float:left; width:6em;text-align:left;">'ifframe.args['name']~=nilthenlocalargs={}args[#args+1]=frame.args['name']args['mini']='1'-- TODO: Build the navbar without using external template?localq={""}q[#q+1]='text-align:left;'style.add(q,frame.args['basestyle'])style.add(q,frame.args['titlestyle'])q[#q+1]='border:none;'args['fontstyle']=table.concat(q)ret[#ret+1]=frame:expandTemplate{title='Navbar',args=args}elseret[#ret+1]='&nbsp;'ret[#ret+1]='[[Category:Navboxes without name]]'endret[#ret+1]='</div>'end-- the title starts hereret[#ret+1]='<span'ifcommon.isset(frame.args['titleclass'])thenret[#ret+1]=' class="'..frame.args['titleclass']..'"'endret[#ret+1]=' style="font-size:'..common.cv((border=="subgroup"orborder=="child"orborder=="none"),'100%','110%')..';">\n'ret[#ret+1]=frame.args['title']ret[#ret+1]='</span>'ret[#ret+1]='</th></tr>'returntable.concat(ret)end--[[ Generates the 'above' and 'below' rows. Returns the generated row and updated 'sep' value (if separation is going to be needed). ]]localfunctionbuild_above_below(frame,border,ttype,text,rstyle,sep)localret={''}ifcommon.isset(text)thenifsepthen-- if separation is neededtable.insert(ret,'<tr style="height: 2px;"><td></td></tr>')end-- start the 'above' or 'below' rowret[#ret+1]='<tr>'ret[#ret+1]='<td class="navbox-abovebelow" style="'ifcommon.isset(colors[ttype])then-- both above and below share same default color from 'colors' tableret[#ret+1]='background:'..common.cv((border~="subgroup"andborder~="child"),colors[ttype]['above'],colors[ttype]['group'])..';'endret[#ret+1]='padding-left:1em;padding-right:1em;text-align:center;'style.add(ret,frame.args['basestyle'])style.add(ret,rstyle)ret[#ret+1]='"'-- calculate and add the colspan (always full table width)localcs=2ifcommon.isset(frame.args['imageleft'])thencs=cs+1endifcommon.isset(frame.args['image'])thencs=cs+1endret[#ret+1]=' colspan="'..cs..'">\n'-- row contentret[#ret+1]=textret[#ret+1]='</td></tr>'sep=true-- now we're going to need separationendreturntable.concat(ret),sepend--[[ Generates a single row of the list. ]]localfunctionbuild_row(frame,border,ttype,k,group,list,groupstyle,liststyle)localret={""}ifcommon.isset(group)then-- there's a group name for current list, so add a cell for itret[#ret+1]='<td class="navbox-group" style="'ifcommon.isset(colors[ttype])thenret[#ret+1]='background:'..common.cv((border~="subgroup"andborder~="child"),colors[ttype]['group'],colors[ttype]['subgroup'])..';'endret[#ret+1]='padding-left:1em; padding-right:1em; white-space:nowrap; text-align:right;'style.add(ret,frame.args['basestyle'])ifcommon.isset(frame.args['groupwidth'])thenret[#ret+1]='width:'..frame.args['groupwidth']..';'endstyle.add(ret,frame.args['groupstyle'])style.add(ret,groupstyle)ret[#ret+1]='">'ret[#ret+1]='<div style="padding:0;">\n'ret[#ret+1]=groupret[#ret+1]='</div></td>'-- start the content cellret[#ret+1]='<td style="text-align:left;border-left-width:2px;border-left-style:solid;'else-- no group name, start the content alreadyret[#ret+1]='<td colspan=2 style="'end-- a bit tricky, but this works as XORif(frame.args['evenodd']=="swap")~=((k%2)==0)thenifcommon.isset(colors[ttype])thenret[#ret+1]='background:'..colors[ttype]['dark']..';'endelseret[#ret+1]='background:transparent;'endifnotcommon.isset(frame.args['groupwidth'])thenret[#ret+1]='width:100%;'endret[#ret+1]='padding: 0;'style.add(ret,frame.args['liststyle'])style.add(ret,common.cv((frame.args['evenodd']=="swap")~=((k%2)==0),frame.args['evenstyle'],frame.args['oddstyle']))style.add(ret,liststyle)ret[#ret+1]='" class="navbox-list '..common.cv((frame.args['evenodd']=="swap")~=((k%2)==0),'navbox-even','navbox-odd')..'">'-- add the <div> with content (same <div> that child navbox has to close when starting table)ret[#ret+1]='<div style="padding:'ifcommon.isset(frame.args['list'..k..'padding'])thenret[#ret+1]=frame.args['list'..k..'padding']elseifcommon.isset(frame.args['listpadding'])thenret[#ret+1]=frame.args['listpadding']elseret[#ret+1]='0em 0.25em'endret[#ret+1]=';">\n'ret[#ret+1]=listret[#ret+1]='</div></td>'returntable.concat(ret)end--[[ Generates the "body" of table (everything below title) ]]localfunctionbuild_body(frame,border,ttype,lists)localret={}localsep=common.isset(frame.args['title'])-- if there was a title, we have to add separation for first rowlocalimgs=true-- add images if presentlocalirows=common.cv((#lists>0),(2*#lists-1),1)-- aff the 'above' rowret[#ret+1],sep=build_above_below(frame,border,ttype,frame.args['above'],frame.args['abovestyle'],sep)fork,vinpairs(lists)doifsepthen-- add separation if neededret[#ret+1]='<tr style="height: 2px;"><td></td></tr>'endtable.insert(ret,'<tr>')-- add left image (if wasn't added yet and is present)ifimgsthenifcommon.isset(frame.args['imageleft'])thenret[#ret+1]='<td style="width:0%;padding:0px 2px 0px 0px;'style.add(ret,frame.args['imageleftstyle'])ret[#ret+1]='" rowspan="'..irows..'">'..frame.args['imageleft']..'</td>'endend-- add the list contentret[#ret+1]=build_row(frame,border,ttype,v['index'],v['group'],v['list'],v['groupstyle'],v['liststyle'])-- add right image (if wasn't added yet and is present)ifimgsthenifcommon.isset(frame.args['image'])thenret[#ret+1]='<td style="width:0%;padding:0px 0px 0px 2px;'style.add(ret,frame.args['imagestyle'])ret[#ret+1]='" rowspan="'..irows..'">'..frame.args['image']..'</td>'end-- mark that images were added alreadyimgs=falseendret[#ret+1]='</tr>'sep=true-- now the separation is going to be needed for sureendret[#ret+1],sep=build_above_below(frame,border,ttype,frame.args['below'],frame.args['belowstyle'],sep)returntable.concat(ret)end-- == Exported functions ==--[[ Generates and returns the whole navbox table. ]]localfunctionbuildNavbox(frame)localtemplate={}localborder=""localttype=""ifcommon.isset(frame.args['border'])thenborder=frame.args['border']elseifcommon.isset(frame.args[1])thenborder=mw.text.trim(frame.args[1])endifcommon.isset(frame.args['type'])thenttype=frame.args['type']end-- TODO: filtering of border and type values?-- prepare the data firstlocallists=scan_lists(frame)-- build the content template[#template+1]=start_box(frame,border,ttype)template[#template+1]=build_title(frame,border,ttype)template[#template+1]=build_body(frame,border,ttype,lists)template[#template+1]=end_box(frame,border,ttype)returntable.concat(template)end-- [[ Workaround for the "Navbox subgroup" template ]]localfunctionbuildNavboxSubgroup(frame)ifnotcommon.isset(frame.args['border'])thenframe.args['border']='child'end-- TODO: add/modify/remove other params?-- call the main functionreturnbuildNavbox(frame)end--[[ Mostly for debugging, generates and returns a table of sets of colors and the values in cells with colors used as backgrounds. ]]localfunctionbuildColorTable(frame)localret={""}table.insert(ret,'<table class="wikitable" style="text-align: center;">')table.insert(ret,'<caption>List of colors in order from darkest to brigthest one</caption>')table.insert(ret,'<tr><th>"type"</th><th>title</th><th>above, below</th><th>group,<br/>sub-above/below</th><th>sub-group</th><th>dark background</th><th>background</th></tr>')fork,vinpairs(colors)dotable.insert(ret,'<tr>')table.insert(ret,'<td>'..k..'</td>')table.insert(ret,'<td style="background:'..v['title']..'">'..v['title']..'</td>')table.insert(ret,'<td style="background:'..v['above']..'">'..v['above']..'</td>')table.insert(ret,'<td style="background:'..v['group']..'">'..v['group']..'</td>')table.insert(ret,'<td style="background:'..v['subgroup']..'">'..v['subgroup']..'</td>')table.insert(ret,'<td style="background:'..v['dark']..'">'..v['dark']..'</td>')table.insert(ret,'<td style="background:'..v['background']..'">'..v['background']..'</td>')table.insert(ret,'</tr>')endtable.insert(ret,'</table>')returntable.concat(ret)end-- export local functionsreturn{['buildNavbox']=buildNavbox,['buildNavboxTemplate']=function(frame)returnbuildNavbox(frame:getParent())end,-- for wrappers['buildNavboxSubgroup']=buildNavboxSubgroup,['buildNavboxSubgroupTemplate']=function(frame)returnbuildNavboxSubgroup(frame:getParent())end,-- for wrappers['buildColorTable']=buildColorTable}-- [[Category:Lua Scripts|{{PAGENAME}}]]