External links from tiddler fields

This is something that has been bugging me for a long time. There appears to be no easy way to render an external link where the URL (or text) is derived from a tiddler field.

I often find myself making link tiddlers where I’ve established the convention of adding the URL to a field of the tiddler and then later to my dismay attempt to render it smartly in the body of the tiddler.

The following work but are not ideal:

  1. {{!!url}}
  2. <a class=“tc-tiddlylink-external” href={{!!url}} target=“_blank” rel=“noopener noreferrer”>My Label</a>

There are some concerns with these approaches as the first will not allow you to adjust the text. And the second is unwieldily to type every time.

I’ve tried the following without success:

  1. [[My Label|{{!!url}}]]
  2. [ext[MyLabel|{{!!url}}]]
  3. <$link to={{!!url}}>My Label</$link>
  4. \procedure extln(label,href) <a class=“…” href=<<href>> target… rel…><<label>></a>
    With <<extln label:”My Label” href:{{!!url}}>>
  5. Use of \define and \function.

Honestly what do I need to get the simplicity of [[label|url]] but with the values being filled in from a tiddler field?

This conversation attempted to address the same issue but I was unable to find a resolution in the thread. So far the only working option is to memorize that complicated <a …> incantation every time and that attempts to DRY this to a \function or \procedure won’t work as one would expect.

How about an interface like this?

<<ext-link "My Label">>  <!-- defaults to field named "url" -->

<<ext-link "Another label" location>> <!-- but you can override it with another field name -->

If that would do, then we could write it like this:

\procedure ext-link(label, field:"url")
  <a 
    class=“tc-tiddlylink-external” 
    href={{{ [<currentTiddler>get<field>] }}} 
    target=“_blank” 
    rel=“noopener noreferrer”
  ><<label>></a>
\end

We could easily add another optional parameter for the tiddler to query, defaulting to <<currentTiddler>>.

This solution is not a panacea. It only works on a field name. That may be enough. But if you want to be able to pass an arbitrary value, it’s fine, but won’t work with a short-form procedure call, which only accept string parameters. (That’s why your #4 fails.) I’d love to see this in embedded syntax, and not a procedure/macro call. That is, it would be great if your #1 or #2 could be made to work. I don’t know how difficult that would be, or even if it’s fundamentally impossible. #3 won’t work for the simple reason that the $link widget is designed for internal links. I think this manages to do #5, except using a procedure rather than a macro.

I would like to point out this is a perfect example of when to make use of tiddlywiki script to write a reusable macro or procedure.

later when I am on my desktop I can share other solutions as well.

1 Like

Ahh that is the magic incantation I needed. Thank you!

1 Like

I also wish there was a way to mark a string as needs WikiText processing after interpolation. Something like <$wiki>[ext[foo|{{transclude}}]]</$wiki> maybe?

It is odd though that it isn’t easy to “write some wikitext but get the value from a transclude” There are other cases when we can’t use the {{transclude}} syntax and it gets very confusing when and where you can. I seem have the same issue with <<var>> text as well. I’m so used to template languages like JSX, Handlebars, etc. where you can drop a {{lookup from something}} and have it be part of the output. TiddlyWiki turns this on and off based on where or how it is used and the rules are either hidden in the documentation or are a form of tribal knowledge.

This was functionality I had looked into a while back but i don’t think anything came of it here :pensive:

It would be nice if we could apply templates to wikilinks using syntax like “[[Hello||externalField]]” and then making a template tiddler for something like <$transclude $tiddler=<<currentTiddler>> field="external"/> or something like that, like what can be done with {{HelloThere||$:/core/ui/TagTemplate}}

{{transclude}}, {{!!field}}, and <<var>> can be used as widget attributes but not in what I think of as “short-form” wikitext — that is, the inline, Markdown-like shortcuts that are syntactic sugar for the underlying widgets. I’m not sure whether this is expressly stated in any “top-level” overviews, but it does come up in some of the wikitext-specific docs, like the “Generating dynamic links” section of Linking in WikiText:

“Short-form” macrocalls (or procedurecalls, or functioncalls, if you will) are subject to the same limitations. For a hypothetical link macro:

<<link label:"Google" url:"http://google.com">> <!-- parameters are always assumed to be literal values, so literal strings are fine -->
<<link label:<<label>> url:{{!!url}}>> <!-- variables and transclusions won't work -->

<!-- but either of the following widgets will work -->
<$macrocall $name="link" label=<<label>> url={{!!url}} />
<$transclude $variable="link" label=<<label>> url={{!!url}} />

Thank you for the explanation. Though I’m still confused why it needs to be so complicated and how those who know enough to write WikiText but might not have such in depth knowledge could do this.

Maybe if we could have a built-in method to do this? Or a tiddler in the main docs that helps people who what this to copy paste something that works.

One of the gotchas I ran into was that the LinkWidget docs mention at the top that if you want an external link use <a> but that is not true as <a href=…>…</a> these are drastically different to <a class=“tc-tiddlylink-external” target=“_blank” rel=“noopener noreferrer” href=…>…</a> which I now have to memorize across all my wikis.

There are some cases where the old \define macro syntax has an advantage because it can perform “lexical substitution” of macro parameter values.

Try this:

\define ext(label,url) <a href=$url$ _target=blank>$label$</a>

<<ext "some text" "{{!!url}}">>

Note how both parameters are quoted in the short-form macro call. This prevents their values from being parsed before being passed into the macro. Then, inside the macro, the $url$ and $label$ substitutions are performed, and the resulting HTML syntax is returned for rendering by the usual TWCore wikitext processing.

In addition, this technique not only works with "{{!!fieldname}}" transclusions, but also with "<<variablename>>" references and even filtered transclusions such as "{{{ [[https://]] [{!!fieldname}] +[join[]] }}}"

enjoy,
-e

5 Likes

With respect I think your error is to rely on shortcuts, to make shortcuts.

For example {{!!url}} is a shortcut to display the contents of the url fieldname. The long cut would be the ‘a’ record in @Scott_Sauyet s macro, or <$transclude $field=url/> however you now want to add a pretty link, information that you need to provide eg “My Lable”.

  • So I would endorse Scotts solution, and put it in a helper tiddler tagged $:/tags/Global along with other macros and tools that are importiant to you. You can then go to my bookmarklets site and place a bookmarklet in your browser, this can then be installed on any wiki with a click.

However

We can get even smarter, personaly I use a small package of tiddlers including a view template tiddler that scans all fields on the current tiddler, and if it finds any containing a value starting http or https generates a link to the external resource using the fieldname as the pretty link.
link-fields.json (1.2 KB) but it is already on the bookmarklets site for a quick install link-fields

  • Using this method you do nothing more than what you have already done and save the external link in a field.

Going much further

I have in the past extended this much further permitting urls to be dropped on a tiddler and added to a link-n field, allow the fieldname thus pretty link to be renamed, allow the creation of an “external link” tiddler allowing additional link related information and tools including notes, tags, iframe view and more.

Back to shortcuts

@Scott_Sauyet’s macro, my solution and other ideas here are in effect shortcuts, if an when there is sufficent demand we may have an additional feature added to the core to enhance the core shortcuts, but if its a less common requirement we tend not to. What about pretty links to urls in other tiddlers, or data tiddlers. There are many things that could be given shortcuts, so we need to choose.

Here’s another type of “shortcut” using a template:

  1. Create a new tiddler and name it ext. Paste this code inside its text field:
<$parameters label><a class="tc-tiddlylink-external" target="_blank" rel="noopener noreferrer" href={{!!title}}><<label>></a></$parameters>

[Edited to fix “smart quotes”]

  1. Create another tiddler, name it whatever you want, and populate its url field with an external url, ie https://www.tiddlywiki.com. In its text field, paste this:
{{!!url||ext|TW main site}}

It means: get current tiddler’s url field, transclude it through the ext template using “TW main site” as a label.

With this syntax:

  • The url can’t be a variable, only a TextReference or a literal text.
  • The label must be a literal text.

So this would also work:

{{https://www.tiddlywiki.com||ext|TW main site}}
{{another-tiddler!!another-field||ext|Fancy label}}

Fred

3 Likes

Great stuff @tw-FRed

you could add additional parameters to alter defaults including a named target window, if desired and document the long form as well, because with lots of parameters it’s nicer to used named parameters rather than positional parameters

if label is not given you could automate it by extracting it from the first value.

You could also make it handle use of the triple curly braces allowing a filtered transclusion.

:heart_decoration:

@tw-FRed I am just using a version of the above ext and note I have to change the quotes from “” to "" and the url form is not working. Just looking now.

There is a pending PR, which may probably fix that. See: Dynamic parameters for macro/procedure/function calls by Jermolene · Pull Request #9055 · TiddlyWiki/TiddlyWiki5 · GitHub

1 Like

Indirectly addressing this Delimiting parameters with = and : can brick your wiki

I’ll leave these enhancements up to the readers as exercise :wink:

Oh! It looks like copy-pasting code from my test tiddlers on tiddlywiki.com @sukima 's message introduced “smart quotes”! I’ll fix my post promptly! Thanks!