Help with getting an evaluated macro into an HTML attribute

Hi. I have a global macro named “time_of_day”.

\define time_of_day()
<$list filter="[<now hh>compare:number:gt[5]compare:number:lt[12]]">
morning
</$list>

<$list filter="[<now hh>compare:number:gt[11]compare:number:lt[19]]">
afternoon
</$list>

<$list filter="[<now hh>compare:number:gt[18]compare:number:lt[24]]">
evening
</$list>

<$list filter="[<now hh>compare:number:gt[0]compare:number:lt[6]]">
night
</$list>
\end

I am trying to get it to return a value in the context of an HTML attribute:

<$link to=Welcome>
<div id='covertiddler' class=<<time_of_day>>></div>
</$link>

I am expecting it to return as

<$link to=Welcome>
<div id='covertiddler' class=evening></div>
</$link>

Instead, I am getting the entire macro piped into the attribute.

I have tried using the set and wikify widget and have still not figured out how to do this correctly.

I’ve moved around items in your macro in order to eliminate extra space characters.

Then the macro gets fed to wikify, the output variable of which gets used inside the div tag. Using “inspect”, I verified that the class was being properly interpreted.

\define time_of_day()
<$list filter="[<now hh>compare:number:gt[5]compare:number:lt[12]]">morning</$list><$list filter="[<now hh>compare:number:gt[11]compare:number:lt[19]]">afternoon</$list><$list filter="[<now hh>compare:number:gt[18]compare:number:lt[24]]">evening</$list><$list filter="[<now hh>compare:number:gt[0]compare:number:lt[6]]">night</$list>
\end

<$wikify text=<<time_of_day>> name="tod">

<$link to=Welcome>
<div id='covertiddler' class=<<tod>>></div>
</$link>

</$wikify>
1 Like

That works! I would never have suspected the extra spaces being an issue. Thank you!

Here’s another, more compact way to write things:

\define time_of_day()
\whitespace trim
<$list filter="[range[ 0],[ 5]match<now hh>]">night</$list>
<$list filter="[range[ 6],[12]match<now hh>]">morning</$list>
<$list filter="[range[13],[18]match<now hh>]">afternoon</$list>
<$list filter="[range[19],[23]match<now hh>]">evening</$list>
\end

<$wikify text=<<time_of_day>> name="tod">
<div class=<<tod>>><$link to=Welcome/></div>
</$wikify>

Notes:

  • Macro are not functions. They don’t “evaluate their contents and return the result”. They are just “named text substitutions”. The macro content is simply inserted in place of the “calling reference”. If the calling reference occurs directly within a “wikitext” context, it is then rendered in place to produce the final result. If the calling reference is used as a widget parameter value, the macro content is left unrendered and simply passed along to the widget for any further handling.

  • Note that macro processing does make some specialized replacements of $param$ and $(variable)$ within the macro content before “returning” it for insertion:

    • Instances of $param$ are replaced by the value of the corresponding named parameter passed into the macro. If no such parameter name is defined, the $param$ reference is left unchanged (as opposed to being removed from the macro output).
    • Instances of $(variable)$ are replaced by the value of the corresponding variable defined outside the macro. If no such variable is defined, the $(variable)$ reference is removed from the macro output.
  • \whitespace trim at the beginning of the macro automatically eliminates the newlines from the output. This allows you to put the different $list widgets on separate lines without affecting the result

  • In my version of the time_of_day() macro, rather than numerically comparing the hour number, I’ve used the range[...],[...] filter operator to generate a list of appropriate hour number literals and then check to see if any of those literals match with the current hour. If a match occurs, the corresponding text output (“morning”, “afternoon”, “evening” or “night”) is produced.

  • The $wikify widget actually renders it’s text=... attribute, storing the resulting output in the variable indicated by the name=... attribute. Thus, <$wikify text=<<time_of_day>> name="tod"> sets tod equal to the rendered output of the <<time_of_day>> macro, producing the result you expected (i.e., just the text “morning”, “afternoon”, “evening” or “night”).

  • The $link widget contents are used to display the text of the specified link. In your code (@Mark_S’s adaptation as well), the $link contents don’t produce any visible output. Thus, although an <a> element is created by the $link widget, nothing is displayed. To address this, I moved the <div class=<<tod>>> syntax to surround the $link widget.

  • As a general rule in TiddlyWiki, you should avoid using id=... within HTML syntax, as the id value is expected to be unique within the entire TiddlyWiki file. However, since tiddler content can potentially be re-displayed in multiple places, this can result in multiple instances of the same id value occuring within the TiddlyWiki file.

  • Since the $link widget now has no explicit content, I used the “short form” of the widget (i.e., <$link to=Welcome/>) which defines the <a> element and also uses the tiddler title (i.e., Welcome) as the default text to display for the link.

Hope this helps,
-e

3 Likes