From a5c258ecac14ce9c5cf2c21b40119db775bd31cb Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" Date: Sat, 24 Jun 2023 10:51:20 +0100 Subject: [PATCH 01/13] Update release note --- .../prerelease/tiddlers/Release 5.3.0.tid | 22 ++++++++++++++----- .../tiddlers/hellothere/HelloThere.tid | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.0.tid b/editions/prerelease/tiddlers/Release 5.3.0.tid index cf1ce0098..6ddf19598 100644 --- a/editions/prerelease/tiddlers/Release 5.3.0.tid +++ b/editions/prerelease/tiddlers/Release 5.3.0.tid @@ -1,6 +1,6 @@ caption: 5.3.0 -created: 20230506164543446 -modified: 20230506164543446 +created: 20230624100932287 +modified: 20230624100932287 tags: ReleaseNotes title: Release 5.3.0 type: text/vnd.tiddlywiki @@ -30,14 +30,24 @@ These changes lay the groundwork for macros and related features to be deprecate The new transclusion architecture is not by itself sufficient to enable us to fully deprecate macros yet. To handle the remaining use cases we propose a new backtick quoted attribute format that allows for the substitution of variable values. See https://github.com/Jermolene/TiddlyWiki5/issues/6663 for details. +! HTTP Requests in WikiText + +<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7422">> new [[WidgetMessage: tm-http-request]] for performing HTTP requests in WikiText. This opens up some exciting new opportunities: + +* Integration with Web-based APIs. The documentation includes an [[example of using the Zotero API|WidgetMessage: tm-http-request Example - Zotero]] to retrieve academic citation data +* Dynamic content loading: additional tiddlers can be imported dynamically after the main wiki has loaded + ! Defaulting to Disabling CamelCase Links -<<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/7513">> CamelCase linking is now disabled by default. (Note that this wiki has CamelCase linking explicitly enabled) +<<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/7513">> CamelCase linking is now disabled by default for new wikis. (Note that this wiki has CamelCase linking explicitly enabled) ! Plugin Improvements +* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/7554">> Google Analytics plugin to use new GA4 code. Note that the update requires manual configuration to use the new "measurement ID" instead of the old "account ID" * <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7260">> Dynannotate pugin to support three additional search modes * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7365">> problem with [[BrowserStorage Plugin]] unnecessarily saving shadow tiddlers + +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7398">> [[BrowserStorage Plugin]] to request that browser storage be persisted without eviction * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7493">> [[CodeMirror Plugin]] to add an option to make trailing spaces visible ! Translation improvement @@ -52,7 +62,7 @@ Improvements to the following translations: ! Usability Improvements -* +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7524">> consistency of layout of "Settings" tab in $:/ControlPanel ! Widget Improvements @@ -69,9 +79,11 @@ Improvements to the following translations: * <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7413">> [[Core Icons]] to allow the size to be controlled with a parameter ** <<.warning """This change can cause problems with non-standard usage of the core icons where the text is directly rendered instead of being transcluded""">> * <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7182">> new [[thisTiddler Variable]] that refers to the tiddler currently being rendered +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7530">> `data-tag-title` attribute to all tag pills, allowing easier [[Custom tag pill styles]] * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7332">> [[Story Tiddler Template Cascade]] handling to fall back to the default template if the output of the cascade is not valid * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7378">> missing file extensions for "audio/mpeg" files - +* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7417">> [[Table-of-Contents Macros]] to add consistent support for an ''exclude'' parameter +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/190613ad2989f70526f86eef17f524087f60eb72">> [[tv-config-static Variable]] for indicating static rendering ! Bug Fixes * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7215">> importing tiddlers by pasting tiddler data diff --git a/editions/tw5.com/tiddlers/hellothere/HelloThere.tid b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid index d58179819..3a2e07fdd 100644 --- a/editions/tw5.com/tiddlers/hellothere/HelloThere.tid +++ b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid @@ -1,6 +1,6 @@ created: 20130822170200000 list: [[A Gentle Guide to TiddlyWiki]] [[Discover TiddlyWiki]] [[Some of the things you can do with TiddlyWiki]] [[Ten reasons to switch to TiddlyWiki]] Examples [[What happened to the original TiddlyWiki?]] -modified: 20230326083239710 +modified: 20230624100932287 tags: TableOfContents title: HelloThere type: text/vnd.tiddlywiki From e5566543c91d1c8dba15fd105aaf711d63ed893e Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Sat, 24 Jun 2023 15:52:43 +0200 Subject: [PATCH 02/13] Make tag-macro and tag*-templates human readable for future improvements (#7559) --- core/ui/MoreSideBar/Tags.tid | 5 ++-- core/ui/TagPickerTagTemplate.tid | 43 +++++++++++++++++++------------- core/ui/TagTemplate.tid | 29 +++++++++++++-------- core/wiki/macros/tag.tid | 38 ++++++++++++++++++++++------ 4 files changed, 76 insertions(+), 39 deletions(-) diff --git a/core/ui/MoreSideBar/Tags.tid b/core/ui/MoreSideBar/Tags.tid index 0a4727bc3..b1b67bb67 100644 --- a/core/ui/MoreSideBar/Tags.tid +++ b/core/ui/MoreSideBar/Tags.tid @@ -3,15 +3,14 @@ tags: $:/tags/MoreSideBar caption: {{$:/language/SideBar/Tags/Caption}} \whitespace trim - <$let tv-config-toolbar-icons="yes" tv-config-toolbar-text="yes" tv-config-toolbar-class="">
- {{$:/core/ui/Buttons/tag-manager}} + {{$:/core/ui/Buttons/tag-manager}}
<$list filter={{$:/core/Filters/AllTags!!filter}}>
- <$transclude tiddler="$:/core/ui/TagTemplate"/> + <$transclude tiddler="$:/core/ui/TagTemplate"/>

diff --git a/core/ui/TagPickerTagTemplate.tid b/core/ui/TagPickerTagTemplate.tid index 6329f86ae..9e8689153 100644 --- a/core/ui/TagPickerTagTemplate.tid +++ b/core/ui/TagPickerTagTemplate.tid @@ -2,22 +2,29 @@ title: $:/core/ui/TagPickerTagTemplate \whitespace trim <$button class=<> tag="a" tooltip={{$:/language/EditTemplate/Tags/Add/Button/Hint}}> -<$list filter="[minlength[1]]"> -<$action-listops $tiddler=<> $field=<> $subfilter="[]"/> - -<$set name="currentTiddlerCSSEscaped" value={{{ [escapecss[]] }}}> -<$action-sendmessage $message="tm-focus-selector" $param=<> preventScroll="true"/> - -<> -<$list filter="[minlength[1]]"> -<$action-setfield $tiddler=<> text="yes"/> - -<> -<$set name="backgroundColor" value={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}> -<$wikify name="foregroundColor" text="""<$macrocall $name="contrastcolour" target=<> fallbackTarget=<> colourA=<> colourB=<>/>"""> -> data-tag-title=<> > -{{||$:/core/ui/TiddlerIcon}}<$view field="title" format="text"/> - - - + <$list filter="[minlength[1]]"> + <$action-listops $tiddler=<> $field=<> $subfilter="[]"/> + + <$set name="currentTiddlerCSSEscaped" value={{{ [escapecss[]] }}}> + <$action-sendmessage $message="tm-focus-selector" $param=<> preventScroll="true"/> + + <> + <$list filter="[minlength[1]]"> + <$action-setfield $tiddler=<> text="yes"/> + + <> + <$set name="backgroundColor" + value={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}} + > + <$wikify name="foregroundColor" + text="""<$macrocall $name="contrastcolour" target=<> fallbackTarget=<> colourA=<> colourB=<>/>""" + > + > + data-tag-title=<> + > + {{||$:/core/ui/TiddlerIcon}}<$view field="title" format="text"/> + + + diff --git a/core/ui/TagTemplate.tid b/core/ui/TagTemplate.tid index f137f22a0..49e836671 100644 --- a/core/ui/TagTemplate.tid +++ b/core/ui/TagTemplate.tid @@ -3,16 +3,23 @@ title: $:/core/ui/TagTemplate \whitespace trim >> <$set name="transclusion" value=<>> -<$macrocall $name="tag-pill-body" tag=<> icon={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}} colour={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}} palette={{$:/palette}} element-tag="""$button""" element-attributes="""popup=<> dragFilter='[all[current]tagging[]]' tag='span'"""/> -<$reveal state=<> type="popup" position="below" animate="yes" class="tc-drop-down"> -<$set name="tv-show-missing-links" value="yes"> -<$transclude tiddler="$:/core/ui/ListItemTemplate"/> - -<$list filter="[all[shadows+tiddlers]tag[$:/tags/TagDropdown]!has[draft.of]]" variable="listItem"> -<$transclude tiddler=<>/> - -
-<$macrocall $name="list-tagged-draggable" tag=<>/> - + <$macrocall $name="tag-pill-body" + tag=<> + icon={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}} + colour={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}} + palette={{$:/palette}} + element-tag="$button" + element-attributes="""popup=<> dragFilter="[all[current]tagging[]]" tag='span'""" + /> + <$reveal state=<> type="popup" position="below" animate="yes" class="tc-drop-down"> + <$set name="tv-show-missing-links" value="yes"> + <$transclude tiddler="$:/core/ui/ListItemTemplate"/> + + <$list filter="[all[shadows+tiddlers]tag[$:/tags/TagDropdown]!has[draft.of]]" variable="listItem"> + <$transclude tiddler=<>/> + +
+ <$macrocall $name="list-tagged-draggable" tag=<>/> +
diff --git a/core/wiki/macros/tag.tid b/core/wiki/macros/tag.tid index 3616fb97d..03dd8cb98 100644 --- a/core/wiki/macros/tag.tid +++ b/core/wiki/macros/tag.tid @@ -9,26 +9,50 @@ color:$(foregroundColor)$; \define tag-pill-inner(tag,icon,colour,fallbackTarget,colourA,colourB,element-tag,element-attributes,actions) +\whitespace trim <$vars foregroundColor=<> - backgroundColor="""$colour$""" -><$element-tag$ + backgroundColor=<<__colour__>> +> +<$element-tag$ $element-attributes$ class="tc-tag-label tc-btn-invisible" style=<> ->$actions$<$transclude tiddler="""$icon$"""/><$view tiddler=<<__tag__>> field="title" format="text" /> +> + <<__actions__>> + <$transclude tiddler=<<__icon__>>/> + <$view tiddler=<<__tag__>> field="title" format="text" /> + \end \define tag-pill-body(tag,icon,colour,palette,element-tag,element-attributes,actions) -<$macrocall $name="tag-pill-inner" tag=<<__tag__>> icon="""$icon$""" colour="""$colour$""" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} element-tag="""$element-tag$""" element-attributes="""$element-attributes$""" actions="""$actions$"""/> +\whitespace trim +<$macrocall $name="tag-pill-inner" + tag=<<__tag__>> + icon=<<__icon__>> + colour=<<__colour__>> + fallbackTarget={{$palette$##tag-background}} + colourA={{$palette$##foreground}} + colourB={{$palette$##background}} + element-tag=<<__element-tag__>> + element-attributes=<<__element-attributes__>> + actions=<<__actions__>> +/> \end \define tag-pill(tag,element-tag:"span",element-attributes:"",actions:"") \whitespace trim >> -<$let currentTiddler=<<__tag__>>> -<$macrocall $name="tag-pill-body" tag=<<__tag__>> icon={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}} colour={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}} palette={{$:/palette}} element-tag="""$element-tag$""" element-attributes="""$element-attributes$""" actions="""$actions$"""/> - + <$let currentTiddler=<<__tag__>>> + <$macrocall $name="tag-pill-body" + tag=<<__tag__>> + icon={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}} + colour={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}} + palette={{$:/palette}} + element-tag=<<__element-tag__>> + element-attributes=<<__element-attributes__>> + actions=<<__actions__>>/> + \end From 3825e2579fb273d014e04c82a4ed8280c94a2e2e Mon Sep 17 00:00:00 2001 From: Saq Imtiaz Date: Sat, 24 Jun 2023 15:57:15 +0200 Subject: [PATCH 03/13] Adds Text substitution support in widget attributes and new operator (#7526) * feat: new text substitution support, first pass * fix: use the widget method instead of evaluating a filter * revert to earlier implementation that emulates macro syntax * fix: capitalize comments * feat: add support for triple backticks for substituted attributes * docs: added docs for substitute operator * chore: more docs tweaks * docs: substituted attributes, refactored docs for widget attributes * docs: fixed typo * docs: more examples for substituted attributes * docs: updated prior documentation on concatenating text and variables * docs: documentation corrections * Update editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid Co-authored-by: btheado --------- Co-authored-by: btheado --- core/modules/filters/substitute.js | 36 ++++++++++ core/modules/parsers/parseutils.js | 18 +++-- core/modules/widgets/widget.js | 2 + core/modules/wiki.js | 28 ++++++++ .../tests/data/filters/substitute.tid | 40 +++++++++++ .../data/widgets/SubstitutedAttributes.tid | 19 ++++++ .../test/tiddlers/tests/test-html-parser.js | 10 +++ .../substitute Operator (Examples).tid | 37 ++++++++++ .../tiddlers/filters/substitute Operator.tid | 27 ++++++++ ...and variables using macro substitution.tid | 3 +- .../wikitext/Filtered Attribute Values.tid | 16 +++++ .../tiddlers/wikitext/HTML in WikiText.tid | 67 ++----------------- .../wikitext/Literal Attribute Values.tid | 30 +++++++++ .../wikitext/Substituted Attribute Values.tid | 45 +++++++++++++ .../wikitext/Transcluded Attribute Values.tid | 14 ++++ .../wikitext/Variable Attribute Values.tid | 14 ++++ .../tiddlers/wikitext/Widget Attributes.tid | 21 ++++++ 17 files changed, 361 insertions(+), 66 deletions(-) create mode 100644 core/modules/filters/substitute.js create mode 100644 editions/test/tiddlers/tests/data/filters/substitute.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid create mode 100644 editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/substitute Operator.tid create mode 100644 editions/tw5.com/tiddlers/wikitext/Filtered Attribute Values.tid create mode 100644 editions/tw5.com/tiddlers/wikitext/Literal Attribute Values.tid create mode 100644 editions/tw5.com/tiddlers/wikitext/Substituted Attribute Values.tid create mode 100644 editions/tw5.com/tiddlers/wikitext/Transcluded Attribute Values.tid create mode 100644 editions/tw5.com/tiddlers/wikitext/Variable Attribute Values.tid create mode 100644 editions/tw5.com/tiddlers/wikitext/Widget Attributes.tid diff --git a/core/modules/filters/substitute.js b/core/modules/filters/substitute.js new file mode 100644 index 000000000..655ef7321 --- /dev/null +++ b/core/modules/filters/substitute.js @@ -0,0 +1,36 @@ +/*\ +title: $:/core/modules/filters/substitute.js +type: application/javascript +module-type: filteroperator + +Filter operator for substituting variables and embedded filter expressions with their corresponding values + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.substitute = function(source,operator,options) { + var results = [], + operands = []; + $tw.utils.each(operator.operands,function(operand,index){ + operands.push({ + name: (index + 1).toString(), + value: operand + }); + }); + source(function(tiddler,title) { + if(title) { + results.push(options.wiki.getSubstitutedText(title,options.widget,{substitutions:operands})); + } + }); + return results; +}; + +})(); + \ No newline at end of file diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 6a0902c6f..1f86dd909 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -305,10 +305,11 @@ exports.parseAttribute = function(source,pos) { start: pos }; // Define our regexps - var reAttributeName = /([^\/\s>"'=]+)/g, - reUnquotedAttribute = /([^\/\s<>"'=]+)/g, + var reAttributeName = /([^\/\s>"'`=]+)/g, + reUnquotedAttribute = /([^\/\s<>"'`=]+)/g, reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g, - reIndirectValue = /\{\{([^\}]+)\}\}/g; + reIndirectValue = /\{\{([^\}]+)\}\}/g, + reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Get the attribute name @@ -361,8 +362,15 @@ exports.parseAttribute = function(source,pos) { node.type = "macro"; node.value = macroInvocation; } else { - node.type = "string"; - node.value = "true"; + var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue); + if(substitutedValue) { + pos = substitutedValue.end; + node.type = "substituted"; + node.rawValue = substitutedValue.match[1] || substitutedValue.match[2]; + } else { + node.type = "string"; + node.value = "true"; + } } } } diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 8ffee0ab7..3780c05cf 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -380,6 +380,8 @@ Widget.prototype.computeAttribute = function(attribute) { } else if(attribute.type === "macro") { var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params}); value = variableInfo.text; + } else if(attribute.type === "substituted") { + value = this.wiki.getSubstitutedText(attribute.rawValue,this) || ""; } else { // String attribute value = attribute.value; } diff --git a/core/modules/wiki.js b/core/modules/wiki.js index ca31da8d2..93e818f21 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1063,6 +1063,34 @@ exports.getTextReferenceParserInfo = function(title,field,index,options) { return parserInfo; } +/* +Parse a block of text of a specified MIME type + text: text on which to perform substitutions + widget + options: see below +Options include: + substitutions: an optional array of substitutions +*/ +exports.getSubstitutedText = function(text,widget,options) { + options = options || {}; + text = text || ""; + var self = this, + substitutions = options.substitutions || [], + output; + // Evaluate embedded filters and substitute with first result + output = text.replace(/\$\{([\S\s]+?)\}\$/g, function(match,filter) { + return self.filterTiddlers(filter,widget)[0] || ""; + }); + // Process any substitutions provided in options + $tw.utils.each(substitutions,function(substitute) { + output = $tw.utils.replaceString(output,new RegExp("\\$" + $tw.utils.escapeRegExp(substitute.name) + "\\$","mg"),substitute.value); + }); + // Substitute any variable references with their values + return output.replace(/\$\((\w+)\)\$/g, function(match,varname) { + return widget.getVariable(varname,{defaultValue: ""}) + }); +}; + /* Make a widget tree for a parse tree parser: parser object 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]] }}}/>) + ++ +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/widgets/SubstitutedAttributes.tid b/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid new file mode 100644 index 000000000..408d202c6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid @@ -0,0 +1,19 @@ +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 +<$let project="TiddlyWiki" disabled="true"> +
+
+ + ++ +title: ExpectedResult + +

\ No newline at end of file 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/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..45a25e3e0 --- /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=<
>/> + +<<.inline-operator-example "[[Hi, I'm $(name)$ and I live in $(address)$]substitute[]]">> + +!Substitute variables and operator parameters +This example uses the following variable: + +* time: <$codeblock code=<