User:Mindrones/Manual:Substitution

Substitution is a function whereby, when an editor saves a page, every expandable item in the wiki code is permanently replaced with its expanded wikitext.

During the next edit, the wikitext won't show the expandable item call anymore, but rather the expanded wikitext that was contained in the expandable item when you saved the page. The substitute text won't change anymore, even if the expandable wikitext will be edited in the future.

In particular:

  • templates can be substituted, as an alternative to be transcluded.
    Ordinarily, a template will be expanded "on the fly", so that the template code on a page calls a separate page every time it is rendered. Also, when someone is editing a page with a normal template call, they see the template call itself in the page.
    When a template is substituted on a page, its substitute text won't be affected by later changes made to the template itself, and the wikitext of the page doesn't contain the template call anymore.
  • parser functions and variables can also be substituted.
    Their current value will be recorded permanently on the page and they will not be re-evaluated whenever someone views the page.

Terminology on this page

edit
expandable
a template, a variable, a core parser function/modifier, or a extension parser function ;
tplarg
a template parameter, possibly specifying a default value

Applications

edit

Substitution may be needed to:

  • Make a page independent:
    from a template
    The rendered page does not change when the template is edited.
    The page can be copied to another MediaWiki installation without copying the template.
    from time
    Substituting time-dependent variables makes a rendered page independent of the time
    from page names
    Substituting page-dependent variables makes a rendered page independent of renaming of the page and of copying the wikitext to another page.
  • Make a page rendering easier and therefore faster for the server.
    Although most page views are served from the cache, pages need to be rendered for previews, and rendered again when the page changes.
  • Analyze and demonstrate the working of templates.
    The relationship between wikitext of a page and its render can become easier to understand after substitution, because one has all wikitext together, and parameter substitutions have been performed.
    Note that wikitext after substitution is often more complex than when the required wikitext would have been written directly, and in some cases substitution works differently than transclusion)

Syntax

edit

The "subst:" modifier

edit

Normal substitution is done by adding the "subst:" modifier after the double opening braces, without intervening spaces.

transclusion sustitution
template {{Medicine}} {{subst:Medicine}}
variable {{FULLPAGENAME}} {{subst:FULLPAGENAME}}
modifier {{uc:foo}} {{subst:uc:foo}}
parser function {{#if:John|yes|no}} {{subst:#if:John|yes|no}}

About the "safesubst:" modifier

edit

The "safesubst:" modifier is explained in the multilevel substitution paragraph below.


How to inspect the result of the substitution before saving

edit

To check the resulting wikitext before saving click on "Show changes".
If the text covers more than one paragraph the diff page is not very suitable for copying the result because of plus signs in the margin.

Check how the page will look like by clicking "Show preview".


Rules for substitution

edit

A save command potentially starts a substitution process which modifies the wikitext before saving.
For any substitution to occur, there has to be at least one explicit occurrence of subst: or safesubst: on the page, immediately after the opening braces of a expandable item.

The new wikitext is equal to what the expanded wikitext in transclusion would be, with these rules:

  • an expandable without subst: or safesubst: is not expanded,
  • there are no occurrences of subst: or safesubst: in the expanded wikitext,
  • a tplarg is not expanded to its default on the page itself,
  • a tplarg is expanded to its default in substituted templates,
  • a tplarg is substituted if and only if the page in which it occurs is substituted. This is not the case if a tplarg is on the page itself, because this page is neither substituted nor transcluded.
  • In directly and indirectly substituted templates, again only <template>s with subst: or safesubst: are expanded.
  • If the substituted title is inside another title it may construct a text subst: or safesubst: causing that other title to be substituted too.
  • A text subst: or safesubst: in a substituted template can also be constructed with a tplarg (be it a parameter value or a default value).
  • A code subst: or safesubst: before a name that is not a valid variable or parser function name, and not the name of an existing template, does not result in substitution, and the prefix is kept in the wikitext.
  • After the substitution process, the new wikitext is expanded as usual for rendering the page.
  • If a page substitutes itself (e.g. in the noinclude-part of a template page) it substitutes the old version.


Substitution when parameters don't depend on other expandable items

edit

Here we explain the basics substitution, that is when the eventual parameters are independent from other expandable items.

Templates

edit

<noinclude> and <includeonly> parts

edit

Moreover, template substitution:

  • excludes <noinclude> parts,
  • removes <includeonly> parts.

About recursive substitution

edit

Using "subst:" the replacement of a template title by its wikitext does not work recursively.

[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Template [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation
{{Tq}}, contains:
{{Tc}}, {{Tm}}

{{Tc}}, contains:

in

{{Tm}}, contains:

M={{{m|3}}}
{{Tq}} {{Tq}} in, M=3 Regular expansion
{{subst:Tq}} {{Tc}}, {{Tm}} in, M=3 Sustitution (not recursive)

For full recursive substitution see multilevel substitution below.

Parameters substitution

edit

In the absence of parameters, the template is replaced by its result.

If there are parameters to be sustituted:

  • undefined parameters with default are replaced by their defaults,
  • undefined parameters without default are left as they are in the template wikitext.
[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Template [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Templates not accepting parameters

{{Tc}}, contains:
in
{{Tc}} {{Tc}} in Regular expansion
{{subst:Tc}} in in Full substitution

Templates parameters without default

{{Tn}}, contains:
start{{{in}}}end
{{Tn}} {{Tn}} start{{{in}}}end Regular expansion
{{subst:Tn}} start{{{in}}}end start{{{in}}}end The parameter "in" is substituted as it is
{{Tn|in=-middle-}} {{Tn|in=-middle-}} start-middle-end Regular expansion
{{subst:Tn|in=-middle-}} start-middle-end start-middle-end Full substitution

Templates parameters with default

{{Tm}}, contains:
M={{{m|3}}}
{{Tm}} {{Tm}} M=3 Regular expansion
{{subst:Tm}} M=3 M=3 The parameter is replaced by its default
{{Tm|m=7}} {{Tm|m=7}} M=7 Regular expansion
{{subst:Tm|m=7}} M=7 M=7 The parameter is replaced by the given value


Variables

edit

The variable tag is replaced by its result.

Variable You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Variables not accepting parameters

{{CURRENTDAYNAME}} {{CURRENTDAYNAME}} {{CURRENTDAYNAME}} Friday Regular expansion, will change every day
{{subst:CURRENTDAYNAME}} Saturday Saturday Full substitution, won't change anymore

Variables accepting parameters

{{NAMESPACE}} {{NAMESPACE}} {{NAMESPACE}} Help Regular expansion, the result depends on the page where you put the code
{{subst:NAMESPACE}} Help Help Full substitution, won't change anymore
{{NAMESPACE:Template:Tn}} {{NAMESPACE:Template:Tn}} Template Regular expansion
{{subst:NAMESPACE:Template:Tn}} Template Template The variable is evaluated and susbstituted


Modifiers and parser functions

edit

The tag is replaced by its result.

Expandable You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Modifiers

Modifiers ns and uc {{ns:12}} {{ns:12}} Help Regular expansion
{{subst:ns:12}} Help Help The modifier is evaluated and susbstituted
{{uc:foo}} {{uc:foo}} FOO Regular expansion
{{subst:uc:foo}} FOO FOO The modifier is evaluated and susbstituted

Parser functions

Parser functions #language and #expr {{#language:th}} {{#language:th}} ไทย Regular expansion
{{subst:#language:th}} ไทย ไทย The parser function is evaluated and susbstituted
{{#expr:2*(100-24)}} {{#expr:2*(100-24)}} 152 Regular expansion
{{subst:#expr:2*(100-24)}} 152 152 The parser function is evaluated and susbstituted, the result won't change anymore

Substitution when parameters depend on other expandable items

edit

When parameters depend on other expandable items, they have to be substituted too, with a separate subst: modifier, otherwise the result is undefined.

Partial and double substitution

edit

Suppose we have a template accepting a parameter: if we apply a sustitution of the template, but not of the parameter, the resulting wikitext is a merge of the two wikitexts, thus representing a "composite template".

[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Expandable [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Inner expandable is a parameter: partial substitution

{{{p|q}}} {{t|a{{{p|q}}}b}} {{t|a{{{p|q}}}b}} start-aqb-end Regular expansion
{{subst:t|a{{{p|q}}}b}} start-a{{{p|q}}}b-end start-aqb-end Partial substitution, the resulting template is a merge of {{t}} and a{{{p|q}}}b

Inner expandable is a template: partial and double substitution

{{3X}}, contains:

{{{1}}}{{{1}}}{{{1}}}

{{t}}, contains:

start-{{{1|pqr}}}-end
{{3X|{{t}}}} {{3X|{{t}}}} start-pqr-endstart-pqr-endstart-pqr-end Regular expansion
{{subst:3X|{{t}}}} {{t}}{{t}}{{t}} start-pqr-endstart-pqr-endstart-pqr-end Partial expansion, the new template is a compound of the two former templates.
{{subst:3X|{{subst:t}}}} start-pqr-endstart-pqr-endstart-pqr-end start-pqr-endstart-pqr-endstart-pqr-end Double substitution, with {{subst:t}}}} expanding to start-pqr-end
{{subst:3X|{{subst:t|{{{1|q}}}}}}} start-q-endstart-q-endstart-q-end start-q-endstart-q-endstart-q-end Double substitution, with {{{1|q}}} not being expanded

NOTE: Partial substitution doesn't work if the inner and/or outer template is predefined.

[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Variable [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation
{{uc}} and {{NAMESPACE}} {{uc:{{NAMESPACE}}}} {{uc:{{NAMESPACE}}}} MANUAL Regular expansion
{{subst:uc:{{NAMESPACE}}}} {{NAMESPACE}} Manual Partial substitution doesn't work! We need to expand the inner variable to get it working properly, as below.
{{subst:uc:{{subst:NAMESPACE}}}} MANUAL MANUAL Double substitution works!


Templates

edit

Parameters substitution

edit
[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Template [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Templates as parameters

{{T2demo}}, contains:

start-{{{1}}}-middle-{{{2}}}-end

{{tc}}, contains:

in
{{T2demo|[[a]]|{{tc}}}} {{T2demo|[[a]]|{{tc}}}} start-[[a]]-middle-in-end Regular expansion
{{subst:T2demo|[[a]]|{{tc}}}} start-[[a]]-middle-{{tc}}-end start-[[a]]-middle-in-end {{tc}} is not expanded.
{{T2demo|[[a]]|{{subst:tc}}}} {{T2demo|[[a]]|in}} start-[[a]]-middle-in-end Only {{tc}} is substituted.
{{subst:T2demo|[[a]]|{{subst:tc}}}} start-[[a]]-middle-in-end start-[[a]]-middle-in-end Now {{tc}} is expanded and then properly substituted.

Variables as parameters

{{T1}}, contains:

start{{{1}}}end
{{T1|{{NAMESPACE}}}} {{T1|{{NAMESPACE}}}} startManualend Regular expansion
{{subst:T1|{{NAMESPACE}}}} start{{NAMESPACE}}end startManualend Only the template is substituted.
{{T1|{{subst:NAMESPACE}}}} {{T1|Manual}} startManualend Only the variable is substituted.
{{subst:T1|{{subst:NAMESPACE}}}} startManualend startManualend Full substitution, template and variable are substituted

Parser functions as parameters

{{T1}}, contains:

start{{{1}}}end
{{T1|{{#expr:3*4}}}} {{T1|{{#expr:3*4}}}} start12end Regular expansion
{{subst:T1|{{#expr:3*4}}}} start{{#expr:3*4}}end start12end Only the template is substituted.
{{T1|{{subst:#expr:3*4}}}} {{T1|12}} start12end Only the parser function is substituted.
{{subst:T1|{{subst:#expr:3*4}}}} start12end start12end Full substitution, template and parser function get substituted

Modifiers as parameters

{{T1}}, contains:

start{{{1}}}end
{{T1|{{uc:AbCdEf}}}} {{T1|{{uc:AbCdEf}}}} startABCDEFend Regular expansion
{{subst:T1|{{uc:AbCdEf}}}} start{{uc:AbCdEf}}end startABCDEFend Only the template is substituted.
{{T1|{{subst:uc:AbCdEf}}}} {{T1|ABCDEF}} startABCDEFend Only the modifier is substituted.
{{subst:T1|{{subst:uc:AbCdEf}}}} startABCDEFend startABCDEFend Full substitution, template and modifier get substituted

Corner cases

edit
[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Template [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Substitution in a template title

{{tc}}, contains:
in
{{Help:L{{tc}}k}} {{Help:L{{tc}}k}} {{Help:Link}} Regular expansion
{{subst:Help:L{{tc}}k}} {{subst:Help:L{{tc}}k}} {{subst:Help:Link}} No substitution because the page "Help:L{{tc}}k" doesn't exist.
{{subst:Help:L{{subst:tc}}k}} Wikitext contained in Help:Link Expansion of the wikitext contained in Help:Link Using {{subst:tc}} triggers a full substitution, and Help:Link exists.
{{Li}}
(doesn't exist)
{{subst:Help:{{subst:Li}}nk}} {{subst:Help:{{subst:Li}}nk}} {{subst:Help:{{subst:Li}}nk}} Using {{subst:Li}} doesn't trigger a full substitution, because Template:Li doesn't exist.

Substitution of a template that returns a template title

Both without substitution and in the case of full substitution, the pipe characters in template calls determine the separation of parameter definitions from each other and from the template name (excluding those inside inner template calls, template parameters, links, and image tags),

This separation does not depend on possible extra pipe characters in the expanded form of the template name and parameter definitions.

However, if after substitution of an inner template the pipe character is in the outer template call, it is one like any other and plays its part in determining the separation.

In other words, parsing is done first once for substitution, and then once for rendering, but in both cases not an extra time in between. In the case of substitution of the inner template only, two subsequent parsings are effective.

{{T6}}, contains:

t2demo|a

{{T2demo}}, contains:

start-{{{1}}}-middle-{{{2}}}-end
{{{{t6}}}} {{{{t6}}}} {{{{t6}}}} The template can't expand because of the quadruple curly braces.
{{ {{t6}} }} {{ {{t6}} }} {{ t2demo|a }} Regular expansion.
{{ {{subst:t6}} }} {{ t2demo|a }} start-a -middle-{{{2}}}-end Using {{subst:t6}} triggers the substitution.
{{subst:{{subst:t6}}}} {{subst:t2demo|a}} start-a-middle-{{{2}}}-end 2 steps substitution!

The first time we save: the internal subst: gets substituted: the result contains a subst: modifier.

When we press edit and save again, another substitution happens and the former wikitext changes again.

{{subst:t2demo|a}} start-a -middle-{{{2}}}-end start-a -middle-{{{2}}}-end


Variables

edit

In the case of substitution of a predefined template, if the expression for one of its parameters contains {{{p|3}}} with undefined p, this code reduces to 3. However, on the page itself, {{{p|3}}} is treated as such, not as 3.


Modifiers

edit
  • {{subst:UC:{{subst:tc}}}} gives IN, the same wikitext as {{UC:{{tc}}}} is expanded to; UC: is applied to the output "in" of Tc.
  • {{subst:ns:{{subst:#expr:2*3}}}} gives File.
  • {{subst:UC:{{subst:3X|abc}}}} gives the wikitext ABCABCABC
  • {{subst:LC:{{subst:#expr:1/100000}}}} gives the wikitext 1e-05 (see LC:)
  • {{subst:UC:{{subst:CURRENTDAYNAME}}}} gives (at the time of writing) the wikitext THURSDAY
  • {{ns:{{subst:#expr:2*3}}}} gives wikitext {{ns:6}} rendered as File.

However:

  1. {{subst:UC:{{tc}}}} gives the wikitext {{TC}} rendered as Template:TC.
  2. {{subst:ns:{{#expr:2*3}}}} stays {{subst:ns:{{#expr:2*3}}}}, rendered as {{subst:ns:6}} (see ns:).


As mentioned before, on substitution, all calls without substitution of templates, variables, and parser functions are treated as plain text. As a result substitution of the outer x: in a nested {{ x:...{{ y:...}} }} often is only suitable if all inner y: are also substituted.

Compare:

  • {{uc:2*{{{p}}}}} gives 2*{{{P}}}
  • {{uc:2*{{{p|q}}}}} gives 2*Q
  • {{subst:uc:2*{{{p|q}}}}} gives the wikitext 2*{{{P|Q}}} rendered as 2*Q

and also (from above):

  • {{subst:UC:{{subst:tc}}}} gives IN, just like {{UC:{{tc}}}} does; UC is applied to the output "in" of Tc.
  • {{subst:UC:{{tc}}}} gives the wikitext {{TC}} rendered as Template:TC.

In the substitution of UC, the inclusion tag {{tc}} is treated as string just like {{{p|q}}}.


Parser functions

edit
[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Parameter [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

Expansion of templates

{{3X}}, contains:
{{{1}}}{{{1}}}{{{1}}}
{{#expr:{{3X|11*}}1}} {{#expr:{{3X|11*}}1}} 1331 Regular expansion (note that {{3X|11*}}1 expands to 11*11*11*1)
{{subst:#expr:{{3X|11*}}1}} <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> The inner template {{3X|11*}}1}} is not expanded, hence you get an error from the parser function "#expr"
{{subst:#expr:{{subst:3X|11*}}1}} 1331 1331 Now the template can be expanded, and you get 1331 substituted

Expansion of modifiers

{{ns:0}} {{#if:{{ns:0}}|yes|no}} {{#if:{{ns:0}}|yes|no}} no Regular expansion
{{subst:#if:{{ns:0}}|yes|no}} yes yes Here {{ns:0}} is not expanded, hence the "if" has a non-null argument and returns a "yes"
{{subst:#if:{{subst:ns:0}}|yes|no}} no no Here {{subst:ns:0}} returns an empty string, hence the if returns a "no"

Expansion of variables

{{CURRENTDAYNAME}} {{#expr:2*{{CURRENTDAY}}}} {{#expr:2*{{CURRENTDAY}}}} 6 Regular expansion
{{subst:#expr:2*{{CURRENTDAY}}}} <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> The variable is not expanded in the substitution phase, hence you get an error from the parser function "#expr"
{{subst:#expr:2*{{subst:CURRENTDAY}}}} 6 6 Now the variable is expanded in the substitution phase, and (at the time of writing) the resulting wikitext is 6.

Expansion of tplargs

{{{p}}} {{#expr:2*{{{p}}}}} <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> Regular expansion: {{{p}}} can't be expanded to a default value hence you get an error from the parser function "#expr".
{{subst:#expr:2*{{{p}}}}} <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> Substitution: same as above.
{{#expr:2*{{{p|3}}}}} {{#expr:2*{{{p|3}}}}} 6 Regular expansion: the tplarg expands to its default.
{{subst:#expr:2*{{{p|3}}}}} <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> <strong class="error">Expression error: Unrecognised punctuation character "{"</strong> The tplarg with default is not replaced by the default in the substitution phase, hence you get an error from the parser function "#expr"


Substitution of templates containing templates: recursive substitution

edit

When substituting a template it may be desirable to carry out a substitution inside the template too. This can be done using the code "safesubst:" in the template.

The "safesubst:" modifier

edit

The subst: modifier can be replaced by the alternative modifier safesubst::

  • during a substitution, the two have the same behaviour.
  • during a transclusion or a direct viewing:
    • the code {{subst:...}} remains unparsed,
    • the code {{safesubst:...}} is ignored, that is the subtemplate, variable, or parser function we apply safesubst: modifier to is evaluated as if no safesubst: modifier were present.

Hence the safesubst: modifier is used in the code of templates which are designed to:

  • produce recursive substitution when substituted,
  • work when transcluded, or to be viewed directly.

Problem: premature substitution

edit

Before we are able to demonstrate what said above, there's a problem to solve.

If we use subst: or safesubst: directly (i.e. after the opening braces) in a template's wikitext, the substitution is performed as soon as the template code is saved, so we lose the subst: or safesubst: modifier.

In the table below, we need to have code like {{subst:Tm}} or {{safesubst:Tm}} AFTER the page is saved!

[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Template [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

{{Tm}}, contains:

M={{{m|3}}}
{{Tm}} {{Tm}} M=3 Regular expansion
{{subst:Tm}} M=3 M=3 Tm is prematurely substituted
{{safesubst:Tm}} M=3 M=3 Tm is prematurely substituted

How to prevent the substitution from being performed as soon as the template code is saved?

Solution: using {{{|subst:}}} and {{{|safesubst:}}}

edit

To prevent premature substitution (i.e., when the template is saved), and to control whether we apply single or multilevel substitution, we use the code:

{{{|safesubst:}}}

which is the code of a variable with undefined name and defaulting to the string "safesubst:".

The reason why we use this is that the empty string is a valid, though uncommon, parameter name, hence it is usually a suitable choice. If the parameter with the empty string as name is undefined, then {{{|safesubst:}}} evaluates to "safesubst:".

[*] Templates wikitext shown omitting the <noinclude>...</noinclude> part
Template [*] You type Wikitext after saving Expanded wikitext
(used to render the page)
Explanation

A

{{Tc}}, contains:

in

{{Tm}}, contains:

M={{{m|3}}}
{{Tc}}, {{Tm}} {{Tc}}, {{Tm}} in, M=3 Regular expansion
{{{{{|subst:}}}Tc}}, {{{{{|subst:}}}Tm}} {{subst:Tc}}, {{subst:Tm}} in, M=3 {{subst:<template>}} evaluates to {{subst:<template>}}, which remains unparsed. Beware that during the next save it will trigger a substitution, which wuill change again the template content!
{{{{{|safesubst:}}}Tc}}, {{{{{|safesubst:}}}Tm}} {{{{{|safesubst:}}}Tc}}, {{{{{|safesubst:}}}Tm}} in, M=3 {{safesubst:<template>}} evaluates to {{safesubst:<template>}}, which is treated as if it was {{<template>}}

B

{{Tr}}, contains:

{{Tc}}, {{{{{|subst:}}}Tm}}

{{Tc}}, contains:

in

{{Tm}}, contains:

M={{{m|3}}}
{{Tr}} {{Tr}} in, M=3 Regular expansion
{{subst:Tr}} {{Tc}}, M=3 in, M=3 ??

{{Tu}}, contains:

{{Tc}}, {{{{{|safesubst:}}}Tm}}

{{Tc}}, contains:

in

{{Tm}}, contains:

M={{{m|3}}}
{{Tu}} {{Tu}} in, M=3 Regular expansion
{{subst:Tu}} {{Tc}}, M=3 in, M=3 ??


Since during a transclusion safesubst: is ignored, this allows us to do:

  • multilevel substitution,
  • but also multilevel transclusion.

one-level substitution

edit

With {{{|safesubst:}}} it is still possible to perform one-level substitution by assigning to the parameter with the empty string as name, the empty string as value, for example using:

{{subst:if|=|expr|1|a}}

Sometimes a template call defines a value of the parameter with the empty string as name, just for inserting this value as comment inside the template tag, or for lay-out of the template tag, see template tag lay-out. When enabling multilevel substitution for such a template, one of the two parameters needs to be given another name.

If the name of the inner template, parser function or variable depends on a parameter without default, then we can simply put safesubst:, because premature substitution is not possible anyway. However, this does not allow us to control whether single- or multilevel substitution is applied,

Multilevel substitution with independent control of each substitution separately

edit

Parameters subst1, subst2 (or whatever names one chooses) can be used with "safesubst:" and the empty string as possible values. Thus we can control for each template, parser function and variable separately (or group them, and control per group) whether it is substituted too when the outer template is substituted. Either possibilty can be made the default.

Inner templates with parameters may control further inner substitutions in the same way; these parameters may depend on the substitution parameter controlling the substitution of the inner template, since if that is not substituted, inner substitutions within that template are not possible.

For example, if template T uses parameter subst1:

  • with the empty string as default, T calls inner templates and parser functions prefixing their names with {{{subst1|}}}; for calling T we can use:
    • {{t|..}} (no substitution)
    • {{subst:t|..}} (one-level substitution)
    • {{subst:t|subst1=subst:|..}} (two-level substitution)
    • {{subst:t|subst1=safesubst:|..}} (ditto)
  • with default "safesubst:", T calls inner templates and parser functions prefixing their names with {{{subst1|safesubst:}}}; for calling T we can use
    • {{t|..}} (no substitution)
    • {{subst:t|subst1=|..}} (one-level substitution)
    • {{subst:t|..}} (two-level substitution)

To transfer the choice of substituting or not to templates and parser functions called inside the inner templates of T, we can add to the call of these inner templates something of the form subst2={{{subst1|}}} or subst2={{{subst1|safesubst:}}}, respectively (parser functions and variables don't get the additional parameter).

See also Help:Calculation#Substitution and m:Template:Example table with computations, with optional substitution.

Partial substitution

edit

Using a template prepared for optional subst=subst: only with ordinary substitution, without specifying parameter values, allows to insert its code into another template, like copy and paste, but all <noinclude> parts and <includeonly> keywords automatically stripped. Executing inserted code instead of calling it may be more efficient for the server.

A typical example for this technique is expanding, within another template, a template used as test expression in a #switch: like m:Template:oom:

  1. Development code:
    {{#switch: {{oom|parameter tag }}|0=case 0 etc.}}
  2. Standard solution:
    {{{{{subst|}}}#switch: {{{{{subst|}}}oom|parameter tag |subst={{{subst|}}}}}|0=case 0 etc.}}
  3. Better solution: create template code by applying substitution using this wikitext:
    {{{{{subst|}}}#switch: {{subst:oom|parameter tag }}|0=case 0 etc.}}

Template:H:mlm is prepared for optional substitution, therefore both solutions work, but the latter solution substituting its code is simpler and more efficient.

Template:H:

If a template uses a parameter whose name is an expression containing a template or parser function, and the template is called with a corresponding parameter definition (in terms of the final name of the parameter) it expands properly only if at the time of expansion of the template the expression for the name of the parameter is or has been evaluated. Thus if the template is substituted without substituting the expression for the parameter name, the parameter definition is "lost", so the parameter becomes undefined. Therefore in such a case no substitution can give the same rendered result as full substitution, while partial substitution gives a different result. See e.g. m:Template:ts1.

Composite operations

edit

By {{A|{{B|p}}}} a template A is called with, as parameter, a call of template B with a parameter p. We could integrate such template calls to a single call {{C|p}} of a "composite template" C with parameter p.

The wikitext for template C would be {{A|{{B|{{{1}}}}}}}, or with optional substitution the following construct:
{{ {{{subst|}}} A|{{ {{{subst|}}} B|{{{1}}} |subst={{{subst|}}} }} |subst={{{subst|}}} }}
The subst={{{subst|}}} is only necessary for recursive substitution as explained above.

Note that it is not useful to specify "{{subst|subst:}}" since in the substitution phase this tag does not reduce to the default "subst:".

If A and/or B is predefined the construct is similar, but without subst={{{subst|}}} for that template.

Includeonly as a primitive method of multi-level substitution

edit

A more primitive method of multi-level substitution, without the option of single-level substitution, is with a pair of includeonly tags. Substitution is prevented by having the template call inside these tags. Substitution is also prevented by having one or both tags anywhere in the template call except inside a parameter definition. Thus the tag(s) can be before, inside, or after "safesubst:" or "subst:", or inside or after the template name. The positions of the two tags only influence the rendering of the template page itself.

The form {{<includeonly>safesubst:</includeonly>something}} suggests that substitution is prevented by discarding "safesubst:" on the page itself, but actually substitution is prevented because the safesubst-syntax is disturbed by the tags.

It doesn't substitute "something" at the time of the creation of the relevant template, but has the desired effect when the template is substituted.

For examples see "preload" in Extension:InputBox and "substitution" in Help:Variable.

  • substituting a template containing {{<includeonly>subst:</includeonly>#expr:2*{{{p|3}}}}} or {{{{{subst}}}#expr:2*{{{p|3}}}}} gives 6 if p is not assigned a value, and twice the number p if it is assigned a value.

Creating a page which applies substitution on the next save

edit

See m:Help:Recursive conversion of wikitext.

Forced substitution

edit

Some templates deliberately refuse to work without substitution, for an example see w:Template:en. This technique is essential for templates like w:Template:en producing some kind of timestamp, e.g. adding pages to dated categories.

The following code in any template T outputs a warning unless recursive substitution with subst=subst: is in effect:
{{{{{subst|}}}ifdef|{{{{{subst|subst:}}}ns:0}}|'''Warning'''}}.
  1. Output for {{T}} or {{subst:T}}: Warning,
  2. output for {{T|subst=subst:}}: Template:Ifdef,
  3. output for {{subst:T|subst=subst:}}: nothing (no remaining wikitext).
This is a rare case where replacing ifdef by #if: doesn't work directly.

Substitution of part of the parameters

edit

Let template A use parameters 1 and 2. Consider creating a template B with one parameter 1, corresponding to A, with a given value q of parameter 2. Pages containing {{A|2=q}} and {{A|1={{{1}}}|2=q}} are rendered the same, but the second has a parameter {{{1}}} while the first does not. See e.g. m:Template:t ps.

However, with substitution (using "subst:" or Special:Expandtemplates) the resulting wikitext is the same, without distinction between a text {{{1}}} and a parameter, it is a parameter anyway, so "1={{{1}}}" is not needed.

If A contains e.g. #expr with an expression containing both parameters the same applies, except that we can only substitute the highest level (A), not the parser function, so we cannot use Special:Expandtemplates.

In general, substituting a parameter and applying a template or parser function sometimes gives the same result as substituting the template or parser function with the triple-braced parameter code and then substituting the parameter.

Without defaults (all rendered the same in one-step substitution as without substitution):

Examples with equality:

  • A template containing p{{{1}}}q{{{2}}}r substituted with 1=u, 2=v gives puqvr; substituted with 2=v it gives p{{{1}}}qvr, which itself, substituted with 1=u gives also puqvr.
  • Two-level substitution of a template containing {{#if:{{{4}}}|{{{3}}}p}} with 3=u, 4=v gives up; substituted with 4=v it gives {{{3}}}p, which itself, substituted with 3=u gives up.

Examples without equality:

  • Two-level substitution of a template containing {{#if:{{{3}}}|{{{4}}}p}} with 3=, 4=v gives the empty string; substituted with 4=v it gives vp, which itself, substituted with 3=u remains vp.
  • Two-level substitution of a template containing {{#if:{{{2}}}|{{{1}}}p}} with 1=u, 2=v gives up; substituted with 2=v it gives {{{1}}}pp (the bug), which itself, substituted with 3=u, gives upp.
  • Two-level substitution of a template containing {{#expr:{{{1}}}*{{{2}}}}} with 1=7, 2=8 gives 56; substituted with 2=8 it gives <strong class="error">Expression error: Unrecognised punctuation character "{"</strong>, which itself, substituted with 1=7, remains the same.

Thus without equality we may or may not get an error message.

One example shows that substitution of one parameter can be affected by the bug mentioned above. However, we can then replace e.g. {{{1}}} by {{{1{{{{{substvoid|}}}void}}}}} and do full substitution, except that substvoid is undefined, preventing the bug. The result works already correctly with transclusion. Subsequently it can be substituted with substvoid=subst: so that we get the plain {{{1}}}.

With defaults:

Rendered the same as without substitution:

  • Two-level substitution of a template containing p{{{1|d}}}q{{{2}}}r with 2=v gives p{{{1|d}}}qvr.
  • Two-level substitution of a template containing {{#if:{{{4}}}|{{{3|d}}}p}} with 4=v gives {{{3|d}}}p.

Not rendered the same as without substitution:

  • Two-level substitution of a template containing {{#if:{{{3|}}}|{{{4}}}p}} with 4=v gives vp.
  • Two-level substitution of a template containing {{#if:{{{2}}}|{{{1|d}}}p}} with 2=v gives {{{1|d}}}pp (the bug).
  • Two-level substitution of a template containing {{#expr:{{{1|6}}}*{{{2}}}}} with 2=8 gives <strong class="error">Expression error: Unrecognised punctuation character "{"</strong>.

After substitution with the parameter definition:

  • {{subst:#if:{{{3|}}}|vp}} gives vp.
  • {{subst:#if:v|{{{1|d}}}p}} gives {{{1|d}}}pp (the bug).
  • {{subst:#expr:{{{1|6}}}*8}} gives <strong class="error">Expression error: Unrecognised punctuation character "{"</strong>.

Rewritten:

  • {{subst:#if:{{subst:#ifeq:{{{3|+}}}|{{{3|-}}}|vp}}}} gives the empty string.
  • {{subst:#if:v|{{subst:#ifeq:{{{1|+}}}|{{{1|-}}}|{{{1}}}|d}}p}} gives dp.
  • {{subst:#expr:{{subst:#ifeq:{{{1|+}}}|{{{1|-}}}|{{{1}}}|6}}*8}} gives 48.

Documenting substitution; preservation of comments

edit

Usage of a template through subst: does not automatically show up in page histories. Therefore providing the line of wikitext containing "subst:" in the edit summary is especially useful.

Also pages with a substituted template do not show up in backlinks, and the template does not appear in the list of transcluded templates on the edit page. The template could add pages to a category to track substitutions, but listing this category on a page may clutter the list of content-based categories the page is in. Also, comments outside noinclude tags are included in the wikitext. Thus a comment can be used to mention the template. Substitution of parameters inside comment tags does not work.

See also Help:Comment tags#Substitution.

Usage considerations

edit

Wikitext after substitution does not show how one can produce a similar result. The wikitext can be long and complicated, and therefore cumbersome to write directly, or it can be simple, e.g. a number resulting from a computation, but cumbersome to find directly. When studying the wikitext of a page one may think that this wikitext is what one is supposed to write and find directly to get the result, even in cases where that would be very impractical.

In such cases documentation of the template call is useful. Just like in computer programming we change the source code and/or the data to produce new results, and we do not directly change the object file, here we would change the template calls and/or the templates, instead of changing the wikitext resulting from substitution directly.

See also

edit

Template:H:f



TEXT TO EVALUATE

edit

Multilevel substitution

edit

todo


Template parameters

edit

Some extensions have the restriction that if they are used in a template with parameters, they only work if the template is substituted.
This applies for example in the case of a template parameter inside an in-page query in Semantic MediaWiki.