This page is part of a static HTML representation of the TiddlyWiki at https://tiddlywiki.com/

Release 5.4.0

1st September 2025 at 12:00am

See the detailed change history on GitHub and other releases.

Introduction

Release v5.4.0 is an important release because it deliberately and forensically loosens backwards compatibility where needed to allow significant new features and fundamental improvements to be made.

Please note that this release note is not yet fully completed, please see the change history on GitHub for the full list of changes included in this release.

See the project plan for full details.

Changes

Translation

EnhancementUpdate Chinese translation

GitHub:
  • change camel-case hint text for chinese translations
  • add alerts ARIA message

Plugin

EnhancementUpdate highlightjs plugin

GitHub:

Update highlightjs version to 11.11.1

BugfixMarkdown: Fix missing inline support and macrocall args parsing error

GitHub:
  • Fix markdown parser to respect parseAsInline option #8917.
  • Fix improper parsing of macrocall, whenenver args contain > character.
  • Use $tw.log.MARKDOWN flag to enable debug messages.

DeprecationPurge deprecated plugins and editions

Impact:
deprecation: The purged deprecated plugins are no longer availabe in the official plugin library
GitHub:

Remove deprecated plugins and editions and some legacy plugins, including:

BugfixFix critical freelinks bugs: first character loss and false positive matches in v5.4.0

GitHub:

This note addresses two major bugs introduced in the Freelinks plugin with the v5.4.0 release:

Fixes: * First Character Loss: The first character of a matched word would incorrectly disappear (e.g., "The" became "he"). This was fixed by correctly timing the filtering of the current tiddler's title during match validation, ensuring proper substring handling. * False Positive Matches: Unrelated words (like "it is" or "Choose") would incorrectly link to a tiddler title. This was resolved by fixing wrong output merging in the Aho-Corasick failure-link handling, eliminating spurious matches from intermediate nodes, and adding cycle detection.

Impact: * Significantly improved correctness and reliability of automatic linking for all users, especially in multilingual and large wikis.

EnhancementBump markdown-it and its plugins to newest version

GitHub:

Upgrade the markdown-it libraries used by the Markdown Plugin:

  • markdown-it: 14.1.0
  • markdown-it-deflist: 3.0.0
  • markdown-it-footnote: 4.0.0
  • markdown-it-ins: 4.0.0
  • markdown-it-mark: 4.0.0
  • markdown-it-sub: 2.0.0
  • markdown-it-sup: 2.0.0

BugfixFix browser storage plugin making wiki dirty

GitHub:

Fixed issue where the browser storage plugin caused the wiki to be marked as dirty every time it starts up. The problem was due to the use of a log tiddler titled $:/info/browser/storage/persisted, the fix is to rename it to $:/state/browser/storage/persisted.

Usability

EnhancementAdd Display Field to list-tagged-draggable and list-links-draggable

GitHub:

A new input parameter, displayField, has been added to the list-links-draggable and list-tagged-draggable macros, allowing users to specify which field (e.g., title, caption, or any custom field) should be displayed when a tiddler is rendered via the draggable macro.

BugfixRefresh widget if "default" parameter input value is changed

GitHub:

EnhancementImprove alert accessibility

GitHub:

Enhancementlist-links-draggable defaults to currentTiddler if tiddler parameter is missing

GitHub:
  • If macro list-links-draggable misses the tiddler parameter it points to currentTiddler variable by default now
  • Also discussed at Talk Tiddlywiki

EnhancementSet modal's mask-closable attribute to yes by default

GitHub:

EnhancementImprove switcher (UI) accessibility

GitHub:

EnhancementImprove tabs macro accessibility

GitHub:

Adds tablist, tabpanel and tab roles to the tabs macro to improve its accessibility. It also adds a selectedAria attribute to the button widget.

Theme

EnhancementMuted palette, minor adjustments

GitHub:

EnhancementBidirectional improvements for core classes

GitHub:

Make some core classes display properly when Tiddlywiki's language uses bidrectional scripts.

EnhancementReplace CSS property macros in Snow White theme

GitHub:

EnhancementUse currentColor to style SVG

Impact:
compatibility-break: SVG icons will inherit colors instead of using #333333 if its parent element has color property set
GitHub:

Replaces hardcoded fill attributes with one fill: currentColor rule to solve the compatibility issues of migrating to lucide icons.

Hackability

EnhancementMulti-valued variables and let filter run prefix

GitHub:

This PR introduces a new filter run prefix :let that assigns the result of the filter run to a variable that is made available for the remaining filter runs of the filter expression. It solves the problem that previously it was impossible to compute values for filter operator parameters; parameters could only be a literal string, text reference or variable reference.

This PR also introduces multi-valued variables, the ability to store a list of results in a variable, not just a single string. They can be assigned with the new :let filter run prefix, or the existing <$let> widget. The full list of values can be retrieved using round brackets instead of the usual angle brackets. In all other contexts only the first item in the list is used as the variable value.

FeatureAdds info tiddlers for viewport dimensions that are updated on window resize.

GitHub:

Adds info tiddlers for viewport dimensions that are updated on window resize.

Example: Main and a user-created window with windowID my-window

WindowInfo tiddlerMeaning
system/main$:/info/browser/window/system/main/outer/widthFull browser window including chrome, tabs, toolbars
system/main$:/info/browser/window/system/main/outer/heightFull browser window including chrome, tabs, toolbars
system/main$:/info/browser/window/system/main/inner/widthViewport width including scrollbars
system/main$:/info/browser/window/system/main/inner/heightViewport height including scrollbars
system/main$:/info/browser/window/system/main/client/widthContent width excluding scrollbars
system/main$:/info/browser/window/system/main/client/heightContent height excluding scrollbars
user/my-window$:/info/browser/window/user/my-window/outer/widthFull browser window including chrome, tabs, toolbars
user/my-window$:/info/browser/window/user/my-window/outer/heightFull browser window including chrome, tabs, toolbars
user/my-window$:/info/browser/window/user/my-window/inner/widthViewport width including scrollbars
user/my-window$:/info/browser/window/user/my-window/inner/heightViewport height including scrollbars
user/my-window$:/info/browser/window/user/my-window/client/widthContent width excluding scrollbars
user/my-window$:/info/browser/window/user/my-window/client/heightContent height excluding scrollbars

EnhancementImport UI now conditionally displays file-type-specific import options

GitHub:

The import UI now displays import options based on the file types being imported. Import options are only shown when relevant files are detected, an example is:

tags: $:/tags/ImportOptions
condition: [match[text/x-markdown]] :or[match[text/markdown]]

FeatureViewToolbar buttons now support condition field

GitHub:

ViewToolbar buttons can now be conditionally displayed based on the currentTiddler using a condition field. Similar to how $:/tags/Exporter and $:/tags/EditorTools already have. An example would be:

tags: $:/tags/ViewToolbar
condition: [<currentTiddler>type[text/x-markdown]] [<currentTiddler>type[text/markdown]]

Widget

EnhancementAdd clamp attribute to RevealWidget

GitHub:

The attribute clamp is added to the RevealWidget to force the popup to be displayed inside its container without overflowing. The value can be right, bottom or both. Clamping to left and top can be accomplished via the positionAllowNegative attribute.

BugfixFixes SelectWidget does not work with multiple options organised into group - issue #8092

GitHub:

Fixed SelectWidget does not work with multiple options organised into group.

EnhancementAllow button widget to use all aria attributes

GitHub:

EnhancementAllow link widget to use all aria attributes

GitHub:

Allow LinkWidget to use all aria attributes directly.

DeprecationThe deprecated events and actions-* atrributes for the eventcatcher widget have been removed.

Impact:
deprecation: Deprecated events and actons-* attributes from the eventcatcher widget
GitHub:

Deprecates and removes the events and actions-* attributes for the $eventcatcher widget.

DeprecationRemove support for Internet Explorer in RangeWidget

Impact:
compatibility-break: RangeWidget will not work on Internet Explorer 10
GitHub:

BugfixFix widgets generating leading space in class attribute when additional class is empty

GitHub:

Fixed a bug in the RevealWidget, DroppableWidget, EventcatcherWidget, and KeyboardWidget where an empty class attribute would generate a leading space in the rendered HTML. By trimming the resulting class string, we shorten the HTML and avoid potential confusion.

FeatureAdd new editcost parameter to diff-text widget

GitHub:

FeatureEnsure rows parameter of edit-text widget takes precedence

GitHub:

Edit-text widget rows parameter takes precedence

BugfixFix ActionLogWidget sluggishness

GitHub:

PR #8972 introduced a change in the ActionLogWidget that could lead to a significant slowdown, which has been fixed.

BugfixFix LetWidget to always set all staged variables on first render

GitHub:

This PR corrects a bug where the LetWidget did not set variables if their value was the empty output of a filtered transclusion.

EnhancementAdd words and lines modes to diff-text widget

GitHub:

The DiffTextWidget now supports two additional diff modes via the mode attribute:

  • mode="words" - Performs word-level diff operations, making differences more intelligible when comparing text
  • mode="lines" - Performs line-level diff operations, highlighting entire lines that have changed

The default mode="chars" continues to work as before, performing character-level diff operations.

Filters

BugfixModify output of some math operators for empty inputs

Impact:
compatibility-break: filter output changes for some math filter operators when input list is empty
GitHub:

The following math operators are changed to output an empty list when the input list is empty:

  • sum[]
  • product[]
  • maxall[]
  • minall[]
  • average[]
  • variance[]
  • standard-deviation[]

FeatureAdded jsondelete operator for deleting properties from JSON objects

GitHub:

Added the jsondelete operator for deleting properties from JSON strings. The operator uses the same code path as jsonset to locate the correct part of the object, ensuring consistency between setting and deleting operations. It supports deleting both object properties and array elements, with support for negative array indexes counted from the end.

FeatureAdd locale support for sort operators

Impact:
compatibility-break: Tiddlywiki no longer works on browsers that doesn't support Intl.Collator
GitHub:

Add a new parameter for sort, nsort, sortan, sortcs and nsortcs to support sorting with a custom locale.

BugfixFix RSOE from decodebase64

GitHub:

decodebase64 Operator now outputs error to the filter operator result.

Node.js

EnhancementWeb server get-file route now supports HTTP Range headers and streaming

GitHub:

The web server's get-file route now supports HTTP Range requests and file streaming, enabling better loading and playback of large media files.

Features

  • HTTP Range header: Enables partial content delivery with 206 Partial Content responses, which is used when the user drags the progress bar in video/audio playback
  • Streaming file delivery: Browsers can now properly seek and stream video files from the /files/ directory. Files are read using Node.js streams for better performance and memory efficiency.
  • Resumable downloads: To save interrupted downloads

FeatureAllows server routes to be prioritized via ordering.

GitHub:

This PR adds support for an info property to server route module exports. The info object may include a priority field, which determines the route’s order of precedence.

Priorities are numeric and follow a descending order: routes with higher priority values are processed first, similar to how saver modules are prioritized.

To maintain backward compatibility with existing code, any module that omits info or info.priority is assigned a default priority of 100. Core server routes have been updated to explicitly use this default value of 100.

FeatureAllows server routes to support multiple HTTP methods.

GitHub:

Allows server routes to support multiple HTTP methods by introducing an exports.methods array.

BugfixAdd output directory to eslint ignore configuration

GitHub:

This PR adds the **/output/** directory to eslint ignore configuration

BugfixFix crash when processing large files from tiddlywiki.files

GitHub:
  • skip reading file content when _canonical_uri is present
  • skip loading file when file size is too large

Internal

SecuritySet AES strength to 256 bit default

GitHub:

This PR changes the default AES encryption setting from 128 bit to 256 bit.

  • Download emtpy.html v5.3.8 from the archve which uses AES 128 bit
  • Create some content
  • Save encrypted as eg: aes-128.html
  • Create aes-256.html with TW v5.4.x
  • Create some content
  • Save encrypted as: aes-256.html

Import decryption test

  • Import aes-256.html into aes-128.html -> Decryption and import works
  • Import aes-128.html into aes-256.html -> Decryption and import works

PerformanceUse sticky flag to improve regexp search performance

Impact:
compatibility-break: Tiddlywiki no longer works on old browsers that doesn't support sticky flag.
GitHub:

DeprecationRender s tag instead of strike

Impact:
compatibility-break: CSS rules using strike selector will broken

strike should be replaced by s.

GitHub:

PerformanceOffload server-only components to a plugin

Impact:
pluginisation: Server components of the core have been moved into a new $:/core-server plugin

It is not necessary for wikis to explicitly include the $:/core-server plugin.

GitHub:

This change reduces the size of the core plugin by 119.3KB or about 4.5%.

EnhancementFix nested span.tc-keyboard element in core

GitHub:

Removes nested <span class="tc-keyboard"> element in core search field.

PerformanceSwitch to native support for converting utf-8 between base64

Impact:
compatibility-break: Encoding & decoding base64 no longer works on browsers that doesn't support TextEncoder or TextDecoder
GitHub:

Replace base64-utf8 module with TextEncoder method to convert between utf-8 and Base64.

EnhancementSplit release notes into individual change notes

GitHub:

Doing so enables us to filter and group changes. For example, we could show all the breaking changes between two releases.

BugfixLet tiddler modules overwrite shadow modules with the same exports but different names

GitHub:

Tiddlers were previously processed before shadows during module registration. The shadow modules registration algorithm only checked for a matching title to prevent overwriting, but a differently named tiddler with the same exports would be overwritten by a shadow. This change swaps the order of $tw.wiki.defineTiddlerModules() and $tw.wiki.defineShadowModules() in boot.js, so that tiddlers are processed after shadows and can therefore override them.

Each group (tiddlers or shadows) is sorted alphabetically, so plugin shadows would previously correctly overwrite core shadows (assuming their name starts with $:/plugins/), which remains unchanged. This change only affects module tiddlers that have the same export as a shadow, but a different name.

PerformanceRemove redundant code in format/json.js

GitHub:

Remove redundant code in core/modules/filters/format/json.js.

DeprecationRemove Opera & Microsoft prefix in browser.js

GitHub:

Remove Opera & Microsoft prefix in $:/core/modules/utils/dom/browser.js.

BugfixFix markup not included in external core edition

GitHub:

Fix the problem that tiddlywiki's raw markup shadow tiddlers in $:/core is not included in HTML.

EnhancementAdd the prevailing mimetype for CSV parser

GitHub:

CSV parser used to support only the very obscure text/tab-delimited-values mimetype so this change adds the more common text/tab-separated-values.

PerformanceSplit escapecss.js into two platforms

GitHub:

Split $:/core/modules/utils/escapecss.js for two platforms: one for the browser, the other for Node.js. The CSS.escape polyfill is moved to core-server.

EnhancementRefactor base64 utility functions

GitHub:

Refactor base64 utility functions in $:/core/modules/utils/utils.js to make it easier for maintainence.

  • Split base64 utility functions to two platforms
  • Use TextEncoder and TextDecoder api in Node.js
  • Do not export base64ToBytes and bytesToBase64

BugfixProtect cached array data from external mutation

GitHub:

Functions returning cached tiddler lists now return shallow copies to prevent external code from inadvertently mutating the cache

FeatureAdd stylesheet wiki information

GitHub:

Extend wiki information tool to display stylesheet information.

BugfixFix images loaded from _canonical_uri tiddlers not having progress classes assigned

GitHub:

Fixes issue whereby transcluding a _canonical_uri tiddler with a missing image did not assign the progress classes tc-image-loading, tc-image-loaded and tc-image-error.

BugfixFix Ctrl-Enter not working in EditTemplate tag name input

GitHub:

The tag name input now calls <<save-tiddler-actions>> from the EditTemplate when Ctrl-Enter (or whichever key is assigned to input-accept-variant) is pressed.

Developer

FeatureAdd ability to serialize WikiText AST nodes back to wikitext strings

GitHub:

This PR introduces a new utility $tw.utils.serializeWikitextParseTree() that can convert WikiText Abstract Syntax Tree (AST) nodes back into wikitext strings.

There is also a utility serializeAttribute for a single attribute node, like an attribute of a widget.

Use Cases

  • Programmatically manipulating wikitext content by modifying the AST, and use this to write it back
  • Building WYSIWYG editors
  • Creating wikitext formatters and linters

Implementation

  • New core plugin tiddlywiki/wikitext-serialize containing most of the logic
  • Separate serialize handlers for each WikiText rule as module-type: wikiruleserializer
  • Test suite with tag $:/tags/wikitext-serialize-test-spec
  • It uses each parser's name as rule (nextMatch.rule.name), each AST node that needs serialization has a type property matching the rule name
    • HTML tags and widgets are handled by the html serializer

Example Usage

// Parse a tiddler's wikitext to AST
var parseTree = $tw.wiki.parseTiddler("MyTiddler").tree;

// Serialize AST back to wikitext string
var wikitextString = $tw.utils.serializeWikitextParseTree(parseTree).trimEnd();

This feature offers new tools for JS plugin developers. It is not a user-facing change.

EnhancementAdd support for commands and startups which return promises

GitHub:

This adds support for async functions to commands and startups.

In both synchronous: true and synchronous: false mode, if you return a promise (manually or by using the async keyword), it will wait for the promise to resolve, and then proceed using the resolved value as the return value of the function.

Importantly, in synchronous: false mode, returning a promise will not change the callback behavior. So you can safely use an async function and still call the callback to continue execution.

Previously, in synchronous: true mode, returning a promise would have just logged the promise to console and halted execution. Now the promise will be awaited, and if the value is truthy, it will be logged to console and halt execution. If the promise resolves to a falsy value, execution will continue. This is the main breaking change, but since logging an opaque promise to console is the most useless of all error messages, this is unlikely to seriously break anything in practice. Throwing anything, truthy or not, will still stop execution (in synchronous: true mode).

This also does not add any error handling code. Rejected promises should still be logged to console as unhandled rejections just as uncaught exceptions are currently.

EnhancementUpdate ESLint target to ES2017

GitHub:

Updates the eslint config to check for syntax newer than ES2017. This uses a plugin to check for newer syntax, for better error messages, and may need to be updated regularly along with eslint to catch the latest features.

DeprecationDeprecate CSS macros supported in 2017 baseline

Impact:
deprecation: Currently all the CSS property macros are deprecated
GitHub:

Mark CSS macros supported in 2017 baseline as deprecated. They are moved to $:/core/macros/deprecated now.

DeprecationDeprecate some utility functions

Impact:
deprecation: Some utility functions are deprecated and are discouraged to be used
GitHub:

Deprecate some utility functions. Some of them are moved to $:/core/modules/utils/deprecated.js.

FeatureAdded an option to enable CORS

GitHub:

Added an option to the TiddlyWiki5 server to enable CORS (ie. don't check same-origin). It is meant for advanced users, do not use it unless you understand the full consequences.

EnhancementAdd th-debug-element hook to allow plugins to add additional info

GitHub:

This PR adds:

  • th-dom-rendering-element hook, that is called right before the DOM node is inserted into the DOM
  • It allows plugins to add debug info
  • An example using an experimental hook can be found at: #9222

BugfixModules in draft tidders should not be executed

GitHub:

Modules in draft tiddlers should not be executed.

This PR:

  • Checks for drafts in $tw.Wiki.prototype.defineTiddlerModules
  • It also reports and blocks draft modules that come from plugins

EnhancementMigrate most deprecated rules

GitHub:

Migrate eslint deprecated rules (except for nodejs related rules). Format related rules are replaced by @stylistic/eslint-plugin.

EnhancementRepacking plugins should update modified timestamp

GitHub:

This PR modifies $tw.utils.repackPlugin() so that it adds the standard tiddler modification fields to plugin tiddlers when they are repacked.

EnhancementUpdate eslint configuration

GitHub:

EnhancementMigrate diff-match-patch library to diff-match-patch-es

Impact:
compatibility-break: The diff-match-patch-es library uses different APIs
  • Default export and the class constructor has been removed
  • Function name has been unified to camelCase
  • Previous options like Diff_Timeout and Diff_EditCost are now passed as an options object in the arguments if needed
GitHub:

Migrate the unmaintained diff-match-patch library to the maintained and modern fork diff-match-patch-es.

Acknowledgements

A warm thank you to the developers who have contributed to this release:

  1. @andrewgoz
  2. @Arlen22
  3. @BramChen
  4. @buggyj
  5. @cdruan
  6. @EvidentlyCube
  7. @Jermolene
  8. @jermolene
  9. @kixam
  10. @kookma
  11. @Leilei332
  12. @linonetwo
  13. @pmario
  14. @s793016
  15. @saqimtiaz
  16. @SmartDever02
  17. @yaisog