Modul:Infobox
Penampilan
![]() | Halaman ini punya modul Lua digunakan padaanggaran 3,310,000 laman, atau lebih kurang 301% dari semua laman. Untuk mengelakkan gangguan besar-besaran dan muatan pelayan, sebarang perubahan sepatutnya diuji pada modul punya subhalamankotak pasirataulaman uji kaji,atau padamodule sandboxanda. Perubahan yang sudah diuji boleh ditambah pada laman ini dalam suntingan tunggal. Pertimbang untuk membincang perubahan padalaman perbincangansebelum melaksanakannya. |
![]() | Modul initertakluk kepada perlindungan laman.Ia merupakan sebuahmodul yang sangat terlihatdengan penggunaan pada bilangan laman yang sangat tinggi, atau kerapditukar ganti.Disebabkan sebarang laku musnah atau kesilapan pada laman ini akan memberi kesan besar pada banyak laman, serta suntingan yang sedikit pun boleh menyebabkan bebanan besar pada pelayan, ia telahdilindungidaripada sebarang suntingan. |
![]() | Modul ini bergantung pada modul-modul lain: |
![]() | This module usesTemplateStyles: |
Module:Infoboxis amodulethat implements the {{Infobox}} template. Please see the template page for usage instructions.
Tracking categories[sunting sumber]
- Kategori:Pages using infobox templates with ignored data cells(38)
- Kategori:Articles using infobox templates with no data rows(550)
- Kategori:Pages using embedded infobox templates with the title parameter(160)
localp={}
localargs={}
localorigArgs={}
localroot
localempty_row_categories={}
localcategory_in_empty_row_pattern='%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]'
localhas_rows=false
locallists={
plainlist_t={
patterns={
'^plainlist$',
'%splainlist$',
'^plainlist%s',
'%splainlist%s'
},
found=false,
styles='Plainlist/styles.css'
},
hlist_t={
patterns={
'^hlist$',
'%shlist$',
'^hlist%s',
'%shlist%s'
},
found=false,
styles='Hlist/styles.css'
}
}
localfunctionhas_list_class(args_to_check)
for_,listinpairs(lists)do
ifnotlist.foundthen
for_,arginpairs(args_to_check)do
for_,patterninipairs(list.patterns)do
ifmw.ustring.find(argor'',pattern)then
list.found=true
break
end
end
iflist.foundthenbreakend
end
end
end
end
localfunctionfixChildBoxes(sval,tt)
localfunctionnotempty(s)returnsands:match('%S')end
ifnotempty(sval)then
localmarker='<span class=special_infobox_marker>'
locals=sval
-- start moving templatestyles and categories inside of table rows
localslast=''
whileslast~=sdo
slast=s
s=mw.ustring.gsub(s,'(</[Tt][Rr]%s*>%s*)(%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*%]%])','%2%1')
s=mw.ustring.gsub(s,'(</[Tt][Rr]%s*>%s*)(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)','%2%1')
end
-- end moving templatestyles and categories inside of table rows
s=mw.ustring.gsub(s,'(<%s*[Tt][Rr])',marker..'%1')
s=mw.ustring.gsub(s,'(</[Tt][Rr]%s*>)','%1'..marker)
ifs:match(marker)then
s=mw.ustring.gsub(s,marker..'%s*'..marker,'')
s=mw.ustring.gsub(s,'([\r\n]|-[^\r\n]*[\r\n])%s*'..marker,'%1')
s=mw.ustring.gsub(s,marker..'%s*([\r\n]|-)','%1')
s=mw.ustring.gsub(s,'(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)'..marker,'%1')
s=mw.ustring.gsub(s,'(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)'..marker,'%1')
s=mw.ustring.gsub(s,'^(%{|[^\r\n]*[\r\n]%s*)'..marker,'%1')
s=mw.ustring.gsub(s,'([\r\n]%{|[^\r\n]*[\r\n]%s*)'..marker,'%1')
s=mw.ustring.gsub(s,marker..'(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)','%1')
s=mw.ustring.gsub(s,marker..'(%s*\n|%})','%1')
end
ifs:match(marker)then
localsubcells=mw.text.split(s,marker)
s=''
fork=1,#subcellsdo
ifk==1then
s=s..subcells[k]..'</'..tt..'></tr>'
elseifk==#subcellsthen
localrowstyle=' style= "display:none" '
ifnotempty(subcells[k])thenrowstyle=''end
s=s..'<tr'..rowstyle..'><'..tt..' colspan=2>\n'..
subcells[k]
elseifnotempty(subcells[k])then
if(k%2)==0then
s=s..subcells[k]
else
s=s..'<tr><'..tt..' colspan=2>\n'..
subcells[k]..'</'..tt..'></tr>'
end
end
end
end
-- the next two lines add a newline at the end of lists for the PHP parser
-- [[Special:Diff/849054481]]
-- remove when [[:phab:T191516]] is fixed or OBE
s=mw.ustring.gsub(s,'([\r\n][%*#;:][^\r\n]*)$','%1\n')
s=mw.ustring.gsub(s,'^([%*#;:][^\r\n]*)$','%1\n')
s=mw.ustring.gsub(s,'^([%*#;:])','\n%1')
s=mw.ustring.gsub(s,'^(%{%|)','\n%1')
returns
else
returnsval
end
end
-- Cleans empty tables
localfunctioncleanInfobox()
root=tostring(root)
ifhas_rows==falsethen
root=mw.ustring.gsub(root,'<table[^<>]*>%s*</table>','')
end
end
-- Returns the union of the values of two tables, as a sequence.
localfunctionunion(t1,t2)
localvals={}
fork,vinpairs(t1)do
vals[v]=true
end
fork,vinpairs(t2)do
vals[v]=true
end
localret={}
fork,vinpairs(vals)do
table.insert(ret,k)
end
returnret
end
-- 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)
localnums={}
fork,vinpairs(args)do
localnum=tostring(k):match('^'..prefix..'([1-9]%d*)$')
ifnumthentable.insert(nums,tonumber(num))end
end
table.sort(nums)
returnnums
end
-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
localfunctionaddRow(rowArgs)
ifrowArgs.headerandrowArgs.header~='_BLANK_'then
has_rows=true
has_list_class({rowArgs.rowclass,rowArgs.class,args.headerclass})
root
:tag('tr')
:addClass(rowArgs.rowclass)
:cssText(rowArgs.rowstyle)
:tag('th')
:attr('colspan','2')
:addClass('infobox-header')
:addClass(rowArgs.class)
:addClass(args.headerclass)
-- @deprecated next; target.infobox-<name>.infobox-header
:cssText(args.headerstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.header,'th'))
ifrowArgs.datathen
root:wikitext(
'[[Category:Pages using infobox templates with ignored data cells]]'
)
end
elseifrowArgs.dataandrowArgs.data:gsub(category_in_empty_row_pattern,''):match('^%S')then
has_rows=true
has_list_class({rowArgs.rowclass,rowArgs.class})
localrow=root:tag('tr')
row:addClass(rowArgs.rowclass)
row:cssText(rowArgs.rowstyle)
ifrowArgs.labelthen
row
:tag('th')
:attr('scope','row')
:addClass('infobox-label')
-- @deprecated next; target.infobox-<name>.infobox-label
:cssText(args.labelstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(rowArgs.label)
:done()
end
localdataCell=row:tag('td')
dataCell
:attr('colspan',notrowArgs.labeland'2'ornil)
:addClass(notrowArgs.labeland'infobox-full-data'or'infobox-data')
:addClass(rowArgs.class)
-- @deprecated next; target.infobox-<name>.infobox(-full)-data
:cssText(rowArgs.datastyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.data,'td'))
else
table.insert(empty_row_categories,rowArgs.dataor'')
end
end
localfunctionrenderTitle()
ifnotargs.titlethenreturnend
has_rows=true
has_list_class({args.titleclass})
root
:tag('caption')
:addClass('infobox-title')
:addClass(args.titleclass)
-- @deprecated next; target.infobox-<name>.infobox-title
:cssText(args.titlestyle)
:wikitext(args.title)
end
localfunctionrenderAboveRow()
ifnotargs.abovethenreturnend
has_rows=true
has_list_class({args.aboveclass})
root
:tag('tr')
:tag('th')
:attr('colspan','2')
:addClass('infobox-above')
:addClass(args.aboveclass)
-- @deprecated next; target.infobox-<name>.infobox-above
:cssText(args.abovestyle)
:wikitext(fixChildBoxes(args.above,'th'))
end
localfunctionrenderBelowRow()
ifnotargs.belowthenreturnend
has_rows=true
has_list_class({args.belowclass})
root
:tag('tr')
:tag('td')
:attr('colspan','2')
:addClass('infobox-below')
:addClass(args.belowclass)
-- @deprecated next; target.infobox-<name>.infobox-below
:cssText(args.belowstyle)
:wikitext(fixChildBoxes(args.below,'td'))
end
localfunctionaddSubheaderRow(subheaderArgs)
ifsubheaderArgs.dataand
subheaderArgs.data:gsub(category_in_empty_row_pattern,''):match('^%S')then
has_rows=true
has_list_class({subheaderArgs.rowclass,subheaderArgs.class})
localrow=root:tag('tr')
row:addClass(subheaderArgs.rowclass)
localdataCell=row:tag('td')
dataCell
:attr('colspan','2')
:addClass('infobox-subheader')
:addClass(subheaderArgs.class)
:cssText(subheaderArgs.datastyle)
:cssText(subheaderArgs.rowcellstyle)
:wikitext(fixChildBoxes(subheaderArgs.data,'td'))
else
table.insert(empty_row_categories,subheaderArgs.dataor'')
end
end
localfunctionrenderSubheaders()
ifargs.subheaderthen
args.subheader1=args.subheader
end
ifargs.subheaderrowclassthen
args.subheaderrowclass1=args.subheaderrowclass
end
localsubheadernums=getArgNums('subheader')
fork,numinipairs(subheadernums)do
addSubheaderRow({
data=args['subheader'..tostring(num)],
-- @deprecated next; target.infobox-<name>.infobox-subheader
datastyle=args.subheaderstyle,
rowcellstyle=args['subheaderstyle'..tostring(num)],
class=args.subheaderclass,
rowclass=args['subheaderrowclass'..tostring(num)]
})
end
end
localfunctionaddImageRow(imageArgs)
ifimageArgs.dataand
imageArgs.data:gsub(category_in_empty_row_pattern,''):match('^%S')then
has_rows=true
has_list_class({imageArgs.rowclass,imageArgs.class})
localrow=root:tag('tr')
row:addClass(imageArgs.rowclass)
localdataCell=row:tag('td')
dataCell
:attr('colspan','2')
:addClass('infobox-image')
:addClass(imageArgs.class)
:cssText(imageArgs.datastyle)
:wikitext(fixChildBoxes(imageArgs.data,'td'))
else
table.insert(empty_row_categories,imageArgs.dataor'')
end
end
localfunctionrenderImages()
ifargs.imagethen
args.image1=args.image
end
ifargs.captionthen
args.caption1=args.caption
end
localimagenums=getArgNums('image')
fork,numinipairs(imagenums)do
localcaption=args['caption'..tostring(num)]
localdata=mw.html.create():wikitext(args['image'..tostring(num)])
ifcaptionthen
data
:tag('div')
:addClass('infobox-caption')
-- @deprecated next; target.infobox-<name>.infobox-caption
:cssText(args.captionstyle)
:wikitext(caption)
end
addImageRow({
data=tostring(data),
-- @deprecated next; target.infobox-<name>.infobox-image
datastyle=args.imagestyle,
class=args.imageclass,
rowclass=args['imagerowclass'..tostring(num)]
})
end
end
-- When autoheaders are turned on, preprocesses the rows
localfunctionpreprocessRows()
ifnotargs.autoheadersthenreturnend
localrownums=union(getArgNums('header'),getArgNums('data'))
table.sort(rownums)
locallastheader
fork,numinipairs(rownums)do
ifargs['header'..tostring(num)]then
iflastheaderthen
args['header'..tostring(lastheader)]=nil
end
lastheader=num
elseifargs['data'..tostring(num)]and
args['data'..tostring(num)]:gsub(
category_in_empty_row_pattern,''
):match('^%S')then
localdata=args['data'..tostring(num)]
ifdata:gsub(category_in_empty_row_pattern,''):match('%S')then
lastheader=nil
end
end
end
iflastheaderthen
args['header'..tostring(lastheader)]=nil
end
end
-- Gets the union of the header and data argument numbers,
-- and renders them all in order
localfunctionrenderRows()
localrownums=union(getArgNums('header'),getArgNums('data'))
table.sort(rownums)
fork,numinipairs(rownums)do
addRow({
header=args['header'..tostring(num)],
label=args['label'..tostring(num)],
data=args['data'..tostring(num)],
datastyle=args.datastyle,
class=args['class'..tostring(num)],
rowclass=args['rowclass'..tostring(num)],
-- @deprecated next; target.infobox-<name> rowclass
rowstyle=args['rowstyle'..tostring(num)],
rowcellstyle=args['rowcellstyle'..tostring(num)]
})
end
end
localfunctionrenderNavBar()
ifnotargs.namethenreturnend
has_rows=true
root
:tag('tr')
:tag('td')
:attr('colspan','2')
:addClass('infobox-navbar')
:wikitext(require('Module:Navbar')._navbar{
args.name,
mini=1,
})
end
localfunctionrenderItalicTitle()
localitalicTitle=args['italic title']andmw.ustring.lower(args['italic title'])
ifitalicTitle==''oritalicTitle=='force'oritalicTitle=='yes'then
root:wikitext(require('Module:Italic title')._main({}))
end
end
-- Categories in otherwise empty rows are collected in empty_row_categories.
-- This function adds them to the module output. It is not affected by
-- args.decat because this module should not prevent module-external categories
-- from rendering.
localfunctionrenderEmptyRowCategories()
for_,sinipairs(empty_row_categories)do
root:wikitext(s)
end
end
-- Render tracking categories. args.decat == turns off tracking categories.
localfunctionrenderTrackingCategories()
ifargs.decat=='yes'thenreturnend
ifargs.child=='yes'then
ifargs.titlethen
root:wikitext(
'[[Category:Pages using embedded infobox templates with the title parameter]]'
)
end
elseif#(getArgNums('data'))==0andmw.title.getCurrentTitle().namespace==0then
root:wikitext('[[Category:Articles using infobox templates with no data rows]]')
end
end
--[=[
Loads the templatestyles for the infobox.
TODO: FINISH loading base templatestyles here rather than in
MediaWiki: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()
localhlist_templatestyles=''
iflists.hlist_t.foundthen
hlist_templatestyles=frame:extensionTag{
name='templatestyles',args={src=lists.hlist_t.styles}
}
end
localplainlist_templatestyles=''
iflists.plainlist_t.foundthen
plainlist_templatestyles=frame:extensionTag{
name='templatestyles',args={src=lists.plainlist_t.styles}
}
end
-- See function description
localbase_templatestyles=frame:extensionTag{
name='templatestyles',args={src='Module:Infobox/styles.css'}
}
localtemplatestyles=''
ifargs['templatestyles']then
templatestyles=frame:extensionTag{
name='templatestyles',args={src=args['templatestyles']}
}
end
localchild_templatestyles=''
ifargs['child templatestyles']then
child_templatestyles=frame:extensionTag{
name='templatestyles',args={src=args['child templatestyles']}
}
end
localgrandchild_templatestyles=''
ifargs['grandchild templatestyles']then
grandchild_templatestyles=frame:extensionTag{
name='templatestyles',args={src=args['grandchild templatestyles']}
}
end
returntable.concat({
-- hlist -> plainlist -> base is best-effort to preserve old Common.css ordering.
-- this ordering is not a guarantee because the rows of interest invoking
-- each class may not be on a specific page
hlist_templatestyles,
plainlist_templatestyles,
base_templatestyles,
templatestyles,
child_templatestyles,
grandchild_templatestyles
})
end
-- common functions between the child and non child cases
localfunctionstructure_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()
ifargs.child~='yes'then
root=mw.html.create('table')
root
:addClass(args.subbox=='yes'and'infobox-subbox'or'infobox')
:addClass(args.bodyclass)
-- @deprecated next; target.infobox-<name>
:cssText(args.bodystyle)
has_list_class({args.bodyclass})
renderTitle()
renderAboveRow()
else
root=mw.html.create()
root
:wikitext(args.title)
end
structure_infobox_common()
returnloadTemplateStyles()..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]~=''then
args[argName]=origArgs[argName]
end
end
-- 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'then
error("Non-table value detected for the prefix table",2)
end
iftype(step)~='number'then
error("Invalid step value detected",2)
end
-- Get arguments without a number suffix, and check for bad input.
fori,vinipairs(prefixTable)do
iftype(v)~='table'ortype(v.prefix)~="string"or
(v.dependandtype(v.depend)~='table')then
error('Invalid input detected to preprocessArgs prefix table',2)
end
preprocessSingleArg(v.prefix)
-- Only parse the depend parameter if the prefix parameter is present
-- and not blank.
ifargs[v.prefix]andv.dependthen
forj,dependValueinipairs(v.depend)do
iftype(dependValue)~='string'then
error('Invalid "depend" parameter value detected in preprocessArgs')
end
preprocessSingleArg(dependValue)
end
end
end
-- Get arguments with number suffixes.
locala=1-- Counter variable.
localmoreArgumentsExist=true
whilemoreArgumentsExist==truedo
moreArgumentsExist=false
fori=a,a+step-1do
forj,vinipairs(prefixTable)do
localprefixArgName=v.prefix..tostring(i)
iforigArgs[prefixArgName]then
-- Do another loop if any arguments are found, even blank ones.
moreArgumentsExist=true
preprocessSingleArg(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]))then
forj,dependValueinipairs(v.depend)do
localdependArgName=dependValue..tostring(i)
preprocessSingleArg(dependArgName)
end
end
end
end
a=a+step
end
end
-- 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('autoheaders')
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')
preprocessArgs({
{prefix='image',depend={'caption','imagerowclass'}}
},10)
preprocessSingleArg('captionstyle')
preprocessSingleArg('imagestyle')
preprocessSingleArg('imageclass')
preprocessArgs({
{prefix='header'},
{prefix='data',depend={'label'}},
{prefix='rowclass'},
{prefix='rowstyle'},
{prefix='rowcellstyle'},
{prefix='class'}
},50)
preprocessSingleArg('headerclass')
preprocessSingleArg('headerstyle')
preprocessSingleArg('labelstyle')
preprocessSingleArg('datastyle')
preprocessSingleArg('below')
preprocessSingleArg('belowclass')
preprocessSingleArg('belowstyle')
preprocessSingleArg('name')
-- different behaviour for italics if blank or absent
args['italic title']=origArgs['italic title']
preprocessSingleArg('decat')
preprocessSingleArg('templatestyles')
preprocessSingleArg('child templatestyles')
preprocessSingleArg('grandchild templatestyles')
end
-- 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()then
origArgs=frame:getParent().args
else
origArgs=frame
end
parseDataParameters()
return_infobox()
end
-- For calling via #invoke within a template
functionp.infoboxTemplate(frame)
origArgs={}
fork,vinpairs(frame.args)doorigArgs[k]=mw.text.trim(v)end
parseDataParameters()
return_infobox()
end
returnp