Sorry for the wall of text. It turned out to be much longer as I wanted it to be.
Anyway … I hope it helps
TLDR; There is a JSON attachment at the end of the post, you can use to play with.
For the same reasons, why browsers don’t allow to execute arbitrary code from different domains. For security reasons.
Yes. Being a software developer is a bit of a problem, because we are used to think differently.
We think like:
But that’s not the mindset wikitext was developed for.
So try to free your mind and try to be open. (for a bit of history
Wikitext is intended to convert human readable plain text into rendered HTML like so:
* element 1
* element 2
* element 3
to be seen as:
- element 1
- element 2
- element 3
Many users want to show this info more dynamically.
- So if there is a new tiddler the list should automagically grow.
That’s what the list-widget is for. Basically any UI element in TW uses lists in some form.
Since this is a very common usecase, a core developer created a list-links macro for this problem, which does a bit more. It also converts the elements into hyperlinks.
<<list-links filter:"[tag[myElement]]">>
So the “complexity” is completely hidden from the end-user.
BUT … But some users want to create such macros. … OK let’s dig a bit deeper.
For a SW developer we need a “macro specification” right?
- We want an unordered list
<ul>
that
- shows users defined elements as list items
<li>
- a “user defined element” is specified by a tag
- the tag is:
myElement
So the initial implementation will look like this.
<ul>
<$list filter="[tag[myElement]]">
<li><<currentTiddler>></li>
</$list>
</ul>
That’s it. … really … that is what wikitext rendering and variables like <<currenTiddler>>
should do.
Everything that comes now adds additional possibilities to create more sophisticated lists using macros, widgets and transclusions
eg: I want to call it like so: <<myList filter:"[tag[anyTag]]">>
\define myList(filter)
<ul>
<$list filter=<<__filter__>> >
<li><<currentTiddler>></li>
</$list>
</ul>
\end
<<myList filter:"[tag[myElement]]">>
Now think about it. That’s the only usecase that filters are designed for. To be executed by $list-widgets.
So which variables do we need here? … As shown in the example, we need 2 variables:
- the
<<__filter__>>
from a macro parameter
- the
<<currentTiddler>>
as the “loop variable”
<<__filter__>>
comes from the macro call in the content area of the text.
(The __ double-underscore are used because of this)
<<currentTiddler>>
… Is “just” a convention we (the core devs) use for “lists”
So what if we want to be much more flexible. … A new spec is needed.
- The code snippet
<li><<currentTiddler>></li>
is named: element
- The content of the
element
should be a template
- A developer creates a
defaulListElement
which is predefined
- The user should be able to redefine that template
To make the code readable and debuggable we need some more “variables” …
- The custom template should show
- the tiddler title
- and the description field if there is one
- There should be a separator between title and description
- The separator should only be there if needed
– spec end
New code
\define myList(filter template)
<$let elementTemplate={{{ [<__template__>is[blank]then{!!defaultListElement}else<__template__>] }}}>
<ul>
<$list filter=<<__filter__>> >
<$let separator={{{ [all[current]get[description]then[--]] }}}>
<<elementTemplate>>
</$let>
</$list>
</ul>
</$let>
The macro is defined at: <$link $to=<<currentTiddler>>/>
\end
<<myList filter:"[tag[myElement]]" >>
elementTemplate
… is “the outer variable” only needed to be defined once.
separator
… depends on the currenTiddler
variable defined by the list-widget it needs to be defined every iteration
That’s how variables are defined … In a context of “lists” … In TW it’s always like this, because that’s what it was designed for.
There still are the <$set
and the <$vars
widget for backwards compatibility reason. And we don’t have a replacement for <$set name=xx filter="[[filter expression]]"
yet.
This example contains the macro call a custom template as a string
<<myList filter:"[tag[myElement]]" template:"""
<li>
<<currentTiddler>>
<span class="tc-tiny-gap"><<separator>></span>
<$transclude field=description/>
</li>
""">>
Conclusion: The wikify-widget is the last resort if no other way is possible. If $wikify is your standard way to create variables, you’ll get performance problems — You are doing it wrong
The code with the custom template will be more complex. That’s why I did add JSON file, with which interested users can play with.
It contains 3 example tiddlers and 3 tiddlers tagged myElement. I of them has a description field.
- simple-list
- filtered-list-macro
- macro-and-templates
creating-variables-and-list-mindset.json (2.1 KB)