User:Pathoschild/2006 ParserFunction substitution check

User:Pathoschild User:Pathoschild (ParserFunction substitution check)
This page details a ParserFunctions method to check that a template is substituted.


Behaviour exploited edit

The method exploits a possible glitch with <includeonly> tags that may be corrected in the future: template modifiers within includeonly tags will be incorrectly displayed if the template is substituted. Consider the code {{<includeonly>subst:</includeonly>NAMESPACE}}; contrary to the expected behaviour, the includeonly tags will be displayed unless the template is not substituted.

For example, the two lines below show the code and displayed result when exploiting this behaviour. Note that the second line, showing the displayed result, contains two obviously different strings. The method relies on this difference.

{{NAMESPACE}}         {{<includeonly>subst:</includeonly>NAMESPACE}}
User                  {{<includeonly>subst:</includeonly>NAMESPACE}}

Explanation of the method edit

Equality check edit

{{#ifeq:{{NAMESPACE}}|{{<includeonly>subst:</includeonly>NAMESPACE}} ... 

The method consists primarily of a simple equality comparison of a magic word; the magic word used here is {{NAMESPACE}}. The ParserFunction equation above compares the namespace variable to itself with includeonly'd substitution. If the template is substituted, the value of the namespace variable will be equal to its substituted value. If the template is not substituted, the behaviour will cause the includeonly tags to be output literally. In that case, the value of the namespace variable is not equal to the resulting broken code.

Output edit

...| |{{error:not substituted|template_name}} ...

If the template is substituted, the ParserFunction above will output nothing. This is the usual desired result if we're trying to make sure that the template is substituted. If the template is not substituted, this function displays the following error:

This template must be substituted. Replace {{{{{1}}}}} with {{subst:{{{1}}}|subst=subst:}}..

Final code edit

{{#ifeq:{{NAMESPACE}}|{{<includeonly>subst:</includeonly>NAMESPACE}}| |{{error:not substituted|TemplateName}}}}

Additional possibilities edit

Hide template edit

...<div style="display:none;">}}

Optionally, adding the styled container above will hide the content of the template. This is useful if you really want users to substituted the template, such as for templates that simply don't function correctly without substitution. In this case, forgetting to substitute the template will lead to a error (and naught else) being output.

If this is done, an equivalent check should be performed at the very bottom of the template to close the container. Otherwise, not substituting the template on a page will blank everything else on the page that happens to be under the template.

{{#ifeq:{{NAMESPACE}}|{{<includeonly>subst:</includeonly>NAMESPACE}}| |</div>}}

Substitution check override edit

{{#if:{{{nosubst|}}}|<div style="display:none;">}}
...
{{#if:{{{nosubst|}}}|</div></div>}}

Adding the ParserFunctions above before and after the substitution check will allow the template to be displayed without substitution by defining the parameter "nosubst" ({{template|nosubst=}}). Theoretically, this should be placed inside an identical check so that these ParserFunctions are only triggered when the error is actually displayed; otherwise, they will close one container opened before the template if one is open and the template is substituted. In practice, such a failsafe is rarely needed.