Exploring default tiddler links hackability in V5.3.0

Jeremy I do understand this is a solution to meeting the design requirement I ask. I suppose I need to understand how this works going forward when it comes to integrating changes into tiddlywiki in the future. Let me illustrate with the example in this thread.

  • To be clear I am in a research phase trying to explore different ways to achieve this.
  • Also I look forward to the release of tw 5.3.0 but perhaps this idea could actually be implemented in that release?

Lets say my idea in the OT, not the method but the result, is accepted as a powerful and necessary addition to tiddlywikis hackability. Would the “redefinition of the link widget” become part of tiddlywiki or would we look at a deeper modification?

  • As we do now I could see a plugin being written to change the behaviour of the parsing of standard links. It will likely demand an overwrite of some core tiddlers. If someone wants to install it, they can and make use of this altered behaviour. If compelling we may then consider implementing this hackability in the core. I suppose in many cases the plugins changes would be incorporated into core tiddlers.
  • If however we make use of the widget pragma, to redefine the current behaviours, allowing hackability of standard links, would we leave the existing core tiddlers as is and include the widget pragma that redefines the link widget or parsing into the core distribution?
    • Going forward would we use the widget pragma to implement changes in the core or only for on demand changes in behaviour?

My impression is that redefining the link widget may be a way to prototype the idea in this topic, but it is not necessarily the way to implement this idea into the core. Hence I now seek clarification.

  • To me this topic was raised to solicit information about how we may look at adding this hackability to the core (in the long run).

Why would I want this considered as a core hack?

  • I believe The power in this idea comes about if all users and developers gain access to this same hackable feature.
  • In some ways it could be argued this is part of tiddlywiki’s operation that lacks the hackability that other similar parts already have, that is its a gap. eg; we can customise all list item templates, not standard links.
  • A little more subtle than that, retain the existing behaviour unless particular conditions arises, as a result arguably we must change the existing behaviour everywhere should such condition arise.
  • It may need a change in the parsing in addition to or instead of altering the link widget.

Thanks @btheado I will look into this today

I’m not sure, but I think you are saying that you need to override the $link widget everywhere in order to make it useful for you. That makes sense and I don’t expect otherwise.

That’s where the $:/tags/Macro tag comes in. If the tiddler defining your widget has that tag, then the custom $link functionality will be used across the entire wiki.

I recommend not applying that tag until you’ve done lots of localized testing. Any bugs will affect all links in your wiki and it might be difficult to recover from the bug.

If you can detect your “particular conditions” using only the information passed to the link widget (i.e. the link text or the tiddler title), then I don’t see why any change to the parser would be needed.

1 Like

I have started a Proof of Concept POC at https://prerelease-play.tiddlyhost.com/

  • @btheado’s code is a great start.
  • Somehow I locked up the wiki (no ones fault but my own) my mistake was keeping the preview open. And have to rebuild it

My Approach;

  • I am immediately generalising this as a hackable solution by transcluding content using tags before and after “links”.

@btheado Brian,

  • Inside your example \widget $link() What is the variable representing the title of the link? currentTiddler is the one in the story.
  • I want it available outside the genesis widget within.
  • It would appear to be something like {{{ [<@params>jsonget<currentTiddler>] }}}

[Edited] It appears to be the “to” variable which $:/core/modules/parsers/wikiparser/rules/prettylink.js provides.

I now have a working example by redefinition of the link widget which does affect the standard links however before I can generalise it I notice a quirk, perhaps specific to this application;

  • Standard links of the forms CAmelCase [[two words]] and [[cute|not so cute]] can now be prefixed or suffixed.

However

  • the actual link widget <$link/> and <$link to=HelloThere/> have no link text appear.
  • Although <$link to=HelloThere>Hi</$link> does show Hi

So I think the example @btheado gave me needs a little finessing to produce a link title when the content of the link widget is empty.

Right, change the parameters line to have to and tiddler if you want to access them directly:

<$parameters to="" tiddler="" $params="@params">

Add a body to the slot widget to give the slot a default value:

<$slot $name=ts-raw><$text text=<<currentTiddler>>/></$slot>

Looks like that is only part of the solution. It works for the first example below, but not the 2nd and 3rd:

<$link/>

<$link to="HelloThere"/>

<$link to="HelloThere"></$link>

I made another change which helps with the 2nd to last test case, but the last case is still rendering different from the default $link widget. I’m a little stumped on that one.

\widget $link()
<!-- Use a parameters widget so we can use `$params` to define a variable
 containing all the passed-in parameters -->
<$parameters to=<<currentTiddler>> tiddler="" $params="@params">
<$genesis
  $type="$link"
  $remappable="no"
  $names="[<@params>jsonindexes[]]"
  $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]">
<$slot $name=ts-raw><$text text=<<to>>/></$slot>
</$genesis>
</$parameters>
\end

#[[some missing tiddler]]
#HelloThere
#[[link text|HelloThere]]
#<$link to="HelloThere">Some different text</$link>
#<$link/>
#<$link to="HelloThere"/>
#<$link to="HelloThere"></$link>

The last case is rendering as

<a class="tc-tiddlylink tc-tiddlylink-resolves" href="#HelloThere">

</a>

instead of like this with the default $link widget

<a class="tc-tiddlylink tc-tiddlylink-resolves" href="#HelloThere">HelloThere</a>
2 Likes

Brilliant stuff @btheado. I think you’re running into a special case of the link widget: if it is empty (ie contains no link text widgets) then the title of the target tiddler is used as the text of the link. I think your override may need to explicitly handle that case.

2 Likes

This is proving to be a very educational problem to explore, learning from your examples @btheado things that are too hard at present to understand for me in GitHub and the Doco’. I will change the title to Exploring default tiddler links hackability in V5.3.0 and repost once the issues are resolved, so people are not confused by the complexity.

  • Interesting, I applied the change to slot and the 1st example fails not the 2nd and 3rd see below via link widget.

Code in use above;

\widget $link()
<!-- Use a parameters widget so we can use `$params` to define a variable
 containing all the passed-in parameters -->
<$parameters to="" tiddler="" $params="@params">
<$let currentTiddler=<<to>> >
<$list filter="[tag[$:/tags/before-links]]" variable=tiddlername>
<$transclude tiddler=<<tiddlername>>/>
</$list>
<$genesis
  $type="$link"
  $remappable="no"
  $names="[<@params>jsonindexes[]]"
  $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]">
<$slot $name=ts-raw><$text text=<<currentTiddler>>/></$slot>
</$genesis>
<$list filter="[tag[$:/tags/after-links]]" variable=tiddlername>
<$transclude tiddler=<<tiddlername>>/>
</$list>
</$let>
</$parameters>
\end $link
  • I saw a hint of this earlier. Perhaps the slot can contain a conditional? if empty then display link title? I am still experimenting. but we have 99%

I’m still stuck. I don’t see how I can have widget code to distinguish between #1 and #2 below. It seems like the slot widget should behave the same for both. I guess I could use the wikify widget to see if <$slot $name=ts-raw/> renders as empty, but that seems kind of ugly.

\widget $$mywidget()
<$slot $name=ts-raw>the body is empty</$slot>
\end

#<$$mywidget/>
#<$$mywidget></$$mywidget>
#<$$mywidget>the body is not empty</$$mywidget>

renders as

  1. the body is empty
  2. the body is not empty

Is it a bug in the slot widget or am I misunderstanding?

Until we can resolve the empty link widget case it would be dangerous to set this as a global replacement for the linkWidget in a wiki.

However I found it is simple to \import tiddlername or perhaps the ImportVariablesWidget could be used in a conditional viewtemplate?

Another desired outcome, where we want access within the new widget is when using the pretty link [[short name|this is the long name]] it would be good if we had access to the pretty name because it could be used to populate the caption field of the target tiddler if one is not available.

Thank you @btheado, It is indeed a bug in slot widget.

For the background, look at the parse trees generated by the three cases:

#<$$mywidget/>
#<$$mywidget></$$mywidget>
#<$$mywidget>the body is not empty</$$mywidget>

The parse trees are similar in each case, with these differences:

  1. The isSelfClosing attribute is true, and there is no children array
  2. The children array is present but empty
  3. The children array is present, containing the text node of the text the body is not empty

The slot widget was only checking for an entirely missing children array. It’s fixed on GitHub by also checking the children array being present but having a zero length.

The prerelease at https://tiddlywiki.com/prerelease/parameterised-transclusions/ should be updated in a few minutes if you can give it a try.

Using the previously developed override of the link widget the last test case still has a problem.

custom-link-widget-test.json (1.9 KB)

Use on latest 5.3.0

  • “Some test cases” is default behaviour
  • “Using custom widget” imports $:/PSaT/linkWidget and fails only in the last item.

Correction Fails on 2 cases

  • <$link/>
  • <$link to="HelloThere"></$link>

The update went through and the only case failing is;

  • <$link/>

Thanks for the explanation and the fix works for me!

The last code for $link I posted works for all 7 test cases included there. Is that the version you are using?

I am now, I added my own mods and must of Broken something, also the revised 5.3.0 pre-release is necessary to avoid he 7th failing - Jeremys fix.

Thanks heaps, I can now explore the possibilities to their fullest extent.

Thanks you @btheado and @jeremyruston we are almost there.

Given the discussion here in I created a small test package for the pre-release. It works well in principal by using a tag driven way to prefix or suffix any link generated by the link widget with an edit button.
link-widger-reimagined.json (1.4 KB) test on prerelease

  • This works against all our versions of link definition
  • It even goes a little too far when applied globally, including appearing in the title, subtitle and site title.
  • However it is a great proof of concept.

However

When you do edit a tiddler the editor is broken, remove the $:/tags/Macro from Link widget reimagined to stop it.

Questions

  • Is the editor somehow using the link widget?
  • Can we fix this?
  • Does this indicate how problems can arise using the widget pragma?
  • Do we need a fix for the Prerelease?

Hi @TW_Tones it sounds like the problem is that your redefinition of the link widget is still in force within the custom link widget. To prevent that, set the variable $link to the empty string before trying to use the link widget.

It would be very helpful if you could use the tiddlywiki.com/share.html feature for these kind of things, it makes it much easier for others to see what you’re talking about.

1 Like