This is a stripped-down version of a single section of Grok TiddlyWiki, optimized for fast loading and readability by search engines. Some features are missing.

For the full Grok TiddlyWiki experience, please visit the wiki version of this page.

Constant strings cannot be combined with transclusions

5th October 2021 at 8:35am

Often we need to build a string of text out of several components, such as variables, constant strings (text that doesn't change), tiddler fields, or filter expressions. It's tempting to simply place the references next to each other, like <<variable>>constant{{!!field}}, but this does not always work correctly, because in many contexts TiddlyWiki requires just one of these items, not several in a row.

Example of the mistake

I want to add a template to the view template which displays an image associated with each tiddler tagged “Artwork”. The image name is the name of the tiddler plus .png. I've tried a number of ways to write this without success.

<!-- Set the current tiddler to this section, so it doesn't matter what tiddler the example snippet is stored in -->
<$tiddler tiddler="Constant strings cannot be combined with transclusions">

1
{{<<currentTiddler>>.png}}

2
[img [<<currentTiddler>>.png]]

3
[img [{{!!title}}.png]]

4
<$image source={{!!title}}.png/>

5
<$image source="{{!!title}}.png"/>

6
<$image source={{!!title}}".png"/>

7
<img src="{{!!title}}.png">

</$tiddler>

1

2

3

4

5

6 <$image source=Constant strings cannot be combined with transclusions".png"/>

7

I'm at my wits' end here. What does TiddlyWiki want from me?

Explanation

Examples 1–3 above are syntax errors because you cannot use transclusions (<<variable>>, <<macro>>, {{field}}, or {{{ filter }}}) inside other links or transclusions. As a rule of thumb, if you're putting brackets inside other brackets with a different shape and you aren't writing a filter, you're probably committing a syntax error.

Examples 4 and 6 are also syntax errors because you cannot combine a transclusion with a constant string within an HTML attribute. You have to pick either one transclusion or one constant string. To put it more broadly, the value of an HTML or widget attribute like src can be exactly one of four things: a "constant string in quotation marks" that never changes, or a transclusion of a {{{ filter result }}}, {{tiddler field}}, or <<macro call/variable reference>> – but never a combination of two or more of those things. (See Summary of Macro and Transclusion Syntax for more on these kinds of transclusion.)

Examples 5 and 7 are valid syntax but don't do what you want. The "double quotation marks" make the entire value of the source or src attribute a constant string – that is, TiddlyWiki doesn't look inside for wikitext and wikify it, it just passes the text on to the $image widget or img tag. As a result, what you're asking TiddlyWiki to do is display an image with the literal title {{!!title}}.png.

To make things a little more complicated, this does work even though what you just learned might suggest it wouldn't:

<$tiddler tiddler="Constant strings cannot be combined with transclusions">

The image should be called "{{!!title}}.png".

</$tiddler>

The image should be called "Constant strings cannot be combined with transclusions.png".

This example differs from the previous ones in that (a) the quotation marks here don't indicate a constant string because they're not used as the value of an HTML or widget attribute – they're just more characters of text to TiddlyWiki here – and (b) TiddlyWiki wikifies anything that ends up directly within the body of a tiddler (rather than in an attribute), including {{!!field transclusions}}.

Solutions

There are two ways to concatenate (smash together) text that needs to be used elsewhere in wikitext or as the value of an attribute: with a filter expression, or with a macro, using text substitution.

With a filter expression

The filter expression is easier to understand and has fewer gotchas, so let's start with that. We use the addsuffix filter operator to add more text to the end an existing input tiddler (or addprefix to add it to the beginning):

<$tiddler tiddler="Constant strings cannot be combined with transclusions">
<$image source={{{ [{!!title}addsuffix[.png]] }}}/>
</$tiddler>

In this particular filter expression, we start with the title of the current tiddler, then add a constant suffix to it. The {{{ triple braces }}} transclude the result of the filter expression directly into a tiddler. We can use constant strings, variables, or fields for any component of the filter, and add as many suffixes or prefixes as we need, so we could say for example:

<$set name="person" value="Soren Bjornstad">
<$set name="role" value="author of Grok TiddlyWiki">

<$text text={{{ [<role>addsuffix[, ]addsuffix<person>addsuffix[.]addprefix[This example is approved by the ]] }}}/>

</$set>
</$set>

This example is approved by the author of Grok TiddlyWiki, Soren Bjornstad.

This approach is still a transclusion, we're just simplifying it to a single transclusion rather than several pieces in a row. So it only works with text that's bound for the body of a tiddler or for an HTML tag or widget attribute; it still doesn't work within things like [[wikitext links]]. This isn't a big deal because there is an associated HTML or widget form for every feature of wikitext, but if you want to use the wikitext form, you might prefer the macro method.

With a macro

To use a macro, we place the concatenation inside a macro, performing text substitution with $dollar signs$ on the part that changes. Then we call the macro as the value of our source attribute:

\define myImageFilename() $(currentTiddler)$.png

<$tiddler tiddler="Constant strings cannot be combined with transclusions">
<$image source=<<myImageFilename>>/>
</$tiddler>

Or, if we prefer, since we're using text substitution, we can even use the wikitext syntax:

\define myImage() [img [$(currentTiddler)$.png]]

<$tiddler tiddler="Constant strings cannot be combined with transclusions">
<<myImage>>
</$tiddler>

If you aren't sure why this works better than the wrong examples, read the Text Substitution section for an explanation.

Notice that we directly substituted a variable into the macro with the $(parenthesized)$ syntax, rather than passing the tiddler title as a parameter and using the $parameter$ syntax. This is because using the result of a macro call inside a macro call, like this, isn't valid syntax:

<$image source=<<myImageFilename <<currentTiddler>>>>/>

As a result, we actually can't pass <<currentTiddler>> in as a parameter; this is an irritating limitation, but for now it's how TiddlyWiki works. See Filters and Transclusions and Using Variables in Macros for more on this situation.

(You can put <<currentTiddler>> in quotation marks to make the syntax valid, but then you're just passing the string <<currentTiddler>> rather than the name of the current tiddler to the macro, which isn't very helpful.)

↑ Common Misunderstandings