Manual:Recursive conversion of wikitext
Normally wikitext like {{subst:a}}
is not saved as {{subst:a}}
if {{template:a}}
exists, because subst: saves the coding of template:a in its place.
With certain coding, subst:
does not automatically convert the first time it is saved.
An editor can create wikitext that is only converted when saved again, or that may be converted each time it has been saved.
Delaying substitution with Template:subst
Substitution can be delayed for one save operation using Template:Subst containing "Subst
"
template used | template coding | Paste or type | Save | Result |
---|---|---|---|---|
Template:subst | {{subst:
|
{{subst:subst}}a|b}}
|
save page | {{subst:a|b}}
|
- The file to be saved initially contains {{subst:subst}}a|b}}
- When saved for the first time, {{subst:subst}} is replaced by the content of the template subst, limited to the included part, that is : {{subst:
- After being saved, the saved file now reads {{subst:a|b}}
- The next save (with or without edits elsewhere on the page) results in normal substitution of template "a".
More complex examples
In {{subst:substancia}}a|b}}
the explicit braces are not balanced - there are two {
and four }
.
The problem with unbalanced braces is that when that code is enclosed within the range of an inclosing {{subst: ... | ... | ... }}
, the parser will identify the parameters of the enclosing {{subst:
under the assumption that what lies between the pipes (or the closing braces) is normal template text and must be balanced.
So if {{subst:subst}}a|b}}
is inside another pair of double braces, the final closing braces }}
of the inner code are taken as closing braces of the outer pair.
See the example with
template used | template coding | Paste or type | Save | Result |
---|---|---|---|---|
Template:T1demo | start-{{{1}}}-end
|
{{subst:t1demo|{{subst:subst}}a|b}}|c}}
|
save page | start-{{subst:a-end|c}}
|
- When saving the file, the first subst:t1demo means that instead of saving the file as-is, the template T1demo should be called with whatever appears to be its parameters, the result replacing the calling sequence. The template T1demo must therefore initialize its parameter :
- The formal analysis sees the well-balanced sequence {{subst:subst}}a between the first and the second pipe : this string is therefore passed as parameter 1.
- The term "b" is then seen between the pipe and a closing braces
}}
, and is therefore identified as a parameter 2. - The template content is then evaluated, replacing {{{1}}}} by the value identified as parameter 1 - and the template apparently makes no use of a parameter 2.
Because of these unbalanced braces, the sequence {{subst:subst}}a|b}} cannot work any more, because it is disarticulated and messed by the enclosing template call.
Braces can be made balanced with Template:)), that substitutes for two closing braces.
template used | template coding | Paste or type | Save | Result |
---|---|---|---|---|
Template:)) | }}
|
{{subst:subst}}a|b{{subst:))}}
|
save page | {{subst:a|b}}
|
Template:T1demo | start-{{{1}}}-end
|
{{subst:t1demo|{{subst:subst}}a|b}}|c{{subst:))}}
|
save page | start-{{subst:a-end|c}}
|
This time, when saving the file, the first subst:t1demo will correctly identify the closing braces that match the opening ones.
But the inner code that is identified as parameters reads : {{subst:subst}}a
|b{{subst:))}}
|c
and the parser now sees two parameters separated by a pipe:
{{subst:subst}}a
b{{subst:))}}
The problem now is that, the opening braces of the intended second subst:
has been hidden to the parser within a formally balanced {{subst:subst}}
; and the closing braces have been hidden as well, within a formally balanced {{))}}
, the parser cannot see that the middle pipe is meant to be inside one of the pairs of braces in the inner code, so it is taken as parameter separator of the outer template or parser function.
To hide this pipe from the first parsing, we therefore also need now magic word "!", which is equivalent to "{{subst:!}}
:
Paste or type | Save | Result |
---|---|---|
{{subst:t1|{{subst:subst}}a{{subst:!}}b{{subst:))}}|c}}
|
Save page | start-{{subst:a|b}}-end
|
- At the first call, the parser correctly identifies the parameters of t1 as being:
{{subst:subst}}a{{subst:!}}b{{subst:))}}|c
- This parameter bloc consists of two parameters separated by a first-level pipe :
{{subst:subst}}a{{subst:!}}b{{subst:))}}
c
- The value of both parameters must now be evaluated, which gives :
{{subst:a|b}}
c
- The value of these parameters is now inserted in the t1 substitution text
start-{{{1}}}-end
, yielding the correct result.
Making a recursively self-converting page
The resulting page can have the same property of making a saved page containing subst, if we use a template "a" specially designed for this purpose.
When used in a calling page, this template would be able to insert active subst:
in the result. But these substitution calls (which normally act when a page is saved) should be neutralized until the template itself is included somewhere : they must not be activated when the special template itself is saved.
To make this template static, two strategies are possible:
<includeonly></includeonly>
is put before (or around) (or within) everysubst:
, preventing the parser from seeing it as a valid (and active)subst:
call,- or, alternatively, every
subst:
is replaced by{{{|subst:}}}
. This nice hack uses the default value assignment for undefined parameters, usually seen as{{{a|b}}}
which means «when substituing, here use the given value of parameter a, but if a is undefined, use "b" as default value». Since in this case there is no variable name, the unnamed variable will always be undefined and will always translate to its default value when the template is included.
A basic form is that of Template:tsubst containing "a{{{{{|subst:}}}subst}}tsubst|b{{{{{|subst:}}}))}}c<noinclude>{{doc|content=This template is used as an example at [[Manual:Recursive conversion of wikitext]][[Category:Demo templates]]}}</noinclude>
", where b represents the parameters, a the output before the template call, and c the output after the template call. These can all depend on the parameters. By itself, this content has no active subst:
, so it is not modified when saved.
Now if template:tsubst appears in a file within a {{subst:tsubst|..}}
, the first time the file is saved, the higher-level {{subst:tsubst|..}}
will therefore be executed.
- The parser will first delimit the parameters of the calling code, get their textual expression, and determine the value of these parameters.
- Since the template:tsubst content has no valid parameter name, its content will always be translated identically when substituted : The two pseudo-parameters
{{{|subst:}}}
will be replaced by their default valuesubst:
. The effective textual content of tsubst after parameter substitution will therefore bea{{subst:subst}}tsubst|b{{subst:rb}}c
. - The value of this initial sequence will expand, after its own substitution, to be replaced by
a{{subst:tsubst|b}}c
in the calling file.
As a result, starting with the wikitext {{subst:tsubst|..}}
, the wikitext is replaced by a{{subst:tsubst|b}}c
on saving the calling file. Recursively, on every save "a" is added before the braces, the parameter values are replaced, and "c" is added after the braces.
The wikitexts "a", "b" and "c" which appear in this simple template:tsubst example are example placeholders for {{{{{|subst:}}}..}}
when used in more elaborate templates, in which case the wikitext produced is the result of expansion of the variable, parser function, or template, as stated in the called elaborate template, at the time of saving the calling file.
- Thus, the substitution of "b" text represents the situation when the calling file was last saved, the succession of "a" gives the history of each successive save, from oldest to newest ; and "c" the history from newest to oldest. In other words, chronological order is inward, toward the template call; the history grows from the inside, the place where the template is kept recursively active.
- Also,
~{{{|~~}}}
gives the signature of the user. - More generally a page can contain multiple template calls, each generating multiple template calls.
- If it is so desired, it may be set up so that the template stops reproducing under a certain condition (e.g. by substituting an empty page), only leaving the old versions of "a" and "c" behind, and, if any, the result of the last substitution in between.
Tailoring rendered output
<span style="display:none">..</span> can be used to hide the template call. Proper nesting inside or around pairs of double or triple braces is not needed, during template expansion these tags are treated as plain text. Thus e.g. the opening tag can be in "b" and the closing tag in "c".
If we have a non-empty "c", for hiding the closing braces "c" needs to start with "</span>". Opening and closing span tags have to be balanced to avoid that the template call and/or its output affect the style after that. This requires an opening span tag in "c" to match the closing tag in the "c" that was previously put. It can come either immediately after the closing tag at the start of "c" (optionally specifying a style overriding the external style), or at the end of "c" (the external style applies also for "c"). If we have a non-empty "a", for hiding the opening braces "a" needs to end with "<span style="display:none">". Thus "a" has to start with a closing span tag to match the opening span tag in the previous "a" (the external style applies for "a", unless it contains an extra pair of span tags). Finally, to match the closing span tag at the start of the leftmost (oldest) "a" an opening span tag is needed to the left of that, while to match the opening span tag in the rightmost (oldest) "c" a closing span tag is needed to the right of that. If "a" is empty this opening span tag is also put; similarly, if "c" is empty this closing span tag is also put.
Thus the whole template call, including "b", is hidden, unless inside "b" we have "</span>" and "<span style="display:none">"; in that case the part of "b" in between has the external style, unless it contains an extra pair of span tags.
Dummy span tag pairs (either with nothing in between or without style specification) could be cleaned up manually from time to time.
Documentation
In the case of automatic conversion of wikitext the original wikitext is not automatically documented. The edit summary can be useful for that. In addition, in the case of automatic conversion just by clicking edit and save, the wikitext, both before and after the conversion, are in the edit history. A code could be put in the edit summary to indicate "no manual change to the wikitext". Thus only the wikitext entered originally is undocumented, unless used in an edit summary (the capacity of which may be too small), or saved in pre- or nowiki-tags on the page itself or within the page's documentation.
Simple live example
Above templates of the form Template:Tsubst containing "a{{{{{|subst:}}}subst}}tsubst|b{{{{{|subst:}}}))}}c<noinclude>{{doc|content=This template is used as an example at [[Manual:Recursive conversion of wikitext]][[Category:Demo templates]]}}</noinclude>
" were discussed, where b represents parameters, a the output before the template call, and c the output after the template call. These can all depend on the parameters. A simple example is this template itself, without parameters, where "a", "b" and "c" are just those explicit letters.
Starting with the wikitext {{subst:tsubst|b}}
, on every save "a" is added before the opening braces and "c" is added after the closing braces.
Live example (automatically changed every time "Save page" is pressed):
aaaaaaaaaaaa{{subst:tsubst|b}}cccccccccccc
Other examples
Examples:
- m:Template:last edit - "a" and "c" are empty, "b" contains edit info
- m:Template:edit counter A - a clean edit counter, displaying |n|
- m:Template:page history - "a" is empty, "b" contains a header, "c" contains edit info
- m:Template:square root - parameter 1 is a number, parameter 2 an approximation of its square root; on every edit/save an iteration step is carried out to improve the approximation.
- m:Template:square root with defaults
- m:Template:square root with defaults A
- m:Template:eraser-left A - "dressing up" a substitution in a parser function
Examples of templates designed for use with the pre-2008 preprocessor, with which they provided an arbitrary number of levels of substitution:
- m:Template:square root A - calculates, with Newton's method, the square root of parameter 1, with initial guess being parameter 2, with absolute error stop criterion (terminating when two successive estimates are within parameter 3), in two saves (or, with a parser function, in one save), printing all successive estimates and the differences between consecutive ones
- m:Template:square root B the same as m:Template:square root A, except that only the final outcome is printed
- m:Template:sqr - ditto, with fixed stop criterion of relative error <1e-11 (based on use of a server with 12-digit results); gives a single value, a call can be put in an expression
- m:Template:multiple substs - a subst generates multiple substs on each level, in two saves (or, called with a parser function, in one save)
Preview
Note that the preview before/without making manual changes to the wikitext is not the same as the rendering of the current page.