You are right, It is not immediately obvious, but there are some interesting mechanisms involved. Let’s start at the beginning, because it is important for context.
TiddlyWiki Conepts
- A) Everything it TiddlyWiki is a tiddler
- B) WikiText is a concise, expressive way of typing a wide range of text formatting, hypertext and interactive features.
- C) TiddlyWiki’s display is driven by an underlaying collection of widgets
Wikitext Rules
TW wikitext follows several rules. To identify a paragraph it looks like this:
- If wikitext is followed by 2 new-line characters, it is a paragraph.
- If text within a tiddler ends without any new-lines, it is a paragraph.
- If a paragraph is identified, use that text and inspect it, if there are “formatting rules”, like bold, italic and so on.
There are similar rules for eg: Headings, Comment block, Code blocks … and so on. Let’s continue with
Formatting Rules
- Bold text can be created using 2 single-quotes as start- and end-marker:
''bold text''
- Italic text can be created using 2 forward slashes as start- and end-marker:
//italic text//
Let’s go with bold. Usually bold text means that something is important or of special interest.
So we need to know how we can define “important” text in HTML syntax. It is: <strong>: The Strong Importance element - HTML: HyperText Markup Language | MDN
That’s the goal
We need a way to go from ''important''
to <strong>important</strong>
Wikitext Parsing
To achieve this goal, in TW there are 3 elements needed.
- A text parser, that converts human readable text into a computer readable text description following the “fundamental rules”. We call this description: parse-tree
- Some javascript logic, that reads the parse-tree and converts it into TW widgets. We call it widget-tree
- Some javascript code, that converts the widget-tree to HTML elements. We call that one “the renderer”
Why do we need those steps?
Because text parsing is “expensive” in terms of CPU cycles needed. So in instead of parsing and rendering HTML text over and over again, whenever a tiddler is displayed, we try to re-use as much information we have, to speed up the rendering.
Why is the parser performance sensitive?
Because of the “Wikitext Rules” that I pointed out above. In reality there are:
- 14 “block rules” similar to paragraph
- 24 “inline rules” like “bold”, “italic” and so on. And there are
- 8 “pragma” rules like
\function, \procedure
and so on
The whole wikitext has to be checked by those rules character by character.
- Starting with “pragmas”, which are valid on a per tiddler base
- Next “block rules” are used to identify blocks, like paragraphs and headings
- If a block is identified, it has to be handed over to the inline-parser
- The inline-parser identifies “Formatting Rules”
What can we do to make it performant?
We try to parse wikitext only once. That means, if a tiddler is shown, we can have a look, if it has been parsed already and we can reuse the parse-tree.
OK → But how does a parse-tree look like
Eg. text: ''important''
-
The TW editor can show the parse-tree if the “Internals Plugin” is installed.
-
Since there is only one line in this tiddler Wikitext Rule - 2 (see above) is active. The whole line is covered in a P(aragraph) element
-
The P element has some children
-
The Formatting Rule - bold was triggered by ''
-
As described above uses the HTML element <strong>
, which they describe as html-tags. The STRONG tag has 1 child.
-
The child of STRONG is a HTML TEXT element, which starts at character position. 2 and ends at character position: 11 (9)
-
The P tag starts at: 0 and ends at: 13
-
The wikitext rule “bold” was identified from (0 → 13)
The parse-tree does not change, except the tiddler is changed. So it is the perfect candidate to be stored and reused internally.
Good – performance improved – What’s next?
As written above at: TiddlyWiki Conepts → C
- C) TiddlyWiki’s display is driven by an underlaying collection of widgets
The parse tree has to be converted to a widget-tree, which already looks very much like the HTML DOM-tree, that browser use to render HTML content. See: DOM (Document Object Model) - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
We can switch the editor preview mode to “widget tree”
-
As seen above in C) widgets are used to “render” the HTML content. TW widgets do have a javascript .render()
and a .refresh()
function
-
There is an element-widget, which renders HTML elements. In this case P tag, a paragraph
-
Inside the paragraph there is a STRONG tag also created by the element widget
-
TEXT is a basic HTML DOM node itself and is rendered as plain text.
That is it - We achieved “the goal”
If we switch the preview to “raw HTML”, we do get:
<p><strong>important</strong></p>
But, but – Then we could directly use HTML Code – and bypass all the parsing and widgeting stuff.
Yes we can – use HTML code directly.
But.
No we can not bypass the parse- and widget-tree for security reasons.
Even if we directly write <p><strong>important</strong></p>
into the TW editor.
The whole thing will start at:
Wikitext Rules, but instead of parsing wikitext, we will now parse HTML text
Why did you mention .render()
and .refresh()
in widgets
Because TW widgets use those js-functions to finally convert the internal data-structure called widget-tree into HTML DOM nodes. .render() is used to create DOM nodes.
Since manipulating the DOM can be slow, TW uses “refresh()” only if the widget-tree changes. This is especially important for the list-widget.
One more optimization to be performant
@Surge … That should finally answer your “purely scientific question”.
Hope that makes sense.
Have fun!
Mario