Exploring default tiddler links hackability in V5.3.0

Background
camelCase and [[tiddler title or phrase]] result in links to a missing or existing tiddler. As I understand it the TiddlyWiki parsing is responsible for this.

I have a set of use cases where I would like to hack this link, a bit like one may hack a list item template.

  • A really simple example maybe on mouse over a link showing a tooltip obtained from the target tiddler. I can do this in my own code with custom list item templates etc…
  • However in this case I would like to be able to do this for any/all links that appear in wikitext.
  • I believe CSS can be applied to such links as it rendered as follows eg; <a class="tc-tiddlylink tc-tiddlylink-missing" href="#A%20link">A link</a>
  • However Imagine if every link actually transcluded a “link item template” who’s default behaviour was as expected, but in which I could introduce alternate code for such links.

Questions

  • Has this being done before?
  • If not how could we do it?
  • Would or must it be a core modification?
  • Is it a useful hack we could add to the core?
  • Could we do something similar via the freelinks plugin?

I just want to mention @jeremyruston and @pmario because I believe either of you may understand this already, as I am sure others do.

  • Happy to illustrate why this would be a valuable hack, but to many I expect it may be self evident.

Hm, if I understand right, this might just require adding a fourth dimension to the three linkstyle dimensions already covered in this linkstyle plugin. It’s a purely css way to change how links appear (including what’s before and after them). Why not have it also specify default and alternate hover text for any link, based on something pulled from the tiddler fields (and/or any other thing that can be cooked up in wikitext)?

-Springer

1 Like

Thanks @Springer springer, perhaps I gave a bad example because this may be achieved with CSS

In reality I want to put a lot more smarts behind the “everyday link” and would like the freedom one gets from using a template to render the items as with list items.

  • I may want to replace the link with a button (that looks like a link) and trigger additional actions.
  • Hide links that meet special conditions like with the prefix *:hide
  • Or trigger additional actions when following a link, including a missing tiddler

In my current work I want links to tiddlers, missing or otherwise without an “object-type field” set, to gain a dropdown to assign the object-type and as a result create the tiddler (if missing).

  • As soon as a tiddler gets an object-type much more will unfold.
    • Starting with the link displaying an icon for its object type.
  • If I can conditionally do this from any mention (link) of a tiddler title;
    • I can create “curated tiddlers” all from the view OR editor of a single tiddler (using output preview) and other methods.

It would be nice if the template could access both the tiddler title and if in use, the pretty name [[pretty name|tiddlername]]

1 Like

I did some experiments with alternative “Missing tiddler hints” that are shown in the “missing tiddler” in the story river. …

I did experiment with links for the uni-link plugin, which “calls macros” instead of creating links … BUT it doesn’t create macros for standard-links. … The problem was “fast backlink” creation, which I didn’t want to mess up.

At the moment the code, that creates tiddler links is relatively simple. …

IMO the main complexity is, that we have to keep “backlinking” in mind. Keeping track of backlinks, is probably the most time consuming algorithm we have in the parsing and rendering flow at the moment.

Free-links may be a second bottleneck we have to be aware of.

… But I didn’t have a closer look to the code atm.

2 Likes

Hi @TW_Tones all forms of tiddler link are internally created by the <$link> widget, so when parameterised transclusion is merged you’ll be able to define a custom override of the <$link> widget that incorporates your popup functionality, and then use it across some or all of the wiki.

6 Likes

@jeremyruston Is the GenesisWidget not enough to create a custom $link widget?

Does this mean we can create functionality like Tobias Beer preview/appear plugins? This will allow us to have a live preview of tiddler content when hovering mouse over its wikilink .

No. The only part that the genesis widget helps with is to allow the custom widget to create an internal link widget that doesn’t get recursively replaced by the custom definition. The genesis widget on its own doesn’t affect how other widgets are interpreted.

Yes to being able to create a live preview of tiddler content. I don’t think the genesis widget helps in duplicating the functionality of the “appear” widget.

1 Like
  • Thanks @jeremyruston for this inside knowledge.
  • In this case I am not seeking how to patch in this behaviour but if I can find how it happens in the core to explore enhancing the core one day to permit this hackability.
    • This is because I am confident such hackability would be valuable if made available to all users of tiddlywiki and allow plugins and other solutions to make use of the hackability rather than bring their own implementations of it.

Is it possible for you to point me to where this occurs so I can consider a modification to achieve what I am looking for?

  • This is presently a research effort on my part, not just seeking a solution.
  • I can see how “parametised transclusions” would permit an ad hoc patch to alter the behaviour, but as it is not in place yet, and I am looking for a more fundamental intervention.
    • This issue is interesting in so far as should I wish to improve hackability in the core will we instead revert to “custom overrides” with widget redefinitions?
    • This is somewhat problematic because I doubt we want the empty-edition release with redefined widgets, and if I want to include this hackability going forward I would have to install a “patch”.

I hope I can satisfy this curiosity as I am exploring a substantial improvement to the way we can use tiddlywiki especially for new users, building new wikis or providing more intuitive ways to add content.

  • I will discuss these in more details later (or sooner if asked), for now I want to see if we can make the default links missing or not hackable.

Given what Jermey says, I understand this part of your response (since the functionality isn’t available yet):

but not this part:

Overriding the link widget sounds pretty fundamental to me with regard to hackability. You would be able to use \widget to redefine $link to do whatever you want (using wikitext). Are you looking for more than that?

Here is a link to the tiddlers containing the javascript code related to link parsing and the link widget: prettylink parser rule | wikilink parser rule | link widget. Maybe that will help you. Making changes involves writing javascript code.

You can paste the following two synonyms into a tiddler on tiddlywiki.com and then in the preview pane change the output to parser tree and then widget tree (also suggest changing the dropdown menu to “inline”):

[[this is a link]] <$link to="this is a link"/>

The parse tree is a little different between the two, but the widget tree for each is identical.

1 Like

First, @btheado Brian thanks for taking the time to respond.

  • Yes true, but My interest is to be able to conditionally replace or prefix/suffix a link with additional logic.
  • Whether we must change the Link Widget is to be determined.
  • Presently in lists and other manifestations of links we can use an alternative template eg; listitem I would like the same mechanism for internal links generated by camel case or pretty link.
  • I am investigating if it would be possible to add this hackability to the core so there is no requirement (in the long run) for a redefined link widget.
  • Thanks, so this demonstrates Jeremys words;

You say;

  • but I am not sure how to make use of this;

So I see then that we may look at

  • the Link widget to see the available parameters and behaviours. Of note is they only relate to html and CSS.
  • the link widget is defined as JavaScript (as expected) in $:/core/modules/widgets/link.js
    • In the link widget we see the following variables have a role to play `tv-wikilinks tv-filter-export-link tv-wikilink-template tv-get-export-link tv-wikilink-tooltip tv-show-missing-links
    • tv-wikilink-template sounds the most helpful however it exists to alter the href format, no more no less.

On going questions

  • I wonder if $:/core/modules/parsers/wikiparser/rules/prettylink.js also handles the CamelCase links?
    • prettylink.js reforms external links directly into a html a tag and href.
      • At some point I would like to alter this in a similar way
    • I wonder if prettylink.js could be modified such that if an internal link, and then a “named tiddler” existed rather than use the link widget it transcluded the “named tiddler”, which by default used the link widget anyway.
      • Then a “mug” like myself could code an alternate way to present such internal links.

Background

  • We can change the look of such links with CSS as mentioned
  • We can use the linkCatcherWidget to intervein or include additional actions on such links
  • But we can not include additional wikitext along side such “automatic” links. This is the hackability I seek.

If asked, I can illustrate what I hope to do with such power “Mehh hhe hhe”

Optional reading;

with Default tiddler links hackability

Allow a user editing a tiddler to name other tiddlers missing or existing, including inserting them in the text via various editor toolbar buttons lincluding the existing Create wikitext link this is all standard tiddlywiki.

  • Either in preview/output or from the view template the links become active links to tiddlers with the title.
  • It is possible to follow any of these links to open a tiddler, missing or existing, but to do this, you must navigate away from the current tiddler.
    • If you are in the middle of composing the tiddler this can be unhelpful and distracting, otherwise you need to do this later and reacquaint yourself with the intention for each tiddler link.

My current design concept would do the following;

  • For any link in the tiddler, If the tiddler is missing or does not have a named field. A drop down to select a value for that field will appear. In this case it is a tiddler type field. Selecting the value for that field (from existing values) will set that field in the tiddler (creating it if missing).
    • As soon as a tiddler has a type this dropdown disappears, but an icon indicating the tiddler type may appear.
  • Any link to a tiddler with a given type (perhaps set in the previous step) could result in additional content, as relevant to that tiddler type, such as the aforementioned icon
    • However for me the real power would be a custom dropdown to select a fieldname into which to place the title of the current “title link”, be it as a single value or into a list field. Thereby formalising what “that title means”, as a value in a named field.
    • Setting a tiddler type, or value in a field allows a whole cascade of buttons, cascades, viewTemplates and content to be triggered, all from inside one tiddler.

This would permit a user to enter in a single tiddler, enter “prose” containing various links as the need arises, to many tiddlers and to create, categorise (via tiddler type) without leaving the tiddler, once a type is known allow the “links in the prose” to be selectively "added to selected fields in the current tiddler, or as a tag on the current tiddler.

  • For example we may name a contact or project name the current tiddler is to belong to and with a click set the current tiddlers project field, and add the contact to the contact list field, still without leaving the tiddler, even edit mode (by virtue of preview).

Of note: I expect I can already achieve all this in an extra list/or view below the the “text view” in the view template, however it would be far more intuitive if this activity can occur in the tiddler body itself.

Hi @TW_Tones

That is just what the custom widget mechanism does: it allows you to customise the wikitext generated by an invocation of a widget (any widget, not just the link widget).

This mechanism for redefining widgets was specifically designed to cope with exactly the use case that you raise in the OP (amongst others). It is the result of listening to user needs for a few years, and then synthesising a single mechanism that can be used to address multiple related needs.

I appreciate that it hasn’t landed with you quite as expected, and so I’d like understand more about why it doesn’t appear to meet your requirements.

In particular, see the “Overriding Core JavaScript Widgets” section of https://tiddlywiki.com/prerelease/parameterised-transclusions/#Custom%20Widgets

Since your goal is to override the link widget everywhere, it will be slightly more complicated than that example. Since you want to change the behavior only in some cases, for the other cases you should pass through all the parameters to the original link widget.

Here is some code (only lightly tested) which will redefine the link widget to do exactly what it already does. IOW, it doesn’t alter the behavior at all:

\widget $link()
<!-- Use a parameters widget so we can use `$params` to define a variable
 containing all the passed-in parameters -->
<$parameters $params="@params">

<$genesis
  $type="$link"
  $remappable="no"
  $names="[<@params>jsonindexes[]]"
  $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]">
<$slot $name=ts-raw/>
</$genesis>

</$parameters>
\end

You can use it as a starting point to add your own custom behavior:

\widget $link()
<!-- Use a parameters widget so we can use `$params` to define a variable
 containing all the passed-in parameters -->
<$parameters $params="@params">

<$list filter="some filter to match the cases you want to change the behavior">
[... your custom code here ...]
</$list>
<$list filter="some filter to match all other cases">
<$genesis
  $type="$link"
  $remappable="no"
  $names="[<@params>jsonindexes[]]"
  $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]">
<$slot $name=ts-raw/>
</$genesis>
</$list>

</$parameters>
\end

Some test cases:

[[some missing tiddler]]

HelloThere

[[link text|HelloThere]]

<$link to="HelloThere">Some different text</$link>
4 Likes

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.