Filters and prefixes

The idea is to get the contents of the ‘caption’ field on an image tiddler displayed in the current tiddler. It is all part of the issue of finding a method of displaying an image caption with the Spotlight plugin.

I am trying to get the syntax correct for this filter, but it is proving elusive:

{{{ [<storyTiddler>_images:all[]get[caption]join[ ]] }}}

or maybe this version

{{{ [<storyTiddler>_images:all[]:map[get[caption]else{!!title}]join[\n] ] }}}

I have tried various versions but they either display nothing, or have a syntax error.

In context, this filter sits inside this procedure:

<!-- also needs SQ Filters plugin -->
\procedure spotlight-actions()
<$action-spotlight
	$images={{{ [<storyTiddler>_images:all[]format:titlelist[]join[ ]] }}}
        $labels={{{ [<storyTiddler>_images:all[]get[caption]join[ ]] }}}
	$start=<<dom-src>>
/>

\end

<$eventcatcher $click=<<spotlight-actions>> selector="img" class="spotlight-mixmedia-example">

If the $labels parameter is supposed to contain a caption for each image title in the $images parameter, then this should work:

{{{ [<storyTiddler>_images:all[]] :map[{!!caption}!is[blank]else<currentTiddler>] +[format:titlelist[]join[ ]] }}} 

Tell me how it goes!

Fred

3 Likes

A step closer. The good news it excutes without an error, but it’s retrurning the path to the image file rather than the content of the caption field of the tiddler that contains it.

Looks like the _images operator automagically extracts _canonical_uri field, so we have to get back to tiddler title before getting the caption.

Try this and tell me if it works:

{{{ [<storyTiddler>_images:all[]] :map[all[tiddlers]_canonical_uri<currentTiddler>else<currentTiddler>get[caption]!is[blank]else<currentTiddler>] +[format:titlelist[]join[ ]] }}} 

I hope your tiddlers don’t include many images, as this filter might be quite slow!

Fred

1 Like

Now that works! i generally only have one image in a tiddler. Now it’s working do you think it could be simplified/shortened?

I don’t know to shorten it, no. Why would you want that?

Fred

1 Like

Only if we can make it more efficient.

Fred’s filter is already very well-constructed; the only part I think you could remove is !is[blank] as get automatically discards blank results. But if you’re looking for a visually simpler alternative, you could use a custom function to make the code a little easier to read:

\function get.caption()
[all[tiddlers]_canonical_uri<currentTiddler>]
~[<currentTiddler>]
:map[get[caption]else<currentTiddler>]
\end

{{{ [<storyTiddler>_images:all[]] :map[get.caption[]] +[format:titlelist[]join[ ]] }}}

Or if you prefer, you could substitute {!!title} for <currentTiddler> to save a few more characters:

\function get.caption()
[all[tiddlers]_canonical_uri{!!title}]
~[{!!title}]
:map[get[caption]else{!!title}]
\end

In both cases, I’ve moved the contents of the :map[...] filter run to the custom function get.caption. This allows us to rewrite it as the output of several filter runs, which some may find a little easier to follow. Here’s a line-by-line break-down — and note that since we’re using this function in a :map run, {!!title}/<currentTiddler> refers to each output of the previous filter, i.e. each image appearing in <<storyTiddler>>.

  • [all[tiddlers]_canonical_uri{!!title}]: Find the first tiddler whose _canonical_uri field matches {!!title}.
  • ~[{!!title}]: If no such tiddler exists, use {!!title} as the fallback value.
  • :map[get[caption]else{!!title}]: For the output of the previous steps, get the caption; if there is no non-blank caption field, use {!!title} instead.

If you use either version, the \function definition needs to go at the top of your tiddler, along with any other pragmas you may be using in the tiddler.

3 Likes