How can I enlist a field containing a list of external links?

This might be an incredibly stupid question, but it’s been driving me crazy for the past hour or so.

Let’s say I have a tiddler with a field called links, containing a list of tiddler titles like so: [[Tiddler1]] [[SomeOtherTiddler]] [[Another tiddler with spaces]] and I’d like to list those links in bullet point format. TW makes this really easy, just use:

<<list-links filter:"[{!!links}enlist-input[]sort[]]">>

And it works as you’d expect.

But now, let’s say I want to have those links be external rather than tiddler titles, and let’s say that (because these links are quite long), I’d like to have them shortened. Trying to use the standard notation that you would use in wikitext, i.e.: [[shortlink|https://some-super-long-link-somewhere.com/]], hasn’t worked at all. enlist and enlist-input always assume a tiddler title and output a link to shortlink|https://some-super-long-link-somewhere.com/.

So this makes me wonder: How do I make this work? How can I, given a list of links in a field, such as:

[[link1|https://somelinkijustcameupwith.c/]] [[second link|https://www.somewhereelse.c/]]

Transform it into:

Somehow, this seems like it should be so easy, and yet I can’t get it working. I’ve tried various filters and searched online to no avail. I have been thinking of simply creating the list of links via html in the field itself, but I don’t really like this, as I prefer to keep my fields as pure information repositories, and leave any kind of formatting or display decisions to the tiddlers / templates that actually use that information.

It’s pretty easy to hit the limits of list-links. It was really meant for local tiddlers, not external references. If you really want to store your links in the way you suggest, then you will probably have to roll your own lister:

<$vars pipe="|">
<ul>
<$list filter="[{!!links}enlist-input[]sort[]]">
<li><a href={{{ [<currentTiddler>split<pipe>last[]] }}}><$text text={{{ [<currentTiddler>split<pipe>first[]] }}}/></a> </li>
</$list>
</ul>
</$vars>
1 Like

You can do it with only a single filter.

{{{ [{my-links-tiddler!!links}enlist-input[]search-replace::regexp[(.*)\|(.*)],[<li><$link to="$2">$1</$link></li>]join[]addprefix[<ul>]addsuffix[</ul>]] }}}
3 Likes

Thats interesting and similar to my approach but you are storing the pretty name with the http link, which is a display component. However I think @jypre has provided the solution to operate with your existing data.

I just thought you may be interested in my approach where the field name is used for the pretty name and the value is http… Url link.

  • I detect link fields by those with a value beginning http
  • So the list is not a single field but multiple fields.
  • although I often use the same field like “discussion” for links here.

Your approach is interesting and jypr’s solution great, but there remains other gaps in handling external links such as including a target with a link. To do this I have actualy stored the full html link a tag in a field.

That would be cool if it worked. Using search-replace might be a good choice in some other context. Here’s the things that need to change:

  • You can’t use angle brackets (or pipes?) in regular expressions in filter runs – they have to be put into variables.
  • The <$link> widget doesn’t work with external links. You have to use <a> anchors.
  • The regular expression shouldn’t look for square brackets.
  • The whole thing needs to be wikified or the whole thing will be just one big link.

By the time you’ve made these changes, you no longer have a single-filter solution. But it is a cool idea to use search-replace to get two things out of one title list.

Mark, see Linking in WikiText expecialy External Links and [ext[TW5|https://tiddlywiki.com]] if there is not a long form of this shortcut form perhaps we could make one. Like [img[https://tiddlywiki.com/favicon.ico]] has the ImageWidget

On further reflection we could use a custom widget to masqurade as the $link widget and test if the to parameter contains an external link and treat it differently or pass it through to the real link widget.

It might be possible to do it with ext[]. I had forgotten about that. But just like <$link>, it will have to be conveyed using variables. There may also be complications from double-interpretation of square brackets.

I’ve attached my code showing the two methods I described. You can play with it and see if it works with ext[] as well.

External Links in List Field.json (766 Bytes)

<$vars 
  rgx1="""(.*)\|(.*)"""
  rgx2="""<li><a href="$2">$1</a></li>"""
  ul1="<ul>" 
  ul2="</ul>"
>
<$wikify name=out text="""{{{ [{!!links}enlist-input[]search-replace::regexp<rgx1>,<rgx2>]+[join[]addprefix<ul1>addsuffix<ul2>] }}}""" >
<<out>>
</$wikify>
</$vars>
1 Like

I just went back to the root question;

[[shortlink|https://some-super-long-link-somewhere.com/]] [[hello|HelloThere]]

  • Note it contains external and internal links.
  • Interestingly the following works {{!!list-field}}

But with other approaches I am getting unexpected results

Thank you to everyone for the answers, they were very educational. Just wanted to say that this solution worked like a charm.

1 Like

@Mark_S My regexp works, I checked it before posting. pipes in regexp are fine. It does nos looks for square brackets and does not contain any either. I am not writing wiki code because it was simpler to write html code (no sqare bracket needed!) and because that code is supposedly only for display (no later editing).

regexp are not the tool for everything but they are often very simplifying the filter steps for the price of a regexp. If the regexp is not too cumbersome, they can also offer a better understanding of what was and what will be.

You’re right about the square brackets!

How did you test?

I created a tiddler with field links and the contents that Riverstream indicated.

I pasted in your filtered transclusion:

{{{ [{!!links}enlist-input[]search-replace::regexp[(.*)\|(.*)],[<li><$link to="$2">$1</$link></li>]join[]addprefix[<ul>]addsuffix[</ul>]] }}}

The only change I made was to use the current tiddler (which has the links field).

I get:

Filter error: Missing closing bracket in filter expression

I could not get it to work at all without putting the regular expression in a variable:

<$vars 
rgx1="(.*)\|(.*)" 
>
{{{ [{ThisTiddler!!links}enlist-input[]search-replace::regexp<rgx1>,[<li><$link to="$2">$1</$link></li>]join[]addprefix[<ul>]addsuffix[</ul>]] }}} 

</$vars>

However, the output could not be used as is because it’s all output as links:

image

The output would need to be wikified.

I guess if we had wikified filtered transclusions, maybe with four braces, we could do it all in one step {{{{ filter }}}} → actual code.

@Mark_S Yes I actually output html links directly!

Like images gallery, I usually store them in a separate tiddler and then loop over the output.

https://neotw.vercel.app/#list-links.json:list-links.json%20links-gallery

Keep in mind if you have what we could call a variable, containing wikitext/html you can now “render it” with the <$transclude $variable=<<varname>> ..

Perhaps try this with your output @Mark_S