What's the proper way to override/augment a built-in wikirule's behavior?

Hello everyone!

I’ve been working on a plugin to augment the behavior of the heading wikirule. Currently, I’m just creating my own wikirule based on heading and disabling the built-in heading rule via configuration, but I was wondering if a better way existed.

I looked into the wikirule loading and execution process, and from my understanding the winner is determined by which parse rule’s match starts the earliest in the text from the current position, with later rules (“later” here defined by JavaScript object iteration order) being favored in the case of a tie - does that sound correct to those of you with a more intimate knowledge of the wikiparser?

Is there a good way for me to have TiddlyWiki favor my wikirule over the built-in one, short of disabling the built-in? Or perhaps I’m going about this entirely the wrong way?

Thanks,
Rob

You only need to give it a “name” that is sorted prior to the one you want to overwrite. Wikirules are “the first one wins”. As you found out already.

@pmario Thanks for the quick reply! Where is this sorting happening? I was under the impression that the parse rule evaluation order was based on JavaScript object iteration order.

I think that’s what I would try in the first instance.

I think that’s right. I don’t think there’s a reliable way to overwrite an existing parse rule.

To change an existing rule the core would expect you to overwrite the module containing the parse rule in question with your own implementation.

As usual though, there is room to introduce new mechanisms if needed.

Yes. … but … the whole thing starts when the parser object is created. The wikitext parser is initialized here:

We need to follow $tw.modules.createClassesFromModules("wikirule" which is here:

We need to follow $tw.modules.forEachMouduleOfType at:

The modules variable from var modules = $tw.modules.types[moduleType]; is alphabetically sorted by the tiddler name. eg: $:/core/modules/parsers/wikiparser/rules/codeblock.js

And IMO that defines the order, the rules applied. … At least, that’s what I think.

Thanks for weighing in, @jeremyruston! I’ll stick with my current solution, then.

I guess what I would be hoping for in this area is something similar to the sort order for the tag operator - defaulting to an alphabetical sort, but overridable via list, list-after, etc. But maybe my “need” here is niche, or I’m inventing problems that don’t exist!

EDIT: I realized that I wanted something like this for another plugin I wrote last year - the plugin had its own notion of “extractor” modules that extract metadata from HTML pages, and I wanted to be able to rely on the ordering of those modules, or allow them to be overriden (eg. the “github” extractor should be tried before a generic “fallback” extractor). I think I ended up pivoting to just using tags rather than forEachModuleOfType in that case.

Ok, thanks for taking the time to tour the code with me!

I think the main problem is, that the object “order” can not be guaranteed. It depends on the browser implementation. IMO it is not cleanly defined by the spec…

See: Does JavaScript guarantee object property order? - Stack Overflow

It is an interesting thread!

TBH, I think your “Custom Markup” could solve 99% of the issues raised?

I’m going back to sleep,
TT :slight_smile: