Dynamic Core Module Reference in TiddlyWiki Plugins

Dynamic Core Module Reference in TiddlyWiki Plugins

The Problem

When overriding a core widget (e.g. text.js), you often need the original version as a sub-widget or fallback. The conventional approach is to maintain a separate copy of the original — but this breaks silently whenever core is upgraded.

The Solution

TiddlyWiki’s core is itself a plugin. All original module source code is preserved in $tw.wiki.getPluginInfo("$:/core").tiddlers, even after being overridden. You can retrieve that source at runtime and re-execute it under a new name.

(function() {
	var pluginInfo = $tw.wiki.getPluginInfo("$:/core");
	var shadowSource = pluginInfo.tiddlers["$:/core/modules/widgets/text.js"].text;

	var twRequire = function(title) {
		return $tw.modules.titles[title] && $tw.modules.titles[title].exports;
	};

	var coreExports = {};
	new Function("exports", "require", shadowSource)(coreExports, twRequire);

	// Register the original "text" widget under a new alias
	exports["plain-text"] = coreExports.text;
})();

Place this IIFE at the top of your overriding module. The original widget is now available as plain-text for internal use, while your custom logic is exported as text.

Why This Works

  • getPluginInfo("$:/core").tiddlers always contains the original shadow source, regardless of any overrides applied on top
  • new Function("exports", "require", source) re-executes the module in isolation, producing a fresh exports object
  • The result is registered into the widget system alongside your override — no separate file needed

Verified Output

// plain-text.js (emptied)   → exports: []
// text.js (override)        → exports: ["plain-text", "text"]  ✓

Advantages over Conventional Approaches

Approach Upgrade-safe? Self-contained?
Copy original into a separate file :cross_mark: Manual sync needed :white_check_mark:
Shadow override only :cross_mark: Loses original :white_check_mark:
Mod-Loader (boot-time patch) :white_check_mark: :cross_mark: Extra dependency
This approach (runtime re-execution) :white_check_mark: Always latest core :white_check_mark: Single file

Caveats

  • The lightweight twRequire shown above only resolves already-loaded modules. If the original module has deep require dependencies at execution time, you may need to extend it.
  • This relies on getPluginInfo being available at module load time, which is the case for all standard module-type: widget modules in TiddlyWiki 5.
  • This is not a silver bullet. If a future core upgrade significantly changes the internal structure or API of the original module, your override will still break — just as it would with a manually maintained copy. The real benefit is simply one less file to maintain, and the guarantee that you’re always executing the latest core source rather than a stale snapshot.

*Discovered while building the Freelinks plugin. Tested on TiddlyWiki v5.4.1-prerelease