This Lua module is used on approximately 271,000 pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.
Transclusion count updated automatically (see documentation).
This module depends on the following other modules:
The bulk of the infobox is generated by blocks of numbered parameters: headerX, labelX, dataX, dataXa, dataXb, and dataXc. The following examples demonstrate the order in which these parameters are used.
localcheck_for_unknown_parameters=require("Module:Check for unknown parameters")._checklocalp={}localargs={}localorigArgs={}localroot-- Returns the union of the values of two tables, as a sequence.localfunctionunion(t1,t2)localvals={}fork,vinpairs(t1)dovals[v]=trueendfork,vinpairs(t2)dovals[v]=trueendlocalret={}fork,vinpairs(vals)dotable.insert(ret,k)endreturnretend-- Returns a table containing the numbers of the arguments that exist-- for the specified prefix. For example, if the prefix was 'data', and-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.localfunctiongetArgNums(prefix,suffix)localnums={}fork,vinpairs(args)dolocalnum=tostring(k):match('^'..prefix..'([0-9]%d*)'..suffix..'$')ifnumthentable.insert(nums,tonumber(num))endendtable.sort(nums)returnnumsend-- Adds a row to the infobox, with either a header cell-- or a label/data cell combination.localfunctionaddRow(rowArgs)ifrowArgs.headerthenroot:tag('tr'):addClass(rowArgs.rowclass):cssText(rowArgs.rowstyle):tag('th'):attr('colspan','4'):addClass('infobox-header'):addClass(rowArgs.class):addClass(args.headerclass)-- @deprecated next; target .infobox-<name> .infobox-header:cssText(args.headerstyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num..'h']):wikitext(rowArgs.header)elseifrowArgs.labelthenifrowArgs.datathenlocalrow=root:tag('tr')row:addClass(rowArgs.rowclass)row:cssText(rowArgs.rowstyle)row:tag('th'):attr('scope','row'):addClass('infobox-label'):cssText(args.labelstyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num..'l']):wikitext(rowArgs.label):done()localdataCell=row:tag('td')dataCell:attr('colspan','3'):addClass('infobox-data'):addClass(rowArgs.class)-- @deprecated next; target .infobox-<name> .infobox-data:cssText(rowArgs.datastyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num]):newline():wikitext(rowArgs.data)elseifrowArgs.dataaorrowArgs.databorrowArgs.datacthenlocalrow=root:tag('tr')row:addClass(rowArgs.rowclass)row:cssText(rowArgs.rowstyle)row:tag('th'):attr('scope','row'):addClass('infobox-label'):cssText(args.labelstyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num..'l']):wikitext(rowArgs.label):done()localdataCella=row:tag('td')dataCella:addClass('infobox-data infobox-data-a'):addClass(rowArgs.classa)-- @deprecated next; target .infobox-<name> .infobox-data-a:cssText(rowArgs.dataastyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num..'a']):newline():wikitext(rowArgs.dataa)ifrowArgs.renderbthenlocaldataCellb=row:tag('td')dataCellb:addClass('infobox-data infobox-data-b'):addClass(rowArgs.classb)-- @deprecated next; target .infobox-<name> .infobox-data-b:cssText(rowArgs.databstyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num..'b']):newline():wikitext(rowArgs.datab)endifrowArgs.rendercthenlocaldataCellc=row:tag('td')dataCellc:addClass('infobox-data infobox-data-c'):addClass(rowArgs.classc)-- @deprecated next; target .infobox-<name> .infobox-data-c:cssText(rowArgs.datacstyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num..'c']):newline():wikitext(rowArgs.datac)endendelseifrowArgs.datathenlocalrow=root:tag('tr')row:addClass(rowArgs.rowclass)row:cssText(rowArgs.rowstyle)localdataCell=row:tag('td')dataCell:attr('colspan','4'):addClass('infobox-full-data'):addClass(rowArgs.class)-- @deprecated next; target .infobox-<name> .infobox-full-data:cssText(rowArgs.datastyle):cssText(rowArgs.rowcellstyle):cssText(args.extracellstyles[rowArgs.num]):newline():wikitext(rowArgs.data)endendlocalfunctionrenderTitle()ifnotargs.titlethenreturnendroot:tag('caption'):addClass('infobox-title'):addClass(args.titleclass)-- @deprecated next; target .infobox-<name> .infobox-title:cssText(args.titlestyle):wikitext(args.title)endlocalfunctionrenderAboveRow()ifnotargs.abovethenreturnendroot:tag('tr'):tag('th'):attr('colspan','4'):addClass('infobox-above'):addClass(args.aboveclass)-- @deprecated next; target .infobox-<name> .infobox-above:cssText(args.abovestyle):wikitext(args.above)endlocalfunctionrenderBelowRow()ifnotargs.belowthenreturnendroot:tag('tr'):tag('td'):attr('colspan','4'):addClass('infobox-below'):addClass(args.belowclass)-- @deprecated next; target .infobox-<name> .infobox-below:cssText(args.belowstyle):newline():wikitext(args.below)endlocalfunctionaddSubheaderRow(subheaderArgs)ifsubheaderArgs.datathenlocalrow=root:tag('tr')row:addClass(subheaderArgs.rowclass)localdataCell=row:tag('td')dataCell:attr('colspan','4'):addClass('infobox-subheader'):addClass(subheaderArgs.class):cssText(subheaderArgs.datastyle):cssText(subheaderArgs.rowcellstyle):newline():wikitext(subheaderArgs.data)endendlocalfunctionrenderSubheaders()ifargs.subheaderthenargs.subheader1=args.subheaderendifargs.subheaderrowclassthenargs.subheaderrowclass1=args.subheaderrowclassendlocalsubheadernums=getArgNums('subheader','')fork,numinipairs(subheadernums)doaddSubheaderRow({data=args['subheader'..tostring(num)],-- @deprecated next; target .infobox-<name> .infobox-subheaderdatastyle=args.subheaderstyle,rowcellstyle=args['subheaderstyle'..tostring(num)],class=args.subheaderclass,rowclass=args['subheaderrowclass'..tostring(num)]})endendlocalfunctionaddImageRow(imageArgs)ifimageArgs.datathenlocalrow=root:tag('tr')row:addClass(imageArgs.rowclass)localdataCell=row:tag('td')dataCell:attr('colspan','4'):addClass('infobox-image'):addClass(imageArgs.class):cssText(imageArgs.datastyle):newline():wikitext(imageArgs.data)endendlocalfunctionrenderImages()ifargs.imagethenargs.image1=args.imageendifargs.captionthenargs.caption1=args.captionendlocalimagenums=getArgNums('image','')fork,numinipairs(imagenums)dolocalcaption=args['caption'..tostring(num)]localdata=mw.html.create():wikitext(args['image'..tostring(num)])ifcaptionthendata:tag('div'):addClass('infobox-caption')-- @deprecated next; target .infobox-<name> .infobox-caption:cssText(args.captionstyle):wikitext(caption)endaddImageRow({data=tostring(data),-- @deprecated next; target .infobox-<name> .infobox-imagedatastyle=args.imagestyle,class=args.imageclass,rowclass=args['imagerowclass'..tostring(num)]})endend-- Gets the union of the header and data argument numbers,-- and renders them all in orderlocalfunctionrenderRows()localrownums=union(getArgNums('header',''),getArgNums('data','[abc]?'))localdatab_count=#(getArgNums('data','b'))localdatac_count=#(getArgNums('data','c'))table.sort(rownums)fork,numinipairs(rownums)doaddRow({num=tostring(num),renderb=datab_count>0,renderc=datac_count>0,header=args['header'..tostring(num)],label=args['label'..tostring(num)],data=args['data'..tostring(num)],datastyle=args.datastyle,class=args['class'..tostring(num)],dataa=args['data'..tostring(num)..'a'],dataastyle=args.datastylea,classa=args['class'..tostring(num)..'a'],datab=args['data'..tostring(num)..'b'],databstyle=args.datastyleb,classb=args['class'..tostring(num)..'b'],datac=args['data'..tostring(num)..'c'],datacstyle=args.datastylec,classc=args['class'..tostring(num)..'c'],rowclass=args['rowclass'..tostring(num)],-- @deprecated next; target .infobox-<name> rowclassrowstyle=args['rowstyle'..tostring(num)],rowcellstyle=args['rowcellstyle'..tostring(num)],})endendlocalfunctionrenderNavBar()ifnotargs.namethenreturnendroot:tag('tr'):tag('td'):attr('colspan','4'):addClass('infobox-navbar'):wikitext(require('Module:Navbar')._navbar{args.name,mini=1,})endlocalfunctionrenderItalicTitle()localitalicTitle=args['italic title']andmw.ustring.lower(args['italic title'])ifitalicTitle==''oritalicTitle=='force'oritalicTitle=='yes'thenroot:wikitext(mw.getCurrentFrame():expandTemplate({title='italic title'}))endend-- Render tracking categories. args.decat == turns off tracking categories.localfunctionrenderTrackingCategories()localtitle=mw.title.getCurrentTitle()ifargs.decat=='yes'thenreturnendif#(getArgNums('data','[abc]?'))==0andtitle.namespace==0thenroot:wikitext('[[Category:Articles using infobox templates with no data rows]]')endroot:wikitext(check_for_unknown_parameters({checkpositional="y",ignoreblank="y",regexp1="header[%d][%d]*",regexp2="label[%d][%d]*",regexp3="data[%d][%d]*[abc]?",regexp4="class[%d][%d]*[abc]?",regexp5="rowclass[%d][%d]*",regexp6="rowstyle[%d][%d]*",regexp7="rowcellstyle[%d][%d]*",unknown="[[Category:Pages using infobox3cols with undocumented parameters|_VALUE_"..title.text.."]]","above","aboveclass","aboverowclass","abovestyle","below","belowclass","belowrowclass","belowstyle","bodyclass","bodystyle","caption","caption1","caption2","captionstyle","child","datastyle","datastylea","datastyleb","datastylec","extracellstyles","headerstyle","image","image1","image2","imageclass","imagerowclass1","imagerowclass2","imagestyle","labelstyle","name","subbox","subheader","subheader2","subheaderclass","subheaderrowclass1","subheaderrowclass2","subheaderstyle","templatestyles","title","titleclass","titlestyle",},origArgs))iforigArgs.header0ororigArgs.label0ororigArgs.data0ororigArgs.data0aororigArgs.data0bororigArgs.data0cororigArgs.class0ororigArgs.rowclass0thenroot:wikitext("[[Category:Pages using infobox3cols with header0 or label0 or data0]]")endiftitle.namespace==10andmw.ustring.sub(title.text,1,7)=="Infobox"thenroot:wikitext("[[Category:Infobox templates|"..mw.ustring.sub(title.text,9).."]]")endend--[=[Loads the templatestyles for the infobox.TODO: FINISH loading base templatestyles here rather than inMediaWiki:Common.css. There are 4-5000 pages with 'raw' infobox tables.See [[Mediawiki_talk:Common.css/to_do#Infobox]] and/or come help :).When we do this we should clean up the inline CSS below too.Will have to do some bizarre conversion category like with sidebar.]=]localfunctionloadTemplateStyles()localframe=mw.getCurrentFrame()-- See function descriptionlocalbase_templatestyles=frame:extensionTag{name='templatestyles',args={src='Module:Infobox/styles.css'}}localtemplatestyles=''ifargs['templatestyles']thentemplatestyles=frame:extensionTag{name='templatestyles',args={src=args['templatestyles']}}endlocalchild_templatestyles=''ifargs['child templatestyles']thenchild_templatestyles=frame:extensionTag{name='templatestyles',args={src=args['child templatestyles']}}endlocalgrandchild_templatestyles=''ifargs['grandchild templatestyles']thengrandchild_templatestyles=frame:extensionTag{name='templatestyles',args={src=args['grandchild templatestyles']}}endreturntable.concat({base_templatestyles,-- see function descriptiontemplatestyles,child_templatestyles,grandchild_templatestyles})end-- common functions between the child and non child caseslocalfunctionstructure_infobox_common()renderSubheaders()renderImages()-- preprocessRows()renderRows()renderBelowRow()renderNavBar()renderItalicTitle()-- renderEmptyRowCategories()renderTrackingCategories()-- cleanInfobox()end-- Specify the overall layout of the infobox, with special settings if the-- infobox is used as a 'child' inside another infobox.localfunction_infobox()root=mw.html.create('table')root:addClass((args.child=='yes'orargs.subbox=='yes')and'infobox-subbox'or'infobox'):addClass(args.child=='yes'and'infobox-3cols-child'ornil):addClass(args.bodyclass)-- @deprecated next; target .infobox-<name>:cssText(args.bodystyle)renderTitle()renderAboveRow()structure_infobox_common()returnloadTemplateStyles()..tostring(root)end-- If the argument exists and isn't blank, add it to the argument table.-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.localfunctionpreprocessSingleArg(argName)iforigArgs[argName]andorigArgs[argName]~=''thenargs[argName]=origArgs[argName]endend-- Assign the parameters with the given prefixes to the args table, in order, in-- batches of the step size specified. This is to prevent references etc. from-- appearing in the wrong order. The prefixTable should be an array containing-- tables, each of which has two possible fields, a "prefix" string and a-- "depend" table. The function always parses parameters containing the "prefix"-- string, but only parses parameters in the "depend" table if the prefix-- parameter is present and non-blank.localfunctionpreprocessArgs(prefixTable,step)iftype(prefixTable)~='table'thenerror("Non-table value detected for the prefix table",2)endiftype(step)~='number'thenerror("Invalid step value detected",2)end-- Get arguments without a number suffix, and check for bad input.fori,vinipairs(prefixTable)doiftype(v)~='table'ortype(v.prefix)~="string"or(v.dependandtype(v.depend)~='table')thenerror('Invalid input detected to preprocessArgs prefix table',2)endpreprocessSingleArg(v.prefix)-- Only parse the depend parameter if the prefix parameter is present-- and not blank.ifargs[v.prefix]andv.dependthenforj,dependValueinipairs(v.depend)doiftype(dependValue)~='string'thenerror('Invalid "depend" parameter value detected in preprocessArgs')endpreprocessSingleArg(dependValue)endendend-- Get arguments with number suffixes.locala=0-- Counter variable.localmoreArgumentsExist=truewhilemoreArgumentsExist==truedomoreArgumentsExist=falsefori=a,a+step-1doforj,vinipairs(prefixTable)dolocalprefixArgName=v.prefix..tostring(i)..(v.suffixor'')iforigArgs[prefixArgName]then-- Do another loop if any arguments are found, even blank ones.moreArgumentsExist=truepreprocessSingleArg(prefixArgName)end-- Process the depend table if the prefix argument is present-- and not blank, or we are processing "prefix1" and "prefix" is-- present and not blank, and if the depend table is present.ifv.dependand(args[prefixArgName]or(i==1andargs[v.prefix]))thenforj,dependValueinipairs(v.depend)dolocaldependArgName=dependValue..tostring(i)..(v.dependsuffixor'')preprocessSingleArg(dependArgName)endendendenda=a+stependend-- Parse the data parameters in the same order that the old {{infobox}} did, so-- that references etc. will display in the expected places. Parameters that-- depend on another parameter are only processed if that parameter is present,-- to avoid phantom references appearing in article reference lists.localfunctionparseDataParameters()preprocessSingleArg('child')preprocessSingleArg('bodyclass')preprocessSingleArg('subbox')preprocessSingleArg('bodystyle')preprocessSingleArg('title')preprocessSingleArg('titleclass')preprocessSingleArg('titlestyle')preprocessSingleArg('above')preprocessSingleArg('aboveclass')preprocessSingleArg('abovestyle')preprocessArgs({{prefix='subheader',depend={'subheaderstyle','subheaderrowclass'}}},10)preprocessSingleArg('subheaderstyle')preprocessSingleArg('subheaderclass')preprocessSingleArg('image')preprocessSingleArg('caption')preprocessArgs({{prefix='image',depend={'caption','imagerowclass'}}},10)preprocessSingleArg('captionstyle')preprocessSingleArg('imagestyle')preprocessSingleArg('imageclass')preprocessArgs({{prefix='header'},{prefix='data',depend={'label'}},{prefix='data',suffix='a',depend={'label'}},{prefix='data',suffix='a'},{prefix='data',suffix='b',depend={'label'}},{prefix='data',suffix='b'},{prefix='data',suffix='c',depend={'label'}},{prefix='data',suffix='c'},{prefix='rowclass'},{prefix='rowstyle'},{prefix='rowcellstyle'},{prefix='class'}},50)preprocessSingleArg('headerclass')preprocessSingleArg('headerstyle')preprocessSingleArg('labelstyle')preprocessSingleArg('datastyle')preprocessSingleArg('datastylea')preprocessSingleArg('datastyleb')preprocessSingleArg('datastylec')preprocessSingleArg('below')preprocessSingleArg('belowclass')preprocessSingleArg('belowstyle')preprocessSingleArg('name')-- different behaviour for italics if blank or absentargs['italic title']=origArgs['italic title']preprocessSingleArg('decat')preprocessSingleArg('templatestyles')preprocessSingleArg('child templatestyles')preprocessSingleArg('grandchild templatestyles')args['extracellstyles']={}forlineinmw.text.gsplit(origArgs['extracellstyles']or'','\n')dolocalequals=line:find('=')ifequalsthenforiinmw.text.gsplit(line:sub(1,equals-1),'%s*,%s*')doargs.extracellstyles[i]=line:sub(equals+1)endendendend-- If called via #invoke, use the args passed into the invoking template.-- Otherwise, for testing purposes, assume args are being passed directly in.functionp.infobox(frame)ifframe==mw.getCurrentFrame()thenorigArgs=frame:getParent().argselseorigArgs=frameendparseDataParameters()return_infobox()end-- For calling via #invoke within a templatefunctionp.infoboxTemplate(frame,extra_args)origArgs=extra_argsor{}fork,vinpairs(frame.args)doorigArgs[k]=mw.text.trim(v)endparseDataParameters()return_infobox()end-- Shortcut for making child infoboxes via #invoke.functionp.child(frame)returnp.infoboxTemplate(frame,{child="yes"})endreturnp