* {{A note}} changed request from {{Tl|edit template-protected}} to {{Tl|edit protected}} because it is cascade protected. [[User:Technical 13|Technical 13]] ([[User talk:Technical 13|talk]]) 16:41, 25 November 2013 (UTC)
::[[File:Pictogram voting comment.svg|20px|link=|alt=]] '''Note:'''<!-- Template:EP --> The module name is "Unsubst", implying a reversal of "subst"; "subst" is a verb, being Wiki shorthand for [[WP:SUBST|substitute]]; so the present participle would be "substing", and may be used in a phrase like "it is substing", hence I think that "isSubsting" is a reasonable name for an identifier, such as a function returning a Boolean result. --[[User:Redrose64|<span style="color:#a80000; background:#ffeeee; text-decoration:inherit">Red</span>rose64]] ([[User talk:Redrose64|talk]]) 17:22, 25 November 2013 (UTC)
: [[File:Red information icon with gradient background.svg|20px|link=|alt=]] '''Not done:'''<!-- Template:EP --> As Redrose64 explained, isSubsting is the correct spelling. Where are you getting this error? Given that we haven't been inundated by people complaining that every maintenance tag (e.g. {{citation needed}}) is giving script errors, I am skeptical that you're seeing this here on enwiki. On non-WMF wikis, do note that you will need an extremely recent version of Scribunto (or you will have to cherry-pick [[gerrit:93019]]). [[User:Anomie|Anomie]][[User talk:Anomie|⚔]] 18:09, 25 November 2013 (UTC)
== You can avoid using {{para|$N}} ==
local specialParams = {
['$params'] = 'parameter list',
['$aliases'] = 'parameter aliases',
['$flags'] = 'flags',
['$B'] = 'template content',
['$template-name'] = 'template invocation name override',
}
You can get the template name from {{code|mw.getCurrentFrame():getTitle()|lua}} <span class="signature">— [[User:Kephir|Keφr]]</span> 08:59, 27 March 2014 (UTC)
function p.main(frame, body)
: I retract that. It does not seem to work. Shame, really. <span class="signature">— [[User:Kephir|Keφr]]</span> 09:28, 27 March 2014 (UTC)
-- If we are substing, this function returns a template invocation, and if
:: Oh wait, the proper code is {{code|mw.getCurrentFrame():getParent():getTitle()|lua}}, and it does work. (And above, I actually meant {{code|mw.getCurrentFrame().parent:getTitle()}}, which does not.) <span class="signature">— [[User:Kephir|Keφr]]</span> 09:50, 27 March 2014 (UTC)
-- not, it returns the template body. The template body can be specified in
::: [[Special:Diff/581707228/598491600|Sandbox version]], needs review and deploy. {{ping|Mr. Stradivarius|Jackmcbarn}} any final comments? Or should we do this thing? My only comment is that I was worried about the expensive mw.title.new until I realized that only gets called on subst so it'd only be a problem if someone adds ~500 substed maintenance tags in one edit (if even that). [[User:Anomie|Anomie]][[User talk:Anomie|⚔]] 10:38, 27 March 2014 (UTC)
-- the body parameter, or in the template parameter defined in the
:::: This is ready to go now, as far as I can see. However, I did tweak the error messages, as they were showing the #invoke call as <code><nowiki>{{#invoke:Unsubst|unsubst}}</nowiki></code>, when actually it's just <code><nowiki>{{#invoke:Unsubst|}}</nowiki></code>. As for the expensive mw.title.new, I agree that if it only gets called on subst then it shouldn't be a problem. — '''''[[User:Mr. Stradivarius|<span style="color: #194D00; font-family: Palatino, Times, serif">Mr. Stradivarius</span>]]''''' <sup>[[User talk:Mr. Stradivarius|♪ talk ♪]]</sup> 12:20, 27 March 2014 (UTC)
-- BODY_PARAM variable. This function can be called from Lua or from
::::: {{ping|Anomie}} Is $N still deliberately in specialParams? (Do we need specialParams at all anymore?) [[User:Jackmcbarn|Jackmcbarn]] ([[User talk:Jackmcbarn|talk]]) 22:21, 27 March 2014 (UTC)
-- #invoke.
:::::: Mr. Stradivarius restored it in [//en.wikipedia.org/w/index.php?title=Module:Unsubst/sandbox&diff=598067783&oldid=598044098], and I agree with his reasoning. [[User:Anomie|Anomie]][[User talk:Anomie|⚔]] 20:23, 29 March 2014 (UTC)
::::::: Ah, I was under the impression that that was done now. Anyway, looks good then. [[User:Jackmcbarn|Jackmcbarn]] ([[User talk:Jackmcbarn|talk]]) 01:35, 30 March 2014 (UTC)
-- 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
I have a local wikipedia copy and get the 'Lua error in Module:Unsubst atline 18: attempt to call field 'isSubsting' (a nill value)' error and I have changed the Unsubst module to the new one but still get the error, is there anything else I need to do?
-- Sanity check for the frame object.
: Yes, you need to upgrade Scribunto to the latest version. Wikipedia uses the cutting-edge version of Scribunto, so you will need to go to the [https://www.mediawiki.org/wiki/Special:ExtensionDistributor/Scribunto download page] and select "master (latest development version)" from the drop-down menu. Earlier versions of Scribunto don't have the mw.isSubsting function. Although it is called the "latest development version", it should be stable enough to use in production. (If it's good enough for Wikipedia, it's probably good enough for you.) Hope this helps. — '''''[[User:Mr. Stradivarius|<span style="color: #194D00; font-family: Palatino, Times, serif">Mr. Stradivarius</span>]]''''' <sup>[[User talk:Mr. Stradivarius|♪ talk ♪]]</sup> 12:19, 22 April 2014 (UTC)
if type(frame) ~= 'table'
::Also, if you don't want to upgrade, then you can use the [https://en.wikipedia.org/w/index.php?title=Module:Unsubst&oldid=579696121 old version] of the module. That will work just fine, but you will need to specify the <code>$N</code> (template name) parameter in the #invoke text, whereas in the latest version this is not necessary. — '''''[[User:Mr. Stradivarius|<span style="color: #194D00; font-family: Palatino, Times, serif">Mr. Stradivarius</span>]]''''' <sup>[[User talk:Mr. Stradivarius|♪ talk ♪]]</sup> 12:25, 22 April 2014 (UTC)
or type(frame.getParent) ~= 'function'
::: Just installed the "master" version of Scribunto and it works :) Thanks very much. <span style="font-size: smaller;" class="autosigned">— Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/195.217.192.7|195.217.192.7]] ([[User talk:195.217.192.7|talk]]) 14:01, 22 April 2014 (UTC)</span><!-- Template:Unsigned IP -->
or not frame:getParent()
then
error(
"argument #1 to 'main' must be a frame object with a parent " ..
"frame available",
2
)
end
== Protected edit request on 22 August 2014 ==
-- Find the invocation name.
local mTemplateInvocation = require('Module:Template invocation')
local name
{{edit protected|Module:Unsubst|answered=yes}}
if frame.args['$template-name'] and '' ~= frame.args['$template-name'] then
<!-- Begin request -->
name = frame.args['$template-name'] -- override whatever the template name is with this name
Please make [[Special:Diff/622347161|these changes]].
else
<!-- End request -->
name = mTemplateInvocation.name(frame:getParent():getTitle())
[[User:Jackmcbarn|Jackmcbarn]] ([[User talk:Jackmcbarn|talk]]) 15:04, 22 August 2014 (UTC)
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
Using this module imposes a time penalty. Not surprising, that. I have been experimenting with a module to translate {{tlx|Literatur}} (a template that attempts to translate de.wiki's [[:de:Vorlage:Literatur|Vorlage:Literatur]] to a {{tlx|citation}} template). In its current form, {{tld|Literatur}} is always subst'd so I tweaked {{tlx|citation/new}} (the sandbox) to use this module. At {{slink|Help_talk:Citation_Style_1|non-English_translator_templates_and_substing}} I was queried about the time penalty. My simple experiments show that there is a significant time penalty for no benefit.
-- 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
In that discussion, I wondered if the translator module might call a special substable version of {{tld|citation}} so I created {{tlx|citation/subst}} which uses this module and then modified the translator module to call that template. The substitution worked as it should except that the substituted template name was {{tld|citation/subst}}. In that discussion at [[WT:CS1]], I also wondered if this module might be tweaked to support a template invocation name override parameter. I have {{diff|Module:Unsubst/sandbox|1039776614|784253929|tweaked the sandbox}} to support {{para|$template-name}}. {{tld|citation/subst}} uses this parameter to set the template name to <code>citation/new</code> and when a {{tlx|Literatur/sandbox}} template is subst'd, the result is an invocation of {{tld|citation/new}}.
-- 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
If there are no objections, I will update the live module from the sandbox. Comments, of course, are welcome.
-- 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
—[[User:Trappist the monk|Trappist the monk]] ([[User talk:Trappist the monk|talk]]) 18:06, 20 August 2021 (UTC)
-- Order parameters
: [[User:Trappist the monk|Trappist the monk]], I was just about to ask the same question. it looks like there are no objections, so I would suggest you go ahead and make the change. thank you. [[User:Frietjes|Frietjes]] ([[User talk:Frietjes|talk]]) 14:58, 8 October 2021 (UTC)
if frame.args['$params'] then
::done
local params, tmp = mw.text.split( frame.args['$params'], '%s*,%s*' ), {}
::—[[User:Trappist the monk|Trappist the monk]] ([[User talk:Trappist the monk|talk]]) 18:22, 8 October 2021 (UTC)
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
== Question about sigs in this template ==
return mTemplateInvocation.invocation(name, args)
end
I'm looking to add a signature option to {{t|Dashboard.wikiedu.org assignment}} using this template so that if someone adds the template, a bot can subst the call and return the original template call plus the user's signature (or maybe even just a timestamp). However, I am concerned that adding in something dynamic like a timestamp will cause issues if the template is substed. Basically, I'm not sure how to code it so that it gives accurate information that stays static after substing. Example:
This is primarily to allow for archiving when the course is over (because at current, sections [[Talk:GLAAD#Wiki_Education_assignment:_Gender_and_Technoculture|like this]] won't ever be archived). Please let me know how far off the mark I am. Thanks! [[User:Primefac|Primefac]] ([[User talk:Primefac|talk]]) 08:17, 16 March 2022 (UTC)
: The module already has a magic value <code><nowiki>__DATE__</nowiki></code> that is replaced with the current month and year when adding the parameter while substing. This is used in maintenance templates. [[User:Anomie|Anomie]][[User talk:Anomie|⚔]] 11:44, 16 March 2022 (UTC)
::Right, I guess it's just a question of how I can best use that to include a timestamp for archival purposes... [[User:Primefac|Primefac]] ([[User talk:Primefac|talk]]) 14:08, 16 March 2022 (UTC)
== Square brackets ==
When I read the documentation I incorrectly assumed that the square brackets were a required part of the syntax, i.e. {{para|$aliases|[œuf>egg,melt>cheese]}} but actually it should be {{para|$aliases|œuf>egg,melt>cheese}} Perhaps the wording can be made clearer? — Martin <small>([[User:MSGJ|MSGJ]] · [[User talk:MSGJ|talk]])</small> 11:53, 17 July 2024 (UTC)
== Substituted wrapper templates ==
A common way this module is used with wrapper templates which are supposed to be replaced, e.g.
It seems to me there could be a simpler way to do this, rather than (a) having to pass all known parameters to the target template, and (b) specifying the target template twice effectively. Could we consider an additional flag for <code>wrapper</code> which could do this? — Martin <small>([[User:MSGJ|MSGJ]] · [[User talk:MSGJ|talk]])</small> 12:02, 17 July 2024 (UTC)
: That doesn't seem like a common use for this module to me. Or if it is, people have been doing some weird stuff with it. Seems like you'd do better with a different module that requires <code>$template-name</code> but doesn't take a <code>$B</code> option. [[User:Anomie|Anomie]][[User talk:Anomie|⚔]] 02:29, 18 July 2024 (UTC)
== Page protections and code architecture ==
This module seems really poorly architected. I do not mean to slight anyone that has worked on this as it is a very useful concept and I realize it was sort of organically developed but this lack of architectural foresight now has significant implications that I want to point out. This module is heavily used to prevent template substitutions but in its 12 million plus transclusions it is basically doing nothing except getting out of the way (i.e., yielding its {{para|$B}}), however, the majority of the logic in this module comes into play during substitutions (which by definition go away at page save time) and yet the entire module is fully protected from any changes by anyone but administrators.
p[''] = p.main -- For backwards compatibility
It seems to me it would be much more useful to develop a module that does the unsubst'ing and another module that checks for substitution and either gets out of the way or loads (on demand) the unsubst'ing module to generate a template invocation that us not {{code|subst:}}ed. The "get out of the way under normal transclusion" module can be a fully protected stub module transcluded upon millions of pages while the unsubst'ing module can be (mostly) unprotected because it is transcluded nowhere (because that is what substitution means).
return p
In any event, I wanted to record my thoughts on the subject until someone comes up with a better solution (which might be me if I get the time since I am thinking about this). —[[User:Uzume|Uzume]] ([[User talk:Uzume|talk]]) 16:04, 12 October 2024 (UTC)
:@[[User:Uzume|Uzume]] I would be happy to port over my completely different implementation at [[wikt:Module:unsubst]] which indeed isn't transcluded on any pages, despite protecting templates which are invoked many millions of times.
:{{pb}}
:The way it works for module-based templates is to have something like this at the top level in the modules which need to be protected, which means it's never called if it's not needed:<syntaxhighlight lang=lua>if mw.isSubsting() then
return require("Module:unsubst")
end</syntaxhighlight>
:There are two issues which need to be considered in doing this, though:
:# I haven't got a ready-made template wrapper which does this for non-Lua templates, but it wouldn't be especially difficult to write one.
:# The if-block implementation assumes that the module it's in is only ever called via <code>#invoke</code> (i.e. that it's not called from other modules, which would result in breakage), which fits Wiktionary's module architecture, but may not be suitable in all Wikipedia modules. However, this shouldn't be too difficult to adapt as appropriate.
:[[User:Theknightwho|Theknightwho]] ([[User talk:Theknightwho|talk]]) 23:07, 4 August 2025 (UTC)
::@[[User:Theknightwho|Theknightwho]]: I haven't thought about this for a while now but thanks for the feedback. Even though we sort of already have the key requirement in {{tlx|ifsubst}} and it should not be that hard to implement a template based on that that either calls {{code|#invoke}} or returns the "body" or an error which could be protected and should not need much further development freeing the module to do just the wikitext template invocation construction, that won't really work as the wikitext generation module needs access to the parent frame which would be lost if there was another template in between. To that end, we {{em|do}} need a single "get out of the way" module that would then be able to do something like the code you provided above. I always like reading your code even when I am confused by how you write it. For example, [[wikt:Module:pages#L-101]] could be simplified to just <syntaxhighlight lang=lua inline>if type(val) ~= "table" then</syntaxhighlight> because it is not an error to call {{code|lang=lua|type}} on {{code|lang=lua|nil}} (or any value; it does throw an error if no value is provided though so <syntaxhighlight lang=lua inline>type(fn())</syntaxhighlight> might be dangerous; a clear difference using expression lists and varargs vs. assignment and function parameters where empty values are implicitly converted to {{code|lang=lua|nil}}). The same logic can be applied to simplify [[wikt:Module:pages#L-108--L-109]] too. I often prefer to not test for {{code|lang=lua|nil}} but just check something is the type I expect and move on. I doubt the comparison prior to the call to {{code|lang=lua|type}} buys you much in terms of speed. I know Lua employs [[string interning]] (sort of like memoization) for the creation of all strings which are immutable. This means every string is compared to all the others via hash tables at creation time and that for every string with a certain value there is only a single instance. That makes {{code|lang=lua|1=~=}} and {{code|lang=lua|1===}} very fast for strings (i.e., literally only a reference comparison since interning guarantees no two strings can be equal unless they are the same reference). Since the results of {{code|lang=lua|type}} are severely limited, I imagine such string construction overhead is minimal and probably based upon literals. Anyway, I got off on a tangent. Thanks for the pointer to your [[wikt:Module:unsubst]] implementation. I think I meant to look at that anyway. —[[User:Uzume|Uzume]] ([[User talk:Uzume|talk]]) 01:51, 5 August 2025 (UTC)
::The problem with your [[wikt:Module:unsubst]] is that it allows transclusions with its {{mlx|unsubst|me|{{=}}...}} syntax so that transclusion stub will eventually get used and eventually the module will end up protected like this one is either due to a large number of transclusions and/or sensitive ones (via a cascade).
::I was thinking of a super simple stub similar to your {{code|me}} stub like:
::<syntaxhighlight lang=lua>
if mw.isSubsting() then
local frame= mw.getCurrentFrame()
return require("Module:" .. frame.args[''] or mw.wikibase.getSitelink('Q15243885'))
end
local mt = {}
function mt:__index(key)
return function(frame)
return key
end
end
return setmetatable({}, mt)
</syntaxhighlight>
::And maybe call this [[Module:Unsubststub]] (or perhaps with your nomenclature [[Module:Unsubstme]]). This would allow something similar to your [[wikt:Module:unsubst]] but without the {{code|me}} transclusion stub (instead always generating an error during transclusions) and this stub code is simple and flexible enough that protections due to high transclusion counts, etc. would not be an issue. It would also allow for potentially different kinds of unsubsting wikitext generation modules to be used for different formats, etc. (e.g., this module vs. [[Module:Unsubst-infobox]], etc.) I appreciate your impressive [[wikt:Module:template parser]] but it is a little heavy compared to this module (although it does seem to only be called during the substing path so the impact is to page save and not to page render). —[[User:Uzume|Uzume]] ([[User talk:Uzume|talk]]) 16:31, 5 August 2025 (UTC)
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
To turn a template into a self-substituting template, wrap the existing template code with:
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.
Due to Lua limitations, parameters are normally ordered randomly when the template is substituted. |$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 |$aliases= (and shouldn't be listed in |$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 |$params=.
Parameter |$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 |$template-name= will override the subst'd template's name with the template name assigned to this parameter.
Example
Consider a template Template:Example containing the following code:
localcheckType=require('libraryUtil').checkTypelocalp={}localBODY_PARAM='$B'localspecialParams={['$params']='parameter list',['$aliases']='parameter aliases',['$flags']='flags',['$B']='template content',['$template-name']='template invocation name override',}functionp.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.ifnotmw.isSubsting()thenifbody~=nilthenreturnbodyelseifframe.args[BODY_PARAM]~=nilthenreturnframe.args[BODY_PARAM]elseerror(string.format("no template content specified (use parameter '%s' from #invoke)",BODY_PARAM),2)endend-- Sanity check for the frame object.iftype(frame)~='table'ortype(frame.getParent)~='function'ornotframe:getParent()thenerror("argument #1 to 'main' must be a frame object with a parent ".."frame available",2)end-- Find the invocation name.localmTemplateInvocation=require('Module:Template invocation')localnameifframe.args['$template-name']and''~=frame.args['$template-name']thenname=frame.args['$template-name']-- override whatever the template name is with this nameelsename=mTemplateInvocation.name(frame:getParent():getTitle())end-- Combine passed args with passed defaultslocalargs={}ifstring.find(','..(frame.args['$flags']or'')..',',',%s*override%s*,')thenfork,vinpairs(frame:getParent().args)doargs[k]=vendfork,vinpairs(frame.args)doifnotspecialParams[k]thenifv=='__DATE__'thenv=mw.getContentLanguage():formatDate('F Y')endargs[k]=vendendelsefork,vinpairs(frame.args)doifnotspecialParams[k]thenifv=='__DATE__'thenv=mw.getContentLanguage():formatDate('F Y')endargs[k]=vendendfork,vinpairs(frame:getParent().args)doargs[k]=vendend-- Trim parameters, if not specified otherwiseifnotstring.find(','..(frame.args['$flags']or'')..',',',%s*keep%-whitespace%s*,')thenfork,vinpairs(args)doargs[k]=mw.ustring.match(v,'^%s*(.*)%s*$')or''endend-- Pull information from parameter aliaseslocalaliases={}ifframe.args['$aliases']thenlocallist=mw.text.split(frame.args['$aliases'],'%s*,%s*')fork,vinipairs(list)dolocaltmp=mw.text.split(v,'%s*>%s*')aliases[tonumber(mw.ustring.match(tmp[1],'^[1-9][0-9]*$'))ortmp[1]]=((tonumber(mw.ustring.match(tmp[2],'^[1-9][0-9]*$')))ortmp[2])endendfork,vinpairs(aliases)doifargs[k]and(notargs[v]orargs[v]=='')thenargs[v]=args[k]endargs[k]=nilend-- Remove empty parameters, if specifiedifstring.find(','..(frame.args['$flags']or'')..',',',%s*remove%-empty%s*,')thenlocaltmp=0fork,vinipairs(args)doifv~=''or(args[k+1]andargs[k+1]~='')or(args[k+2]andargs[k+2]~='')thentmp=kelsebreakendendfork,vinpairs(args)doifv==''thenifnot(type(k)=='number'andk<tmp)thenargs[k]=nilendendendend-- Order parametersifframe.args['$params']thenlocalparams,tmp=mw.text.split(frame.args['$params'],'%s*,%s*'),{}fork,vinipairs(params)dov=tonumber(mw.ustring.match(v,'^[1-9][0-9]*$'))orvifargs[v]thentmp[v],args[v]=args[v],nilendendfork,vinpairs(args)dotmp[k],args[k]=args[k],nilendargs=tmpendreturnmTemplateInvocation.invocation(name,args)endp['']=p.main-- For backwards compatibilityreturnp