Module:Unsubst
This Lua module is used on approximately 12,500,000 pages, or roughly 2385496% of all 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. |
{{#ifeq:Unsubst|doc|{{#if:|}}|{{#switch:
{{#if: | | {{#ifeq:Module|Module | module | other }} }}| module =
{{#switch: protected
| pre-alpha | prealpha | pa = | alpha | a = | beta | b = | release | r | general | g = | protected | protect | p = [[File:{{#switch:Lua error in Module:Effective_protection_level at line 14: attempt to index local 'title' (a nil value).|autoconfirmed=Semi|extendedconfirmed=Extended|accountcreator|templateeditor=Template|#default=Full}}-protection-shackle.svg|40x40px|link=|alt=Protected]] | semiprotected | semiprotect | semi =}} | {{#switch: protected
| pre-alpha | prealpha | pa = This module is rated as pre-alpha. It is unfinished, and may or may not be in active development. It should not be used from article namespace pages. Modules remain pre-alpha until the original editor (or someone who takes one over if it is abandoned for some time) is satisfied with the basic structure. | alpha | a = This module is rated as alpha. It is ready for third-party input, and may be used on a few pages to see if problems arise, but should be watched. Suggestions for new features or changes in their input and output mechanisms are welcome. | beta | b = This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. | release | r | general | g = This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. | protected | protect | p = 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. | semiprotected | semiprotect | semi = 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 semi-protected from editing. | #default = Module rating is invalid or not specified.}} |
| | {{#switch: Unsubst | doc | sandbox = | {{#ifeq: | true | | {{#switch: protected | pre-alpha | prealpha | pa = | alpha | a = | beta | b = | release | r | general | g = | protected | protect | p = | semiprotected | semiprotect | semi = }} }} }} }}
| other | #default = Error: {{Module rating}} must be placed in the Module namespace. }}}}
Maintenance templates, such as {{Citation needed}} or {{Refimprove}}, should never be substituted. A trick to avoid that is to make a template substitute to its transcluded form. This module implements that trick.
Infoboxes should use Module:Unsubst-infobox, as should any other templates with parameters listed in block format by default.
Usage[edit]
To turn a template into a self-substituting template, wrap the existing template code with:
{{SAFESUBST:<noinclude />#invoke:Unsubst||$B= [ ... existing template code ... ] }}
The wikitext to display when not substed must be given as "$B". All other parameters passed to the #invoke will be copied to the generated template invocation as default values. If the value of any of these default parameters is __DATE__
, that value in the generated template invocation will be the current month and year.
Some templates have a {{#switch:o
|c|close = |e|empty|s|single|v|void |o|open |p|pair = <{{#if:|noinclude|noinclude}}{{#if:| {{{attribs}}}}} }}{{#switch:o |c|close = |e|empty|s|single|v|void = /> |o|open = > |p|pair = {{#ifeq:noinclude|!--||>}}... }}{{#switch:o |e|empty|s|single|v|void |o|open = |c|close |p|pair = {{#ifeq:noinclude|!--|-->|</noinclude>}} }}
but no matching{{#switch:c |c|close = |e|empty|s|single|v|void |o|open |p|pair = <{{#if:|noinclude|noinclude}}{{#if:| {{{attribs}}}}} }}{{#switch:c |c|close = |e|empty|s|single|v|void = /> |o|open = > |p|pair = {{#ifeq:noinclude|!--||>}}... }}{{#switch:c |e|empty|s|single|v|void |o|open = |c|close |p|pair = {{#ifeq:noinclude|!--|-->|</noinclude>}} }}
at the end of the template. In such cases the missing{{#switch:c |c|close = |e|empty|s|single|v|void |o|open |p|pair = <{{#if:|noinclude|noinclude}}{{#if:| {{{attribs}}}}} }}{{#switch:c |c|close = |e|empty|s|single|v|void = /> |o|open = > |p|pair = {{#ifeq:noinclude|!--||>}}... }}{{#switch:c |e|empty|s|single|v|void |o|open = |c|close |p|pair = {{#ifeq:noinclude|!--|-->|</noinclude>}} }}
must be added before the ending}}
.
Advanced[edit]
{{SAFESUBST:<noinclude />#invoke:Unsubst||$params=[ parameters ]|$aliases=[ aliases ]|$flags=[ flags ]|$B= [ ... existing template code ... ] }}
Due to Lua limitations, parameters are normally ordered randomly when the template is substituted. |{{SAFESUBST:#if:$params|$params=}}
can be used in #invoke:Unsubst to list template parameters in order, comma-separated (e.g. egg,bacon,sausage,cheese,spam
). Numbered parameters should be before others in the list. Any remaining parameters are tacked onto the end of the generated invocation.
Parameter aliases can be listed in |{{SAFESUBST:#if:$aliases|$aliases=}}
(and shouldn't be listed in |{{SAFESUBST:#if:$params|$params=}}
), and will be replaced automatically. Each alias and its replacement should be formatted as alias>replacement
, and each of those pairs should be comma-separated (e.g. œuf>egg,melt>cheese
). Note that this parameter can function with or without |{{SAFESUBST:#if:$params|$params=}}
.
Parameter |{{SAFESUBST:#if:$flags|$flags=}}
can be used to modify other facets of the module's behaviour; entries are comma-separated. Valid flags are override
(allows parameters in the #invoke: to take precedence over parameters in the original template invocation); keep-whitespace
(prevents whitespace from being trimmed from unnamed parameters); and remove-empty
(removes empty parameters).
These parameters can be manipulated using parser functions to provide more complicated options (note that in the parameters any parser function, or template or module invocation, should also have SAFESUBST:<noinclude />
).
Parameter |{{SAFESUBST:#if:$template-name|$template-name=}}
will override the subst'd templates name with the template name assigned to this parameter.
Example[edit]
Consider a template Template:Example containing the following code:
{{SAFESUBST:<noinclude />#invoke:Unsubst||foo=bar |date=__DATE__ |$B= [ ... Template code goes here ... ] }}
Original | Result |
---|---|
subst:example|tlsc|...}}{{#if:||{{{2}}}}}{{#if:||{{{3}}}}}{{#if:||{{{4}}}}}{{#if:||{{{5}}}}}{{#if:||{{{6}}}}}{{#if:||{{{7}}}}}{{#if:||{{{8}}}}}{{#if:||{{{9}}}}}{{#if:||{{{10}}}}}{{#if:||{{{11}}}}}{{#if:||{{{12}}}}}{{#if:||{{{13}}}}}{{#if:||{{{14}}}}}{{#if:||{{{15}}}}}{{#if:||{{{16}}}}}{{#if:||{{{17}}}}}{{#if:||...}}}} | {{Example|date={{#time:F Y}}}}
|
subst:example|tlsc|...}}{{#if:foo=X||foo=X}}{{#if:||{{{3}}}}}{{#if:||{{{4}}}}}{{#if:||{{{5}}}}}{{#if:||{{{6}}}}}{{#if:||{{{7}}}}}{{#if:||{{{8}}}}}{{#if:||{{{9}}}}}{{#if:||{{{10}}}}}{{#if:||{{{11}}}}}{{#if:||{{{12}}}}}{{#if:||{{{13}}}}}{{#if:||{{{14}}}}}{{#if:||{{{15}}}}}{{#if:||{{{16}}}}}{{#if:||{{{17}}}}}{{#if:||...}}}} | {{Example|foo=X|date={{#time:F Y}}}}
|
subst:example|tlsc|...}}{{#if:baz=X||baz=X}}{{#if:||{{{3}}}}}{{#if:||{{{4}}}}}{{#if:||{{{5}}}}}{{#if:||{{{6}}}}}{{#if:||{{{7}}}}}{{#if:||{{{8}}}}}{{#if:||{{{9}}}}}{{#if:||{{{10}}}}}{{#if:||{{{11}}}}}{{#if:||{{{12}}}}}{{#if:||{{{13}}}}}{{#if:||{{{14}}}}}{{#if:||{{{15}}}}}{{#if:||{{{16}}}}}{{#if:||{{{17}}}}}{{#if:||...}}}} | {{Example|baz=X|date={{#time:F Y}}}}
|
subst:example|tlsc|...}}{{#if:date=January 2001||date=January 2001}}{{#if:||{{{3}}}}}{{#if:||{{{4}}}}}{{#if:||{{{5}}}}}{{#if:||{{{6}}}}}{{#if:||{{{7}}}}}{{#if:||{{{8}}}}}{{#if:||{{{9}}}}}{{#if:||{{{10}}}}}{{#if:||{{{11}}}}}{{#if:||{{{12}}}}}{{#if:||{{{13}}}}}{{#if:||{{{14}}}}}{{#if:||{{{15}}}}}{{#if:||{{{16}}}}}{{#if:||{{{17}}}}}{{#if:||...}}}} | {{Example|foo=bar|date=January 2001}}
|
{{#if:{{#ifeq:Unsubst|sandbox|1}}{{#ifeq:Unsubst|doc|1}}|| }}
local checkType = require('libraryUtil').checkType local p = {} local BODY_PARAM = '$B' local specialParams = { ['$params'] = 'parameter list', ['$aliases'] = 'parameter aliases', ['$flags'] = 'flags', ['$B'] = 'template content', ['$template-name'] = 'template invocation name override', } function p.main(frame, body) -- If we are substing, this function returns a template invocation, and if -- not, it returns the template body. The template body can be specified in -- the body parameter, or in the template parameter defined in the -- BODY_PARAM variable. This function can be called from Lua or from -- #invoke. -- Return the template body if we aren't substing. if not mw.isSubsting() then if body ~= nil then return body elseif frame.args[BODY_PARAM] ~= nil then return frame.args[BODY_PARAM] else error(string.format( "no template content specified (use parameter '%s' from #invoke)", BODY_PARAM ), 2) end end -- Sanity check for the frame object. if type(frame) ~= 'table' or type(frame.getParent) ~= 'function' or not frame:getParent() then error( "argument #1 to 'main' must be a frame object with a parent " .. "frame available", 2 ) end -- Find the invocation name. local mTemplateInvocation = require('Module:Template invocation') local name if frame.args['$template-name'] and '' ~= frame.args['$template-name'] then name = frame.args['$template-name'] -- override whatever the template name is with this name else name = mTemplateInvocation.name(frame:getParent():getTitle()) end -- 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 -- Trim parameters, if not specified otherwise if not string.find( ','..(frame.args['$flags'] or '')..',', ',%s*keep%-whitespace%s*,' ) then for k, v in pairs( args ) do args[k] = mw.ustring.match(v, '^%s*(.*)%s*$') or '' end end -- Pull information from parameter aliases local aliases = {} 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*' ) aliases[tonumber(mw.ustring.match(tmp[1], '^[1-9][0-9]*$')) or tmp[1]] = ((tonumber(mw.ustring.match(tmp[2], '^[1-9][0-9]*$'))) or tmp[2]) end end for k, v in pairs( aliases ) do if args[k] and ( not args[v] or args[v] == '' ) then args[v] = args[k] end args[k] = nil end -- Remove empty parameters, if specified if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*remove%-empty%s*,' ) then local tmp = 0 for k, v in ipairs( args ) do if v ~= '' or ( args[k+1] and args[k+1] ~= '' ) or ( args[k+2] and args[k+2] ~= '' ) then tmp = k else break end end for k, v in pairs( args ) do if v == '' then if not (type(k) == 'number' and k < tmp) then args[k] = nil end end end end -- Order parameters if frame.args['$params'] then local params, tmp = mw.text.split( frame.args['$params'], '%s*,%s*' ), {} for k, v in ipairs(params) do v = tonumber(mw.ustring.match(v, '^[1-9][0-9]*$')) or v if args[v] then tmp[v], args[v] = args[v], nil end end for k, v in pairs(args) do tmp[k], args[k] = args[k], nil end args = tmp end return mTemplateInvocation.invocation(name, args) end p[''] = p.main -- For backwards compatibility return p