Jump to content

Help:Substitution

From Meta, a Wikimedia project coordination wiki
This is an archived version of this page, as edited by 114.125.117.189 (talk) at 21:06, 3 May 2018 (Freedom). It may differ significantly from the current version.


Substitution is automatic conversion of wikitext of a page when the page is saved, in the case that the wikitext refers to one or more variables, or parser functions.

In the case of template substitution the template call is replaced by the template content with substitution of the parameters. Thus a template is used as macro and the page is macro expanded when the page is saved rather than, as usually happens, when the page is viewed.

In the case of substitution of a variable or parser function the reference to it is replaced by the resulting value.

Substitution is done by putting the subst: or safesubst: after the double opening braces without intervening spaces like in the examples: {{subst:FULLPAGENAME}} and {{safesubst:FULLPAGENAME}}. The code safesubst: is useful in multilevel substitution, see below.

The result (in the form of the difference with the saved wikitext) can be seen before (or without) saving by pressing "Show changes". However, if the text covers more than one paragraph this diff page is not very suitable for copying the result (e.g. for stepwise substitution without saving every step), because of plus signs in the margin.

Applications

Substitution of a template:

  • Make a rendered page independent of the template:
    • The rendered page does not change when the template is edited.
    • The page can be copied to another MediaWiki wiki without copying the template.
  • Make page rendering easier and therefore faster for the server.
  • Analyse and demonstrate the working of templates. However, in some cases substitution works differently.
  • Make the correspondence between wikitext and rendered page easier to understand (this may apply, the opposite may also apply).

Substitution of a time-dependent variable:

  • Make a rendered page independent of the time.

Substitution of a page-dependent variable:

  • Make a rendered page independent of renaming of the page and of copying the wikitext to another page (the opposite applies if the variable PAGENAME is used in a no-include part of the page to include the page itself).

Some MediaWiki 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.

Overview

Like on the page Help:Expansion, on this page templates, parser functions and variables are collectively called templates in italics, and a triple-braced wikitext referring to a template parameter, and possibly specifying a default value, is called a tplarg.

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, in a template, immediately after the opening braces.

The new wikitext is equal to what the expanded wikitext in transclusion would be, resulting from the wikitext without these occurrences of subst: or safesubst:, while not expanding templates without subst: or safesubst:, and not expanding a tplarg on the page itself to this default, even though in substituted templates the default mechanism does work. (There is no prefix for substituting a tplarg, it 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 templates 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, etc. A text subst: or safesubst: in a substituted template can also be constructed with a tplarg (parameter value or 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.

Examples:

  • {{subst:Help:L{{tc}}k}} using , does not do substitution, because Help:L{{tc}}k is not an existing page, although in the regular expansion phase Help:L{{tc}}k expands to Help:Link. Thus the resulting wikitext is the same as the original wikitext and in the regular expansion phase expanded to {{subst:Help:Link}}.
  • {{subst:#if:{{ns:0}}|yes|no}} gives the wikitext "yes", while {{subst:#if:{{subst:ns:0}}|yes|no}} gives the wikitext "no", and {{#if:{{ns:0}}|yes|no}} expands to "no".

The wikitext resulting from full substitution is not always equal to the expanded wikitext of transclusion: a tplarg with default on the page itself is not replaced by the default in the substitution phase, while in transclusion it does expand to the default. This can affect the result of a parser function that is directly or indirectly applied to the tplarg.

Example:

{{#expr:2*{{{p|3}}}}} is expanded to 6, while {{subst:#expr:2*{{{p|3}}}}} is replaced by the wikitext <strong class="error">Expression error: Unrecognised punctuation character "{"</strong>.

On substitution of a template that contains this, {{{p|3}}} is either replaced by the value of {{{p}}} or by 3, so then there is no difference.

{{ {{t6}} }} using expands to {{ t2demo|a }}; {{subst:{{subst:t6}} }} gives the wikitext {{subst:t2demo|a }} rendered the same as the wikitext, and on the next edit/save changed into start-a -middle-{{{2}}}-end; {{ {{subst:t6}} }} gives the wikitext {{ t2demo|a }}, rendered as start-a -middle-{{{2}}}-end. This is because, both without substitution and in the case of full substitution, the pipe characters in template calls, excluding those inside inner template calls, template parameters, links, and image tags, determine the separation of parameter definitions from each other and from the template name. 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.

If a page substitutes itself (e.g. in the noinclude-part of a template page) it substitutes the old version.

Usage considerations

As mentioned, a change of an ordinary template after substitution does not affect the page in which it was substituted, and a substituted variable depending on time no longer depends on time, etc. However, a substitution of e.g. {{#expr:2*3}} does not affect rendering at all.

The relationship between wikitext of a page and its rendering can become easier to understand after substitution, because one has all wikitext together, and parameter substitutions have been performed.

It can also become more complex. Separately focusing on understanding a template call and understanding the template content can be easier. Wikitext after substitution is often more complex than when the required wikitext would have been written directly.

Unlike a template call (if one knows about templates), 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.

Ordinary templates

In the case of substituting an ordinary template, the template tag is replaced by the wikitext of the template, with the parameter values substituted for the parameters.

Example: , containing
start-{{{1}}}-middle-{{{2}}}-end and called as {{subst:t2|[[a]]|{{tc}}}} (see ) gives the wikitext:
start-[[a]]-middle-{{tc}}-end, rendering as
start-amiddle--end.

Substitution removes the noinclude parts and the includeonly tags.

Parameters:

  • A substitution with p=r replaces {{{p}}} and {{{p|q}}} by r; this includes the cases that r is of the form {{{s}}} or {{{s|t}}}.
  • A substitution with undefined p preserves {{{p}}} and replaces {{{p|q}}} by the default q.

With "subst:" the replacement of a template tag by wikitext does not work recursively. For full recursive substitution use Special:ExpandTemplates. See also substall, and multilevel substitution below.

Stepwise substitution of templates including other templates including more templates etc. can be useful for analyzing and documenting the behaviour of complex templates, for an example see m:Template talk:Lop.

However, after a substitution a page may render differently, e.g. if templates produce braces, pipes, and/or equals signs which after substitution determine expansion of other templates, but without substitution are treated as plain text.

In the absence of parameters, template substitution can be compared with copying the wikitext, or the rendering of a previewed or saved {{ msgnw:pagename }} inclusion. However, template substitution excludes <noinclude> parts, removes <includeonly> tags, and replaces undefined parameters with defaults by the defaults.

Predefined templates

In the case of substituting a predefined template, without parameters depending on other templates, the tag is replaced by the result.

Note: subst: has to be added directly in front of the predefined template name without intervening spaces.

Applying subst to a variable works like applying it to a template. E.g. a timestamp:

{{subst:CURRENTYEAR}}-{{subst:CURRENTMONTH}}-{{subst:CURRENTDAY}} T {{subst:CURRENTTIME}} [[w:UTC|]]

may give the wikitext

2010-04-10 T 06:30 [[w:UTC|UTC]]

rendered as

2010-04-10 T 06:30 UTC

In the case of substituting a predefined template with a parameter depending on another template, that has to be substituted too, with a separate subst: modifier, otherwise the result is undefined.

  • {{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.
  • {{ns:{{subst:#expr:2*3}}}} gives wikitext {{ns:6}} rendered as .
  • {{subst:t1|{{subst:NAMESPACE}}}} gives the wikitext startHelpend (see )
  • {{subst:t1|{{subst:#expr:3*4}}}} gives the wikitext start12end
  • {{subst:t1|{{subst:uc:AbCdEf}}}} gives the wikitext startABCDEFend
  • {{subst:#expr:{{subst:3X|11*}}1}} gives the wikitext 1331
  • {{subst:UC:{{subst:3X|abc}}}} gives the wikitext ABCABCABC
  • {{subst:LC:{{subst:#expr:1/100000}}}} gives the wikitext 1e-05 (see LC:)
  • {{subst:#expr:2*{{subst:CURRENTDAY}}}} gives (at the time of writing) the wikitext 30
  • {{subst:UC:{{subst:CURRENTDAYNAME}}}} gives (at the time of writing) the wikitext THURSDAY

However:

  1. {{subst:UC:{{tc}}}} gives the wikitext {{TC}} rendered as .
  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.

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.

Examples:

  • {{#expr:2*{{{p}}}}} gives Expression error: Unrecognized punctuation character "{".
  • {{#expr:2*{{{p|3}}}}} gives 6
  • {{subst:#expr:2*{{{p|3}}}}} gives Expression error: Unrecognised punctuation character "{"
  • 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.

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; U is applied to the output "in" of Tc.
  • {{subst:UC:{{tc}}}} gives the wikitext {{TC}} rendered as .

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

Partial substitution

Inside an ordinary template one can apply substitution to an ordinary template call containing a parameter, to replace it by the direct wikitext containing the parameter. It amounts to automatically merging the two templates (creating a "composite template" like a composite function). It is not possible if the inner and/or outer template is predefined. (However, manually merging e.g. a call of #expr inside another one is useful for increasing the accuracy of the result by avoiding intermediate rounding to 12 digits.)

This way one can dispense with the optional substitution technique described below, and apply substitution of the resulting outer template by simply using "subst:" (unless there are more nesting levels).

Example:

  • {{subst:t}} gives the wikitext start-{{{1|pqr}}}-end, just that of Template:T, without noinclude parts and includeonly tags
  • {{subst:t|a{{{p|q}}}b}} gives the wikitext start-a{{{p|q}}}b-end

Examples with double substitution:

  • {{subst:3X|{{subst:t}}}} gives the wikitext start-{{{1|pqr}}}-endstart-{{{1|pqr}}}-endstart-{{{1|pqr}}}-endstart-{{{1|q}}}-end
  • {{subst:3X|{{subst:t|{{{1|q}}}}}}} gives the wikitext start-{{{1|q}}}-endstart-{{{1|q}}}-endstart-{{{1|q}}}-end

Multilevel substitution

When substituting a template it may be desirable to carry out a substitution inside the template too. This can be done with "safesubst:" in the template. To prevent premature substitution (i.e., when the template is saved), and to control whether single- or multilevel substitution is applied, this code is provided as default value of an otherwise unused parameter. Since the empty string is a possible but for other purposes uncommon parameter name, it is usually a suitable choice for the name of this parameter, so we can use the code {{{|safesubst:}}}.

The difference with {{{|subst:}}} is that {{{|safesubst:}}}, evaluating to safesubst: if the parameter with the empty string as name is undefined, not only allows multilevel substitution but also multilevel transclusion, because on transclusion it is ignored. 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, e.g. {{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

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 .

Partial substitution

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: