This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This Lua module is used on approximately 197,000 pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
Usage
{{SAFESUBST:<noinclude />#invoke:Unsubst-infobox||$B=template body|$params=parameters}}
Infoboxes should never be substituted. A trick to avoid that is to make a template substitute to its transcluded form. This module is similar to Module:Unsubst. parameters is a comma-separated list of the names of parameters the invoking infobox template can take.
Parameter list
- $B
- The content of the template, as it would be without the module being used.
- $params
- A comma-separated list of template parameters, without any aliases. There is a bug when including positional parameters like
$params=1
in the template and{{subst:example|a}}
in the article where it will be overwritten like{{subst:example|a|1=}}
. - $aliases
- A comma-separated list of parameter replacements, in the format
old1>new1,old2>new2
. There is a bug when including positional parameters like|$aliases=2>details|$params=details
in the template and{{subst:example|abc|def|ghi}}
in the article where there is an inconsistency that causes data to be lost like{{subst:example|abc|details=def}}
- $set3
- Usually a shorter list of parameters, comma-separated. Replaces $params when all the parameters used in a substitution (ignoring those erroneously absent from $params) are in this list. This might be used if an infobox has multiple parameters that are only applicable to some group of articles.
- $set2
- Conditionally replaces $set3 or $params, whichever was last chosen. Usually bigger than them.
- $set1
- Conditionally replaces $set3, $set2 or $params, whichever was last chosen. Usually bigger than them.
- $extra
- A comma-separated list of any parameters listed in $params (or $set1, $set2, or $set3, whichever was chosen) which don't need to be shown after substitution unless they are already being used in the template; i.e. if a parameter is in both lists and is not used or blank in a particular transclusion, then on substitution the parameter will not be displayed.
- $indent
- The number of additional spaces before each line. Useful for child infoboxes.
- $flags
- A list of comma-separated flags. The only valid input for this parameter at present is "override", which tells the template to supersede the original input to the template with any parameters which are set in the module; i.e. if the template transclusion uses
|number=6
but the module invocation uses|date=7
, if the module invocation containsoverride
in|$flags=
then the output will be|date=7
and if it doesn't then the output will be|date=6
. - $template-name
- May be used to override the default template name.
All other parameters are treated as input to the template. If the input value is not blank and the input parameter is a valid parameter of the template, then the value will appear in the post-substitution content if the transclusion's value is blank; if the module invocation contains override
in |$flags=
then the value will appear in the post-substitution content regardless of what the transclusion's value is.
local p = {}
local specialParams = {
['$params'] = 'all parameters',
['$extra'] = 'extra parameters',
['$set1'] = 'parameter set 1',
['$set2'] = 'parameter set 2',
['$set3'] = 'parameter set 3',
['$aliases'] = 'parameter aliases',
['$indent'] = 'indent',
['$flags'] = 'flags',
['$B'] = 'template content',
['$template-name'] = 'template invocation name override'
}
p[''] = function ( frame )
if not frame:getParent() then
error( '{{#invoke:Unsubst-infobox|}} makes no sense without a parent frame' )
end
if not frame.args['$B'] then
error( '{{#invoke:Unsubst-infobox|}} requires parameter $B (template content)' )
end
if not frame.args['$params'] then
error( '{{#invoke:Unsubst-infobox|}} requires parameter $params (parameter list)' )
end
if mw.isSubsting() then
---- substing
-- Combine passed args with passed defaults
local args = {}
if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*override%s*,' ) then
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
for k, v in pairs( frame.args ) do
if not specialParams[k] then
if v == '__DATE__' then
v = mw.getContentLanguage():formatDate( 'F Y' )
end
args[k] = v
end
end
else
for k, v in pairs( frame.args ) do
if not specialParams[k] then
if v == '__DATE__' then
v = mw.getContentLanguage():formatDate( 'F Y' )
end
args[k] = v
end
end
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
end
-- Build an equivalent template invocation
-- First, find the title to use
local titleobj = mw.title.new(frame:getParent():getTitle())
local title
if titleobj.namespace == 10 then -- NS_TEMPLATE
title = titleobj.text
elseif titleobj.namespace == 0 then -- NS_MAIN
title = ':' .. titleobj.text
else
title = titleobj.prefixedText
end
if frame.args['$template-name'] and '' ~= frame.args['$template-name'] then
title = frame.args['$template-name'] -- override whatever the template name is with this name
end
-- Remove empty fields
for k, v in pairs( args ) do
if v == '' then args[k] = nil end
end
-- Pull information from parameter aliases
local aliases, extra = {}, {}
if frame.args['$aliases'] then
local list = mw.text.split( frame.args['$aliases'], '%s*,%s*' )
for k, v in ipairs( list ) do
local tmp = mw.text.split( v, '%s*>%s*' )
local alias = (tonumber(mw.ustring.match(tmp[1], '^[1-9][0-9]*$'))) or tmp[1]
aliases[alias] = ((tonumber(mw.ustring.match(tmp[2], '^[1-9][0-9]*$'))) or tmp[2])
extra[alias] = true
end
end
for k, v in pairs( aliases ) do
if args[k] and not args[v] then args[v], args[k] = args[k], nil end
end
-- Build the invocation body with numbered args first, then named
local ret = '{{' .. title
for k, v in ipairs( args ) do
if mw.ustring.find( v, '=', 1, true ) then
-- likely something like 1=foo=bar, we need to do it as a named arg
break
end
ret = ret .. '|' .. v
args[k] = nil
end
-- Pull lists from special parameters
local discard = {}
local params = mw.text.split( frame.args['$params'], '%s*,%s*' )
for k, v in ipairs( params ) do
-- Numbered args don't go here
if mw.ustring.match(v, '^[1-9][0-9]*$') then
table.insert( discard, 1, k )
end
end
for k, v in ipairs( discard ) do table.remove( params, v ) end
local sets, setparams = {{}, {}, {}}, {}
for k = 1, 3 do
local v = frame.args['$set' .. k]
if v then
setparams[k] = mw.text.split( v, '%s*,%s*' )
discard = {}
for x, y in ipairs( setparams[k] ) do
sets[k][setparams[k][x]] = true
-- Numbered args don't go here
if mw.ustring.match(y, '^[1-9][0-9]*$') then
table.insert( discard, 1, x )
end
end
for x, y in ipairs( discard ) do table.remove( setparams[k], y ) end
end
end
if frame.args['$extra'] then
local tmp = mw.text.split( frame.args['$extra'], '%s*,%s*' )
for k, v in ipairs( tmp ) do extra[(tonumber(mw.ustring.match(v, '^[1-9][0-9]*$'))) or v] = true end
end
-- Replace parameter list with short version if full version not necessary
local tmp = {}
for k, v in ipairs( sets ) do
if next(v) then -- if table v is not empty
for _, x in ipairs( params ) do
if args[x] and not v[x] then
tmp[k] = true
break
end
end
if not tmp[k] then params = setparams[k] end
end
end
-- Align parameters correctly and remove extra ones
local maxlength = 0
discard = {}
for k, v in ipairs( params ) do
if (not extra[v]) or args[v] then
local tmp = mw.ustring.len( tostring( v ) )
if tmp > maxlength then maxlength = tmp end
else
table.insert( discard, 1, k )
end
end
for k, v in ipairs( discard ) do table.remove( params, v ) end
local indent = mw.ustring.rep(' ', (tonumber(frame.args['$indent']) or 0))
-- Numbered args after discontinuity continue first
discard = {}
for k, v in pairs( args ) do
if mw.ustring.match(k, '^[1-9][0-9]*$') then table.insert ( discard, 1, k ) end
end
for k, v in ipairs( discard ) do table.insert( params, 1, v ) end
local space, newline = ' ', '\n'
if not next(params) then space, newline = '', '' end
for k, v in ipairs( params ) do
local tmp = space
if mw.ustring.match( mw.ustring.sub( ( args[v] or '' ) .. ' ', 1, 1 ), '[%*:;#]' ) then tmp = '\n' end
ret = ret .. newline .. indent .. '|' .. space .. v .. string.rep(' ', (maxlength - mw.ustring.len( v ))) .. space .. '=' .. tmp .. (args[v] or '')
end
ret = ret .. newline .. '}}'
ret = mw.ustring.gsub(ret, '%s+\n', '\n')
return ret
else
-- Not substing
-- Just return the "body"
return frame.args['$B']
end
end
return p