Wikification, in TiddlyWiki, is the process of taking wikitext and turning it into pure HTML that a browser can read directly (or, occasionally, into plain text or some other format). This includes processing markup like //italics//
, rendering widgets, calling procedures, transcluding other tiddlers, and so on.
Wikification can be understood as a sort of pre-processing or pre-rendering: first TiddlyWiki renders the wikitext into HTML, then your browser renders the HTML on your screen.
When wikification happens
Obviously, processing and formatting wikitext is one of the most essential functions of TiddlyWiki. It happens any time a tiddler is displayed. However, just because you put some wikitext somewhere in TiddlyWiki does not guarantee it will be wikified.
In general, any time a chunk of wikitext ends up in the body of a tiddler that is being displayed, TiddlyWiki tries to wikify it. The chunk might be the entire text of the tiddler or the result of a single transclusion (in the most general sense, including field transclusions, variable transclusions, procedure calls, macro calls, and transcluded filter expressions). If the result of wikifying one of these things still contains wikifiable wikitext – for instance, the result of wikifying the {{tiddler!!field}}
transclusion syntax is some wikitext contained in the field
field – TiddlyWiki will try to wikify that as well. It will repeat this step until there is no more unwikified wikitext, or until it detects that it has gotten stuck in an infinite loop (recall Ex:SelfTransclusion).
However, there is one huge exception: when you use a variable or field transclusion as a parameter to an HTML or widget attribute, the result of this transclusion is not wikified. In other words, TiddlyWiki doesn't attempt to repeatedly wikify the result of the initial transclusion like it does with body text; it does it exactly once and then stops.
This will become more clear with an example:
<$let testVar1="XYZ">
<$let testVar2="<<testVar1>>">
<<testVar2>>
</$let>
</$let>
XYZ
As you can see, XYZ
is rendered by this snippet. Let's follow along with TiddlyWiki to see why:
- In the first
$let
widget, the variabletestVar1
gets set to the textXYZ
. - In the second
$let
widget, the variabletestVar2
gets set to the text<<testVar1>>
. - The variable
<<testVar2>>
is used directly within the body of the tiddler. When rendering the tiddler, TiddlyWiki comes to this variable transclusion and looks up the value of the variabletestVar2
; it finds the text<<testVar1>>
. <<testVar1>>
is a new chunk of wikitext that can be further processed, so TiddlyWiki wikifies that as well. This time that process finds another variable transclusion, and it substitutes the value of the variabletestVar1
, yieldingXYZ
.- At this point, there is nothing left to do with the text
XYZ
, since it is already plain text with no wikitext syntax, so TiddlyWiki sends the textXYZ
to your browser to display and moves on to the rest of the tiddler.
However, if we make a minor change so that testVar2
is the attribute of a widget…
<$let testVar1="XYZ">
<$let testVar2="<<testVar1>>">
<$text text=<<testVar2>>/>
</$let>
</$let>
<<testVar1>>
…now the literal text <<testVar1>>
prints out:
- In the first
$let
widget, the variabletestVar1
gets set to the textXYZ
. - In the second
$let
widget, the variabletestVar2
gets set to the text<<testVar1>>
. <<testVar2>>
is used as an HTML attribute. When rendering the tiddler, TiddlyWiki comes to this variable transclusion and looks up the value of the variabletestVar2
; it finds<<testVar1>>
.- Because this is an HTML attribute, TiddlyWiki does not attempt to wikify the result,
<<testVar1>>
, again; instead, it passes it directly to the$text
widget. - The
$text
widget sees that it's been asked to display the text<<testVar1>>
, so it does so.
You might initially think this has something to do with the $text
widget in particular, since that widget's usual use is to inhibit wikification or formatting, but that isn't the case; it applies to any widget or HTML tag, as we'll see in a moment.
(Note: Using a single $let
widget instead of two in the above examples would have exactly the same effect as using two separate ones; we've simply left them separate in this example to make the order of operations as clear as possible.)
Manual wikification
That was a good example for demonstrating what TiddlyWiki does and does not wikify, but it didn't do anything useful, so at this point it may be hard to see why it matters that TiddlyWiki does not repeatedly wikify attributes. As a more practical example, let's suppose that we're creating a wiki about animals, and we want to include a picture of each animal in its corresponding tiddler. We might add an imageurl
field to each tiddler to store the URL of an appropriate image. We then want to create a template, called TiddlerImage
, that displays the image found in the imageurl
field of the current tiddler.
Let's try this in our sample wiki. We can start the TiddlerImage
tiddler with the HTML syntax for an image:
<img src={{!!imageurl}}>
Now, if we populate the imageurl
field on some tiddler with a URL and include the template transclusion {{||TiddlerImage}}
, the image will appear. If you don't have an image URL handy, you can use this picture of a cat: https://upload.wikimedia.org/wikipedia/commons/b/bb/Kittyply_edit1.jpg?download
.
However, what if you want to keep part of the URL in another tiddler? In the above URL, perhaps we are using a lot of images from Wikimedia Commons in our wiki, and we want to store the base URL https://upload.wikimedia.org/wikipedia/commons
in a tiddler called WikimediaCommonsUrl
. Then in the imageurl
we could just use: {{WikimediaCommonsUrl}}/b/bb/Kittyply_edit1.jpg?download
. This way, if Wikimedia Commons ever changes its web address (unlikely, to be sure!), we can quickly update all our links.
If you try this, though, you'll find that the image doesn't appear; instead a “broken image” icon will appear. Since it might be hard to see exactly why it doesn't work, try selecting the image with your browser's element inspector (if you've forgotten how that works, review When Things Go Wrong). After a close look at the HTML, the problem should be obvious: the src
attribute literally begins with {{WikimediaCommonsUrl}}
, it hasn't been replaced with the contents of that tiddler. Since that isn't a valid URL of an image, no image is displayed.
How, then, can we get the transclusion to expand? What we need is a way to wikify the wikitext while it's still in a variable, rather than waiting until it's actually rendered as part of a tiddler (because it never will be rendered as part of a tiddler the way we're using it). The appropriately named $wikify
widget provides this capability. We can modify our example to use this widget as follows:
<$wikify name="wikifiedImageUrl" text={{!!imageurl}}>
<img src=<<wikifiedImageUrl>>>
</$wikify>
If you try again using this snippet, you'll find that the image appears as expected.
The $wikify
widget has several other options, such as the format to parse the text into (plain text, HTML, a JSON parse tree, and so on). You can read about them in the documentation on https://tiddlywiki.com.
Parameter and variable references in macros and procedures require wikification
It is worth pointing out that both <<variable references>>
and <<__macro-parameter-as-variable references__>>
are not evaluated until they are wikified, which means that such references do not work at all when their containing procedure or macro is used directly as the value of an HTML or widget attribute:
\procedure myText(text) Text: <<text>>
* ''OK:'' <<myText "test text">>
* ''Bad:'' <$text text=<<myText "test text">>/>
- OK: Text: test text
- Bad: Text: <<text>>
You can fix this by manually wikifying:
\procedure myText(text) Text: <<text>>
''OK:'' <<myText "test text">>
<$wikify name="wikitext" text="""<<myText "test text">>""">
''Also OK:'' <$text text=<<wikitext>>/>
</$wikify>
OK: Text: test text
Also OK: Text: test text
If you use a macro, you can also use text substitution to get the result you want, and this is one of the key scenarios in which macros may remain more convenient than procedures:
\define myText(text) Text: $text$
* ''OK:'' <<myText "test text">>
* ''Also OK:'' <$text text=<<myText "test text">>/>
- OK: Text: test text
- Also OK: Text: test text
Exercises
Add the following snippet to a new tiddler:
\define wikipediaLink(articleName)
https://en.wikipedia.org/wiki/$articleName$
\end
<$transclude $variable="wikipediaLink" articleName={{!!wikipedia-article}}/>
Alter this snippet so the contents of the wikipedia-article
field on the current tiddler can be a transclusion of a different tiddler field. (As it stands, the transclusion will render, but not as part of a link, since the transclusion within the wikipedia-article
field is only seen after being returned from the wikipediaLink
macro.)
In this snippet, we had to quote the value of text
in the $wikify
widget (using triple quotes, since the text we were quoting contained single quotes). What goes wrong if we don't quote it? Why do you think this happens?
\procedure myText(text) Text: <<text>>
''OK:'' <<myText "test text">>
<$wikify name="wikitext" text="""<<myText "test text">>""">
''Also OK:'' <$text text=<<wikitext>>/>
</$wikify>
OK: Text: test text
Also OK: Text: test text