TiddlyWiki5 icon indicating copy to clipboard operation
TiddlyWiki5 copied to clipboard

Plugin Type Mechanism

Open Arlen22 opened this issue 7 months ago • 3 comments

After much spirited discussion at #4262 and #9064, I'm removing the vnd.json.gz plugin type and just including the core changes that would enable plugins to implement the equivalent functionality.

This allows plugin content to be saved and loaded via JavaScript, dynamically or otherwise, quite flexibly. All it does is add two methods (parse and stringify) which in the JSON version just stringifies and parses the text field, but other plugin types can do whatever they want as long as they return the same data from those two methods.

Since the text field has no meaning unless it is parsed, the plugin type is free to store whatever data they want in the text field, whether that be a remote URL (which still has to be preloaded, since this is sync and may be called multiple times), or any custom compressed data format desired.

$tw.modules.define("$:/boot/plugininfo/json","plugininfo",{
  name: "application/json",
  /**
   * @param {$tw.Tiddler} tiddler 
   * @returns {{ tiddlers: Record<string, TiddlerFields> }}
   */
  parse: function(tiddler){ return $tw.utils.parseJSONSafe(tiddler.fields.text, function(){}); },
  /**
   * @param {TiddlerFields} fields 
   * @param {{ tiddlers: Record<string, TiddlerFields> }} data 
   * @returns {string} the plugin tiddler text field
   */
  stringify: function(fields, data){ return JSON.stringify(data); },
});

Arlen22 avatar May 22 '25 19:05 Arlen22

Deploy Preview for tiddlywiki-previews ready!

Name Link
Latest commit ff274ec03b9805eef1b35210c2ea55b4052f466e
Latest deploy log https://app.netlify.com/projects/tiddlywiki-previews/deploys/68cc72139f3a410008e9c399
Deploy Preview https://deploy-preview-9068--tiddlywiki-previews.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

netlify[bot] avatar May 22 '25 19:05 netlify[bot]

Confirmed: Arlen22 has already signed the Contributor License Agreement (see contributing.md)

github-actions[bot] avatar May 22 '25 19:05 github-actions[bot]

📊 Build Size Comparison: empty.html

Branch Size
Base (master) 2528.4 KB
PR 2529.7 KB

Diff: ⬆️ Increase: +1.2 KB

github-actions[bot] avatar May 22 '25 19:05 github-actions[bot]

@Jermolene and anyone else who works on the core.

I don't know what the best way is to implement a plugin that does this.

  • There are no good places to add Javascript to the template other than raw markup.
  • Library tiddlers cannot be shadow tiddlers, they have to be normal tiddlers.
  • There is no raw markup between bootprefix and boot, so I have to manually create the $tw variable myself if I do use raw markup.

I think the best I can come up with is to add a tag for boot hook script tags between bootprefix and boot, otherwise I have to create $tw manually in rawmarkup. To be fair, that's probably a really good thing to have anyway, that way plugins aren't forced to use rawmarkup and create the $tw variable manually.

<!--~~ Boot kernel prologue ~~-->
<div id="bootKernelPrefix" style="display:none;">
`{{ $:/boot/bootprefix.js ||$:/core/templates/javascript-tiddler}}`
</div>
<!--~~ $:/tags/BootHook ~~-->
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/BootHook]] ||$:/core/templates/javascript-tiddler}}}`
<!--~~ Boot kernel ~~-->
<div id="bootKernel" style="display:none;">
`{{ $:/boot/boot.js ||$:/core/templates/javascript-tiddler}}`
</div>

Then on the server I'll just add it during startup. Obviously that prevents the format from being used on the server, but that's not really an issue. It's not ideal, but it's the best I've come up with so far.

Arlen22 avatar Sep 18 '25 20:09 Arlen22

Currently this prevents plugins from being loaded from the filesystem as a single compressed file and uncompressed. And it probably means that if you pack a plugin, it can't be unpacked, so this really doesn't solve much, but the problem is that the server startup code really has a chicken and egg problem. The client is easy to solve because the server generates the client after startup has finished, by which time all plugins are fully loaded and doing whatever they want. On the server, the plugin has to register by adding itself to the serializer hashmap.

Arlen22 avatar Sep 18 '25 20:09 Arlen22

I still think the easiest way would be to add it directly to boot. Trying to put it in a plugin is architecturally impossible.

Arlen22 avatar Sep 18 '25 20:09 Arlen22

so essentially, all this does right now is literally compress the core on the server so it can be render it or send it to the client.

Arlen22 avatar Sep 18 '25 20:09 Arlen22

@Jermolene, what if instead of including fflate as a library, we included a polyfill of Compression Streams API based on fflate so that we can remove it in the future?

  • https://github.com/101arrowz/compression-streams-polyfill
  • https://github.com/MattiasBuelens/web-streams-polyfill

Arlen22 avatar Sep 23 '25 19:09 Arlen22

I think that's a good idea.

pmario avatar Sep 24 '25 11:09 pmario

I think that's a good idea.

As a library the same way SJCL is? I was expecting more pushback. I think this would be the easiest compromise and it's the only thing I can find that doesn't require a massive rework of the boot sequence.

Arlen22 avatar Sep 24 '25 19:09 Arlen22