- <$macrocall $name="toc-selective-expandable" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter="[all[current]] -[<__selectedTiddler__>get[text]]"/>
+ <$macrocall $name="toc-selective-expandable" tag=<<__tag__>> sort=<<__sort__>> itemClassFilter="[all[current]] -[<__selectedTiddler__>get[text]]" exclude=<<__exclude__>>/>
@@ -210,9 +210,9 @@ tags: $:/tags/Macro
$tiddler>
\end
-\define toc-tabbed-internal-nav(tag,sort:"",selectedTiddler:"$:/temp/toc/selectedTiddler",unselectedText,missingText,template:"")
+\define toc-tabbed-internal-nav(tag,sort:"",selectedTiddler:"$:/temp/toc/selectedTiddler",unselectedText,missingText,template:"",exclude)
\whitespace trim
<$linkcatcher to=<<__selectedTiddler__>>>
- <$macrocall $name="toc-tabbed-external-nav" tag=<<__tag__>> sort=<<__sort__>> selectedTiddler=<<__selectedTiddler__>> unselectedText=<<__unselectedText__>> missingText=<<__missingText__>> template=<<__template__>>/>
+ <$macrocall $name="toc-tabbed-external-nav" tag=<<__tag__>> sort=<<__sort__>> selectedTiddler=<<__selectedTiddler__>> unselectedText=<<__unselectedText__>> missingText=<<__missingText__>> template=<<__template__>> exclude=<<__exclude__>> />
$linkcatcher>
\end
diff --git a/core/wiki/tags/PageControls.tid b/core/wiki/tags/PageControls.tid
index c6234751c..c0f1cb233 100644
--- a/core/wiki/tags/PageControls.tid
+++ b/core/wiki/tags/PageControls.tid
@@ -1,2 +1,2 @@
title: $:/tags/PageControls
-list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/layout]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]
+list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/layout]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/network-activity]] [[$:/core/ui/Buttons/more-page-actions]]
diff --git a/core/wiki/tags/ViewTemplateBodyFilter.tid b/core/wiki/tags/ViewTemplateBodyFilter.tid
index ab7ff262a..7b9fb7fd8 100644
--- a/core/wiki/tags/ViewTemplateBodyFilter.tid
+++ b/core/wiki/tags/ViewTemplateBodyFilter.tid
@@ -1,3 +1,2 @@
title: $:/tags/ViewTemplateBodyFilter
-list: $:/config/ViewTemplateBodyFilters/hide-body $:/config/ViewTemplateBodyFilters/code-body $:/config/ViewTemplateBodyFilters/stylesheet $:/config/ViewTemplateBodyFilters/system $:/config/ViewTemplateBodyFilters/import $:/config/ViewTemplateBodyFilters/plugin $:/config/ViewTemplateBodyFilters/default
-
+list: $:/config/ViewTemplateBodyFilters/hide-body $:/config/ViewTemplateBodyFilters/code-body $:/config/ViewTemplateBodyFilters/stylesheet $:/config/ViewTemplateBodyFilters/core-ui-advanced-search $:/config/ViewTemplateBodyFilters/core-ui-tags $:/config/ViewTemplateBodyFilters/system $:/config/ViewTemplateBodyFilters/import $:/config/ViewTemplateBodyFilters/plugin $:/config/ViewTemplateBodyFilters/default
\ No newline at end of file
diff --git a/editions/de-AT/tiddlers/external/tiddlywiki.files b/editions/de-AT/tiddlers/external/tiddlywiki.files
index 0c59b7bc5..fd714a0df 100644
--- a/editions/de-AT/tiddlers/external/tiddlywiki.files
+++ b/editions/de-AT/tiddlers/external/tiddlywiki.files
@@ -3,7 +3,7 @@
{
"file": "../../../tw5.com/tiddlers/images/New Release Banner.png",
"fields": {
- "type": "image/jpg",
+ "type": "image/jpeg",
"title": "New Release Banner",
"tags": "picture"
}
diff --git a/editions/dev/tiddlers/Widget `destroy` method examples.tid b/editions/dev/tiddlers/Widget `destroy` method examples.tid
new file mode 100644
index 000000000..5ff04bdd0
--- /dev/null
+++ b/editions/dev/tiddlers/Widget `destroy` method examples.tid
@@ -0,0 +1,36 @@
+created: 20230601123245916
+modified: 20230601125015463
+title: Widget `destroy` method examples
+type: text/vnd.tiddlywiki
+
+!! When using a v-dom library
+
+Virtual DOM libraries manages its internal state and apply state to DOM periodically, this is so called [["controlled" component|https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components]]. When Tiddlywiki remove a DOM element controlled by a v-dom library, it may throws error.
+
+So when creating a plugin providing v-dom library binding, you need to tell v-dom library (for example, React.js) the DOM element is removed. We will use `destroy` method for this.
+
+```js
+ render() {
+ // ...other render related code
+ if (this.root === undefined || this.containerElement === undefined) {
+ // initialize the v-dom library
+ this.root = ReactDom.createRoot(document.createElement('div'));
+ }
+ }
+
+ destroy() {
+ // end the lifecycle of v-dom library
+ this.root && this.root.unmount();
+ }
+```
+
+The `destroy` method will be called by parent widget. If you widget don't have any child widget, you can just write your own tear down logic. If it may have some child widget, don't forget to call original `destroy` method in the `Widget` class to destroy children widgets.
+
+```js
+Widget.prototype.destroy();
+this.root && this.root.unmount();
+/** if you are using ESNext
+super.destroy();
+this.root?.unmount();
+*/
+```
\ No newline at end of file
diff --git a/editions/dev/tiddlers/from tw5.com/mechanisms/TestingMechanism.tid b/editions/dev/tiddlers/from tw5.com/mechanisms/TestingMechanism.tid
index c334ab256..37659629f 100644
--- a/editions/dev/tiddlers/from tw5.com/mechanisms/TestingMechanism.tid
+++ b/editions/dev/tiddlers/from tw5.com/mechanisms/TestingMechanism.tid
@@ -2,7 +2,7 @@ modified: 20141013085608911
tags: Mechanisms
title: TestingMechanism
-TiddlyWiki5 incorporates the Jasmine JavaScript testing framework (see http://pivotal.github.io/jasmine/). It allows the same tests to be run both in the browser and under Node.js.
+TiddlyWiki5 incorporates the Jasmine JavaScript testing framework (see https://jasmine.github.io/). It allows the same tests to be run both in the browser and under Node.js.
! TiddlyWiki5 Testing Components
diff --git a/editions/dev/tiddlers/from tw5.com/moduletypes/WidgetModules.tid b/editions/dev/tiddlers/from tw5.com/moduletypes/WidgetModules.tid
index 1a8bf5edf..0b0b3f33a 100644
--- a/editions/dev/tiddlers/from tw5.com/moduletypes/WidgetModules.tid
+++ b/editions/dev/tiddlers/from tw5.com/moduletypes/WidgetModules.tid
@@ -1,7 +1,8 @@
-title: WidgetModules
+created: 20131101130700000
+modified: 20230601130631884
tags: dev moduletypes
-created: 201311011307
-modified: 201311011307
+title: WidgetModules
+type: text/vnd.tiddlywiki
! Introduction
@@ -78,4 +79,10 @@ The individual methods defined by the widget object are documented in the source
!! Widget `refreshChildren` method
!! Widget `findNextSiblingDomNode` method
!! Widget `findFirstDomNode` method
+!! Widget `destroy` method
+
+<<.from-version "5.3.0">> Gets called when any parent widget is unmounted from the widget tree.
+
+[[Examples|Widget `destroy` method examples]]
+
!! Widget `removeChildDomNodes` method
diff --git a/editions/dev/tiddlers/system/configWikiParserRulesInlineWikilink.tid b/editions/dev/tiddlers/system/configWikiParserRulesInlineWikilink.tid
new file mode 100644
index 000000000..9a395abd6
--- /dev/null
+++ b/editions/dev/tiddlers/system/configWikiParserRulesInlineWikilink.tid
@@ -0,0 +1,3 @@
+title: $:/config/WikiParserRules/Inline/wikilink
+
+enable
\ No newline at end of file
diff --git a/editions/dev/tiddlers/system/doc-styles.tid b/editions/dev/tiddlers/system/doc-styles.tid
new file mode 100644
index 000000000..24234d47a
--- /dev/null
+++ b/editions/dev/tiddlers/system/doc-styles.tid
@@ -0,0 +1,40 @@
+created: 20150117152612000
+modified: 20230325101137075
+tags: $:/tags/Stylesheet
+title: $:/editions/tw5.com/doc-styles
+type: text/vnd.tiddlywiki
+
+a.doc-from-version.tc-tiddlylink {
+ display: inline-block;
+ border-radius: 1em;
+ background: <
>;
+ color: <>;
+ fill: <>;
+ padding: 0 0.4em;
+ font-size: 0.7em;
+ text-transform: uppercase;
+ font-weight: bold;
+ line-height: 1.5;
+ vertical-align: text-bottom;
+}
+
+a.doc-deprecated-version.tc-tiddlylink {
+ display: inline-block;
+ border-radius: 1em;
+ background: red;
+ color: <>;
+ fill: <>;
+ padding: 0 0.4em;
+ font-size: 0.7em;
+ text-transform: uppercase;
+ font-weight: bold;
+ line-height: 1.5;
+ vertical-align: text-bottom;
+}
+
+.doc-deprecated-version svg,
+.doc-from-version svg {
+ width: 1em;
+ height: 1em;
+ vertical-align: text-bottom;
+}
diff --git a/editions/dev/tiddlers/system/version-macros.tid b/editions/dev/tiddlers/system/version-macros.tid
new file mode 100644
index 000000000..0fb7dcf12
--- /dev/null
+++ b/editions/dev/tiddlers/system/version-macros.tid
@@ -0,0 +1,14 @@
+code-body: yes
+created: 20161008085627406
+modified: 20221007122259593
+tags: $:/tags/Macro
+title: $:/editions/tw5.com/version-macros
+type: text/vnd.tiddlywiki
+
+\define .from-version(version)
+<$link to={{{ [<__version__>addprefix[Release ]] }}} class="doc-from-version">{{$:/core/images/warning}} New in: <$text text=<<__version__>>/>$link>
+\end
+
+\define .deprecated-since(version, superseded:"TODO-Link")
+<$link to="Deprecated - What does it mean" class="doc-deprecated-version tc-btn-invisible">{{$:/core/images/warning}} Deprecated since: <$text text=<<__version__>>/>$link> (see <$link to=<<__superseded__>>><$text text=<<__superseded__>>/>$link>)
+\end
diff --git a/editions/es-ES/tiddlers/$__Acknowledgements.tid b/editions/es-ES/tiddlers/$__Acknowledgements.tid
index 48074d928..d907bc9e6 100644
--- a/editions/es-ES/tiddlers/$__Acknowledgements.tid
+++ b/editions/es-ES/tiddlers/$__Acknowledgements.tid
@@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
TiddlyWiki incorpora código de los siguientes proyectos OpenSource:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
-* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
+* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
...y materiales de estos otros proyectos:
diff --git a/editions/fr-FR/tiddlers/$__Acknowledgements.tid b/editions/fr-FR/tiddlers/$__Acknowledgements.tid
index 1adf217a0..6e9f6e0e5 100644
--- a/editions/fr-FR/tiddlers/$__Acknowledgements.tid
+++ b/editions/fr-FR/tiddlers/$__Acknowledgements.tid
@@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
TiddlyWiki intègre du code provenant de ces excellents projets OpenSource<>
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
-* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
+* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
Et des contenus provenenant de ces sources<>
diff --git a/editions/prerelease/tiddlers/Release 5.3.1.tid b/editions/prerelease/tiddlers/Release 5.3.1.tid
new file mode 100644
index 000000000..dcea04fb5
--- /dev/null
+++ b/editions/prerelease/tiddlers/Release 5.3.1.tid
@@ -0,0 +1,57 @@
+caption: 5.3.1
+created: 20230701133439630
+modified: 20230701133439630
+tags: ReleaseNotes
+title: Release 5.3.1
+type: text/vnd.tiddlywiki
+
+//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.3.0...master]]//
+
+! Overview of v5.3.1
+
+
+! Plugin Improvements
+
+*
+
+! Translation improvement
+
+Improvements to the following translations:
+
+* Chinese
+* Polish
+
+! Usability Improvements
+
+*
+
+! Widget Improvements
+
+*
+
+! Filter improvements
+
+*
+
+! Hackability Improvements
+
+*
+
+! Bug Fixes
+
+*
+
+! Node.js Improvements
+
+*
+
+! Performance Improvements
+
+*
+
+! Acknowledgements
+
+[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki:
+
+<<.contributors """
+""">>
diff --git a/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid b/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid
index d8f641602..a42bdc774 100644
--- a/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid
+++ b/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid
@@ -1,6 +1,6 @@
title: $:/config/LocalPluginLibrary
tags: $:/tags/PluginLibrary
-url: http://127.0.0.1:8080/prerelease/library/v5.2.2/index.html
+url: http://127.0.0.1:8080/prerelease/library/v5.3.1/index.html
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease Local)
A locally installed version of the official ~TiddlyWiki plugin library at tiddlywiki.com for testing and debugging. //Requires a local web server to share the library//
diff --git a/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid b/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid
index 510d876d0..555b81ab6 100644
--- a/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid
+++ b/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid
@@ -1,6 +1,6 @@
title: $:/config/OfficialPluginLibrary
tags: $:/tags/PluginLibrary
-url: https://tiddlywiki.com/prerelease/library/v5.2.8/index.html
+url: https://tiddlywiki.com/prerelease/library/v5.3.1/index.html
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease)
The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
diff --git a/editions/prerelease/tiddlers/system/configWikiParserRulesInlineWikilink.tid b/editions/prerelease/tiddlers/system/configWikiParserRulesInlineWikilink.tid
new file mode 100644
index 000000000..9a395abd6
--- /dev/null
+++ b/editions/prerelease/tiddlers/system/configWikiParserRulesInlineWikilink.tid
@@ -0,0 +1,3 @@
+title: $:/config/WikiParserRules/Inline/wikilink
+
+enable
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/data/deserializers/case 6.tid b/editions/test/tiddlers/tests/data/deserializers/case 6.tid
new file mode 100644
index 000000000..b6e653c39
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/deserializers/case 6.tid
@@ -0,0 +1,8 @@
+title: dezerializer test data case 6
+type: application/json
+
+[
+ {"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\n\n","title":"GettingStarted","modified":"20230601125601619"},
+ {"created":"20230601125507054","text":"Welcome to \"TiddlyWiki\".\n\nThis is a test tiddler.","tags":"","title":"Hello There \"Welcome\"","modified":"20230601125551144"},
+ {"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\n\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}
+]
diff --git a/editions/test/tiddlers/tests/data/filters/substitute.tid b/editions/test/tiddlers/tests/data/filters/substitute.tid
new file mode 100644
index 000000000..873d8e0ba
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/filters/substitute.tid
@@ -0,0 +1,40 @@
+title: Filters/substitute
+description: Test substitute operator
+type: text/vnd.tiddlywiki-multiple
+tags: [[$:/tags/wiki-test-spec]]
+
+title: substitute filter data 1
+tags: Hello There [[Welcome to TiddlyWiki]] GettingStarted
+
+TiddlyWiki
++
+title: substitute filter data 2
+
+The output of the filter `[[substitute filter data 1]tags[]]` is ${[[substitute filter data 1]tags[]]}$.
++
+title: substitute filter data 3
+
+Welcome to $(projectname)$ $1$ $2$ $3$. Tiddlers starting with `substitute`: ${[prefix[substitute]format:titlelist[]join[ ]]}$.
++
+title: Output
+
+\whitespace trim
+<$let projectname="TiddlyWiki">
+(<$text text={{{ [[]substitute[]] }}}/>)
+(<$text text={{{ [[Hello There, welcome to $TiddlyWiki$]substitute[]] }}}/>)
+(<$text text={{{ [[Welcome to $(projectname)$]substitute[]] }}}/>)
+(<$text text={{{ [[Welcome to $(projectname)$ $1$]substitute[today]] }}}/>)
+(<$text text={{{ [[This is not a valid embedded filter ${ hello )$]substitute[]] }}}/>)
+(<$text text={{{ [{substitute filter data 2}substitute[]] }}}/>)
+(<$text text={{{ [{substitute filter data 3}substitute[every],[day]] }}}/>)
+$let>
++
+title: ExpectedResult
+
+()
+(Hello There, welcome to $TiddlyWiki$)
+(Welcome to TiddlyWiki)
+(Welcome to TiddlyWiki today)
+(This is not a valid embedded filter ${ hello )$)
+(The output of the filter `[[substitute filter data 1]tags[]]` is Hello.)
+(Welcome to TiddlyWiki every day $3$. Tiddlers starting with `substitute`: [[substitute filter data 1]] [[substitute filter data 2]] [[substitute filter data 3]].)
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets.tid b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets.tid
new file mode 100644
index 000000000..5d351583e
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets.tid
@@ -0,0 +1,23 @@
+title: ImportVariables/WithSetWidgets
+description: Import variables defined with a set widget
+type: text/vnd.tiddlywiki-multiple
+tags: [[$:/tags/wiki-test-spec]]
+
+title: Output
+
+\whitespace trim
+\import Definitions
+<$text text=<>/>,
+<$text text=<>/>
++
+title: Definitions
+
+\whitespace trim
+<$set name="one" value="elephant">
+<$set name="two" value="giraffe">
+$set>
+$set>
++
+title: ExpectedResult
+
+elephant,giraffe
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets2.tid b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets2.tid
new file mode 100644
index 000000000..23fa58c57
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets2.tid
@@ -0,0 +1,22 @@
+title: ImportVariables/WithSetWidgets2
+description: Import variables defined with a set widget without whitespace pragma
+type: text/vnd.tiddlywiki-multiple
+tags: [[$:/tags/wiki-test-spec]]
+
+title: Output
+
+\whitespace trim
+\import Definitions
+<$text text=<>/>,
+<$text text=<>/>
++
+title: Definitions
+
+<$set name="one" value="elephant">
+<$set name="two" value="giraffe">
+$set>
+$set>
++
+title: ExpectedResult
+
+elephant,giraffe
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/data/importvariables/WithSetWidgetsAndMacros.tid b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgetsAndMacros.tid
new file mode 100644
index 000000000..eaa81f38c
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgetsAndMacros.tid
@@ -0,0 +1,29 @@
+title: ImportVariables/WithSetWidgetsAndMacros
+description: Import variables defined with a set widget without whitespace pragma
+type: text/vnd.tiddlywiki-multiple
+tags: [[$:/tags/wiki-test-spec]]
+
+title: Output
+
+\whitespace trim
+\import Definitions
+<$text text=<>/>,
+<$text text=<>/>,
+<$text text=<>/>,
+<$text text=<>/>
++
+title: Definitions
+
+\define name() Bugs Bunny
+\procedure address()
+Bunny Hill
+\end
+
+<$set name="one" value="elephant">
+<$set name="two" value="giraffe">
+$set>
+$set>
++
+title: ExpectedResult
+
+Bugs Bunny,Bunny Hill,elephant,giraffe
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid b/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid
new file mode 100644
index 000000000..9d5538573
--- /dev/null
+++ b/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid
@@ -0,0 +1,21 @@
+title: Widgets/SubstitutedAttributes
+description: Attributes specified as string that should have substitution performed.
+type: text/vnd.tiddlywiki-multiple
+tags: [[$:/tags/wiki-test-spec]]
+
+title: Output
+
+\whitespace trim
+<$set name="var with spaces" value="spaces">
+<$let project="TiddlyWiki" disabled="true" var-with-dashes="dashes">
+
+
+$let>
+$set>
+
++
+title: ExpectedResult
+
+
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/test-deserialize-operator.js b/editions/test/tiddlers/tests/test-deserialize-operator.js
new file mode 100644
index 000000000..c629de3ae
--- /dev/null
+++ b/editions/test/tiddlers/tests/test-deserialize-operator.js
@@ -0,0 +1,44 @@
+/*\
+title: test-deserialize-operator.js
+type: application/javascript
+tags: [[$:/tags/test-spec]]
+
+Tests deserialize[] filter operator with various core deserializers
+
+\*/
+(function(){
+
+ /* jslint node: true, browser: true */
+ /* eslint-env node, browser, jasmine */
+ /* eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/
+ /* global $tw, require */
+ "use strict";
+
+
+ describe("deserialize operator tests", function() {
+
+ it("should support the deserialize[] operator", function() {
+ //Unknown deserializer as operand
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[unknown/deserializer]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/UnknownDeserializer")]);
+
+ //Missing operand
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/MissingOperand")]);
+
+ //Deserialize TiddlyWiki file
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"}]']);
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"},{"title":"Hello \\"There\\"","text":"Protractor"}]']);
+
+ // Deserialize JSON payload containing tiddlers
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]]")).toEqual( [ `[{"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\\n\\n","title":"GettingStarted","modified":"20230601125601619"},{"created":"20230601125507054","text":"Welcome to \\"TiddlyWiki\\".\\n\\nThis is a test tiddler.","tags":"","title":"Hello There \\"Welcome\\"","modified":"20230601125551144"},{"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\\n\\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}]` ]);
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]jsonindexes[]] :map[{dezerializer test data case 6}jsonget,[title]]")).toEqual([ 'GettingStarted', 'Hello There "Welcome"', 'TiddlyWiki' ]);
+
+ //Deserialize TiddlyWiki file with an mismatched deserializer
+ expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[application/json]]")).toEqual([jasmine.stringMatching('JSON error')]);
+ });
+ });
+
+})();
+
+
+
+
\ No newline at end of file
diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js
index 49a790166..9e2f53b1a 100644
--- a/editions/test/tiddlers/tests/test-filters.js
+++ b/editions/test/tiddlers/tests/test-filters.js
@@ -99,14 +99,14 @@ Tests the filtering mechanism.
},
"TiddlerSix": {
title: "TiddlerSix",
- text: "Missing inaction from TiddlerOne",
+ text: "Missing inaction from [[TiddlerOne]]",
filter: "[[one]] [[a a]] [subfilter{hasList!!list}]",
tags: []
},
"TiddlerSeventh": {
title: "TiddlerSeventh",
text: "",
- list: "TiddlerOne [[Tiddler Three]] [[a fourth tiddler]] MissingTiddler",
+ list: "[[TiddlerOne]] [[Tiddler Three]] [[a fourth tiddler]] [[MissingTiddler]]",
tags: ["one"]
},
"Tiddler8": {
@@ -144,7 +144,7 @@ Tests the filtering mechanism.
modified: "201304152211"
},{
title: "Tiddler Three",
- text: "The speed of sound in light\n\nThere is no TiddlerZero but TiddlerSix",
+ text: "The speed of sound in light\n\nThere is no [[TiddlerZero]] but [[TiddlerSix]]",
tags: ["one","two"],
cost: "56",
value: "80",
@@ -252,9 +252,9 @@ Tests the filtering mechanism.
});
it("should handle the lookup operator", function() {
- expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,,Tidd");
- expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd");
- expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd");
+ expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],,Tidd");
+ expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd");
+ expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler],[tags]]").join(",")).toBe(",one,one");
});
@@ -397,8 +397,8 @@ Tests the filtering mechanism.
expect(wiki.filterTiddlers("[all[shadows]tag[two]]").join(",")).toBe("$:/TiddlerFive");
expect(wiki.filterTiddlers("[all[shadows+tiddlers]tag[two]]").join(",")).toBe("$:/TiddlerFive,$:/TiddlerTwo,Tiddler Three");
expect(wiki.filterTiddlers("[all[tiddlers+shadows]tag[two]]").join(",")).toBe("$:/TiddlerTwo,Tiddler Three,$:/TiddlerFive");
- expect(wiki.filterTiddlers("[all[shadows+tiddlers]]").join(",")).toBe("$:/TiddlerFive,TiddlerSix,TiddlerSeventh,Tiddler8,$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne");
- expect(wiki.filterTiddlers("[all[tiddlers+shadows]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne,$:/TiddlerFive,TiddlerSix,TiddlerSeventh,Tiddler8");
+ expect(wiki.filterTiddlers("[all[shadows+tiddlers]]").join(",")).toBe("$:/TiddlerFive,Tiddler8,TiddlerSeventh,TiddlerSix,$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne");
+ expect(wiki.filterTiddlers("[all[tiddlers+shadows]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne,$:/TiddlerFive,Tiddler8,TiddlerSeventh,TiddlerSix");
expect(wiki.filterTiddlers("[all[tiddlers]tag[two]]").join(",")).toBe("$:/TiddlerTwo,Tiddler Three");
expect(wiki.filterTiddlers("[all[orphans+tiddlers+tags]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,Tiddler Three,TiddlerOne,two,one");
});
@@ -420,10 +420,10 @@ Tests the filtering mechanism.
it("should handle the tagging operator", function() {
expect(wiki.filterTiddlers("[[one]tagging[]sort[title]]").join(",")).toBe("Tiddler Three,Tiddler8,TiddlerOne,TiddlerSeventh");
- expect(wiki.filterTiddlers("[[one]tagging[]]").join(",")).toBe("Tiddler Three,TiddlerOne,TiddlerSeventh,Tiddler8");
+ expect(wiki.filterTiddlers("[[one]tagging[]]").join(",")).toBe("Tiddler Three,TiddlerOne,Tiddler8,TiddlerSeventh");
expect(wiki.filterTiddlers("[[two]tagging[]sort[title]]").join(",")).toBe("$:/TiddlerFive,$:/TiddlerTwo,Tiddler Three");
var fakeWidget = {wiki: wiki, getVariable: function(name) {return name === "currentTiddler" ? "one": undefined;}};
- expect(wiki.filterTiddlers("[all[current]tagging[]]",fakeWidget).join(",")).toBe("Tiddler Three,TiddlerOne,TiddlerSeventh,Tiddler8");
+ expect(wiki.filterTiddlers("[all[current]tagging[]]",fakeWidget).join(",")).toBe("Tiddler Three,TiddlerOne,Tiddler8,TiddlerSeventh");
});
it("should handle the untagged operator", function() {
@@ -990,10 +990,10 @@ Tests the filtering mechanism.
expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne,hasList,one");
expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("has filter,TiddlerOne,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test,one,hasList");
expect(wiki.filterTiddlers("[!sortsub:string]",anchorWidget).join(",")).toBe("hasList,one,filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne");
- expect(wiki.filterTiddlers("[sortsub:number]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test,$:/ShadowPlugin");
- expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,has filter,hasList,TiddlerOne,one");
- expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test");
- expect(wiki.filterTiddlers("[!sortsub:string]",anchorWidget).join(",")).toBe("filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
+ expect(wiki.filterTiddlers("[sortsub:number]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test,$:/ShadowPlugin");
+ expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,has filter,hasList,TiddlerOne,one");
+ expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test");
+ expect(wiki.filterTiddlers("[!sortsub:string]",anchorWidget).join(",")).toBe("filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[[TiddlerOne]] [[$:/TiddlerTwo]] [[Tiddler Three]] [[a fourth tiddler]] +[!sortsub:number]",anchorWidget).join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler");
expect(wiki.filterTiddlers("a1 a10 a2 a3 b10 b3 b1 c9 c11 c1 +[sortsub:alphanumeric]",anchorWidget).join(",")).toBe("a1,a2,a3,a10,b1,b3,b10,c1,c9,c11");
// #7155. The order of the output is the same as the input when an undefined variable is used in the subfitler
@@ -1066,7 +1066,11 @@ Tests the filtering mechanism.
});
it("should handle the deserializers operator", function() {
- expect(wiki.filterTiddlers("[deserializers[]]").join(",")).toBe("application/javascript,application/json,application/x-tiddler,application/x-tiddler-html-div,application/x-tiddlers,text/css,text/html,text/plain");
+ var expectedDeserializers = ["application/javascript","application/json","application/x-tiddler","application/x-tiddler-html-div","application/x-tiddlers","text/css","text/html","text/plain"];
+ if($tw.browser) {
+ expectedDeserializers.unshift("(DOM)");
+ }
+ expect(wiki.filterTiddlers("[deserializers[]]").join(",")).toBe(expectedDeserializers.join(","));
});
it("should handle the charcode operator", function() {
diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js
index cdc8dee47..d2266ca5e 100644
--- a/editions/test/tiddlers/tests/test-html-parser.js
+++ b/editions/test/tiddlers/tests/test-html-parser.js
@@ -161,6 +161,16 @@ describe("HTML tag new parser tests", function() {
expect($tw.utils.parseAttribute(" attrib1>",0)).toEqual(
{ type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 }
);
+ expect($tw.utils.parseAttribute("p=`blah` ",1)).toEqual(null);
+ expect($tw.utils.parseAttribute("p=`blah` ",0)).toEqual(
+ { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 8 }
+ );
+ expect($tw.utils.parseAttribute("p=```blah``` ",0)).toEqual(
+ { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 12 }
+ );
+ expect($tw.utils.parseAttribute("p=`Hello \"There\"`",0)).toEqual(
+ { start: 0, name: 'p', type: 'substituted', rawValue: 'Hello "There"', end: 17 }
+ );
});
it("should parse HTML tags", function() {
diff --git a/editions/test/tiddlers/tests/test-prefixes-filter.js b/editions/test/tiddlers/tests/test-prefixes-filter.js
index 62f329d66..a8d109d73 100644
--- a/editions/test/tiddlers/tests/test-prefixes-filter.js
+++ b/editions/test/tiddlers/tests/test-prefixes-filter.js
@@ -434,6 +434,15 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
expect(wiki.filterTiddlers("[tag[shopping]] :map[get[title]addprefix[-]addprefixaddprefix[of]addprefix]").join(",")).toBe("0of4-Brownies,1of4-Chick Peas,2of4-Milk,3of4-Rice Pudding");
});
+ it("should handle the :then prefix", function() {
+ expect(wiki.filterTiddlers("[[one]] :then[[two]]").join(",")).toBe("two");
+ expect(wiki.filterTiddlers("[[one]] :then[tag[shopping]]").join(",")).toBe("Brownies,Chick Peas,Milk,Rice Pudding");
+ expect(wiki.filterTiddlers("[[one]] [[two]] [[three]] :then[[four]]").join(",")).toBe("four");
+ expect(wiki.filterTiddlers("[[one]] :then[tag[nonexistent]]").join(",")).toBe("one");
+ expect(wiki.filterTiddlers(":then[[two]]").length).toBe(0);
+ expect(wiki.filterTiddlers("[[notatiddler]is[tiddler]] :then[[two]]").length).toBe(0);
+ });
+
it("should handle macro parameters for filter run prefixes",function() {
var widget = require("$:/core/modules/widgets/widget.js");
var rootWidget = new widget.widget({ type:"widget", children:[ {type:"widget", children:[]} ] },
diff --git a/editions/test/tiddlers/tests/test-wikitext.js b/editions/test/tiddlers/tests/test-wikitext.js
index cdd729cfc..eddef73f7 100644
--- a/editions/test/tiddlers/tests/test-wikitext.js
+++ b/editions/test/tiddlers/tests/test-wikitext.js
@@ -45,16 +45,6 @@ describe("WikiText tests", function() {
it("should support attributes specified as macro invocations", function() {
expect(wiki.renderTiddler("text/html","TiddlerFour")).toBe("This is a link
");
});
- it("should identify wikiwords to automatically link", function() {
- expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No wikilinks here").indexOf("header");
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","@@.myclass\n\n\nContent
\n@@")).toBe("");
diff --git a/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid b/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid
index 11abdd2e9..89417bc65 100644
--- a/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid
+++ b/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid
@@ -9,9 +9,13 @@ tags: Concepts
<$button actions=<>>$text$$button>
\end
-ShadowTiddlers are tiddlers that are loaded from within [[Plugins]]. Unlike ordinary tiddlers, they don't appear in most lists.
+ShadowTiddlers are tiddlers that are loaded from [[Plugins]] at the wiki startup. Unlike ordinary tiddlers, they don't appear in most lists.
-ShadowTiddlers can be overridden with an ordinary tiddler of the same name. If that tiddler is subsequently deleted then the original shadow tiddler is automatically restored.
+!! Overriding Shadow Tiddlers to modify plugins
+
+A ShadowTiddler can be overridden with an ordinary tiddler of the same name. This leaves the shadow tiddler intact but the plugin will use the overriding tiddler in its place, effectively allowing users to modify the behaviour of plugins.
+
+Users are cautioned against overriding shadow tiddlers because if the shadow tiddler is changed in a plugin update, the overriding tiddler may no longer perform as intended. To remedy this, the overriding tiddler may be modified or deleted. If the overriding tiddler is deleted, then the plugin falls back to using the original shadow tiddler.
!! Overridden Shadow Tiddlers
diff --git a/editions/tw5.com/tiddlers/features/Deserializers.tid b/editions/tw5.com/tiddlers/features/Deserializers.tid
new file mode 100644
index 000000000..1da4813df
--- /dev/null
+++ b/editions/tw5.com/tiddlers/features/Deserializers.tid
@@ -0,0 +1,20 @@
+created: 20230627093650105
+modified: 20230627094356394
+tags: Features
+title: Deserializers
+type: text/vnd.tiddlywiki
+
+Deserializer [[modules|Modules]] parse text in various formats into their JSON representation as tiddlers. The deserializer modules available in a wiki can be seen using the [[deserializers operator|deserializers Operator]] and can be used with the [[deserialize Operator]].
+
+The TiddlyWiki core provides the following deserializers:
+
+|!Deserializer |!Description |
+|(DOM)|Extracts tiddlers from a DOM node, should not be used with the <<.op deserialize[]>> operator |
+|application/javascript|Parses a JavaScript module as a tiddler extracting fields from the header comment|
+|application/json|Parses [[JSON|JSON in TiddlyWiki]] into tiddlers|
+|application/x-tiddler|Parses the [[.tid file format|TiddlerFiles]] as a tiddler|
+|application/x-tiddler-html-div|Parses the [[.tiddler file format|TiddlerFiles]] as a tiddler|
+|application/x-tiddlers|Parses the [[MultiTiddlerFile format|MultiTiddlerFiles]] as tiddlers|
+|text/css|Parses CSS as a tiddler extracting fields from the header comment|
+|text/html|Parses an HTML file into tiddlers. Supports ~TiddlyWiki Classic HTML files, ~TiddlyWiki5 HTML files and ordinary HTML files|
+|text/plain|Parses plain text as a tiddler|
\ No newline at end of file
diff --git a/editions/tw5.com/tiddlers/filters/Conditional Operators.tid b/editions/tw5.com/tiddlers/filters/Conditional Operators.tid
index 7028e6dad..6d21e0864 100644
--- a/editions/tw5.com/tiddlers/filters/Conditional Operators.tid
+++ b/editions/tw5.com/tiddlers/filters/Conditional Operators.tid
@@ -1,12 +1,12 @@
created: 20190802113703788
-modified: 20190802132727925
+modified: 20230501175143648
tags: Filters
title: Conditional Operators
type: text/vnd.tiddlywiki
-<<.from-version "5.1.20">>The conditional filter operators allow ''if-then-else'' logic to be expressed within filters.
+<<.from-version "5.1.20">>The conditional filter operators allow for ''if-then-else'' logic to be expressed within filters.
-The foundation is the convention that an empty list can be used to represent the boolean value ''false'' and a list with at one (or more) entries to represent ''true''.
+The foundation is the convention that an empty list can be used to represent the Boolean value <<.value false>> and a list with at one (or more) entries to represent <<.value true>>.
The conditional operators are:
@@ -19,10 +19,12 @@ The conditional operators are:
These operators can be combined. For example:
-<<.inline-operator-example "[[New Tiddler]is[missing]then[I am missing]else[No I am not missing]]">>
+<<.operator-example 1 "[[New Tiddler]is[missing]then[I am missing]else[No I am not missing]]">>
-The [[else Operator]] can be used to apply a defaults for missing values. In this example, we take advantage of the fact that the [[get Operator]] returns an empty list if the field or tiddler does not exist:
+The <<.olink else>> operator can be used to apply a defaults for missing values. In this example, we take advantage of the fact that the <<.olink get>> operator returns an empty list if the field or tiddler does not exist:
-<<.inline-operator-example "[[HelloThere]get[custom-field]else[default-value]]">>
+<<.operator-example 2 "[[HelloThere]get[custom-field]else[default-value]]">>
-<
>
+! Filter Run Prefixes
+
+The [[:then|:then Filter Run Prefix]] and [[:else|:else Filter Run Prefix]] filter run prefixes serve a similar purpose as the conditional operators. Refer to their documentation for more information.
\ No newline at end of file
diff --git a/editions/tw5.com/tiddlers/filters/deserialize Operator.tid b/editions/tw5.com/tiddlers/filters/deserialize Operator.tid
new file mode 100644
index 000000000..7205d09c6
--- /dev/null
+++ b/editions/tw5.com/tiddlers/filters/deserialize Operator.tid
@@ -0,0 +1,17 @@
+caption: deserialize
+created: 20230601195749377
+from-version: 5.3.0
+modified: 20230627094109762
+op-input: a selection of strings
+op-output: JSON representations of tiddlers extracted from input titles.
+op-parameter: the deserializer module to be used to extract tiddlers from the input
+op-purpose: extract JSON representation of tiddlers from the input strings
+tags: [[Filter Operators]] [[Special Operators]]
+title: deserialize Operator
+type: text/vnd.tiddlywiki
+
+{{Deserializers}}
+
+
+
+<<.operator-examples "deserialize">>
\ No newline at end of file
diff --git a/editions/tw5.com/tiddlers/filters/deserializers Operator.tid b/editions/tw5.com/tiddlers/filters/deserializers Operator.tid
index 2501553e8..7691be970 100644
--- a/editions/tw5.com/tiddlers/filters/deserializers Operator.tid
+++ b/editions/tw5.com/tiddlers/filters/deserializers Operator.tid
@@ -1,14 +1,14 @@
caption: deserializers
created: 20210506115203172
from-version: 5.2.0
-modified: 20210506130322593
+modified: 20230627094238610
op-input: ignored
op-output: the title of each available deserializer
op-parameter: none
-tags: [[Filter Operators]] [[Special Operators]] [[Selection Constructors]]
+tags: [[Filter Operators]] [[Special Operators]] [[Selection Constructors]]
title: deserializers Operator
type: text/vnd.tiddlywiki
-<<.tip "You can specify a specific deserializer for a DropzoneWidget to use">>
+<<.tip "You can specify a specific [[deserializer|Deserializers]] for a DropzoneWidget to use">>
<<.operator-examples "deserializers">>
diff --git a/editions/tw5.com/tiddlers/filters/examples/deserialize Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/deserialize Operator (Examples).tid
new file mode 100644
index 000000000..5170809b7
--- /dev/null
+++ b/editions/tw5.com/tiddlers/filters/examples/deserialize Operator (Examples).tid
@@ -0,0 +1,29 @@
+created: 20230601200356736
+modified: 20230602105036887
+tags: [[Operator Examples]] [[deserialize Operator]]
+title: deserialize Operator (Examples)
+type: text/vnd.tiddlywiki
+
+\define html-data()
+
+
+
+
+ Test Data
+
+
+
+
+
+
+
+
+\end
+
+This example uses the predefined variable `html-data`:
+<$codeblock code=<> language="HTML"/>
+
+<<.operator-example 1 "[deserialize[text/html]]">>
diff --git a/editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid
new file mode 100644
index 000000000..ece8aecf6
--- /dev/null
+++ b/editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid
@@ -0,0 +1,37 @@
+created: 20230614225302905
+modified: 20230614233448662
+tags: [[Operator Examples]] [[substitute Operator]]
+title: substitute Operator (Examples)
+type: text/vnd.tiddlywiki
+
+\define time() morning
+\define field() modified
+\procedure sentence() This tiddler was last $(field)$ on ${[{!!modified}format:date[DDth MMM YYYY]]}$
+\define name() Bugs Bunny
+\define address() Rabbit Hole Hill
+
+!Substitute <<.op substitute[]>> operator parameters
+<<.operator-example 1 "[[Hi, I'm $1$ and I live in $2$]substitute[Bugs Bunny],[Rabbit Hole Hill]]">>
+
+!Substitute variables
+This example uses the following variables:
+
+* name: <$codeblock code=<>/>
+* address: <$codeblock code=<>/>
+
+<<.operator-example 2 "[[Hi, I'm $(name)$ and I live in $(address)$]substitute[]]">>
+
+!Substitute variables and operator parameters
+This example uses the following variable:
+
+* time: <$codeblock code=<