Help:Recursive conversion of wikitext
From The Scuba Wiki
MediaWiki Handbook: Contents, Readers, Editors, Moderators, System admins +/- |
Contents |
Making a saved page containing subst
Automatic conversion of wikitext can, on saving, lead to wikitext which in turn is converted when saved again.
Normally wikitext like {{subst:a|b}} is not saved as such if the template exists, because the substitution is applied. It can be created using Template:subst containing "{{subst:
" by {{subst:subst}}a|b}} producing the wikitext {{subst:a|b}}; on the next save (with or without edits elsewhere on the page) this results in substitution of template "a".
However, in {{subst:subst}}a|b}} the visible braces are not balanced. If the whole code is nested inside another pair of double braces, the final closing braces of the inner code are taken as closing braces of the outer pair, e.g., using template:t1 ( talk edit history links ):
- {{subst:t1|{{subst:subst}}a|b}}|c}} gives the wikitext "start{{subst:aend|c}}"
With template:rb ( talk edit history links ) the braces can be made balanced:
- {{subst:subst}}a|b{{subst:rb}} gives the wikitext "{{subst:a|b}}"
However, the first pipe in the inner code is not 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. Therefore we also need template:! ( talk edit history links ):
- {{subst:t1|{{subst:subst}}a{{subst:!}}b{{subst:rb}}|c}} gives the wikitext start{{subst:a|b}}end
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.
To make this template static, <includeonly></includeonly> is put before (or around) every "subst:".
A basic form is that of Template:tsubst containing "a{{<includeonly></includeonly>subst:subst}}tsubst|b{{<includeonly></includeonly>subst:rb}}c
" 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. Starting with the wikitext {{subst:tsubst|..}}, 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" can contain {{<includeonly></includeonly>subst:..}}, in which case the wikitext produced is the result of expansion of the variable, parser function, or template at the time of saving. Also, ~<includeonly></includeonly>~~ gives the signature of the user.
Thus "b" represents the latest situation, and "a" and "c" the history, where chronological order is inward, toward the template call; in other words, the history grows from the inside.
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.
Message "template loop detected"
If in a substitution a template calls itself, we may get the message "template loop detected" as wikitext comment. Also hidden braces can cause wrong parsing. Sometimes this is harmless because there is a next phase in which the parsing is correct. Templates like template:rb ( talk edit history links ), template:rightbraces1 ( talk edit history links ), template:subst1 ( talk edit history links ) and, in general, these templates help to get it all correct. See also template:square root with defaults A ( talk edit history links ).
Instead of putting the construct of the previous section inside an if-construct, we can also have conditions inside it, e.g. the name of the template and each parameter can depend on conditions. See e.g. template:square root with defaults ( talk edit history links ).
Parser functions
- This does not apply with the new preprocessor, installed on Wikimedia wikis on 24 January 2008, and the default on the English Wikipedia.
If the substitution call is in a parameter of a parser function which is also substituted, two conversions are carried out in one save, see Help:Parser_function#Extra_execution_phase. If the template calls itself inside a parameter of a parser function (e.g., it calls itself conditionally) the first iteration step creates a situation as mentioned. If both these conditions apply (as mentioned, this applies after this step, but it can also apply directly), an indefinite number of iteration steps is carried out in one go. To avoid the need of an intermediate edit/save, a dummy condition such as {{#if:x|..}} can be applied on the calling page.
In the case of an indefinite number of iteration steps, of course the process has to be made finite by proper conditions. The system is protected against infinite repetition by the "pre-expand include size " limitation.
We may also simulate the process of "saving a page n extra times" with n dummy parser functions such as {{subst:#if:x|{{subst:#if:1|{{subst:#if:x|{{subst:#if:x| .... }} }} }} }}. See also template:iterate ( talk edit history links ).
If, on the contrary, the parser functions are not to be dummy, yet every appearance of a parser function still causes the parser to convert once, one must sufficiently "dress up" any substituted text.
In the case of one parser function:
- use plain braces and pipes for the parser function
- use balanced braces inside each parser function parameter
- use for the call to the template itself:
{{<includeonly></includeonly>subst:subst}}subst {{<includeonly></includeonly>subst:rb}}template_name {{<includeonly></includeonly>subst:!}}par1 {{<includeonly></includeonly>subst:!}}par2 ... {{<includeonly></includeonly>subst:!}}parn {{<includeonly></includeonly>subst:rb}}
See template:eraser-left A ( talk edit history links ) for an example.
Numeric range
ParserFunctions has the odd limitation that not all numbers produced as output are accepted as input (see also mw:Extension:ParserFunctions (extended) , where this has been rectified): numbers with absolute value outside the range 1e-4 until 1e12 (for Wikimedia; it depends on the operating system of the server) are produced in scientific notation, but only accepted in regular notation.
While this does not affect intermediary results within an expression evaluated by a single #expr or #ifexpr, it affects intermediary results in the case of nesting of such functions, hence also intermediary results of a substitution template call, even if that call carries out multiple iteration steps in one save.
Any iterative process where a parameter converges to a value outside or near an edge of the range 1e-4 until 1e12 is likely to have intermediary results outside this range, after which no further computations are possible. Rescaling can help to carry out the computation anyway.
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 by just pressing edit and save, both the wikitext before and after the conversion are in the edit history. A code could be put in the edit summary to indicate "no manual change in the wikitext". Thus only the wikitext entered for the first step is undocumented, unless it is put in the edit summary (whose capacity may be too small), or is put in pre- or nowiki-tags in the page itself or the talk page.
Using a two-step method like {{subst:iterate|5|{{subst:square root|5|2}}}} we get in the edit history {{subst:#if:x|{{subst:#if:x|{{subst:#if:x|{{subst:#if:x|{{subst:#if:x|{{subst:square root|5|2.25}}<br>2}}}}}}}}}}, providing in this case a fairly good documentation:
- the 5 is constant
- the starting value 2 is in this case documented by producing it as first output.
Conversion from "iterate" to multiple "#if" is not shown.
Examples
aaaaaa{{subst:tsubst|b}}cccccc
Examples of templates providing one level of substitution:
- template:last edit ( talk edit history links ) - "a" and "c" are empty, "b" contains edit info
- template:edit counter A ( talk edit history links ) - a clean edit counter, displaying |n|
- template:page history ( talk edit history links ) - "a" is empty, "b" contains a header, "c" contains edit info
- template:square root ( talk edit history links ) - 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.
- template:square root with defaults ( talk edit history links )
- template:square root with defaults A ( talk edit history links )
- template:eraser-left A ( talk edit history links ) - "dressing up" a substitution in a parser function
Overview of various levels of substitution obtained by putting the call to the template in one or more levels of parser functions (which for larger numbers of levels can be abbreviated using template:iterate ( talk edit history links )):
*1 steps with 1 edit: **{{subst:tsubst}} *2 steps with 1 edit: **{{subst:#if:x|{{subst:tsubst}}}} *3 steps with 1 edit: **{{subst:#if:x|{{subst:iterate|1|{{subst:tsubst}}}}}} **{{subst:#if:x|{{subst:#if:x|{{subst:tsubst}}}}}} *4 steps with 1 edit: **{{subst:#if:x|{{subst:iterate|2|{{subst:tsubst}}}}}} **{{subst:#if:x|{{subst:#if:x|{{subst:#if:x|{{subst:tsubst}}}}}}}} *2 steps with 2 edits: **{{subst:tsubst}} (see above) *3 steps with 2 edits: **{{subst:#if:x|{{subst:tsubst}}}} (see above) **{{subst:iterate|1|{{subst:tsubst}}}} ***documented by {{subst:#if:x|a{{subst:tsubst|b}}c}} in the wikitext after 1 edit *4 steps with 2 edits: **{{subst:iterate|2|{{subst:tsubst}}}} ***documented by {{subst:#if:x|{{subst:#if:x|a{{subst:tsubst|b}}c}}}} in the wikitext after 1 edit **{{subst:#if:x|{{subst:iterate|1|{{subst:tsubst}}}}}} (see above) **{{subst:#if:x|{{subst:#if:x|{{subst:tsubst}}}}}} (see above) *5 steps with 2 edits: **{{subst:iterate|3|{{subst:tsubst}}}} ***documented by {{subst:#if:x|{{subst:#if:x|{{subst:#if:x|a{{subst:tsubst|b}}c}}}}}} in the wikitext after 1 edit **{{subst:#if:x|{{subst:iterate|2|{{subst:tsubst}}}}}} (see above) **{{subst:#if:x|{{subst:#if:x|{{subst:#if:x|{{subst:tsubst}}}}}}}} (see above)
The following output is the result of the above plus subsequent edit/saves:
- 1 steps with 1 edit:
- aaaaa{{subst:tsubst|b}}ccccc
- 2 steps with 1 edit:
- aaaaaa{{subst:tsubst|b}}cccccc
- 3 steps with 1 edit:
- aaaaaaa{{subst:tsubst|b}}ccccccc
- aaaaaaa{{subst:tsubst|b}}ccccccc
- 4 steps with 1 edit:
- aaaaaaaa{{subst:tsubst|b}}cccccccc
- aaaaaaaa{{subst:tsubst|b}}cccccccc
- 2 steps with 2 edits:
- aaaaa{{subst:tsubst|b}}ccccc (see above)
- 3 steps with 2 edits:
- aaaaaa{{subst:tsubst|b}}cccccc (see above)
- aaaaaa{{subst:tsubst|b}}cccccc
- documented by aa{{subst:tsubst|b}}cc in the wikitext after 1 edit
- 4 steps with 2 edits:
- aaaaaaa{{subst:tsubst|b}}ccccccc
- documented by aaa{{subst:tsubst|b}}ccc in the wikitext after 1 edit
- aaaaaaa{{subst:tsubst|b}}ccccccc (see above)
- aaaaaaa{{subst:tsubst|b}}ccccccc (see above)
- aaaaaaa{{subst:tsubst|b}}ccccccc
- 5 steps with 2 edits:
- aaaaaaaa{{subst:tsubst|b}}cccccccc
- documented by aaaa{{subst:tsubst|b}}cccc in the wikitext after 1 edit
- aaaaaaaa{{subst:tsubst|b}}cccccccc (see above)
- aaaaaaaa{{subst:tsubst|b}}cccccccc (see above)
- aaaaaaaa{{subst:tsubst|b}}cccccccc
Examples of templates providing an arbitrary number of levels of substitution:
- template:square root A ( talk edit history links ) - 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
- template:square root B ( talk edit history links ) the same as {{square root A}}, except that only the final outcome is printed
- template:sqr ( talk edit history links ) - 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
- template:multiple substs ( talk edit history links ) - 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.
See also
Category:Recursive conversion templates
Links to other help pages
- Help contents
- Meta | Wikinews | Wikipedia | Wikiquote | Wiktionary | commons: | mw: | b: | s: | mw:Manual | google
- Versions of this help page (for other languages see below)
- Meta | Wikinews | Wikipedia | Wikiquote | Wiktionary
- What links here on Meta or from Meta | Wikipedia | MediaWiki
- Reading
- Go | Search | Stop words | URL | Namespace | Page name | Section
- Backlinks | Link | Piped link | Interwiki link | Redirect | Category | Image page
- Logging in and preferences
- Logging in | Preferences | User style
- Editing
- Advanced editing | Editing FAQ | Edit toolbar | Export | Import | Shortcuts
- Tracking changes
- Recent changes (enhanced) | Related changes | Watching pages | Diff
- Page history | Edit summary | User contributions | Minor edit | Patrolled edit
- Style & formatting
- Wikitext examples | Reference card | HTML in wikitext | List | Table | Sorting | Colors
- Special input and output
- Inputbox | Special characters | Displaying a formula | Images (uploads) | EasyTimeline
- Advanced functioning
- Template | Advanced templates | Parser function | ParserFunctions | Parameter default
- Variable | Magic word | System message | Substitution | Array | Calculation
- Page management
- Starting a new page | Renaming (moving) a page | Protecting pages | Deleting a page
- Special pages
- Talk page | Testing | Sandbox | CentralNotice