MEpedia:Substitution

From MEpedia, a crowd-sourced encyclopedia of ME and CFS science and history
Shortcut:
  • H:SUBST

Substitution is a function whereby, when an editor saves a page, an item in the wikicode is permanently replaced with its current value. In particular, a template can be substituted, as an alternative to transclusion. The difference is that when a template is substituted on a page, its appearance on that page will no longer be affected by later changes made to the template itself.

Substitution is done using the subst: modifier after the double opening braces. For example, to substitute the template {{font}}

{{font}}, type {{subst:font}}. You can check the resulting wikitext before saving by clicking "Show changes" (and see what the page will look like by clicking "Show preview").

Variables and parser functions can also be substituted, meaning that their current value will be recorded permanently on the page – they will not be re-evaluated whenever someone views the page.

When to use substitution

Generally speaking, templates are transclusion rather than substituted, although there are some that are specifically designed to be substituted (and may not work if transcluded). Some reasons for substituting templates include:

  • making the resulting page independent of future changes to the template
  • enabling other automatic replacements to occur (for example, a template may contain four tildes, which will be replaced by the user's signature and timestamp provided the template is substituted)
  • enabling the page to be copied to another project without copying the template
  • making page rendering faster for the server
  • making the correspondence between wikitext and rendered page easier to understand (the opposite may also apply)

Disadvantages of substitution may include:

  • Updates to the template will not be reflected on the target page
  • The resulting wikitext is longer and more complicated
  • Other users cannot see that the text was produced using a template (and will not learn to use the template)

Time-dependent variables are substituted to make the rendered page independent of the time at which it is viewed. Substituting page-dependent variables makes the resulting wikitext independent of renaming of the page and of copying to another page.

Syntax

To substitute a template, use the same syntax as for transclusion, but include subst: after the opening double braces. For example, to substitute the template {{font}}

{{font}}, type {{subst:font}}. Parameters can be included as in the case of transclusion, for example {{subst:font|Some article}}.

Pages not in the template namespace can also be substituted, e.g. {{subst:User:Cleverclogs/My box}}. To substitute the current content of a page in mainspace (i.e. one with no namespace prefix), two colons are required, as in {{subst::Page}}. If a substituted page or template does not exist, the entire expression (with braces and subst:) will remain unchanged in the wikitext and on the page.

Use the same syntax to substitute variables and parser functions, e.g. {{subst:PAGENAME}} or {{subst:#switch:{{NUMBEROFADMINS}}|1=Foo|1000=Car|#default=Baz}}.

There may be whitespace between the opening braces and the "subst:". However it is recommended not to have any space or newlines immediately after the "subst:", as this will not work in every case.

Technical implementation

Substitution is part of the process performed on saving a page, and causes the wikitext saved as a result of the edit to differ from the text which the user actually entered in the edit window. Other replacements performed during this process include expansion of links using the pipe trick, and replacement of multiple tildes with signatures and timestamps.

This means that substitution necessarily occurs before any actions performed at the time of page rendering (conversion of the stored wikitext to HTML). In particular, substitutions are done before transclusions. So typing {{subst:Help:L{{in(tut)}}k}} will not do substitution, even though {{in(tut)}}

{{in(tut)}} returns the text "in" and Help:Link exists. The transclusion of {{in(tut)}}

{{in(tut)}} has not yet taken place when the substitution is attempted. However, replace {{in(tut)}} with {{subst:in(tut)}}, and both substitutions will be performed in the expected order.

Similarly:

  • Typing {{subst:#if:{{x0}}|yes|no}} gives the wikitext "yes", even though {{x0}}

{{x0}} is an empty template, since the conditional parameter evaluates to the non-empty string "{{x0}}". However {{subst:#if:{{subst:x0}}|yes|no}} produces "no", since the inner substitution is performed first.

  • Typing {{subst:#expr:2*{{{p|3}}}}} returns Expression error: unrecognised punctuation character "{", as the undefined parameter {{{p}}} has not been replaced by its default value (3) when the substitution occurs.
  • If {{box-header}}

{{box-header}} contains the text "color|a", then {{ {{subst:t6}} }} will produce the wikitext "{{ color|a }}", rendered as "!" Contrast this with the behaviour of {{ {{box-header}} }}, which is rendered as "{{

{{{title}}}

}}", because the parser does not reinterpret the pipe as a separator during the non-substituted expansion stage. (Similarly, {{subst:{{subst:box-header}} }} gives the wikitext {{subst:color|a }}, which only on the next edit will be substituted with !.)

Clicking the "Show changes" button during editing shows the wikitext that will result after substitution and other immediate replacements are carried out. Clicking "Show preview" shows what the rendered page will look like after these replacements.

If a page substitutes itself (e.g. in the noinclude part of a template page) it substitutes the old version, as it was before the current edit.

If the expansion of a substituted template itself contains instances of the subst: syntax, then the substitutions are performed recursively. However substitution is not automatically recursive – if a substituted template contains ordinary transclusions or variables and parser functions which are not explicitly substituted, then these will not be substituted.

Note also that if instances of the subst: syntax appear in a template that is being transcluded, then they will be rendered unchanged (as "{{subst:...}}"), since no substitution in wikitext is possible at the rendering stage. This feature can be exploited to control template behaviour (see below, Making templates behave differently when transcluded or substituted). However, it may be inconvenient when a template is designed to be possible to transclude as well as substitute – in this case safesubst: can be used instead of subst: (see next section).

The safesubst: modifier

Shortcut:
  • MEpedia:SAFESUBST

The subst: modifier can be replaced by the alternative modifier safesubst:. The two have the same behaviour, except when they are encountered during non-substituted expansion (transclusion or direct viewing) of a template. In this situation, the code {{subst:...}} remains unparsed, whereas {{safesubst:...}} is treated as if no modifier were present (so the subtemplate is transcluded or the variable or parser function evaluated).

Hence the safesubst: modifier is used in the code of templates which are designed to produce recursive substitution when substituted, but are also intended to work when transcluded – or simply to be viewed directly. Using plain subst: in such templates would break in the case of transclusion (and possibly on direct viewing). For details on how to implement this (in particular, how to prevent the substitution from being performed as soon as the template code is saved), see the next section.

Recursive substitution

As mentioned above, substitution is not automatically recursive. So if a substituted template has code containing transclusions of other templates and parser functions, that code will be copied "as is" into the resulting wikitext – the transcluded items will not themselves be substituted.

To make substitution work recursively, then, you must include the subst: syntax in the code of the calling template. However, you cannot do this by simply typing "subst:" within the template, as the substitution would then be performed as soon as the template is saved. There are two ways to work around this problem:

  • Use <includeonly>subst:</includeonly> in place of plain subst:. The includeonly tags break up the substitution syntax when the template is saved, but those tags will be stripped away when it is later substituted, allowing the inner substitution to take effect.
  • Make "subst:" the possible value of an expression containing a parameter, such as {{{subst-foo|subst:}}}, which will evaluate to "subst:" provided the parameter subst-foo is not set. This is a more flexible solution, as it allows the behaviour to be controlled via the parameter. For example, such a template might be called using {{subst:t|subst-foo=|..}}, assigning the parameter an empty value and thus turning off the second level of substitution. If it is not planned to use the parameter, the parameter name is often chosen to be the empty string, giving {{{|subst:}}}.

To ensure that the template will still work as intended if it is transcluded instead of substituted, use safesubst: instead of subst:. This also applies if the template is also to be viewed directly, on its own page (although in this case, if the first of the above methods is used, plain subst: will still work, as the includeonly tags will cause the parser to ignore the subst: on direct viewing).

To see what a template will produce when fully expanded, without the need to explicitly substitute all subtemplates etc., the Special:ExpandTemplates tool can be used.

Recursive substitution in guided tours

Guided tours can make posts on behalf of users, such as automatically posting the contents of a wiki page onto a talk page. Unlike normal substitution or transclusion, however, this function of guided tours does not respect <includeonly>...</includeonly> and similar markup. To make recursive substitution work via guided tour posting, you can use the "Delaying" method described on Meta.

Examples

{{!}} substitutes to |.

Contents of {{foo}}. When you open [[Template:foo]], it looks: The result of {{subst:foo}}.
{{!}}

{{PAGENAME}}
{{#if: 1 | yes | no}}


Template:foo
yes

{{!}}

{{PAGENAME}}
{{#if: 1 | yes | no}}

{{{{{|subst:}}}!}}

{{{{{|subst:}}}PAGENAME}}
{{{{{|subst:}}}#if: 1 | yes | no}}

{{subst:!}}

{{subst:PAGENAME}}
{{subst:#if: 1 | yes | no}}


Template:foo
yes

{{{{{|safesubst:}}}!}}

{{{{{|safesubst:}}}PAGENAME}}
{{{{{|safesubst:}}}#if: 1 | yes | no}}


Template:foo
yes


Template:foo
yes

Making templates behave differently when transcluded or substituted

Sometimes it is desirable to make a template behave differently when substituted than when transcluded. A common trick for doing this is to use an expression like {{{{{subst|subst:}}}ns:0}}. This evaluates to the empty string if the template is being substituted (since the inner substitution takes effect, giving the prefix of namespace 0, which is empty), but to "{{subst:ns:0}}" if the template is being transcluded (since substitution cannot take place after transclusion).

A common application is in templates which are designed only to be substituted, to make them produce a warning if they are mistakenly transcluded instead. This is done in templates like {{prod}}

{{prod}}, which are designed to produce a timestamp (e.g. for adding pages to dated categories), and will not be able to do this if transcluded.

A template, {{issubst}}

{{issubst}}, has been created to simplify this. It returns "yes" if substitution is being performed, or the empty string otherwise. This can then be used as the parameter of a conditional parser function to make the template display a warning method if it is being transcluded, or to otherwise change the behaviour of a template depending on whether it is being transcluded or substituted.

Documenting substitution

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. It can even contain the values of the parameters, because substitution of parameters works even in comments.

Limitation

Substitution is not available inside <ref>...</ref> tags. If you write , it is not substituted nor transcluded, but remains as-is.

However it is possible to bypass this limitation by using the magic word #tag. If you write for instance , the content of the reference can be substituted and the will be replaced with <ref>...</ref>.

Templates for substitution

{{require subst}}, {{subst check top}}

{{subst check top}}, and {{subst check bottom}}

{{subst check bottom}} can wrap templates which require subst:

{{issubst}} - Returns "yes" when substituted.

{{ifsubst}} - Similar to #if: magic word, judging from substituted or not.

See also