From c185e373c5f269baac0d88b33896f59b509c6864 Mon Sep 17 00:00:00 2001 From: Simon Huber Date: Tue, 17 Oct 2023 12:54:20 +0200 Subject: [PATCH 001/105] Use display: grid for editor toolbar, editor and preview (#7787) * make toolbar, editor and preview display: grid * correct display of bitmap editor * grid-area: toolbar not only when preview is shown * use dedicated classes and tc-grid and no brittle CSS selectors * no need for width: 100% * cleanup style definitions * use semantic classnames --- core/ui/EditTemplate/body/default.tid | 2 +- themes/tiddlywiki/vanilla/base.tid | 43 ++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/core/ui/EditTemplate/body/default.tid b/core/ui/EditTemplate/body/default.tid index 68133d48e..31322f7fa 100644 --- a/core/ui/EditTemplate/body/default.tid +++ b/core/ui/EditTemplate/body/default.tid @@ -18,7 +18,7 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$ importState=<> > <$dropzone importTitle=<> autoOpenOnImport="no" contentTypesFilter={{$:/config/Editor/ImportContentTypesFilter}} class="tc-dropzone-editor" enable={{{ [{$:/config/DragAndDrop/Enable}match[no]] :else[subfilter{$:/config/Editor/EnableImportFilter}then[yes]else[no]] }}} filesOnly="yes" actions=<> >
-
+
<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/> diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 031b849bf..214352b23 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1365,6 +1365,11 @@ html body.tc-body.tc-single-tiddler-window { margin-top: 8px; } +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview .tc-editor-toolbar, +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview-hidden .tc-editor-toolbar { + grid-area: toolbar; +} + .tc-editor-toolbar button { vertical-align: middle; background-color: <>; @@ -1576,9 +1581,30 @@ html body.tc-body.tc-single-tiddler-window { overflow: auto; } -.tc-tiddler-preview-preview { - float: right; - width: 49%; +.tc-tiddler-editor { + display: grid; +} + +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview { + grid-template-areas: + "toolbar toolbar" + "editor preview"; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto 1fr; +} + +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview-hidden { + grid-template-areas: + "toolbar" + "editor"; + grid-template-columns: 1fr; + grid-template-rows: auto 1fr; +} + +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview .tc-tiddler-preview-preview { + grid-area: preview; + overflow-wrap: anywhere; + word-break: normal; border: 1px solid <>; margin: 4px 0 3px 3px; padding: 3px 3px 3px 3px; @@ -1593,12 +1619,15 @@ html body.tc-body.tc-single-tiddler-window { """>> -.tc-tiddler-frame .tc-tiddler-preview .tc-edit-texteditor { - width: 49%; +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview .tc-edit-texteditor, +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview-hidden .tc-edit-texteditor { + grid-area: editor; } -.tc-tiddler-frame .tc-tiddler-preview canvas.tc-edit-bitmapeditor { - max-width: 49%; +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview canvas.tc-edit-bitmapeditor, +.tc-tiddler-frame .tc-tiddler-editor.tc-tiddler-preview-hidden canvas.tc-edit-bitmapeditor { + grid-area: editor; + max-width: 100%; } .tc-edit-fields { From 326ae61929a9a271a45f4863e7e4d13a33adbbe7 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 18 Oct 2023 22:08:56 +0700 Subject: [PATCH 002/105] Fix encodebase64 and decodebase64 filters (#7683) * Fix encodebase64 and decodebase64 filters The documentation for encodebase64 says that the input is treated as binary data, but in fact the input is being treated as text data, with an extra UTF-8 encoding step being performed first. Likewise, the decodebase64 documentation says that it outputs binary data, but in fact it will do a UTF-8 decoding step before producing output, which will in fact garble binary data. This commit changes the behavior of encodebase64 and decodebase64 to match what the documentation says they do. It also adds an optional `text` suffix to both filters to keep the current behavior. Finally, an optional `urlsafe` suffix is added to both filters to allow them to use the "URL-safe" variant of base64 (using `-` instead of `+` and `_` instead of `/`). * Try to fix failing test Turns out a little more than this is going to be needed. * Fix binary base64 encoding, including unit tests * Update base64 filter documentation * Can't use replaceAll, too new Have to use String.replace with a global regex instead * Replace uses of window.btoa() in rest of code Since window.btoa() is not available under Node.js, we'll replace all uses of it with the $tw.utils.base64encode() function that now works correctly for binary data. * Add link to UTF-8 glossary definition at MDN --- core/modules/filters/encodings.js | 8 +++-- core/modules/savers/github.js | 2 +- core/modules/utils/dom/http.js | 2 +- core/modules/utils/utils.js | 31 ++++++++++++++++--- editions/test/tiddlers/tests/test-utils.js | 23 ++++++++++++++ .../filters/decodebase64 Operator.tid | 7 ++++- .../filters/encodebase64 Operator.tid | 7 ++++- 7 files changed, 70 insertions(+), 10 deletions(-) diff --git a/core/modules/filters/encodings.js b/core/modules/filters/encodings.js index 23c743a03..a43a15f76 100644 --- a/core/modules/filters/encodings.js +++ b/core/modules/filters/encodings.js @@ -18,16 +18,20 @@ Export our filter functions exports.decodebase64 = function(source,operator,options) { var results = []; + var binary = operator.suffixes && operator.suffixes.indexOf("binary") !== -1; + var urlsafe = operator.suffixes && operator.suffixes.indexOf("urlsafe") !== -1; source(function(tiddler,title) { - results.push($tw.utils.base64Decode(title)); + results.push($tw.utils.base64Decode(title,binary,urlsafe)); }); return results; }; exports.encodebase64 = function(source,operator,options) { var results = []; + var binary = operator.suffixes && operator.suffixes.indexOf("binary") !== -1; + var urlsafe = operator.suffixes && operator.suffixes.indexOf("urlsafe") !== -1; source(function(tiddler,title) { - results.push($tw.utils.base64Encode(title)); + results.push($tw.utils.base64Encode(title,binary,urlsafe)); }); return results; }; diff --git a/core/modules/savers/github.js b/core/modules/savers/github.js index f9b87263d..c0a34f2d6 100644 --- a/core/modules/savers/github.js +++ b/core/modules/savers/github.js @@ -31,7 +31,7 @@ GitHubSaver.prototype.save = function(text,method,callback) { headers = { "Accept": "application/vnd.github.v3+json", "Content-Type": "application/json;charset=UTF-8", - "Authorization": "Basic " + window.btoa(username + ":" + password), + "Authorization": "Basic " + $tw.utils.base64Encode(username + ":" + password), "If-None-Match": "" }; // Bail if we don't have everything we need diff --git a/core/modules/utils/dom/http.js b/core/modules/utils/dom/http.js index 083381d8d..27c3e65d6 100644 --- a/core/modules/utils/dom/http.js +++ b/core/modules/utils/dom/http.js @@ -187,7 +187,7 @@ HttpClientRequest.prototype.send = function(callback) { for (var i=0; i> operator produces), so only certain byte sequences in the input are valid. If the input is binary data encoded in base64 format (such as an image, audio file, video file, etc.), then use the optional `binary` suffix, which will allow all byte sequences. Note that the output will then be binary, ''not'' text, and should probably not be passed into further filter operators. + +The optional `urlsafe` suffix, if present, causes the decoder to assume that the base64 input uses `-` and `_` instead of `+` and `/` for the 62nd and 63rd characters of the base64 "alphabet", which is usually referred to as "URL-safe base64" or "bae64url". <<.operator-examples "decodebase64">> diff --git a/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid b/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid index ddbc73078..a7943d726 100644 --- a/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid +++ b/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid @@ -1,6 +1,7 @@ caption: encodebase64 op-input: a [[selection of titles|Title Selection]] op-output: the input with base 64 encoding applied +op-suffix: optional: `binary` to treat input as binary data, `urlsafe` for URL-safe output op-parameter: op-parameter-name: op-purpose: apply base 64 encoding to a string @@ -11,6 +12,10 @@ from-version: 5.2.6 See Mozilla Developer Network for details of [[base 64 encoding|https://developer.mozilla.org/en-US/docs/Glossary/Base64]]. TiddlyWiki uses [[library code from @nijikokun|https://gist.github.com/Nijikokun/5192472]] to handle the conversion. -The input strings are interpreted as binary data. The output strings are base64 encoded. +The input strings are interpreted as [[UTF-8 encoded|https://developer.mozilla.org/en-US/docs/Glossary/UTF-8]] text (or binary data instead if the `binary` suffix is present). The output strings are base64 encoded. + +The optional `binary` suffix, if present, causes the input string to be interpreted as binary data instead of text. Normally, an extra UTF-8 encoding step will be added before the base64 output is produced, so that emojis and other Unicode characters will be encoded correctly. If the input is binary data, such as an image, audio file, video, etc., then the UTF-8 encoding step would produce incorrect results, so using the `binary` suffix causes the UTF-8 encoding step to be skipped. + +The optional `urlsafe` suffix, if present, will use the alternate "URL-safe" base64 encoding, where `-` and `_` are used instead of `+` and `/` respectively, allowing the result to be used in URL query parameters or filenames. <<.operator-examples "encodebase64">> From efaa8dd1e8c9442c9a35406f9af51062f4661301 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Wed, 18 Oct 2023 17:10:04 +0200 Subject: [PATCH 003/105] tm-open-window set focus to existing window (#7708) * tm-open-window set focus to existing window * tm-open-window: update docs --- core/modules/startup/windows.js | 3 ++- .../messages/WidgetMessage_ tm-open-window.tid | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/modules/startup/windows.js b/core/modules/startup/windows.js index 384961b7b..aa9f982ed 100644 --- a/core/modules/startup/windows.js +++ b/core/modules/startup/windows.js @@ -40,7 +40,7 @@ exports.startup = function() { variables = $tw.utils.extend({},paramObject,{currentTiddler: title, "tv-window-id": windowID}); // Open the window var srcWindow, - srcDocument; + srcDocument; // In case that popup blockers deny opening a new window try { srcWindow = window.open("","external-" + windowID,"scrollbars,width=" + width + ",height=" + height + (top ? ",top=" + top : "" ) + (left ? ",left=" + left : "" )), @@ -52,6 +52,7 @@ exports.startup = function() { $tw.windows[windowID] = srcWindow; // Check for reopening the same window if(srcWindow.haveInitialisedWindow) { + srcWindow.focus(); return; } // Initialise the document diff --git a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-open-window.tid b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-open-window.tid index d820aea01..77a072395 100644 --- a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-open-window.tid +++ b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-open-window.tid @@ -1,6 +1,6 @@ caption: tm-open-window created: 20160424181447704 -modified: 20220301162140993 +modified: 20230831201518773 tags: Messages title: WidgetMessage: tm-open-window type: text/vnd.tiddlywiki @@ -20,10 +20,17 @@ The `tm-open-window` [[message|Messages]] opens a tiddler in a new //browser// w The `tm-open-window` message is best generated with the ActionSendMessageWidget, which in turn is triggered by a widget such as the ButtonWidget. The message is handled by the core itself. -<<.tip """When used with the ActionSendMessageWidget, <<.param 'param'>> becomes <<.param '$param'>> """>> -<<.tip """Parameters <<.param template>>, <<.param windowTitle>>, <<.param width>>, <<.param height>>, <<.param left>> and <<.param top>> require the ActionSendMessageWidget.""">> -<<.tip """<<.from-version 5.2.2>> To close a window opened with tm-open-window use [[WidgetMessage: tm-close-window]]""">> -<<.tip """<<.from-version 5.2.2>> To open a tiddler in more than one new window, use a unique value for <<.param windowID>>""">> +<<.tip """When used with the ActionSendMessageWidget, <<.param 'param'>> becomes <<.param '$param'>>.
+Parameters <<.param template>>, <<.param windowTitle>>, <<.param width>>, <<.param height>>, <<.param left>> and <<.param top>> require the ActionSendMessageWidget. """>> + +<<.tip """<<.from-version 5.2.2>> +To close a window opened with tm-open-window use [[WidgetMessage: tm-close-window]]
+To open a tiddler in more than one new window, use a unique value for <<.param windowID>> +""">> + +<<.tip """<<.from-version 5.3.2>> +If the new window is hidden by other windows, clicking the "open" button again will bring it to the foreground and set focus to the new window. This behaviour should be consistent for all browsers now +""">> <$macrocall $name='wikitext-example-without-html' src=""" From f89b52e521880b3e2fc1a536ebd3a6adec5e5130 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Thu, 19 Oct 2023 15:54:16 +0100 Subject: [PATCH 004/105] Docs: Link to format operator from titlelist tiddler --- editions/tw5.com/tiddlers/concepts/Title List.tid | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/concepts/Title List.tid b/editions/tw5.com/tiddlers/concepts/Title List.tid index a49a665ad..67bb4e339 100644 --- a/editions/tw5.com/tiddlers/concepts/Title List.tid +++ b/editions/tw5.com/tiddlers/concepts/Title List.tid @@ -1,5 +1,5 @@ created: 20150117152418000 -modified: 20220523075540462 +modified: 20231019155036098 tags: Concepts title: Title List type: text/vnd.tiddlywiki @@ -15,3 +15,7 @@ Title lists are used in various places, including PermaLinks and the ListField. They are in fact the simplest case of a [[filter|Filters]], and are thus a way of expressing a [[selection of titles|Title Selection]]. <<.warning """The [[Title List]] format cannot reliably represent items that contain certain specific character sequences such as `]] `. Thus it should not be used where there is a possibility of such sequences occurring.""">> + +See also: + +* The [[format Operator]] with the 'titlelist' suffix conditionally wraps double square brackets around a string if it contains whitespace From 8617fa39dc80df7b7ef12497828f987e693a0513 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Fri, 20 Oct 2023 10:20:14 +0100 Subject: [PATCH 005/105] Tweak appearance of Chinese community link --- editions/tw5.com/tiddlers/hellothere/HelloThere.tid | 2 +- editions/tw5.com/tiddlers/system/tw5.com-styles.tid | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/hellothere/HelloThere.tid b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid index 92d4cd6c5..ddb91a41e 100644 --- a/editions/tw5.com/tiddlers/hellothere/HelloThere.tid +++ b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid @@ -20,7 +20,7 @@ TiddlyWiki lets you choose where to keep your data, guaranteeing that in the dec
<$link to="中文社区 - Chinese Community" class="tc-btn-big-green tc-card"> -中文社区 - Chinese Community +中文社区
Chinese Community
diff --git a/editions/tw5.com/tiddlers/system/tw5.com-styles.tid b/editions/tw5.com/tiddlers/system/tw5.com-styles.tid index a0c9083af..dd60694f4 100644 --- a/editions/tw5.com/tiddlers/system/tw5.com-styles.tid +++ b/editions/tw5.com/tiddlers/system/tw5.com-styles.tid @@ -148,6 +148,7 @@ type: text/vnd.tiddlywiki } .tc-cards.tc-small { + text-align: center; font-size: 0.7em; } From 4ebaba8e89b93cc94cb96661286a1a92ab6ebfb9 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Mon, 23 Oct 2023 10:13:32 +0100 Subject: [PATCH 006/105] Tweak wording --- editions/prerelease/tiddlers/Release 5.3.2.tid | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index b21851cb6..17058d731 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -17,18 +17,16 @@ description: Under development ``` <% if [match[Elephant]] %> It is an elephant +<% elseif [match[Giraffe]] %> + It is a giraffe <% else %> - <% if [match[Giraffe]] %> - It is a giraffe - <% else %> - It is completely unknown - <% endif %> + It is completely unknown <% endif %> ``` !! Explicit Templates for the ListWidget -<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7784">> support for `<$list-template>` and `<$list-empty>` as immediate children of the <<.wid "ListWidget">> widget to specify the list item template and/or the empty template. Note that the <<.attr "emptyMessage">> and <<.attr "template">> attributes take precedence if they are present. For example: +<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7784">> support for `<$list-template>` and `<$list-empty>` as immediate children of the <<.wid "ListWidget">> widget to specify the list item template and/or the empty template. For example: ``` <$list filter=<>> @@ -41,6 +39,8 @@ description: Under development ``` +Note that the <<.attr "emptyMessage">> and <<.attr "template">> attributes take precedence if they are present. + !! jsonset operator <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7742">> [[jsonset Operator]] for setting values within JSON objects From 246751be1ba45cf94be907dc0804ae3f5193e149 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 25 Oct 2023 19:14:49 +0700 Subject: [PATCH 007/105] Fix last filter operator when zero items selected (#7809) Previously, [last[0]] was incorrectly returning the entire list. It now returns zero items as it should. --- core/modules/filters/listops.js | 1 + editions/test/tiddlers/tests/test-filters.js | 1 + 2 files changed, 2 insertions(+) diff --git a/core/modules/filters/listops.js b/core/modules/filters/listops.js index 02d92831a..89bd8eeb7 100644 --- a/core/modules/filters/listops.js +++ b/core/modules/filters/listops.js @@ -58,6 +58,7 @@ Last entry/entries in list exports.last = function(source,operator,options) { var count = $tw.utils.getInt(operator.operand,1), results = []; + if(count === 0) return results; source(function(tiddler,title) { results.push(title); }); diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 9e2f53b1a..727f64ca4 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -365,6 +365,7 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[sort[title]first[8]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three"); expect(wiki.filterTiddlers("[sort[title]first[x]]").join(",")).toBe("$:/ShadowPlugin"); expect(wiki.filterTiddlers("[sort[title]last[]]").join(",")).toBe("TiddlerOne"); + expect(wiki.filterTiddlers("[sort[title]last[0]]").join(",")).toBe(""); expect(wiki.filterTiddlers("[sort[title]last[2]]").join(",")).toBe("Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[sort[title]last[8]]").join(",")).toBe("$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[sort[title]last[x]]").join(",")).toBe("TiddlerOne"); From 6a52081d6bf85119a6883d1be3214e5716cfc883 Mon Sep 17 00:00:00 2001 From: Simon Huber Date: Wed, 25 Oct 2023 14:29:40 +0200 Subject: [PATCH 008/105] Don't set focus on field-name input field when deleting field using delete-field button (#7806) --- core/ui/EditTemplate/fields.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/ui/EditTemplate/fields.tid b/core/ui/EditTemplate/fields.tid index 6a767517b..e4381cbe7 100644 --- a/core/ui/EditTemplate/fields.tid +++ b/core/ui/EditTemplate/fields.tid @@ -89,7 +89,7 @@ $value={{{ [subfilterget[text]] }}}/> <$button class="tc-btn-invisible" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}> -<$action-deletefield $field=<>/><$set name="currentTiddlerCSSescaped" value={{{ [escapecss[]] }}}><$action-sendmessage $message="tm-focus-selector" $param=<>/> +<$action-deletefield $field=<>/> {{$:/core/images/delete-button}} From 23a576b8bd73544478819cd4c48d17dc5210061d Mon Sep 17 00:00:00 2001 From: Scott Sauyet Date: Wed, 25 Oct 2023 08:37:24 -0400 Subject: [PATCH 009/105] Tweak TOC to not show expander for sublist with all children excluded (#7802) --- core/wiki/macros/toc.tid | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/wiki/macros/toc.tid b/core/wiki/macros/toc.tid index a925e7ee5..a3f5b002a 100644 --- a/core/wiki/macros/toc.tid +++ b/core/wiki/macros/toc.tid @@ -118,7 +118,7 @@ tags: $:/tags/Macro <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item" >
  • >> <$link to={{{ [get[target]else] }}}> - <$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}"> + <$list filter="[all[current]tagging[]$sort$limit[1]] -[subfilter<__exclude__>]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}"> <$reveal type="nomatch" stateTitle=<> text="open"> <$button setTitle=<> setTo="open" class="tc-btn-invisible tc-popup-keep"> <$transclude tiddler=<> /> @@ -145,7 +145,7 @@ tags: $:/tags/Macro <$qualify name="toc-state" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix] }}}> <$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
  • >> - <$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="""<$button class="tc-btn-invisible">{{$:/core/images/blank}}<>"""> + <$list filter="[all[current]tagging[]$sort$limit[1]] -[subfilter<__exclude__>]" variable="ignore" emptyMessage="""<$button class="tc-btn-invisible">{{$:/core/images/blank}}<>"""> <$reveal type="nomatch" stateTitle=<> text="open"> <$button setTitle=<> setTo="open" class="tc-btn-invisible tc-popup-keep"> <$transclude tiddler=<> /> From 801e8e312c1cb398643d8c608f6bb83303d4ceed Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Thu, 26 Oct 2023 15:05:59 +0700 Subject: [PATCH 010/105] Fix window.btoa call in browser (#7814) --- core/modules/utils/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/utils/utils.js b/core/modules/utils/utils.js index 21e87f30d..9fffb1714 100644 --- a/core/modules/utils/utils.js +++ b/core/modules/utils/utils.js @@ -823,8 +823,8 @@ exports.hashString = function(str) { Base64 utility functions that work in either browser or Node.js */ if(typeof window !== 'undefined') { - exports.btoa = window.btoa; - exports.atob = window.atob; + exports.btoa = function(binstr) { return window.btoa(binstr); } + exports.atob = function(b64) { return window.atob(b64); } } else { exports.btoa = function(binstr) { return Buffer.from(binstr, 'binary').toString('base64'); From 902c7f55ba2673d2fe961b9fbc98237b02ec3611 Mon Sep 17 00:00:00 2001 From: Simon Huber Date: Thu, 26 Oct 2023 12:43:24 +0200 Subject: [PATCH 011/105] Fix overflow issue of codemirror editor within grid container (#7794) * fix overflow issue of codemirror editor within grid container * tiddler preview needs overflow: auto, too --- plugins/tiddlywiki/codemirror/styles.tid | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/tiddlywiki/codemirror/styles.tid b/plugins/tiddlywiki/codemirror/styles.tid index a070a614d..d0083805d 100755 --- a/plugins/tiddlywiki/codemirror/styles.tid +++ b/plugins/tiddlywiki/codemirror/styles.tid @@ -56,6 +56,11 @@ name: tiddlywiki rendering-intent: auto; } +.tc-tiddler-frame .tc-tiddler-editor .tc-edit-texteditor, +.tc-tiddler-frame .tc-tiddler-editor .tc-tiddler-preview-preview { + overflow: auto; +} + .cm-s-tiddlywiki.CodeMirror, .cm-s-tiddlywiki .CodeMirror-gutters { background-color: <>; color: <>; } .cm-s-tiddlywiki .CodeMirror-gutters {background: <>; border-right: 1px solid <>;} .cm-s-tiddlywiki .CodeMirror-linenumber {color: <>;} From e593f802782521266d385f1e6b4e4af0667ce87a Mon Sep 17 00:00:00 2001 From: FrittRo <86629477+frittro@users.noreply.github.com> Date: Fri, 27 Oct 2023 10:53:09 +1300 Subject: [PATCH 012/105] Signing CLA (#7818) --- licenses/cla-individual.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/licenses/cla-individual.md b/licenses/cla-individual.md index 2a2066e8f..023ef792e 100644 --- a/licenses/cla-individual.md +++ b/licenses/cla-individual.md @@ -553,3 +553,5 @@ BuckarooBanzay, @BuckarooBanzay, 2023/09/01 Timur, @T1mL3arn, 2023/10/04 Wang Ke, @Gk0Wk, 2023/10/17 + +@frittro, 2023/10/27 \ No newline at end of file From 4b56cb42983d4134715eb7fe7b083fdcc04980f0 Mon Sep 17 00:00:00 2001 From: Maurycy Zarzycki Date: Sun, 29 Oct 2023 10:05:24 +0100 Subject: [PATCH 013/105] Add support for running in-browser tests via playwright in GitHub CLI (#7820) * Add support for running in-browser tests via playwright in GitHub CLI * `ci.yml` was updated to store the report so that it can be inspected on failure * `ci-test.sh` was added as an expansion to `test.sh` which installs and runs playwright * `playwright.spec.js` does the actual verification of opening the test TW edition in browser, waiting for the tests to finish and then verifying it has indeed passed * `playwright.config.js` Playwrifht configuration * Add support for running in-browser tests via playwright in GitHub CLI * `ci.yml` was updated to store the report so that it can be inspected on failure * `ci-test.sh` was added as an expansion to `test.sh` which installs and runs playwright * `playwright.spec.js` does the actual verification of opening the test TW edition in browser, waiting for the tests to finish and then verifying it has indeed passed * `playwright.config.js` Playwrifht configuration * Fix file permissions for `ci-test.sh` * Increased node version for github actions to support playwright * Add installation of the required @playwright/test library during CI test execution --- .github/workflows/ci.yml | 10 +++++-- .gitignore | 4 ++- bin/ci-test.sh | 16 +++++++++++ editions/test/playwright.spec.js | 25 +++++++++++++++++ playwright.config.js | 46 ++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100755 bin/ci-test.sh create mode 100644 editions/test/playwright.spec.js create mode 100644 playwright.config.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8daf2f468..a146d15a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: - master - tiddlywiki-com env: - NODE_VERSION: "12" + NODE_VERSION: "18" jobs: test: runs-on: ubuntu-latest @@ -14,7 +14,13 @@ jobs: - uses: actions/setup-node@v1 with: node-version: "${{ env.NODE_VERSION }}" - - run: "./bin/test.sh" + - run: "./bin/ci-test.sh" + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 build-prerelease: runs-on: ubuntu-latest if: github.ref == 'refs/heads/master' diff --git a/.gitignore b/.gitignore index 351c576ad..0ab5b300f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ tmp/ output/ node_modules/ - +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/bin/ci-test.sh b/bin/ci-test.sh new file mode 100755 index 000000000..dd90c4db6 --- /dev/null +++ b/bin/ci-test.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# test TiddlyWiki5 for tiddlywiki.com + +npm install playwright @playwright/test +npx playwright install chromium firefox --with-deps + +node ./tiddlywiki.js \ + ./editions/test \ + --verbose \ + --version \ + --rendertiddler $:/core/save/all test.html text/plain \ + --test \ + || exit 1 + +npx playwright test diff --git a/editions/test/playwright.spec.js b/editions/test/playwright.spec.js new file mode 100644 index 000000000..1d8c624c7 --- /dev/null +++ b/editions/test/playwright.spec.js @@ -0,0 +1,25 @@ +const { test, expect } = require('@playwright/test'); +const {resolve} = require('path'); + +const indexPath = resolve(__dirname, 'output', 'test.html'); +const crossPlatformIndexPath = indexPath.replace(/^\/+/, ''); + + +test('get started link', async ({ page }) => { + // The tests can take a while to run + const timeout = 1000 * 30; + test.setTimeout(timeout); + + // Load the generated test TW html + await page.goto(`file:///${crossPlatformIndexPath}`); + + // Sanity check + await expect(page.locator('.tc-site-title'), "Expected correct page title to verify the test page was loaded").toHaveText('TiddlyWiki5'); + + // Wait for jasmine results bar to appear + await expect(page.locator('.jasmine-overall-result'), "Expected jasmine test results bar to be present").toBeVisible({timeout}); + + // Assert the tests have passed + await expect(page.locator('.jasmine-overall-result.jasmine-failed'), "Expected jasmine tests to not have failed").not.toBeVisible(); + await expect(page.locator('.jasmine-overall-result.jasmine-passed'), "Expected jasmine tests to have passed").toBeVisible(); +}); diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 000000000..491679a6f --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,46 @@ +const { defineConfig, devices } = require('@playwright/test'); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + testDir: './editions/test/', + + // Allow parallel tests + fullyParallel: true, + + // Prevent accidentally committed "test.only" from wrecking havoc + forbidOnly: !!process.env.CI, + + // Do not retry tests on failure + retries: 0, + + // How many parallel workers + workers: process.env.CI ? 1 : undefined, + + // Reporter to use. See https://playwright.dev/docs/test-reporters + reporter: 'html', + + // Settings shared with all the tests + use: { + // Take a screenshot when the test fails + screenshot: { + mode: 'only-on-failure', + fullPage: true + } + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + } + ], +}); + From 1001590326960e9df4e6a637daf9abb7a04a9213 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Mon, 30 Oct 2023 15:51:06 +0100 Subject: [PATCH 014/105] Macros -- Make "New in 5.3.0" Info More Prominent (#7750) * Macros -- Make "New in 5.3.0" Info More Prominent * Add links to new text substitution possibilities --- editions/tw5.com/tiddlers/concepts/Macros.tid | 10 +++++++--- editions/tw5.com/tiddlers/macros/CoreMacros.tid | 2 +- .../wikitext/Transclusion and Substitution.tid | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/editions/tw5.com/tiddlers/concepts/Macros.tid b/editions/tw5.com/tiddlers/concepts/Macros.tid index 8377046f6..884551996 100644 --- a/editions/tw5.com/tiddlers/concepts/Macros.tid +++ b/editions/tw5.com/tiddlers/concepts/Macros.tid @@ -1,9 +1,15 @@ created: 20140211171341271 -modified: 20230419103154328 +modified: 20230922094937115 tags: Concepts Reference title: Macros type: text/vnd.tiddlywiki +!! Important + +<<.from-version "5.3.0">> Macros have been [[superseded|Macro Pitfalls]] by [[Procedures]], [[Functions]] and [[Custom Widgets]] which together provide more robust and flexible ways to encapsulate and re-use code. + +For text substitutions it is now recommended to use: [[Substituted Attribute Values]], [[substitute Operator]] and [[Transclusion and Substitution]] + !! Introduction A <<.def macro>> is a named snippet of text. They are typically defined with the [[Pragma: \define]]: @@ -26,8 +32,6 @@ The parameters that are specified in the macro call are substituted for special * `$parameter-name$` is replaced with the value of the named parameter * `$(variable-name)$` is replaced with the value of the named [[variable|Variables]]). -<<.from-version "5.3.0">> Macros have been [[superseded|Macro Pitfalls]] by [[Procedures]], [[Custom Widgets]] and [[Functions]] which together provide more robust and flexible ways to encapsulate and re-use code. It is now recommended to only use macros when textual substitution is specifically required. - !! How Macros Work Macros are implemented as a special kind of [[variable|Variables]]. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled. diff --git a/editions/tw5.com/tiddlers/macros/CoreMacros.tid b/editions/tw5.com/tiddlers/macros/CoreMacros.tid index 56d43bd2f..01879e3ac 100644 --- a/editions/tw5.com/tiddlers/macros/CoreMacros.tid +++ b/editions/tw5.com/tiddlers/macros/CoreMacros.tid @@ -5,4 +5,4 @@ type: text/vnd.tiddlywiki The following [[macros|Macros]] are built into ~TiddlyWiki's core: -<> +<> diff --git a/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid b/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid index 8d0a52cdc..15dd9b4cc 100644 --- a/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid +++ b/editions/tw5.com/tiddlers/wikitext/Transclusion and Substitution.tid @@ -1,5 +1,5 @@ created: 20141018090608643 -modified: 20230419103154329 +modified: 20231030124224424 tags: WikiText title: Transclusion and Substitution type: text/vnd.tiddlywiki @@ -55,6 +55,6 @@ As described in [[Introduction to filter notation]], you can also transclude a v ! Textual Substitution -Textual substitution occurs when the value of a macro/variable is used. It is described in [[Macros]]. +Textual substitution occurs when the value of a macro/variable is used. It is described in [[Substituted Attribute Values]] and [[substitute Operator]] -The key difference between substitution and transclusion is that substitution occurs before WikiText parsing. This means that you can use substitution to build WikiText constructions. Transclusions are processed independently, and cannot be combined with adjacent text to define WikiText constructions. +The key difference between substitution and transclusion is that substitution occurs before WikiText parsing. This means that you can use substitution to build ~WikiText constructions. Transclusions are processed independently, and cannot be combined with adjacent text to define ~WikiText constructions. From 6567843927a3e455dda2bf6fb473a944bca6bda4 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Thu, 2 Nov 2023 15:44:29 +0700 Subject: [PATCH 015/105] Make unit tests run faster in Github Actions (#7829) --- bin/ci-test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/ci-test.sh b/bin/ci-test.sh index dd90c4db6..ffcae66b2 100755 --- a/bin/ci-test.sh +++ b/bin/ci-test.sh @@ -2,9 +2,6 @@ # test TiddlyWiki5 for tiddlywiki.com -npm install playwright @playwright/test -npx playwright install chromium firefox --with-deps - node ./tiddlywiki.js \ ./editions/test \ --verbose \ @@ -13,4 +10,7 @@ node ./tiddlywiki.js \ --test \ || exit 1 +npm install playwright @playwright/test +npx playwright install chromium firefox --with-deps + npx playwright test From 758089cbb35e40ac35b8205ab9be243d13725a40 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Tue, 7 Nov 2023 04:18:31 +0700 Subject: [PATCH 016/105] Alternate fix for inconsistent list template syntax (#7827) * Alternate fix for inconsistent list template syntax First attempt, which fails on the ListWidget/WithMissingTemplate test. * Make WithMissingTemplate test pass, inefficiently Unfortunately, this ends up being very inefficient, because the clone-and-mutate logic is repeated for every list item. Not ideal. * More efficient way to do it This also makes the failing test pass, but far more efficiently. * Improve performance of list template discovery Since parse tree nodes never change after widget creation (whereas attribute values *can* change), we can safely search for the explicit list templtaes only once, at widget creation time. This saves time as the search doesn't have to be done on each re-render, and also allows us to safely do a clone-and-mutate step to extract the list widget's body (if any) without any `$list-empty` or other items. That, in turn, allows using the list widget's body as the template even if `$list-empty` is specified inside the widget body. --- core/modules/widgets/list.js | 44 ++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/core/modules/widgets/list.js b/core/modules/widgets/list.js index 39c7e1b84..faedf72cc 100755 --- a/core/modules/widgets/list.js +++ b/core/modules/widgets/list.js @@ -28,6 +28,18 @@ Inherit from the base widget class */ ListWidget.prototype = new Widget(); +ListWidget.prototype.initialise = function(parseTreeNode,options) { + // Bail if parseTreeNode is undefined, meaning that the ListWidget constructor was called without any arguments so that it can be subclassed + if(parseTreeNode === undefined) { + return; + } + // First call parent constructor to set everything else up + Widget.prototype.initialise.call(this,parseTreeNode,options); + // Now look for <$list-template> and <$list-empty> widgets as immediate child widgets + // This is safe to do during initialization because parse trees never change after creation + this.findExplicitTemplates(); +} + /* Render this widget into the DOM */ @@ -68,8 +80,6 @@ ListWidget.prototype.execute = function() { this.counterName = this.getAttribute("counter"); this.storyViewName = this.getAttribute("storyview"); this.historyTitle = this.getAttribute("history"); - // Look for <$list-template> and <$list-empty> widgets as immediate child widgets - this.findExplicitTemplates(); // Compose the list elements this.list = this.getTiddlerList(); var members = [], @@ -92,6 +102,7 @@ ListWidget.prototype.findExplicitTemplates = function() { var self = this; this.explicitListTemplate = null; this.explicitEmptyTemplate = null; + this.hasTemplateInBody = false; var searchChildren = function(childNodes) { $tw.utils.each(childNodes,function(node) { if(node.type === "list-template") { @@ -100,6 +111,8 @@ ListWidget.prototype.findExplicitTemplates = function() { self.explicitEmptyTemplate = node.children; } else if(node.type === "element" && node.tag === "p") { searchChildren(node.children); + } else { + self.hasTemplateInBody = true; } }); }; @@ -160,11 +173,11 @@ ListWidget.prototype.makeItemTemplate = function(title,index) { // Check for a <$list-item> widget if(this.explicitListTemplate) { templateTree = this.explicitListTemplate; - } else if (!this.explicitEmptyTemplate) { + } else if(this.hasTemplateInBody) { templateTree = this.parseTreeNode.children; } } - if(!templateTree) { + if(!templateTree || templateTree.length === 0) { // Default template is a link to the title templateTree = [{type: "element", tag: this.parseTreeNode.isBlock ? "div" : "span", children: [{type: "link", attributes: {to: {type: "string", value: title}}, children: [ {type: "text", text: title} @@ -414,4 +427,27 @@ ListItemWidget.prototype.refresh = function(changedTiddlers) { exports.listitem = ListItemWidget; +/* +Make <$list-template> and <$list-empty> widgets that do nothing +*/ +var ListTemplateWidget = function(parseTreeNode,options) { + // Main initialisation inherited from widget.js + this.initialise(parseTreeNode,options); +}; +ListTemplateWidget.prototype = new Widget(); +ListTemplateWidget.prototype.render = function() {} +ListTemplateWidget.prototype.refresh = function() { return false; } + +exports["list-template"] = ListTemplateWidget; + +var ListEmptyWidget = function(parseTreeNode,options) { + // Main initialisation inherited from widget.js + this.initialise(parseTreeNode,options); +}; +ListEmptyWidget.prototype = new Widget(); +ListEmptyWidget.prototype.render = function() {} +ListEmptyWidget.prototype.refresh = function() { return false; } + +exports["list-empty"] = ListEmptyWidget; + })(); From 215bd4e015f3069e007c14ab57937d0eade7ba88 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 15 Nov 2023 05:10:58 +0700 Subject: [PATCH 017/105] Avoid skipping extra whitespace in wikiparser.js (#7835) When wikiparser parses text looking for a pragma block, it skips whitespace before looking for the next pragma. If no pragma is found, we should return the parse position to the original location so that the skipped whitespace can be parsed as a text node. This allows the attribute `join=" and "` to parse as " and " rather than "and ". --- core/modules/parsers/wikiparser/wikiparser.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 293b7d3d3..1606d982d 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -194,6 +194,7 @@ Parse any pragmas at the beginning of a block of parse text WikiParser.prototype.parsePragmas = function() { var currentTreeBranch = this.tree; while(true) { + var savedPos = this.pos; // Skip whitespace this.skipWhitespace(); // Check for the end of the text @@ -204,6 +205,7 @@ WikiParser.prototype.parsePragmas = function() { var nextMatch = this.findNextMatch(this.pragmaRules,this.pos); // If not, just exit if(!nextMatch || nextMatch.matchIndex !== this.pos) { + this.pos = savedPos; break; } // Process the pragma rule From e4bf7c5f440cc5eb1fc499cec29eac37382add12 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Sat, 18 Nov 2023 17:13:27 +0100 Subject: [PATCH 018/105] fix the add field button tooltip (#7842) --- core/ui/EditTemplate/fields.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/ui/EditTemplate/fields.tid b/core/ui/EditTemplate/fields.tid index e4381cbe7..0edc33505 100644 --- a/core/ui/EditTemplate/fields.tid +++ b/core/ui/EditTemplate/fields.tid @@ -54,7 +54,7 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$ \whitespace trim <$vars name={{{ [get[text]] }}}> <$reveal type="nomatch" text="" default=<>> -<$button tooltip=<>> +<$button tooltip={{$:/language/EditTemplate/Fields/Add/Button/Hint}}> <$action-sendmessage $message="tm-add-field" $name=<> $value={{{ [subfilterget[text]] }}}/> From bf8b3cff03adee1c76fa03914bdfd22b34e790f4 Mon Sep 17 00:00:00 2001 From: Saq Imtiaz Date: Mon, 20 Nov 2023 09:38:04 +0100 Subject: [PATCH 019/105] Fixes Text Parser being impacted by overrides to codeblock widget (#7844) * fix: overriding codeblock widget should not impact text parser * fix: whitespace changes --- core/modules/parsers/textparser.js | 9 +++++---- ...tomWidget-CodeblockOverride-TextParser.tid | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid diff --git a/core/modules/parsers/textparser.js b/core/modules/parsers/textparser.js index 06b08f30f..17f9bde10 100644 --- a/core/modules/parsers/textparser.js +++ b/core/modules/parsers/textparser.js @@ -14,10 +14,12 @@ The plain text parser processes blocks of source text into a degenerate parse tr var TextParser = function(type,text,options) { this.tree = [{ - type: "codeblock", + type: "genesis", attributes: { - code: {type: "string", value: text}, - language: {type: "string", value: type} + $type: {name: "$type", type: "string", value: "$codeblock"}, + code: {name: "code", type: "string", value: text}, + language: {name: "language", type: "string", value: type}, + $remappable: {name: "$remappable", type:"string", value: "no"} } }]; this.source = text; @@ -32,4 +34,3 @@ exports["text/css"] = TextParser; exports["application/x-tiddler-dictionary"] = TextParser; })(); - diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid new file mode 100644 index 000000000..484f0c4a3 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid @@ -0,0 +1,20 @@ +title: Transclude/CustomWidget/CodeblockOverride-TextParser +description: Test that overriding codeblock widget does not impact text parser +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $codeblock(code) +<$transclude $variable="copy-to-clipboard" src=<>/> +<$genesis $type="$codeblock" $remappable="no" code=<>/> +\end + +\procedure myvariable() hello + +<$transclude $variable="myvariable" $type="text/plain" $output="text/plain"/> ++ +title: ExpectedResult + +

    hello

    \ No newline at end of file From ab72cc7b097a504fc2ab6edadfb0e987075f1475 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Tue, 21 Nov 2023 18:05:13 +0700 Subject: [PATCH 020/105] Allow negative indexes in json operators (#7849) * Add unit tests for negative indexes in json ops * Allow negative indexes in JSON operators Negative indexes will be treated as counting from the end, so -1 means last item of the array, -2 means next-to-last item, and so on. * Add documentation for negative indexes --- core/modules/filters/json-ops.js | 24 +++++++++++++++---- .../test/tiddlers/tests/test-json-filters.js | 21 ++++++++++++++++ .../tw5.com/tiddlers/filters/jsonextract.tid | 8 +++++++ editions/tw5.com/tiddlers/filters/jsonget.tid | 8 +++++++ editions/tw5.com/tiddlers/filters/jsonset.tid | 8 +++++++ .../tw5.com/tiddlers/filters/jsontype.tid | 8 +++++++ 6 files changed, 72 insertions(+), 5 deletions(-) diff --git a/core/modules/filters/json-ops.js b/core/modules/filters/json-ops.js index 51e509432..75a34e94a 100644 --- a/core/modules/filters/json-ops.js +++ b/core/modules/filters/json-ops.js @@ -213,6 +213,18 @@ function getDataItemType(data,indexes) { } } +function getItemAtIndex(item,index) { + if($tw.utils.hop(item,index)) { + return item[index]; + } else if($tw.utils.isArray(item)) { + index = $tw.utils.parseInt(index); + if(index < 0) { index = index + item.length }; + return item[index]; // Will be undefined if index was out-of-bounds + } else { + return undefined; + } +} + /* Given a JSON data structure and an array of index strings, return the value at the end of the index chain, or "undefined" if any of the index strings are invalid */ @@ -225,7 +237,7 @@ function getDataItem(data,indexes) { for(var i=0; i> operator uses multiple operands to specify the indexes o [jsonextract[d],[g]] --> {"x":"max","y":"may","z":"maize"} ``` +<<.from-version "5.3.2">> Negative indexes into an array are counted from the end, so -1 means the last item, -2 the next-to-last item, and so on: + +``` +[jsonextract[d],[f],[-1]] --> null +[jsonextract[d],[f],[-2]] --> false +[jsonextract[d],[f],[-4]] --> "six" +``` + Indexes can be dynamically composed from variables and transclusions: ``` diff --git a/editions/tw5.com/tiddlers/filters/jsonget.tid b/editions/tw5.com/tiddlers/filters/jsonget.tid index d9caa680e..c50cbd6f2 100644 --- a/editions/tw5.com/tiddlers/filters/jsonget.tid +++ b/editions/tw5.com/tiddlers/filters/jsonget.tid @@ -51,6 +51,14 @@ The <<.op jsonget>> operator uses multiple operands to specify the indexes of th [jsonget[d],[f],[0]] --> "five" ``` +<<.from-version "5.3.2">> Negative indexes into an array are counted from the end, so -1 means the last item, -2 the next-to-last item, and so on: + +``` +[jsonget[d],[f],[-1]] --> null +[jsonget[d],[f],[-2]] --> false +[jsonget[d],[f],[-4]] --> "six" +``` + Indexes can be dynamically composed from variables and transclusions: ``` diff --git a/editions/tw5.com/tiddlers/filters/jsonset.tid b/editions/tw5.com/tiddlers/filters/jsonset.tid index 9f70f6eb4..81552c7a1 100644 --- a/editions/tw5.com/tiddlers/filters/jsonset.tid +++ b/editions/tw5.com/tiddlers/filters/jsonset.tid @@ -51,6 +51,14 @@ The <<.op jsonset>> operator uses multiple operands to specify the indexes of th [jsonset[d],[f],[Panther]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": "Panther","g": {"x": "max","y": "may","z": "maize"}}"} ``` +Negative indexes into an array are counted from the end, so -1 means the last item, -2 the next-to-last item, and so on: + +``` +[jsonset[d],[f],[-1],[Elephant]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five","six",true,false,"Elephant"],"g": {"x": "max","y": "may","z": "maize"}}"} +[jsonset[d],[f],[-2],[Elephant]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five","six",true,"Elephant",null],"g": {"x": "max","y": "may","z": "maize"}}"} +[jsonset[d],[f],[-4],[Elephant]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five","Elephant",true,false,null],"g": {"x": "max","y": "may","z": "maize"}}"} +``` + Indexes can be dynamically composed from variables and transclusions: ``` diff --git a/editions/tw5.com/tiddlers/filters/jsontype.tid b/editions/tw5.com/tiddlers/filters/jsontype.tid index b88f865dd..6bff01914 100644 --- a/editions/tw5.com/tiddlers/filters/jsontype.tid +++ b/editions/tw5.com/tiddlers/filters/jsontype.tid @@ -61,6 +61,14 @@ The <<.op jsontype>> operator uses multiple operands to specify the indexes of t [jsontype[d],[f],[2]] --> "boolean" ``` +<<.from-version "5.3.2">> Negative indexes into an array are counted from the end, so -1 means the last item, -2 the next-to-last item, and so on: + +``` +[jsontype[d],[f],[-1]] --> "null" +[jsontype[d],[f],[-2]] --> "boolean" +[jsontype[d],[f],[-4]] --> "string" +``` + Indexes can be dynamically composed from variables and transclusions: ``` From 9012d36859d33db23183d93d14d2bbc351dd235f Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 21 Nov 2023 11:23:10 +0000 Subject: [PATCH 021/105] Allow scrollable widget to bind scroll position to a tiddler (#7649) * Initial Commit * Update version number --- core/modules/widgets/scrollable.js | 40 +++++++++++++++++++ .../system/temp-my-scroll-position.tid | 3 ++ .../tiddlers/widgets/ScrollableWidget.tid | 29 +++++++++++++- 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 editions/prerelease/tiddlers/system/temp-my-scroll-position.tid diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index 15b61e0c8..c95820ef3 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -171,6 +171,42 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { parent.insertBefore(this.outerDomNode,nextSibling); this.renderChildren(this.innerDomNode,null); this.domNodes.push(this.outerDomNode); + // If the scroll position is bound to a tiddler + if(this.scrollableBind) { + // After a delay for rendering, scroll to the bound position + setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); + // Save scroll position on DOM scroll event + this.outerDomNode.addEventListener("scroll",function(event) { + var existingTiddler = self.wiki.getTiddler(self.scrollableBind), + newTiddlerFields = { + title: self.scrollableBind, + "scroll-left": self.outerDomNode.scrollLeft.toString(), + "scroll-top": self.outerDomNode.scrollTop.toString() + }; + if(!existingTiddler || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { + self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); + } + }); + } +}; + +ScrollableWidget.prototype.updateScrollPositionFromBoundTiddler = function() { + var tiddler = this.wiki.getTiddler(this.scrollableBind); + if(tiddler) { + var scrollLeftTo = this.outerDomNode.scrollLeft; + if(parseFloat(tiddler.fields["scroll-left"]).toString() === tiddler.fields["scroll-left"]) { + scrollLeftTo = parseFloat(tiddler.fields["scroll-left"]); + } + var scrollTopTo = this.outerDomNode.scrollTop; + if(parseFloat(tiddler.fields["scroll-top"]).toString() === tiddler.fields["scroll-top"]) { + scrollTopTo = parseFloat(tiddler.fields["scroll-top"]); + } + this.outerDomNode.scrollTo({ + top: scrollTopTo, + left: scrollLeftTo, + behavior: "instant" + }) + } }; /* @@ -178,6 +214,7 @@ Compute the internal state of the widget */ ScrollableWidget.prototype.execute = function() { // Get attributes + this.scrollableBind = this.getAttribute("bind"); this.fallthrough = this.getAttribute("fallthrough","yes"); this["class"] = this.getAttribute("class"); // Make child widgets @@ -193,6 +230,9 @@ ScrollableWidget.prototype.refresh = function(changedTiddlers) { this.refreshSelf(); return true; } + if(changedAttributes.bind || changedTiddlers[this.getAttribute("bind")]) { + this.updateScrollPositionFromBoundTiddler(); + } return this.refreshChildren(changedTiddlers); }; diff --git a/editions/prerelease/tiddlers/system/temp-my-scroll-position.tid b/editions/prerelease/tiddlers/system/temp-my-scroll-position.tid new file mode 100644 index 000000000..c4a164070 --- /dev/null +++ b/editions/prerelease/tiddlers/system/temp-my-scroll-position.tid @@ -0,0 +1,3 @@ +title: $:/my-scroll-position +scroll-left: 0 +scroll-top: 100 diff --git a/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid b/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid index 6fda3a974..d31eb6e31 100644 --- a/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid @@ -1,6 +1,6 @@ caption: scrollable created: 20140324223413403 -modified: 20220620115347910 +modified: 20230731100903977 tags: Widgets title: ScrollableWidget type: text/vnd.tiddlywiki @@ -16,12 +16,15 @@ The content of the `<$scrollable>` widget is displayed within a pair of wrapper |!Attribute |!Description | |class |The CSS class(es) to be applied to the outer DIV | |fallthrough |See below | +|bind |<<.from-version "5.3.2">> Optional title of tiddler to which the scroll position should be bound | + +Binding the scroll position to a tiddler automatically copies the scroll coordinates into the `scroll-left` and `scroll-top` fields as scrolling occurs. Conversely, setting those field values will automatically cause the scrollable to scroll if it can. <$macrocall $name=".note" _="""If a scrollable widget can't handle the `tm-scroll` message because the inner DIV fits within the outer DIV, then by default the message falls through to the parent widget. Setting the ''fallthrough'' attribute to `no` prevents this behaviour."""/> ! Examples -This example requires the following CSS definitions from [[$:/_tw5.com-styles]]: +These examples require the following CSS definitions from [[$:/_tw5.com-styles]]: ``` .tc-scrollable-demo { @@ -33,6 +36,8 @@ This example requires the following CSS definitions from [[$:/_tw5.com-styles]]: } ``` +!! Simple Usage + This wiki text shows how to display a list within the scrollable widget: < @@ -46,3 +51,23 @@ This wiki text shows how to display a list within the scrollable widget: ">> +!! Binding scroll position to a tiddler + +[[Current scroll position|$:/my-scroll-position]]: {{$:/my-scroll-position!!scroll-left}}, {{$:/my-scroll-position!!scroll-top}} + +<$button> +<$action-setfield $tiddler="$:/my-scroll-position" scroll-left="100" scroll-top="100"/> +Set current scroll position to 100,100 + + +< +<$list filter='[tag[Reference]]'> + +<$view field='title'/>: <$list filter='[all[current]links[]sort[title]]' storyview='pop'> +<$link><$view field='title'/> + + + + +">> + From 145a8d699253fcfadfc0b46658fdd13680d9a0b0 Mon Sep 17 00:00:00 2001 From: Scott Sauyet Date: Tue, 21 Nov 2023 06:24:17 -0500 Subject: [PATCH 022/105] Simplify Permalink/Permaview URLs (#7729) * Simplify Permalink/Permaview URLs * Fix lint warnings by removing arrow functions * Remove commented sample code * Remove post-ES5 code * Add many more allowable non-percent-encodedcharacters * Fix more ES6+ stuff, add end-of-sentence padding character. * Fix to match standards * Move the new code from boot to util * Change from custom map/filter to $tw.utils.each * Make `each` blocks multi-line * Move the permalink handling to its own file * Remove auto-navigation * Revert "Remove auto-navigation" This reverts commit ca1e5cf387922d8dd2883cb37f8d85e187158c90. --- core/modules/startup/story.js | 14 +- core/modules/utils/twuri-encoding.js | 128 ++++++++++++++++++ .../tw5.com/tiddlers/concepts/PermaLinks.tid | 16 +++ 3 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 core/modules/utils/twuri-encoding.js diff --git a/core/modules/startup/story.js b/core/modules/startup/story.js index 734f6ae76..da2df6542 100644 --- a/core/modules/startup/story.js +++ b/core/modules/startup/story.js @@ -122,10 +122,10 @@ function openStartupTiddlers(options) { var hash = $tw.locationHash.substr(1), split = hash.indexOf(":"); if(split === -1) { - target = $tw.utils.decodeURIComponentSafe(hash.trim()); + target = $tw.utils.decodeTWURITarget(hash.trim()); } else { - target = $tw.utils.decodeURIComponentSafe(hash.substr(0,split).trim()); - storyFilter = $tw.utils.decodeURIComponentSafe(hash.substr(split + 1).trim()); + target = $tw.utils.decodeTWURITarget(hash.substr(0,split).trim()); + storyFilter = $tw.utils.decodeTWURIList(hash.substr(split + 1).trim()); } } // If the story wasn't specified use the current tiddlers or a blank story @@ -198,19 +198,19 @@ function updateLocationHash(options) { // Assemble the location hash switch(options.updateAddressBar) { case "permalink": - $tw.locationHash = "#" + encodeURIComponent(targetTiddler); + $tw.locationHash = "#" + $tw.utils.encodeTiddlerTitle(targetTiddler); break; case "permaview": - $tw.locationHash = "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList)); + $tw.locationHash = "#" + $tw.utils.encodeTiddlerTitle(targetTiddler) + ":" + $tw.utils.encodeFilterPath($tw.utils.stringifyList(storyList)); break; } // Copy URL to the clipboard switch(options.copyToClipboard) { case "permalink": - $tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler)); + $tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + $tw.utils.encodeTiddlerTitle(targetTiddler)); break; case "permaview": - $tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList))); + $tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + $tw.utils.encodeTiddlerTitle(targetTiddler) + ":" + $tw.utils.encodeFilterPath($tw.utils.stringifyList(storyList))); break; } // Only change the location hash if we must, thus avoiding unnecessary onhashchange events diff --git a/core/modules/utils/twuri-encoding.js b/core/modules/utils/twuri-encoding.js new file mode 100644 index 000000000..f4a5bd947 --- /dev/null +++ b/core/modules/utils/twuri-encoding.js @@ -0,0 +1,128 @@ +/*\ +title: $:/core/modules/utils/twuri-encoding.js +type: application/javascript +module-type: utils + +Utility functions related to permalink/permaview encoding/decoding. + +\*/ +(function(){ + + // The character that will substitute for a space in the URL + var SPACE_SUBSTITUTE = "_"; + + // The character added to the end to avoid ending with `.`, `?`, `!` or the like + var TRAILER = "_"; + + // The character that will separate out the list elements in the URL + var CONJUNCTION = ";"; + + // Those of the allowed url characters claimed by TW + var CLAIMED = [SPACE_SUBSTITUTE, ":", CONJUNCTION]; + + // Non-alphanumeric characters allowed in a URL fragment + // More information at https://www.rfc-editor.org/rfc/rfc3986#appendix-A + var VALID_IN_URL_FRAGMENT = "-._~!$&'()*+,;=:@/?".split(""); + + // The subset of the pchars we will not percent-encode in permalinks/permaviews + var SUBSTITUTES = [] + $tw.utils.each(VALID_IN_URL_FRAGMENT, function(c) { + if (CLAIMED.indexOf(c) === -1) { + SUBSTITUTES.push(c) + } + }); + + // A regex to match the percent-encoded characters we will want to replace. + // Something similar to the following, depending on SPACE and CONJUNCTION + // /(%2D|%2E|%7E|%21|%24|%26|%27|%28|%29|%2A|%2B|%3B|%3D|%40|%2F|%3F)/g + + var CHAR_MATCH_STR = [] + $tw.utils.each(SUBSTITUTES, function(c) { + CHAR_MATCH_STR.push("%" + c.charCodeAt(0).toString(16).toUpperCase()) + }) + var CHAR_MATCH = new RegExp("(" + CHAR_MATCH_STR.join("|") + ")", "g"); + + // A regex to match the SPACE_SUBSTITUTE character + var SPACE_MATCH = new RegExp("(\\" + SPACE_SUBSTITUTE + ")", "g"); + + // A regex to match URLs ending with sentence-ending punctuation + var SENTENCE_ENDING = new RegExp("(\\.|\\!|\\?|\\" + TRAILER + ")$", "g"); + + // A regex to match URLs ending with sentence-ending punctuation plus the TRAILER + var SENTENCE_TRAILING = new RegExp("(\\.|\\!|\\?|\\" + TRAILER + ")\\" + TRAILER + "$", "g"); + + // An object mapping the percent encodings back to their source characters + var PCT_CHAR_MAP = SUBSTITUTES.reduce(function (a, c) { + a["%" + c.charCodeAt(0).toString(16).toUpperCase()] = c + return a + }, {}); + + // Convert a URI List Component encoded string (with the `SPACE_SUBSTITUTE` + // value as an allowed replacement for the space character) to a string + exports.decodeTWURIList = function(s) { + var parts = s.replace(SENTENCE_TRAILING, "$1").split(CONJUNCTION); + var withSpaces = [] + $tw.utils.each(parts, function(s) { + withSpaces.push(s.replace(SPACE_MATCH, " ")) + }); + var withBrackets = [] + $tw.utils.each(withSpaces, function(s) { + withBrackets .push(s.indexOf(" ") >= 0 ? "[[" + s + "]]" : s) + }); + return $tw.utils.decodeURIComponentSafe(withBrackets.join(" ")); + }; + + // Convert a URI Target Component encoded string (with the `SPACE_SUBSTITUTE` + // value as an allowed replacement for the space character) to a string + exports.decodeTWURITarget = function(s) { + return $tw.utils.decodeURIComponentSafe( + s.replace(SENTENCE_TRAILING, "$1").replace(SPACE_MATCH, " ") + ) + }; + + // Convert a URIComponent encoded title string (with the `SPACE_SUBSTITUTE` + // value as an allowed replacement for the space character) to a string + exports.encodeTiddlerTitle = function(s) { + var extended = s.replace(SENTENCE_ENDING, "$1" + TRAILER) + var encoded = encodeURIComponent(extended); + var substituted = encoded.replace(/\%20/g, SPACE_SUBSTITUTE); + return substituted.replace(CHAR_MATCH, function(_, c) { + return PCT_CHAR_MAP[c]; + }); + }; + + // Convert a URIComponent encoded filter string (with the `SPACE_SUBSTITUTE` + // value as an allowed replacement for the space character) to a string + exports.encodeFilterPath = function(s) { + var parts = s.replace(SENTENCE_ENDING, "$1" + TRAILER) + .replace(/\[\[(.+?)\]\]/g, function (_, t) {return t.replace(/ /g, SPACE_SUBSTITUTE )}) + .split(" "); + var nonEmptyParts = [] + $tw.utils.each(parts, function(p) { + if (p) { + nonEmptyParts.push (p) + } + }); + var trimmed = []; + $tw.utils.each(nonEmptyParts, function(s) { + trimmed.push(s.trim()) + }); + var encoded = []; + $tw.utils.each(trimmed, function(s) { + encoded.push(encodeURIComponent(s)) + }); + var substituted = []; + $tw.utils.each(encoded, function(s) { + substituted.push(s.replace(/\%20/g, SPACE_SUBSTITUTE)) + }); + var replaced = [] + $tw.utils.each(substituted, function(s) { + replaced.push(s.replace(CHAR_MATCH, function(_, c) { + return PCT_CHAR_MAP[c]; + })) + }); + return replaced.join(CONJUNCTION); + }; + +})(); + \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/concepts/PermaLinks.tid b/editions/tw5.com/tiddlers/concepts/PermaLinks.tid index 40c7a1925..1b15460fa 100644 --- a/editions/tw5.com/tiddlers/concepts/PermaLinks.tid +++ b/editions/tw5.com/tiddlers/concepts/PermaLinks.tid @@ -40,6 +40,22 @@ There are technical restrictions on the legal characters in an URL fragment. To Both the target tiddler title and the story filter should be URL encoded (but not the separating colon). TiddlyWiki generates properly encoded URLs which can look quite ugly. However, in practice browsers will usually perfectly happily process arbitrary characters in URL fragments. Thus when creating permalinks manually you can choose to ignore URL encoding. +!! Simpler URLS + +<<.from-version "5.3.2">> The URLs generated are simplified from the hard-to-read percent encoding when feasible. Spaces are replaced with underscores (`_`), many punctuation characters are allowed to remain unencoded, and permaview filters receive a simpler encoding. For example the tiddler "Hard Linebreaks with CSS - Example", which percent-encoded would look like + +> @@font-family:monospace;#Hard%20Linebreaks%20with%20CSS%20-%20Example@@ + +instead looks like + +> @@font-family:monospace;#Hard_Linebreaks_with_CSS_-_Example@@ + +Existing story filter URLs like + +> @@font-family:monospace;#:[tag[Features]]%20+[limit[5]]@@ + +will continue to work. + ! Permalink Behaviour Two important aspects of TiddlyWiki's behaviour with permalinks can be controlled via options in the [[control panel|$:/ControlPanel]] <<.icon $:/core/images/options-button>> ''Settings'' tab: From a4850ba3d9864317979fee308888b01584dd092b Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Tue, 21 Nov 2023 12:30:05 +0100 Subject: [PATCH 023/105] make all list-* macros readable for easier future improvements (#7551) * make all list-* widgets readable for easier future improvements * remove whitespace on closing braces --- core/wiki/macros/list.tid | 173 +++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 78 deletions(-) diff --git a/core/wiki/macros/list.tid b/core/wiki/macros/list.tid index 5464ecad1..c9dd2ad71 100644 --- a/core/wiki/macros/list.tid +++ b/core/wiki/macros/list.tid @@ -4,17 +4,17 @@ tags: $:/tags/Macro \define list-links(filter,type:"ul",subtype:"li",class:"",emptyMessage,field:"caption") \whitespace trim <$genesis $type=<<__type__>> class=<<__class__>>> -<$list filter=<<__filter__>> emptyMessage=<<__emptyMessage__>>> -<$genesis $type=<<__subtype__>>> -<$link to={{!!title}}> -<$let tv-wikilinks="no"> -<$transclude field=<<__field__>>> -<$view field="title"/> - - - - - + <$list filter=<<__filter__>> emptyMessage=<<__emptyMessage__>>> + <$genesis $type=<<__subtype__>>> + <$link to={{!!title}}> + <$let tv-wikilinks="no"> + <$transclude field=<<__field__>>> + <$view field="title"/> + + + + + \end @@ -25,34 +25,42 @@ tags: $:/tags/Macro \define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate) \whitespace trim -<$vars targetTiddler="""$tiddler$""" targetField="""$field$"""> -<$genesis $type=<<__type__>> class="$class$"> -<$list filter="[list[$tiddler$!!$field$]]" emptyMessage=<<__emptyMessage__>>> -<$droppable actions=<> tag="""$subtype$""" enable=<>> -
    -
    -<$transclude tiddler="""$itemTemplate$"""> -<$link to={{!!title}}> -<$let tv-wikilinks="no"> -<$transclude field="caption"> -<$view field="title"/> - - - - -
    - - -<$tiddler tiddler=""> -<$droppable actions=<> tag="div" enable=<>> -
    -{{$:/core/images/blank}} -
    -
    - - - - + <$vars targetTiddler="""$tiddler$""" targetField="""$field$"""> + <$genesis $type=<<__type__>> class="$class$"> + <$list filter="[list[$tiddler$!!$field$]]" emptyMessage=<<__emptyMessage__>>> + <$droppable + actions=<> + tag="""$subtype$""" + enable=<> + > +
    +
    + <$transclude tiddler="""$itemTemplate$"""> + <$link to={{!!title}}> + <$let tv-wikilinks="no"> + <$transclude field="caption"> + <$view field="title"/> + + + + +
    + + + <$tiddler tiddler=""> + <$droppable + actions=<> + tag="div" + enable=<> + > +
    + {{$:/core/images/blank}} +
    +
    + + + + \end @@ -60,50 +68,59 @@ tags: $:/tags/Macro \whitespace trim <$set name="order" filter="[<__tag__>tagging[]]"> - -<$list filter="[<__tag__>tagging[]]"> -<$action-deletefield $field="list-before"/> -<$action-deletefield $field="list-after"/> - - -<$action-listops $tiddler=<<__tag__>> $field="list" $filter="+[enlist] +[insertbefore,]"/> - - - - -<$list filter="[!contains:tags<__tag__>]"> -<$fieldmangler tiddler=<>> -<$action-sendmessage $message="tm-add-tag" $param=<<__tag__>>/> - - + + <$list filter="[<__tag__>tagging[]]"> + <$action-deletefield $field="list-before"/> + <$action-deletefield $field="list-after"/> + + + <$action-listops $tiddler=<<__tag__>> $field="list" $filter="+[enlist] +[insertbefore,]"/> + + + + + <$list filter="[!contains:tags<__tag__>]"> + <$fieldmangler tiddler=<>> + <$action-sendmessage $message="tm-add-tag" $param=<<__tag__>>/> + + \end \define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"") \whitespace trim -<$set name="tag" value=<<__tag__>>> -<$list filter="[<__tag__>tagging[]$subFilter$]" emptyMessage=<<__emptyMessage__>> storyview=<<__storyview__>>> -<$genesis $type=<<__elementTag__>> class="tc-menu-list-item"> -<$droppable actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" enable=<>> -<$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/> -<$genesis $type=<<__elementTag__>>> -<$transclude tiddler="""$itemTemplate$"""> -<$link to={{!!title}}> -<$view field="title"/> - - - - - - -<$tiddler tiddler=""> -<$droppable actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" enable=<>> -<$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/> -<$genesis $type=<<__elementTag__>> style="height:0.5em;"> - - - - + <$set name="tag" value=<<__tag__>>> + <$list + filter="[<__tag__>tagging[]$subFilter$]" + emptyMessage=<<__emptyMessage__>> + storyview=<<__storyview__>> + > + <$genesis $type=<<__elementTag__>> class="tc-menu-list-item"> + <$droppable + actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" + enable=<> + > + <$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/> + <$genesis $type=<<__elementTag__>>> + <$transclude tiddler="""$itemTemplate$"""> + <$link to={{!!title}}> + <$view field="title"/> + + + + + + + <$tiddler tiddler=""> + <$droppable + actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" + enable=<> + > + <$genesis $type=<<__elementTag__>> class="tc-droppable-placeholder"/> + <$genesis $type=<<__elementTag__>> style="height:0.5em;"/> + + + \end From 37c625384af79deba0934e3071bcfc5ebe9f4349 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Tue, 21 Nov 2023 12:42:17 +0100 Subject: [PATCH 024/105] add archive HTML wikis, add index.html + css (#7776) * add archive HTML wikis, add index.html + css * only build archive for release version * tested and add more docs * fix indent * fix spacing * add $TW5_BUILD_OUTPUT_ARCHIVE env variable for testing * use $TW5_BUILD_OUTPUT_ARCHIVE to check if archive should be built * use TW5_BUILD_ARCHIVE as requested --- .github/workflows/ci.yml | 1 + bin/build-site.sh | 20 +++++++++++++++++++- editions/tw5.com/tiddlywiki.info | 7 ++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a146d15a8..737d523ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,7 @@ jobs: TW5_BUILD_TIDDLYWIKI: "./node_modules/tiddlywiki/tiddlywiki.js" TW5_BUILD_MAIN_EDITION: "./editions/tw5.com" TW5_BUILD_OUTPUT: "./output" + TW5_BUILD_ARCHIVE: "./output" steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 diff --git a/bin/build-site.sh b/bin/build-site.sh index aa8a29f63..5b36de4e1 100755 --- a/bin/build-site.sh +++ b/bin/build-site.sh @@ -84,10 +84,27 @@ echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n" ###################################################### # -# Core distribution +# Core distributions # ###################################################### +# Conditionally build archive if $TW5_BUILD_ARCHIVE variable is set, otherwise do nothing +# +# /archive/Empty-TiddlyWiki-.html Empty archived version +# /archive/TiddlyWiki-.html Full archived version + +if [ -n "$TW5_BUILD_ARCHIVE" ]; then + +node $TW5_BUILD_TIDDLYWIKI \ + $TW5_BUILD_MAIN_EDITION \ + --verbose \ + --version \ + --load $TW5_BUILD_OUTPUT/build.tid \ + --output $TW5_BUILD_ARCHIVE \ + --build archive \ + || exit 1 +fi + # /index.html Main site # /favicon.ico Favicon for main site # /static.html Static rendering of default tiddlers @@ -95,6 +112,7 @@ echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n" # /static/* Static single tiddlers # /static/static.css Static stylesheet # /static/favicon.ico Favicon for static pages + node $TW5_BUILD_TIDDLYWIKI \ $TW5_BUILD_MAIN_EDITION \ --verbose \ diff --git a/editions/tw5.com/tiddlywiki.info b/editions/tw5.com/tiddlywiki.info index 2065260bc..5ce9a2f1b 100644 --- a/editions/tw5.com/tiddlywiki.info +++ b/editions/tw5.com/tiddlywiki.info @@ -54,7 +54,12 @@ "--render","$:/core/templates/static.template.css","static/static.css","text/plain"], "external-js": [ "--render","$:/core/save/offline-external-js","[[external-]addsuffixaddsuffix[.html]]","text/plain", - "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffixaddsuffix[.js]]","text/plain"] + "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffixaddsuffix[.js]]","text/plain"], + "archive":[ + "--render","$:/core/save/all","[[archive/TiddlyWiki-]addsuffixaddsuffix[.html]]","text/plain", + "--render","$:/editions/tw5.com/download-empty","[[archive/Empty-TiddlyWiki-]addsuffixaddsuffix[.html]]","text/plain", + "--render","[[TiddlyWiki Archive]]","archive/index.html","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","archive/static.css","text/plain"] }, "config": { "retain-original-tiddler-path": true From 0cd3c9a8ac42c0c9ac7d4fe80379a96583c1fd33 Mon Sep 17 00:00:00 2001 From: Eric Haberstroh Date: Tue, 21 Nov 2023 12:44:39 +0100 Subject: [PATCH 025/105] Add usemap attribute to image widget (#7634) * Add usemap attribute to image macro Allow for a usemap attribute on the $image macro call which is passed through to the resulting img tag. This makes the use of HTML image maps [1] possible. [1]: * Document new usemap attribute in ImageWidget * Update version docs --------- Co-authored-by: Jeremy Ruston --- core/modules/widgets/image.js | 6 +++++- editions/tw5.com/tiddlers/widgets/ImageWidget.tid | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/modules/widgets/image.js b/core/modules/widgets/image.js index 533b657cc..52496fd74 100644 --- a/core/modules/widgets/image.js +++ b/core/modules/widgets/image.js @@ -100,6 +100,9 @@ ImageWidget.prototype.render = function(parent,nextSibling) { if(this.imageClass) { domNode.setAttribute("class",this.imageClass); } + if(this.imageUsemap) { + domNode.setAttribute("usemap",this.imageUsemap); + } if(this.imageWidth) { domNode.setAttribute("width",this.imageWidth); } @@ -139,6 +142,7 @@ ImageWidget.prototype.execute = function() { this.imageWidth = this.getAttribute("width"); this.imageHeight = this.getAttribute("height"); this.imageClass = this.getAttribute("class"); + this.imageUsemap = this.getAttribute("usemap"); this.imageTooltip = this.getAttribute("tooltip"); this.imageAlt = this.getAttribute("alt"); this.lazyLoading = this.getAttribute("loading"); @@ -149,7 +153,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ ImageWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes["class"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) { + if(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes["class"] || changedAttributes.usemap || changedAttributes.tooltip || changedTiddlers[this.imageSource]) { this.refreshSelf(); return true; } else { diff --git a/editions/tw5.com/tiddlers/widgets/ImageWidget.tid b/editions/tw5.com/tiddlers/widgets/ImageWidget.tid index c888c3a31..0f4bd9012 100644 --- a/editions/tw5.com/tiddlers/widgets/ImageWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ImageWidget.tid @@ -1,6 +1,6 @@ caption: image created: 20140416160234142 -modified: 20220721102303815 +modified: 20231121114351165 tags: Widgets title: ImageWidget type: text/vnd.tiddlywiki @@ -21,6 +21,7 @@ Any content of the `<$image>` widget is ignored. |alt |The alternative text to be associated with the image | |class |CSS classes to be assigned to the `` element | |loading|<<.from-version "5.2.3">>Optional. Set to `lazy` to enable lazy loading of images loaded from an external URI | +|usemap|<<.from-version "5.3.2">>Optional usemap attribute to be assigned to the `` element for use with HTML image maps | The width and the height can be specified as pixel values (eg "23" or "23px") or percentages (eg "23%"). They are both optional; if not provided the browser will use CSS rules to size the image. From 06b1cc4bca54f8b9a2d205d7cf194fb0caa79a81 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 21 Nov 2023 11:49:34 +0000 Subject: [PATCH 026/105] Scrollable widget: Fix crash in CI --- core/modules/widgets/scrollable.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index c95820ef3..58597461b 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -191,6 +191,10 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { }; ScrollableWidget.prototype.updateScrollPositionFromBoundTiddler = function() { + // Bail if we're running on the fakedom + if(!this.outerDomNode.scrollTo) { + return; + } var tiddler = this.wiki.getTiddler(this.scrollableBind); if(tiddler) { var scrollLeftTo = this.outerDomNode.scrollLeft; From de6b866f22a8262c8c531e8fbace999563148aa2 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 21 Nov 2023 11:54:37 +0000 Subject: [PATCH 027/105] Fix detection of DOM properties Alternate fix for #7714 --- core/modules/utils/dom/dom.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/modules/utils/dom/dom.js b/core/modules/utils/dom/dom.js index 9c06fc8b0..338d96280 100644 --- a/core/modules/utils/dom/dom.js +++ b/core/modules/utils/dom/dom.js @@ -313,7 +313,7 @@ exports.collectDOMVariables = function(selectedNode,domNode,event) { variables["dom-" + attribute.name] = attribute.value.toString(); }); - if(selectedNode.offsetLeft) { + if("offsetLeft" in selectedNode) { // Add variables with a (relative and absolute) popup coordinate string for the selected node var nodeRect = { left: selectedNode.offsetLeft, @@ -338,12 +338,12 @@ exports.collectDOMVariables = function(selectedNode,domNode,event) { } } - if(domNode && domNode.offsetWidth) { + if(domNode && ("offsetWidth" in domNode)) { variables["tv-widgetnode-width"] = domNode.offsetWidth.toString(); variables["tv-widgetnode-height"] = domNode.offsetHeight.toString(); } - if(event && event.clientX && event.clientY) { + if(event && ("clientX" in event) && ("clientY" in event)) { if(selectedNode) { // Add variables for event X and Y position relative to selected node selectedNodeRect = selectedNode.getBoundingClientRect(); From ad9cb8a0a8c740aeef3e795dca74e7dc979de528 Mon Sep 17 00:00:00 2001 From: Marxsal Date: Tue, 21 Nov 2023 03:55:54 -0800 Subject: [PATCH 028/105] Modify SetWidget to include use to set global variables. (#7608) * Modify SetWidget to include use to set global variables. * Make sample variables easier to read. * Change text to indicate use of pragma whitespace trim. * Make compliant with 5.3.1 (?) release --- .../tw5.com/tiddlers/widgets/SetWidget.tid | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/widgets/SetWidget.tid b/editions/tw5.com/tiddlers/widgets/SetWidget.tid index fe05e8faa..f5b0786f3 100644 --- a/editions/tw5.com/tiddlers/widgets/SetWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/SetWidget.tid @@ -1,6 +1,6 @@ caption: set created: 20131115182700000 -modified: 20220523075522407 +modified: 20230720174707977 tags: Widgets title: SetWidget type: text/vnd.tiddlywiki @@ -120,3 +120,19 @@ src='<$set name="myTiddler" value="HelloThere"> '/> <<< + +!! Using the Set Widget to Create Global Variables + +There are times when it makes sense to use the features of the [[SetWidget]] rather than procedures or functions to create global variables. This can be accomplished by placing the set variable widget in a tiddler that is tagged [[$:/tags/Global|SystemTag: $:/tags/Global]]. If multiple variables are required, the set variable widget can be nested as shown here: + +<<< +
    + +``` +<$set name="myGlobalVariable" value="I am global"> + <$set name="myOtherGlobalVariable" value="I am also a global variable."> + + +``` +
    +<<< From 4c2979286b6836f4331b31649e3d17b7b074ca6f Mon Sep 17 00:00:00 2001 From: yaisog Date: Tue, 21 Nov 2023 12:58:12 +0100 Subject: [PATCH 029/105] Change separators to match doc (#7303) --- core/modules/wiki.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 3eae3902d..430c46466 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1287,7 +1287,7 @@ exports.search = function(text,options) { console.log("Regexp error parsing /(" + text + ")/" + flags + ": ",e); } } else if(options.some) { - terms = text.trim().split(/ +/); + terms = text.trim().split(/[^\S\xA0]+/); if(terms.length === 1 && terms[0] === "") { searchTermsRegExps = null; } else { @@ -1298,7 +1298,7 @@ exports.search = function(text,options) { searchTermsRegExps.push(new RegExp("(" + regExpStr + ")",flags)); } } else { // default: words - terms = text.split(/ +/); + terms = text.split(/[^\S\xA0]+/); if(terms.length === 1 && terms[0] === "") { searchTermsRegExps = null; } else { From 62bb8affa48aec958fc73104b060f6a90efc8e1b Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 22 Nov 2023 20:05:40 +0000 Subject: [PATCH 030/105] Add data attribute support to button and other widgets (#7769) * Add data attribute support to button widget * Fix typo * Refactor ready for making mechanism more generic * Apply more generic implementation to multiplate widgets * Refactor to use existing widget.assignAttributes() method * Fix typo * Clarify docs * Update docs * Update select widget to support style.* attributes * Remove obsolete comment * Fixes refresh issues for checkbox and links widgets for data attributes (#7846) * fix: refresh issues with checkbox and links widgets * fix: indenting * Feat: add support for data attributes to Draggable and Droppable widgets (#7845) * Docs clarification * docs: add style and data attributes to Draggable and Droppable widget docs (#7850) * Refactors Select widget to directly create DOM node (#7848) * fix: refactored SelectWidget to directly create DOM nodes * fix: refactored SelectWidget to directly create DOM nodes * fix: improve refresh handling for select widget * Fixes issues in the PR "Button widget data attributes" (#7852) * fix: fixed ordered attributes handling and improved tests to catch event attributes * fix: clean up code from testing * fix: more tests and refactoring * fix: use lowercase when checking for event attribute prefix * fix: use lowercase when checking for event attribute prefix * fix: changed comment wording * fix: minor refactoring * refactor: for brevity --------- Co-authored-by: Saq Imtiaz --- core/modules/utils/fakedom.js | 6 +- core/modules/widgets/browse.js | 10 ++++ core/modules/widgets/button.js | 18 +++++- core/modules/widgets/checkbox.js | 11 ++++ core/modules/widgets/draggable.js | 21 +++++-- core/modules/widgets/droppable.js | 16 ++++- core/modules/widgets/link.js | 14 ++++- core/modules/widgets/radio.js | 4 ++ core/modules/widgets/range.js | 4 ++ core/modules/widgets/select.js | 60 +++++++++++-------- core/modules/widgets/widget.js | 54 +++++++++++------ core/wiki/macros/tabs.tid | 10 +++- .../ButtonWidget-DataAttributes.tid | 27 +++++++++ .../CheckboxWidget-DataAttributes.tid | 22 +++++++ .../DraggableWidget-DataAttributes.tid | 27 +++++++++ .../DroppableWidget-DataAttributes.tid | 27 +++++++++ .../LinkWidget-DataAttributes.tid | 27 +++++++++ .../DataAttributes/OrderedStyleAttributes.tid | 15 +++++ .../SelectWidget-DataAttributes.tid | 27 +++++++++ .../widgets/ElementWidgetEventAttributes.tid | 15 +++++ .../widgets/ElementWidgetStyleAttributes.tid | 15 +++++ .../tw5.com/tiddlers/widgets/BrowseWidget.tid | 4 +- .../tw5.com/tiddlers/widgets/ButtonWidget.tid | 4 +- .../tiddlers/widgets/CheckboxWidget.tid | 4 +- .../tiddlers/widgets/DraggableWidget.tid | 5 +- .../tiddlers/widgets/DroppableWidget.tid | 4 +- .../tw5.com/tiddlers/widgets/LinkWidget.tid | 4 +- .../tw5.com/tiddlers/widgets/RadioWidget.tid | 4 +- .../tw5.com/tiddlers/widgets/RangeWidget.tid | 4 +- .../tw5.com/tiddlers/widgets/SelectWidget.tid | 5 +- 30 files changed, 399 insertions(+), 69 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid create mode 100644 editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid diff --git a/core/modules/utils/fakedom.js b/core/modules/utils/fakedom.js index d28161ac6..0c1f5fa54 100755 --- a/core/modules/utils/fakedom.js +++ b/core/modules/utils/fakedom.js @@ -104,7 +104,11 @@ TW_Element.prototype.setAttribute = function(name,value) { if(this.isRaw) { throw "Cannot setAttribute on a raw TW_Element"; } - this.attributes[name] = value + ""; + if(name === "style") { + this.style = value; + } else { + this.attributes[name] = value + ""; + } }; TW_Element.prototype.setAttributeNS = function(namespace,name,value) { diff --git a/core/modules/widgets/browse.js b/core/modules/widgets/browse.js index de3c91fb8..8130825b0 100644 --- a/core/modules/widgets/browse.js +++ b/core/modules/widgets/browse.js @@ -70,6 +70,11 @@ BrowseWidget.prototype.render = function(parent,nextSibling) { } return false; },false); + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Insert element parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -95,6 +100,11 @@ BrowseWidget.prototype.execute = function() { Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ BrowseWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if($tw.utils.count(changedAttributes) > 0) { + this.refreshSelf(); + return true; + } return false; }; diff --git a/core/modules/widgets/button.js b/core/modules/widgets/button.js index a724d8448..958b6f6da 100644 --- a/core/modules/widgets/button.js +++ b/core/modules/widgets/button.js @@ -59,6 +59,11 @@ ButtonWidget.prototype.render = function(parent,nextSibling) { $tw.utils.pushTop(classes,"tc-popup-handle"); } domNode.className = classes.join(" "); + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Assign other attributes if(this.style) { domNode.setAttribute("style",this.style); @@ -250,7 +255,7 @@ ButtonWidget.prototype.updateDomNodeClasses = function() { //Add new classes from updated class attribute. $tw.utils.pushTop(domNodeClasses,newClasses); this.domNode.className = domNodeClasses.join(" "); -} +}; /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering @@ -260,8 +265,15 @@ ButtonWidget.prototype.refresh = function(changedTiddlers) { if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) { this.refreshSelf(); return true; - } else if(changedAttributes["class"]) { - this.updateDomNodeClasses(); + } else { + if(changedAttributes["class"]) { + this.updateDomNodeClasses(); + } + this.assignAttributes(this.domNodes[0],{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/checkbox.js b/core/modules/widgets/checkbox.js index fc987d815..e07513b0a 100644 --- a/core/modules/widgets/checkbox.js +++ b/core/modules/widgets/checkbox.js @@ -53,6 +53,11 @@ CheckboxWidget.prototype.render = function(parent,nextSibling) { this.labelDomNode.appendChild(this.inputDomNode); this.spanDomNode = this.document.createElement("span"); this.labelDomNode.appendChild(this.spanDomNode); + // Assign data- attributes + this.assignAttributes(this.inputDomNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Add a click event handler $tw.utils.addEventListeners(this.inputDomNode,[ {name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"} @@ -325,6 +330,11 @@ CheckboxWidget.prototype.refresh = function(changedTiddlers) { $tw.utils.removeClass(this.labelDomNode,"tc-checkbox-checked"); } } + this.assignAttributes(this.inputDomNode,{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); return this.refreshChildren(changedTiddlers) || refreshed; } }; @@ -332,3 +342,4 @@ CheckboxWidget.prototype.refresh = function(changedTiddlers) { exports.checkbox = CheckboxWidget; })(); + \ No newline at end of file diff --git a/core/modules/widgets/draggable.js b/core/modules/widgets/draggable.js index f759ab121..22fdc37e9 100644 --- a/core/modules/widgets/draggable.js +++ b/core/modules/widgets/draggable.js @@ -52,6 +52,11 @@ DraggableWidget.prototype.render = function(parent,nextSibling) { classes.push("tc-draggable"); } domNode.setAttribute("class",classes.join(" ")); + // Assign data- attributes and style. attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Insert the node into the DOM and render any children parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -108,13 +113,19 @@ DraggableWidget.prototype.updateDomNodeClasses = function() { Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ DraggableWidget.prototype.refresh = function(changedTiddlers) { - var changedAttributes = this.computeAttributes(), - changedAttributesCount = $tw.utils.count(changedAttributes); - if(changedAttributesCount === 1 && changedAttributes["class"]) { - this.updateDomNodeClasses(); - } else if(changedAttributesCount > 0) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes.tag || changedAttributes.selector || changedAttributes.dragimagetype || changedAttributes.enable || changedAttributes.startactions || changedAttributes.endactions) { this.refreshSelf(); return true; + } else { + if(changedAttributes["class"]) { + this.assignDomNodeClasses(); + } + this.assignAttributes(this.domNodes[0],{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/droppable.js b/core/modules/widgets/droppable.js index 104503b25..0dcba1688 100644 --- a/core/modules/widgets/droppable.js +++ b/core/modules/widgets/droppable.js @@ -42,6 +42,11 @@ DroppableWidget.prototype.render = function(parent,nextSibling) { domNode = this.document.createElement(tag); this.domNode = domNode; this.assignDomNodeClasses(); + // Assign data- attributes and style. attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Add event handlers if(this.droppableEnable) { $tw.utils.addEventListeners(domNode,[ @@ -166,8 +171,15 @@ DroppableWidget.prototype.refresh = function(changedTiddlers) { if(changedAttributes.tag || changedAttributes.enable || changedAttributes.disabledClass || changedAttributes.actions || changedAttributes.effect) { this.refreshSelf(); return true; - } else if(changedAttributes["class"]) { - this.assignDomNodeClasses(); + } else { + if(changedAttributes["class"]) { + this.assignDomNodeClasses(); + } + this.assignAttributes(this.domNodes[0],{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/link.js b/core/modules/widgets/link.js index 6f199d395..0d89ee22d 100755 --- a/core/modules/widgets/link.js +++ b/core/modules/widgets/link.js @@ -43,6 +43,11 @@ LinkWidget.prototype.render = function(parent,nextSibling) { } else { // Just insert the link text var domNode = this.document.createElement("span"); + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); this.domNodes.push(domNode); @@ -138,6 +143,11 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) { widget: this }); } + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Insert the link into the DOM and render any children parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -207,8 +217,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ LinkWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.to || changedTiddlers[this.to] || changedAttributes["aria-label"] || changedAttributes.tooltip || - changedAttributes["class"] || changedAttributes.tabindex || changedAttributes.draggable || changedAttributes.tag) { + if($tw.utils.count(changedAttributes) > 0) { this.refreshSelf(); return true; } @@ -218,3 +227,4 @@ LinkWidget.prototype.refresh = function(changedTiddlers) { exports.link = LinkWidget; })(); + \ No newline at end of file diff --git a/core/modules/widgets/radio.js b/core/modules/widgets/radio.js index 363836227..aa7a32cf1 100644 --- a/core/modules/widgets/radio.js +++ b/core/modules/widgets/radio.js @@ -40,6 +40,10 @@ RadioWidget.prototype.render = function(parent,nextSibling) { ); this.inputDomNode = this.document.createElement("input"); this.inputDomNode.setAttribute("type","radio"); + this.assignAttributes(this.inputDomNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); if(isChecked) { this.inputDomNode.checked = true; } diff --git a/core/modules/widgets/range.js b/core/modules/widgets/range.js index 4dd55dc3c..db2699cc4 100644 --- a/core/modules/widgets/range.js +++ b/core/modules/widgets/range.js @@ -50,6 +50,10 @@ RangeWidget.prototype.render = function(parent,nextSibling) { this.inputDomNode.setAttribute("disabled",true); } this.inputDomNode.value = this.getValue(); + this.assignAttributes(this.inputDomNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Add a click event handler $tw.utils.addEventListeners(this.inputDomNode,[ {name:"mousedown", handlerObject:this, handlerMethod:"handleMouseDownEvent"}, diff --git a/core/modules/widgets/select.js b/core/modules/widgets/select.js index ab9bef74e..f1ea3b331 100644 --- a/core/modules/widgets/select.js +++ b/core/modules/widgets/select.js @@ -40,7 +40,31 @@ SelectWidget.prototype.render = function(parent,nextSibling) { this.parentDomNode = parent; this.computeAttributes(); this.execute(); - this.renderChildren(parent,nextSibling); + //Create element + var domNode = this.document.createElement("select"); + if(this.selectClass) { + domNode.classname = this.selectClass; + } + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); + if(this.selectMultiple) { + domNode.setAttribute("multiple","multiple"); + } + if(this.selectSize) { + domNode.setAttribute("size",this.selectSize); + } + if(this.selectTabindex) { + domNode.setAttribute("tabindex",this.selectTabindex); + } + if(this.selectTooltip) { + domNode.setAttribute("title",this.selectTooltip); + } + this.renderChildren(domNode,nextSibling); + this.parentDomNode.insertBefore(domNode,nextSibling); + this.domNodes.push(domNode); this.setSelectValue(); if(this.selectFocus == "yes") { this.getSelectDomNode().focus(); @@ -113,7 +137,7 @@ SelectWidget.prototype.setSelectValue = function() { Get the DOM node of the select element */ SelectWidget.prototype.getSelectDomNode = function() { - return this.children[0].domNodes[0]; + return this.domNodes[0]; }; // Return an array of the selected opion values @@ -149,27 +173,7 @@ SelectWidget.prototype.execute = function() { this.selectTooltip = this.getAttribute("tooltip"); this.selectFocus = this.getAttribute("focus"); // Make the child widgets - var selectNode = { - type: "element", - tag: "select", - children: this.parseTreeNode.children - }; - if(this.selectClass) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"class",this.selectClass); - } - if(this.selectMultiple) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"multiple","multiple"); - } - if(this.selectSize) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"size",this.selectSize); - } - if(this.selectTabindex) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"tabindex",this.selectTabindex); - } - if(this.selectTooltip) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"title",this.selectTooltip); - } - this.makeChildWidgets([selectNode]); + this.makeChildWidgets(); }; /* @@ -178,17 +182,21 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of SelectWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // If we're using a different tiddler/field/index then completely refresh ourselves - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tooltip) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tooltip || changedAttributes.tabindex) { this.refreshSelf(); return true; - // If the target tiddler value has changed, just update setting and refresh the children } else { if(changedAttributes.class) { this.selectClass = this.getAttribute("class"); this.getSelectDomNode().setAttribute("class",this.selectClass); } - + this.assignAttributes(this.getSelectDomNode(),{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); var childrenRefreshed = this.refreshChildren(changedTiddlers); + // If the target tiddler value has changed, just update setting and refresh the children if(changedTiddlers[this.selectTitle] || childrenRefreshed) { this.setSelectValue(); } diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 6c3997179..af4892b9e 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -413,16 +413,34 @@ Widget.prototype.getAttribute = function(name,defaultText) { }; /* -Assign the computed attributes of the widget to a domNode +Assign the common attributes of the widget to a domNode options include: -excludeEventAttributes: ignores attributes whose name begins with "on" +sourcePrefix: prefix of attributes that are to be directly assigned (defaults to the empty string meaning all attributes) +destPrefix: prefix to be applied to attribute names that are to be directly assigned (defaults to the emtpy string which means no prefix is added) +changedAttributes: hashmap by attribute name of attributes to process (if missing, process all attributes) +excludeEventAttributes: ignores attributes whose name would begin with "on" */ Widget.prototype.assignAttributes = function(domNode,options) { options = options || {}; - var self = this; + var self = this, + changedAttributes = options.changedAttributes || this.attributes, + sourcePrefix = options.sourcePrefix || "", + destPrefix = options.destPrefix || "", + EVENT_ATTRIBUTE_PREFIX = "on"; var assignAttribute = function(name,value) { + // Process any style attributes before considering sourcePrefix and destPrefix + if(name.substr(0,6) === "style." && name.length > 6) { + domNode.style[$tw.utils.unHyphenateCss(name.substr(6))] = value; + return; + } + // Check if the sourcePrefix is a match + if(name.substr(0,sourcePrefix.length) === sourcePrefix) { + name = destPrefix + name.substr(sourcePrefix.length); + } else { + value = undefined; + } // Check for excluded attribute names - if(options.excludeEventAttributes && name.substr(0,2) === "on") { + if(options.excludeEventAttributes && name.substr(0,2).toLowerCase() === EVENT_ATTRIBUTE_PREFIX) { value = undefined; } if(value !== undefined) { @@ -432,26 +450,24 @@ Widget.prototype.assignAttributes = function(domNode,options) { namespace = "http://www.w3.org/1999/xlink"; name = name.substr(6); } - // Handle styles - if(name.substr(0,6) === "style." && name.length > 6) { - domNode.style[$tw.utils.unHyphenateCss(name.substr(6))] = value; - } else { - // Setting certain attributes can cause a DOM error (eg xmlns on the svg element) - try { - domNode.setAttributeNS(namespace,name,value); - } catch(e) { - } + // Setting certain attributes can cause a DOM error (eg xmlns on the svg element) + try { + domNode.setAttributeNS(namespace,name,value); + } catch(e) { } } - } - // Not all parse tree nodes have the orderedAttributes property + }; + // If the parse tree node has the orderedAttributes property then use that order if(this.parseTreeNode.orderedAttributes) { $tw.utils.each(this.parseTreeNode.orderedAttributes,function(attribute,index) { - assignAttribute(attribute.name,self.attributes[attribute.name]); - }); + if(attribute.name in changedAttributes) { + assignAttribute(attribute.name,self.getAttribute(attribute.name)); + } + }); + // Otherwise update each changed attribute irrespective of order } else { - $tw.utils.each(Object.keys(self.attributes).sort(),function(name) { - assignAttribute(name,self.attributes[name]); + $tw.utils.each(changedAttributes,function(value,name) { + assignAttribute(name,self.getAttribute(name)); }); } }; diff --git a/core/wiki/macros/tabs.tid b/core/wiki/macros/tabs.tid index bc8a0255f..1805bc9be 100644 --- a/core/wiki/macros/tabs.tid +++ b/core/wiki/macros/tabs.tid @@ -4,7 +4,15 @@ code-body: yes \define tabs-button() \whitespace trim -<$button set=<> setTo=<> default=<<__default__>> selectedClass="tc-tab-selected" tooltip={{!!tooltip}} role="switch"> +<$button + set=<> + setTo=<> + default=<<__default__>> + selectedClass="tc-tab-selected" + tooltip={{!!tooltip}} + role="switch" + data-tab-title=<> +> <$tiddler tiddler=<>> <$set name="tv-wikilinks" value="no"> <$transclude tiddler=<<__buttonTemplate__>> mode="inline"> diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid new file mode 100644 index 000000000..da3d7080a --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/ButtonWidget +description: Data Attributes for ButtonWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$button tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked"> +my tiddler + +<$button tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> +hello + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

    my tiddler
    hello

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid new file mode 100644 index 000000000..521fa3a13 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid @@ -0,0 +1,22 @@ +title: Widgets/DataAttributes/CheckboxWidget +description: Data Attributes for CheckboxWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$checkbox tag="done" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}} onclick="clicked"> Is it done? ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid new file mode 100644 index 000000000..feeb89ded --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/DraggableWidget +description: Data Attributes for DraggableWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$draggable tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked"> +my tiddler + +<$draggable tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> +hello + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

    my tiddler
    hello

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid new file mode 100644 index 000000000..3c7284eb1 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/DroppableWidget +description: Data Attributes for DroppableWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$droppable tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked"> +my tiddler + +<$droppable tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> +hello + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

    my tiddler
    hello

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid new file mode 100644 index 000000000..e99e265bb --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/LinkWidget +description: Data Attributes for LinkWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$link data-id="mytiddler" style.color="red" to="Temp" onclick="clicked"> +link to Temp + +<$link tag="button" data-id={{Temp}} style.color={{{ [[Temp]get[color]] }}} to="SomeTiddler"> +some tiddler + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

    link to Temp

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid new file mode 100644 index 000000000..2f6d2cb1a --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid @@ -0,0 +1,15 @@ +title: Widgets/DataAttributes/OrderedStyleAttributes +description: Ordered style attributes +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +
    +hello +
    ++ +title: ExpectedResult + +

    hello

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid new file mode 100644 index 000000000..de2c9995e --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/SelectWidget +description: Data Attributes for SelectWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$select tiddler='New Tiddler' field='text' default='Choose a new text' data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}} onclick="clicked"> + + + + + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid b/editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid new file mode 100644 index 000000000..4c2f6eb04 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid @@ -0,0 +1,15 @@ +title: Widgets/ElementWidgetEventAttributes +description: Element widget should not support event attributes starting with "on" +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +
    +TiddlyWiki +
    ++ +title: ExpectedResult + +

    TiddlyWiki

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid b/editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid new file mode 100644 index 000000000..a36a51323 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid @@ -0,0 +1,15 @@ +title: Widgets/ElementWidgetStyleAttributes +description: Element widget should support style.* attributes +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +
    +TiddlyWiki +
    ++ +title: ExpectedResult + +

    TiddlyWiki

    \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid b/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid index 28012bd68..b0364a71a 100644 --- a/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/BrowseWidget.tid @@ -1,6 +1,6 @@ caption: browse created: 20131024141900000 -modified: 20200421221304177 +modified: 20231113093304323 tags: Widgets title: BrowseWidget type: text/vnd.tiddlywiki @@ -20,6 +20,8 @@ The content of the <<.wid BrowseWidget>> widget is ignored. |accept |<<.from-version "5.1.23">> Optional comma delimited [[list of file accepted extensions|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers]] and/or MIME types | |message |Optional override of widget message to be generated. The files will be passed in the JavaScript object `event.target.files` | |param |Optional parameter to be passed with the custom message | +|data-* |<<.from-version "5.3.2">> Optional [[data attributes|https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes]] to be assigned to the HTML element | +|style.* |<<.from-version "5.3.2">> Optional [[CSS properties|https://developer.mozilla.org/en-US/docs/Web/CSS/Reference]] to be assigned to the HTML element | On iPhone/iPad choosing the multiple option will remove the ability to take photographs/videos directly into TiddlyWiki. diff --git a/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid b/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid index da61838af..d74c09575 100644 --- a/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid @@ -1,6 +1,6 @@ caption: button created: 20131024141900000 -modified: 20220810192251345 +modified: 20231113093304323 tags: Widgets TriggeringWidgets title: ButtonWidget type: text/vnd.tiddlywiki @@ -41,6 +41,8 @@ The content of the `<$button>` widget is displayed within the button. |aria-label |Optional [[Accessibility]] label | |tooltip |Optional tooltip | |class |An optional CSS class name to be assigned to the HTML element| +|data-* |<<.from-version "5.3.2">> Optional [[data attributes|https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes]] to be assigned to the HTML element | +|style.* |<<.from-version "5.3.2">> Optional [[CSS properties|https://developer.mozilla.org/en-US/docs/Web/CSS/Reference]] to be assigned to the HTML element | |style |An optional CSS style attribute to be assigned to the HTML element | |tag |An optional html tag to use instead of the default "button" | |dragTiddler |An optional tiddler title making the button draggable and identifying the payload tiddler. See DraggableWidget for details | diff --git a/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid b/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid index 47e83e875..00ecbb6f8 100644 --- a/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/CheckboxWidget.tid @@ -3,7 +3,7 @@ colors: red orange yellow blue created: 20131024141900000 fruits: bananas oranges grapes list: [[CheckboxWidget (tag Mode)]] [[CheckboxWidget (field Mode)]] [[CheckboxWidget (listField Mode)]] [[CheckboxWidget (index Mode)]] [[CheckboxWidget (listIndex Mode)]] [[CheckboxWidget (filter Mode)]] [[CheckboxWidget (indeterminate)]] -modified: 20230316192632667 +modified: 20231113093304323 tags: Widgets TriggeringWidgets title: CheckboxWidget type: text/vnd.tiddlywiki @@ -38,5 +38,7 @@ The content of the `<$checkbox>` widget is displayed within an HTML `
    \end \define image-picker-include-tagged-images(actions) -<$macrocall $name="image-picker" filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]" actions="""$actions$"""/> +<$macrocall $name="image-picker" filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[!has[draft.of]sort[title]]" actions=<<__actions__>>/> \end diff --git a/core/wiki/macros/tag-picker.tid b/core/wiki/macros/tag-picker.tid index e1b1a7139..ede53ec26 100644 --- a/core/wiki/macros/tag-picker.tid +++ b/core/wiki/macros/tag-picker.tid @@ -16,7 +16,7 @@ second-search-filter: [tags[]is[system]search:titlesort[]] emptyMessage="<$action-listops $tiddler=<> $field=<<__tagField__>> $subfilter='-[]'/>" > <$action-listops $tiddler=<> $field=<<__tagField__>> $subfilter="[trim[]]"/> - $actions$ + <$transclude $variable="__actions__"/> <> @@ -102,7 +102,7 @@ second-search-filter: [tags[]is[system]search:titlesort[]] <$set name="tag" value={{{ [get[text]] }}}> <$button set=<> setTo="" class=""> <$action-listops $tiddler=<> $field=<<__tagField__>> $subfilter="[trim[]]"/> - $actions$ + <$transclude $variable="__actions__"/> <$set name="currentTiddlerCSSEscaped" value={{{ [escapecss[]] }}}> <><$action-sendmessage $message="tm-focus-selector" $param=<>/> From 1cb607249e50344829dcbc9a4ed49335842e5058 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Fri, 24 Nov 2023 13:02:09 +0000 Subject: [PATCH 036/105] Fix syncer race condition (#7843) * Initial commit * Log task choosing * A tiny bit more logging * Typo * Restructure syncer to use a single state machine --- core/modules/syncer.js | 286 +++++++++++++++++++++++------------------ 1 file changed, 164 insertions(+), 122 deletions(-) diff --git a/core/modules/syncer.js b/core/modules/syncer.js index c06fcb143..58b087b8d 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -24,7 +24,7 @@ Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval"; Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading"; Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done"; Syncer.prototype.titleSyncThrottleInterval = "$:/config/SyncThrottleInterval"; -Syncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer +Syncer.prototype.taskTimerInterval = 0.25 * 1000; // Interval for sync timer Syncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s... Syncer.prototype.errorRetryInterval = 5 * 1000; // Interval to retry after an error Syncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s @@ -74,9 +74,11 @@ function Syncer(options) { this.titlesHaveBeenLazyLoaded = {}; // Hashmap of titles of tiddlers that have already been lazily loaded from the server // Timers this.taskTimerId = null; // Timer for task dispatch - this.pollTimerId = null; // Timer for polling server // Number of outstanding requests this.numTasksInProgress = 0; + // True when we want to force an immediate sync from the server + this.forceSyncFromServer = false; + this.timestampLastSyncFromServer = new Date(); // Listen out for changes to tiddlers this.wiki.addEventListener("change",function(changes) { // Filter the changes to just include ones that are being synced @@ -187,6 +189,7 @@ Syncer.prototype.readTiddlerInfo = function() { // Record information for known tiddlers var self = this, tiddlers = this.getSyncedTiddlers(); + this.logger.log("Initialising tiddlerInfo for " + tiddlers.length + " tiddlers"); $tw.utils.each(tiddlers,function(title) { var tiddler = self.wiki.getTiddler(title); if(tiddler) { @@ -203,33 +206,38 @@ Syncer.prototype.readTiddlerInfo = function() { Checks whether the wiki is dirty (ie the window shouldn't be closed) */ Syncer.prototype.isDirty = function() { - this.logger.log("Checking dirty status"); - // Check tiddlers that are in the store and included in the filter function - var titles = this.getSyncedTiddlers(); - for(var index=0; index tiddlerInfo.changeCount) { + var self = this; + function checkIsDirty() { + // Check tiddlers that are in the store and included in the filter function + var titles = self.getSyncedTiddlers(); + for(var index=0; index tiddlerInfo.changeCount) { + return true; + } + } else { + // If the tiddler isn't known on the server then it needs to be saved to the server return true; } - } else { - // If the tiddler isn't known on the server then it needs to be saved to the server + } + } + // Check tiddlers that are known from the server but not currently in the store + titles = Object.keys(self.tiddlerInfo); + for(index=0; index 0 || updates.deletions.length > 0) { - self.processTaskQueue(); - } - } - }); - } else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) { - this.logger.log("Retrieving skinny tiddler list"); - cancelNextSync(); - this.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) { - triggerNextSync(); - // Check for errors - if(err) { - self.displayError($tw.language.getString("Error/RetrievingSkinny"),err); - return; - } - // Keep track of which tiddlers we already know about have been reported this time - var previousTitles = Object.keys(self.tiddlerInfo); - // Process each incoming tiddler - for(var t=0; t= (this.timestampLastSyncFromServer.valueOf() + this.pollTimerInterval)))) { + return new SyncFromServerTask(this); + } + // Third, we check tiddlers that are known from the server but not currently in the store, and so need deleting on the server titles = Object.keys(this.tiddlerInfo); for(index=0; index Date: Fri, 24 Nov 2023 15:11:21 +0000 Subject: [PATCH 037/105] Update release note --- .../prerelease/tiddlers/Release 5.3.2.tid | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index 17058d731..ced4957f2 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -49,7 +49,7 @@ Note that the <<.attr "emptyMessage">> and <<.attr "template">> attributes take <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7746">> QR Code plugin to be able to read QR codes and a number of other bar code formats -! Translation improvement +! Translation improvements Improvements to the following translations: @@ -61,10 +61,13 @@ Improvements to the following translations: * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/1be8f0a9336952d4745d2bd4f2327e353580a272">> Comments Plugin to use predefined palette colours * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7785">> Evernote Importer Plugin to support images and other attachments +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7790">> `$floating` attribute to Dynannotate Plugin to support popups that do not disappear when another part of the screen is clicked. Instead they have to dismissed manually ! Widget Improvements -* +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7734">> ImageWidget encoding for more image types +* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7634">> ImageWidget to add a "usemap" attribute +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7649">> the ScrollableWidget to allow the scroll position to be bound to a tiddler, so that changes to the tiddler affect the scroll position, and vice versa ! Usability Improvements @@ -73,8 +76,10 @@ Improvements to the following translations: ! Hackability Improvements -* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7737">> an automatic build of the external core TiddlyWiki at https://tiddlywiki.com/empty-external-core.html +* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7769">> all the relevant core widgets to allow arbitrary `data-*` attributes and `style.*` attributes to be applied to the generated DOM nodes. This is useful for passing data to the EventCatcherWidget +* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7849">> [[jsonextract Operator]], [[jsonget Operator]], [[jsonset Operator]] and [[jsontype Operator]] to allow negative indexes into arrays to be counted from the end of the array * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7690">> the default page layout to better support CSS grid and flexbox layouts +* <<.link-bage-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7787">> the editor to use grid layout, simplifying customisation ! Bug Fixes @@ -87,10 +92,20 @@ Improvements to the following translations: * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/6088">> upgrade download link in Firefox * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7698">> refreshing of transcluded functions * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7789">> resizing of height of textareas in control panel +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7683">> [[encodebase64 Operator]] and [[decodebase64 Operator]] to work properly with binary data +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7708">> [[WidgetMessage: tm-open-window]] when opening an existing window to bring it to the front and focus it +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7809">> behaviour of [[last Operator]] when zero items selected +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7806">> incorrectly setting focus on field name input field when deleting field using the delete field button +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7802">> [[Table-of-Contents Macros]] to not show expander icon for a sublist that has all children excluded +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7794">> overflow of [[CodeMirror Plugin]] editor within grid container +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7835">> wikitest parser removing whitespace when parsing pragmas +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7842">> tooltip for editor add field button +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7844">> plain text parser being susceptible to the CodeBlockWidget being redefined +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7855">> pragmas not working within the action string of several core macros ! Node.js Improvements -* +* <> a significant flaw in the synchronisation algorithm used by the client-server configuration. The flaw could lead to tiddlers temporarily disappearing from the browser ! Performance Improvements @@ -100,6 +115,12 @@ Improvements to the following translations: ! Developer Improvements * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7751">> global hook handling to support removing hooks +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7539">> some useful npm scripts to `package.json` + +! Infrastructure Improvements + +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7820">> Continuous Integration tests to use Playwright to run our browser-based tests +* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7737">> an automatic build of the external core TiddlyWiki at https://tiddlywiki.com/empty-external-core.html ! Acknowledgements @@ -110,13 +131,19 @@ AnthonyMuscio BramChen BuckarooBanzay BurningTreeC +CrossEye EvidentlyCube +Gk0Wk joebordes kookma linonetwo mateuszwilczek +oflig +pille1842 pmario rmunn +saqimtiaz simonbaird T1mL3arn +yaisog """>> From 64812f5c062e3eaeaa8ef158851ffcece4babb13 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Sat, 25 Nov 2023 16:35:05 +0700 Subject: [PATCH 038/105] Add join attribute to list widget (#7694) * Add join attribute to list widget * Use new join attribute in HTML saving templates This simplifies the logic involved in saving tiddlers in JSON format into TW html files, and should also slightly speed up the saving process depending on how often that list widget gets refreshed. * Unit tests for list widget's new join attribute * Add `<$list-join>` widget Allows specifying complicated join text more easily than an attribute --- core/modules/widgets/list.js | 90 ++++++++++++++++--- core/templates/html-json-skinny-tiddler.tid | 1 - core/templates/html-json-tiddler.tid | 2 +- core/templates/store.area.template.html.tid | 8 +- core/ui/ViewTemplate/subtitle.tid | 7 +- .../prerelease/tiddlers/Release 5.3.2.tid | 27 ++++++ .../data/list-widget/WithJoinTemplate.tid | 30 +++++++ .../WithJoinTemplateInBlockMode.tid | 32 +++++++ editions/test/tiddlers/tests/test-widget.js | 39 ++++++++ .../tw5.com/tiddlers/widgets/ListWidget.tid | 22 ++++- .../tiddlyweb/html-json-skinny-tiddler.tid | 1 - .../tiddlyweb/html-json-tiddler.tid | 3 +- 12 files changed, 237 insertions(+), 25 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid create mode 100644 editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid diff --git a/core/modules/widgets/list.js b/core/modules/widgets/list.js index faedf72cc..78976f69a 100755 --- a/core/modules/widgets/list.js +++ b/core/modules/widgets/list.js @@ -50,8 +50,8 @@ ListWidget.prototype.render = function(parent,nextSibling) { $tw.modules.applyMethods("storyview",this.storyViews); } this.parentDomNode = parent; - this.computeAttributes(); - this.execute(); + var changedAttributes = this.computeAttributes(); + this.execute(changedAttributes); this.renderChildren(parent,nextSibling); // Construct the storyview var StoryView = this.storyViews[this.storyViewName]; @@ -71,7 +71,7 @@ ListWidget.prototype.render = function(parent,nextSibling) { /* Compute the internal state of the widget */ -ListWidget.prototype.execute = function() { +ListWidget.prototype.execute = function(changedAttributes) { var self = this; // Get our attributes this.template = this.getAttribute("template"); @@ -80,6 +80,10 @@ ListWidget.prototype.execute = function() { this.counterName = this.getAttribute("counter"); this.storyViewName = this.getAttribute("storyview"); this.historyTitle = this.getAttribute("history"); + // Create join template only if needed + if(this.join === undefined || (changedAttributes && changedAttributes.join)) { + this.join = this.makeJoinTemplate(); + } // Compose the list elements this.list = this.getTiddlerList(); var members = [], @@ -102,6 +106,7 @@ ListWidget.prototype.findExplicitTemplates = function() { var self = this; this.explicitListTemplate = null; this.explicitEmptyTemplate = null; + this.explicitJoinTemplate = null; this.hasTemplateInBody = false; var searchChildren = function(childNodes) { $tw.utils.each(childNodes,function(node) { @@ -109,6 +114,8 @@ ListWidget.prototype.findExplicitTemplates = function() { self.explicitListTemplate = node.children; } else if(node.type === "list-empty") { self.explicitEmptyTemplate = node.children; + } else if(node.type === "list-join") { + self.explicitJoinTemplate = node.children; } else if(node.type === "element" && node.tag === "p") { searchChildren(node.children); } else { @@ -152,6 +159,24 @@ ListWidget.prototype.getEmptyMessage = function() { } }; +/* +Compose the template for a join between list items +*/ +ListWidget.prototype.makeJoinTemplate = function() { + var parser, + join = this.getAttribute("join",""); + if(join) { + parser = this.wiki.parseText("text/vnd.tiddlywiki",join,{parseAsInline:true}) + if(parser) { + return parser.tree; + } else { + return []; + } + } else { + return this.explicitJoinTemplate; // May be null, and that's fine + } +}; + /* Compose the template for a list item */ @@ -160,6 +185,7 @@ ListWidget.prototype.makeItemTemplate = function(title,index) { var tiddler = this.wiki.getTiddler(title), isDraft = tiddler && tiddler.hasField("draft.of"), template = this.template, + join = this.join, templateTree; if(isDraft && this.editTemplate) { template = this.editTemplate; @@ -185,12 +211,12 @@ ListWidget.prototype.makeItemTemplate = function(title,index) { } } // Return the list item - var parseTreeNode = {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree}; + var parseTreeNode = {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree, join: join}; + parseTreeNode.isLast = index === this.list.length - 1; if(this.counterName) { parseTreeNode.counter = (index + 1).toString(); parseTreeNode.counterName = this.counterName; parseTreeNode.isFirst = index === 0; - parseTreeNode.isLast = index === this.list.length - 1; } return parseTreeNode; }; @@ -206,7 +232,7 @@ ListWidget.prototype.refresh = function(changedTiddlers) { this.storyview.refreshStart(changedTiddlers,changedAttributes); } // Completely refresh if any of our attributes have changed - if(changedAttributes.filter || changedAttributes.variable || changedAttributes.counter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) { + if(changedAttributes.filter || changedAttributes.variable || changedAttributes.counter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.join || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) { this.refreshSelf(); result = true; } else { @@ -310,10 +336,29 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) { } } else { // Cycle through the list, inserting and removing list items as needed + var mustRecreateLastItem = false; + if(this.join && this.join.length) { + if(this.children.length !== this.list.length) { + mustRecreateLastItem = true; + } else if(prevList[prevList.length-1] !== this.list[this.list.length-1]) { + mustRecreateLastItem = true; + } + } + var isLast = false, wasLast = false; for(t=0; t0) { + // First re-create previosly-last item that will no longer be last + this.removeListItem(t-1); + this.insertListItem(t-1,this.list[t-1]); + } this.insertListItem(t,this.list[t]); hasRefreshed = true; } else { @@ -322,9 +367,15 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) { this.removeListItem(n); hasRefreshed = true; } - // Refresh the item we're reusing - var refreshed = this.children[t].refresh(changedTiddlers); - hasRefreshed = hasRefreshed || refreshed; + // Refresh the item we're reusing, or recreate if necessary + if(mustRecreateLastItem && (isLast || wasLast)) { + this.removeListItem(t); + this.insertListItem(t,this.list[t]); + hasRefreshed = true; + } else { + var refreshed = this.children[t].refresh(changedTiddlers); + hasRefreshed = hasRefreshed || refreshed; + } } } } @@ -414,8 +465,17 @@ ListItemWidget.prototype.execute = function() { this.setVariable(this.parseTreeNode.counterName + "-first",this.parseTreeNode.isFirst ? "yes" : "no"); this.setVariable(this.parseTreeNode.counterName + "-last",this.parseTreeNode.isLast ? "yes" : "no"); } + // Add join if needed + var children = this.parseTreeNode.children, + join = this.parseTreeNode.join; + if(join && join.length && !this.parseTreeNode.isLast) { + children = children.slice(0); + $tw.utils.each(join,function(joinNode) { + children.push(joinNode); + }) + } // Construct the child widgets - this.makeChildWidgets(); + this.makeChildWidgets(children); }; /* @@ -450,4 +510,14 @@ ListEmptyWidget.prototype.refresh = function() { return false; } exports["list-empty"] = ListEmptyWidget; +var ListJoinWidget = function(parseTreeNode,options) { + // Main initialisation inherited from widget.js + this.initialise(parseTreeNode,options); +}; +ListJoinWidget.prototype = new Widget(); +ListJoinWidget.prototype.render = function() {} +ListJoinWidget.prototype.refresh = function() { return false; } + +exports["list-join"] = ListJoinWidget; + })(); diff --git a/core/templates/html-json-skinny-tiddler.tid b/core/templates/html-json-skinny-tiddler.tid index 1e3c032f3..6f5b7ff35 100644 --- a/core/templates/html-json-skinny-tiddler.tid +++ b/core/templates/html-json-skinny-tiddler.tid @@ -1,4 +1,3 @@ title: $:/core/templates/html-json-skinny-tiddler -<$list filter="[compare:number:gteq[1]] ~[!match[1]]">`,`<$text text=<>/> <$jsontiddler tiddler=<> exclude="text" escapeUnsafeScriptChars="yes"/> diff --git a/core/templates/html-json-tiddler.tid b/core/templates/html-json-tiddler.tid index 6b62b4ac9..2e12290a7 100644 --- a/core/templates/html-json-tiddler.tid +++ b/core/templates/html-json-tiddler.tid @@ -1,3 +1,3 @@ title: $:/core/templates/html-json-tiddler -<$list filter="[!match[1]]">`,`<$text text=<>/><$jsontiddler tiddler=<> escapeUnsafeScriptChars="yes"/> \ No newline at end of file +<$jsontiddler tiddler=<> escapeUnsafeScriptChars="yes"/> \ No newline at end of file diff --git a/core/templates/store.area.template.html.tid b/core/templates/store.area.template.html.tid index 84dd0c432..b148a2ff3 100644 --- a/core/templates/store.area.template.html.tid +++ b/core/templates/store.area.template.html.tid @@ -6,14 +6,14 @@ title: $:/core/templates/store.area.template.html <$list filter="[[storeAreaFormat]is[variable]getvariable[]else[json]match[json]]"> `` `` diff --git a/core/ui/ViewTemplate/subtitle.tid b/core/ui/ViewTemplate/subtitle.tid index a0436b095..a7c010287 100644 --- a/core/ui/ViewTemplate/subtitle.tid +++ b/core/ui/ViewTemplate/subtitle.tid @@ -4,11 +4,8 @@ tags: $:/tags/ViewTemplate \whitespace trim <$reveal type="nomatch" stateTitle=<> text="hide" tag="div" retain="yes" animate="yes">
    -<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate/Subtitle]!has[draft.of]]" variable="subtitleTiddler" counter="indexSubtitleTiddler"> -<$list filter="[match[no]]" variable="ignore"> -  - -<$transclude tiddler=<> mode="inline"/> +<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate/Subtitle]!has[draft.of]]" variable="subtitleTiddler"> +<$transclude tiddler=<> mode="inline"/><$list-join> 
    diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index ced4957f2..adcff9e67 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -41,6 +41,33 @@ description: Under development Note that the <<.attr "emptyMessage">> and <<.attr "template">> attributes take precedence if they are present. +!! Joiners for the ListWidget + +<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7694">> a <<.attr "join">> attribute to the <<.wid "ListWidget">> widget to insert a short piece of text between list items. This is both easier to use and faster than using the <<.attr "counter">> attribute for the same purpose. So if your list looked like this: + +``` +<$list filter=<> counter="counter" variable="item"> +<$text text=<>/><$list filter="[match[no]]" variable="ignore"><$text text=", "/> + +``` + +You can replace it with: + +``` +<$list filter=<> variable="item" join=", "> +<$text text=<>/> + +``` + +If the joiner text that you need is long and awkward to write in an attribute, you can use the new `<$list-join>` widget. Like `<$list-template>` and `<$list-empty>`, it must be an immediate child of the <<.wid "ListWidget">>: + +``` +<$list filter=<> variable="item"> +<$text text=<>/> +<$list-join>, and also let's not forget + +``` + !! jsonset operator <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7742">> [[jsonset Operator]] for setting values within JSON objects diff --git a/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid new file mode 100644 index 000000000..f1b6f25e9 --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid @@ -0,0 +1,30 @@ +title: ListWidget/WithJoinTemplate +description: List widget with join template and $list-empty +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + Item:<> + + <$list-empty> + None! + + + <$list-join>, + +\end + +<> + +<> + ++ +title: ExpectedResult + +

    Item:1,Item:2,Item:3

    None!

    \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid new file mode 100644 index 000000000..c12f4c801 --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid @@ -0,0 +1,32 @@ +title: ListWidget/WithJoinTemplateInBlockMode +description: List widget with join template and $list-empty in block mode +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + + Item:<> + + <$list-empty> + None! + + + <$list-join>
    + +\end + +<> + +<> + ++ +title: ExpectedResult +comment: I wish there was a good way to get rid of these extraneous paragraph elements + +

    Item:1


    Item:2


    Item:3

    None! \ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-widget.js b/editions/test/tiddlers/tests/test-widget.js index 4da9e20b0..0d1351f31 100755 --- a/editions/test/tiddlers/tests/test-widget.js +++ b/editions/test/tiddlers/tests/test-widget.js @@ -527,6 +527,45 @@ describe("Widget module", function() { expect(wrapper.children[0].children[15].sequenceNumber).toBe(53); }); + var testListJoin = function(oldList, newList) { + return function() { + var wiki = new $tw.Wiki(); + // Add some tiddlers + wiki.addTiddler({title: "Numbers", text: "", list: oldList}); + var text = "<$list filter='[list[Numbers]]' variable='item' join=', '><>"; + var widgetNode = createWidgetNode(parseText(text,wiki),wiki); + // Render the widget node to the DOM + var wrapper = renderWidgetNode(widgetNode); + // Test the rendering + expect(wrapper.innerHTML).toBe("

    " + oldList.split(' ').join(', ') + "

    "); + // Change the list and ensure new rendering is still right + wiki.addTiddler({title: "Numbers", text: "", list: newList}); + refreshWidgetNode(widgetNode,wrapper,["Numbers"]); + expect(wrapper.innerHTML).toBe("

    " + newList.split(' ').join(', ') + "

    "); + } + } + + it("the list widget with join should update correctly when empty list gets one item", testListJoin("", "1")); + it("the list widget with join should update correctly when empty list gets two items", testListJoin("", "1 2")); + it("the list widget with join should update correctly when single-item list is appended to", testListJoin("1", "1 2")); + it("the list widget with join should update correctly when single-item list is prepended to", testListJoin("1", "2 1")); + it("the list widget with join should update correctly when list is appended", testListJoin("1 2 3 4", "1 2 3 4 5")); + it("the list widget with join should update correctly when last item is removed", testListJoin("1 2 3 4", "1 2 3")); + it("the list widget with join should update correctly when first item is inserted", testListJoin("1 2 3 4", "0 1 2 3 4")); + it("the list widget with join should update correctly when first item is removed", testListJoin("1 2 3 4", "2 3 4")); + it("the list widget with join should update correctly when first two items are swapped", testListJoin("1 2 3 4", "2 1 3 4")); + it("the list widget with join should update correctly when last two items are swapped", testListJoin("1 2 3 4", "1 2 4 3")); + it("the list widget with join should update correctly when last item is moved to the front", testListJoin("1 2 3 4", "4 1 2 3")); + it("the list widget with join should update correctly when last item is moved to the middle", testListJoin("1 2 3 4", "1 4 2 3")); + it("the list widget with join should update correctly when first item is moved to the back", testListJoin("1 2 3 4", "2 3 4 1")); + it("the list widget with join should update correctly when middle item is moved to the back", testListJoin("1 2 3 4", "1 3 4 2")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 1", testListJoin("1 3 4", "1 2 3")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 2", testListJoin("1 3 4", "1 3 2")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 3", testListJoin("1 3 4", "2 1 3")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 4", testListJoin("1 3 4", "2 3 1")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 5", testListJoin("1 3 4", "3 1 2")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 6", testListJoin("1 3 4", "3 2 1")); + var testCounterLast = function(oldList, newList) { return function() { var wiki = new $tw.Wiki(); diff --git a/editions/tw5.com/tiddlers/widgets/ListWidget.tid b/editions/tw5.com/tiddlers/widgets/ListWidget.tid index 592185d36..ce4389261 100644 --- a/editions/tw5.com/tiddlers/widgets/ListWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ListWidget.tid @@ -84,6 +84,7 @@ The action of the list widget depends on the results of the filter combined with |limit |<<.from-version "5.3.2">> Optional numeric limit for the number of results that are returned. Negative values will return the results from the end of the list | |template |The title of a template tiddler for transcluding each tiddler in the list. When no template is specified, the body of the ListWidget serves as the item template. With no body, a simple link to the tiddler is returned. | |editTemplate |An alternative template to use for [[DraftTiddlers|DraftMechanism]] in edit mode | +|join |<<.from-version "5.3.2">> Text to include between each list item | |variable |The name for a [[variable|Variables]] in which the title of each listed tiddler is stored. Defaults to ''currentTiddler'' | |counter |<<.from-version "5.2.0">> Optional name for a [[variable|Variables]] in which the 1-based numeric index of each listed tiddler is stored (see below) | |emptyMessage |Message to be displayed when the list is empty | @@ -120,10 +121,29 @@ Displays as: <<< -Note that using the `counter` attribute can reduce performance when working with list items that dynamically reorder or update themselves. The best advice is only to use it when it is really necessary: to obtain a numeric index, or to detect the first or last entries in the list. +Note that using the `counter` attribute can reduce performance when working with list items that dynamically reorder or update themselves. The best advice is only to use it when it is really necessary: to obtain a numeric index, or to detect the first or last entries in the list. Note that if you are only using it to insert something (like a comma) between list items, the `join` attribute performs much better and you should use it instead of `counter`. Setting `counter="transclusion"` is a handy way to make child elements for each list element be identified as unique. A common use case are multiple [[tag macros|tag Macro]] for the same tag generated by a list widget. Refer to [[tag macro examples|tag Macro (Examples)]] for more details. +!! `join` attribute + +<<.from-version "5.3.2">> The optional `join` attribute allow you to insert some [[WikiText]] between each list item without needing to use the `counter` attribute, which can become quite slow if the list is updated frequently. + +<<.from-version "5.3.2">> If the widget `<$list-join>` is found as an immediate child of the <<.wid "ListWidget">> widget then the content of that widget is used as the "join" template, included between two list items. Note that the <<.attr "join">> attribute takes precedence if it is present. + +For example: + + +``` +<$list filter="[tag[About]sort[title]]" join=", " variable="item"><> +``` + +Displays as: + +<<< +<$list filter="[tag[About]sort[title]]" join=", " variable="item"><> +<<< + !! Edit mode The `<$list>` widget can optionally render draft tiddlers through a different template to handle editing, see DraftMechanism. diff --git a/plugins/tiddlywiki/tiddlyweb/html-json-skinny-tiddler.tid b/plugins/tiddlywiki/tiddlyweb/html-json-skinny-tiddler.tid index d4f96fde7..b7329c265 100644 --- a/plugins/tiddlywiki/tiddlyweb/html-json-skinny-tiddler.tid +++ b/plugins/tiddlywiki/tiddlyweb/html-json-skinny-tiddler.tid @@ -1,4 +1,3 @@ title: $:/core/templates/html-json-skinny-tiddler -<$list filter="[compare:number:gteq[1]] ~[!match[1]]">`,`<$text text=<>/> <$jsontiddler tiddler=<> exclude="text" escapeUnsafeScriptChars="yes" $revision=<> $bag="default" $_is_skinny=""/> diff --git a/plugins/tiddlywiki/tiddlyweb/html-json-tiddler.tid b/plugins/tiddlywiki/tiddlyweb/html-json-tiddler.tid index bd7a0deec..f357321fb 100644 --- a/plugins/tiddlywiki/tiddlyweb/html-json-tiddler.tid +++ b/plugins/tiddlywiki/tiddlyweb/html-json-tiddler.tid @@ -1,4 +1,3 @@ title: $:/core/templates/html-json-tiddler -<$list filter="[!match[1]]">`,`<$text text=<>/> -<$jsontiddler tiddler=<> escapeUnsafeScriptChars="yes" $revision=<> $bag="default">/> +<$jsontiddler tiddler=<> escapeUnsafeScriptChars="yes" $revision=<> $bag="default"/> From 233b871fdf7406c5a50e1c0f391e4aed1bbb180a Mon Sep 17 00:00:00 2001 From: Saq Imtiaz Date: Sun, 26 Nov 2023 18:42:53 +0100 Subject: [PATCH 039/105] Update help for CommandsCommand to avoid deduplication (#7858) --- core/language/en-GB/Help/commands.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/language/en-GB/Help/commands.tid b/core/language/en-GB/Help/commands.tid index 454159b44..7551885f0 100644 --- a/core/language/en-GB/Help/commands.tid +++ b/core/language/en-GB/Help/commands.tid @@ -10,7 +10,7 @@ Sequentially run the command tokens returned from a filter Examples ``` ---commands "[enlist{$:/build-commands-as-text}]" +--commands "[enlist:raw{$:/build-commands-as-text}]" ``` ``` From 6bd69cc53ff95efc36fdbea615825ef0dcc5de1e Mon Sep 17 00:00:00 2001 From: Maurycy Zarzycki Date: Mon, 27 Nov 2023 22:53:42 +0100 Subject: [PATCH 040/105] Add changes to PL translation from 233b871fdf7406c5a50e1c0f391e4aed1bbb180a (#7862) --- languages/pl-PL/Help/commands.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/pl-PL/Help/commands.tid b/languages/pl-PL/Help/commands.tid index a0bc5932d..1085ac0a5 100644 --- a/languages/pl-PL/Help/commands.tid +++ b/languages/pl-PL/Help/commands.tid @@ -10,7 +10,7 @@ Uruchamia komendy zwrócone przez filtr. Dla przykładu: ``` ---commands "[enlist{$:/build-commands-as-text}]" +--commands "[enlist:raw{$:/build-commands-as-text}]" ``` ``` From 8f661423f7a36257ffabc31ffc1b8a0eb95f1ae8 Mon Sep 17 00:00:00 2001 From: Bram Chen Date: Tue, 28 Nov 2023 06:01:25 +0800 Subject: [PATCH 041/105] Update chinese translations (#7859) * Update help for CommandsCommand --- languages/zh-Hans/Help/commands.tid | 2 +- languages/zh-Hant/Help/commands.tid | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/languages/zh-Hans/Help/commands.tid b/languages/zh-Hans/Help/commands.tid index 68f86f20c..5a6754ec6 100644 --- a/languages/zh-Hans/Help/commands.tid +++ b/languages/zh-Hans/Help/commands.tid @@ -10,7 +10,7 @@ description: 运行从筛选器传回的命令 示例 ``` ---commands "[enlist{$:/build-commands-as-text}]" +--commands "[enlist:raw{$:/build-commands-as-text}]" ``` ``` diff --git a/languages/zh-Hant/Help/commands.tid b/languages/zh-Hant/Help/commands.tid index afeaa1e49..eead14103 100644 --- a/languages/zh-Hant/Help/commands.tid +++ b/languages/zh-Hant/Help/commands.tid @@ -10,7 +10,7 @@ description: 執行從篩選器傳回的命令 範例 ``` ---commands "[enlist{$:/build-commands-as-text}]" +--commands "[enlist:raw{$:/build-commands-as-text}]" ``` ``` From a21f45b93a0935b6f84daba8b773771b21b59071 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 28 Nov 2023 10:53:38 +0000 Subject: [PATCH 042/105] Release note: fix typos --- editions/prerelease/tiddlers/Release 5.3.2.tid | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index adcff9e67..ce1338ba0 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -106,7 +106,7 @@ Improvements to the following translations: * <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7769">> all the relevant core widgets to allow arbitrary `data-*` attributes and `style.*` attributes to be applied to the generated DOM nodes. This is useful for passing data to the EventCatcherWidget * <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7849">> [[jsonextract Operator]], [[jsonget Operator]], [[jsonset Operator]] and [[jsontype Operator]] to allow negative indexes into arrays to be counted from the end of the array * <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7690">> the default page layout to better support CSS grid and flexbox layouts -* <<.link-bage-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7787">> the editor to use grid layout, simplifying customisation +* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7787">> the editor to use grid layout, simplifying customisation ! Bug Fixes @@ -132,7 +132,7 @@ Improvements to the following translations: ! Node.js Improvements -* <> a significant flaw in the synchronisation algorithm used by the client-server configuration. The flaw could lead to tiddlers temporarily disappearing from the browser +* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7843">> a significant flaw in the synchronisation algorithm used by the client-server configuration. The flaw could lead to tiddlers temporarily disappearing from the browser ! Performance Improvements From 3b84088b27b33d8e2057e52f0cc6810f100c667e Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 28 Nov 2023 11:44:21 +0000 Subject: [PATCH 043/105] Syncer: Reduce logging intensity --- core/modules/syncer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 58b087b8d..12781ad5a 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -425,7 +425,7 @@ Syncer.prototype.processTaskQueue = function() { if((!this.syncadaptor.isReady || this.syncadaptor.isReady()) && this.numTasksInProgress === 0) { // Choose the next task to perform var task = this.chooseNextTask(); - self.logger.log("Chosen next task " + task); + // self.logger.log("Chosen next task " + task); // Perform the task if we had one if(typeof task === "object" && task !== null) { this.numTasksInProgress += 1; @@ -551,14 +551,14 @@ SaveTiddlerTask.prototype.run = function(callback) { revision: revision, timestampLastSaved: new Date() }; - self.syncer.logger.log("Updating tiddler info in SaveTiddlerTask.run for " + self.title + " " + JSON.stringify(self.syncer.tiddlerInfo[self.title])); + // self.syncer.logger.log("Updating tiddler info in SaveTiddlerTask.run for " + self.title + " " + JSON.stringify(self.syncer.tiddlerInfo[self.title])); // Invoke the callback callback(null); },{ tiddlerInfo: self.syncer.tiddlerInfo[self.title] }); } else { - this.syncer.logger.log(" Not Dispatching 'save' task:",this.title,"tiddler does not exist"); + // this.syncer.logger.log(" Not Dispatching 'save' task:",this.title,"tiddler does not exist"); $tw.utils.nextTick(callback(null)); } }; @@ -582,7 +582,7 @@ DeleteTiddlerTask.prototype.run = function(callback) { return callback(err); } // Remove the info stored about this tiddler - self.syncer.logger.log("Deleting tiddler info in DeleteTiddlerTask.run for " + self.title); + // self.syncer.logger.log("Deleting tiddler info in DeleteTiddlerTask.run for " + self.title); delete self.syncer.tiddlerInfo[self.title]; // Invoke the callback callback(null); @@ -659,7 +659,7 @@ SyncFromServerTask.prototype.run = function(callback) { } else if(this.syncer.syncadaptor.getSkinnyTiddlers) { this.syncer.logger.log("Retrieving skinny tiddler list"); this.syncer.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) { - self.syncer.logger.log("Retrieved skinny tiddler list"); + // self.syncer.logger.log("Retrieved skinny tiddler list"); // Check for errors if(err) { self.syncer.displayError($tw.language.getString("Error/RetrievingSkinny"),err); From 53d493b8766b4bb28fd3c3b1d75d40e330032e5b Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 28 Nov 2023 11:51:56 +0000 Subject: [PATCH 044/105] Conditional shortcut docs: highlight use of "condition" variable --- .../tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid b/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid index 6cdfb1517..3ea99433e 100644 --- a/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid +++ b/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki <<.from-version "5.3.2">> The conditional shortcut syntax provides a convenient way to express if-then-else logic within WikiText. It evaluates a filter and considers the condition to be true if there is at least one result (regardless of the value of that result). +Within an "if" or "elseif" clause, the variable `condition` contains the value of the first result of evaluating the filter condition. + A simple example: <$macrocall $name='wikitext-example-without-html' @@ -55,7 +57,6 @@ src='\procedure test(animal) Notes: * Clauses are parsed in inline mode by default. Force block mode parsing by following the opening `<% if %>`, `<% elseif %>` or `<% else %>` with two line breaks -* Within an "if" or "elseif" clause, the variable `condition` contains the value of the first result of evaluating the filter condition * Widgets and HTML elements must be within a single conditional clause; it is not possible to start an element in one conditional clause and end it in another * The conditional shortcut syntax cannot contain pragmas such as procedure definitions From c2e61fffe0fd2cb0abbff377cf72c211e02363b5 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Tue, 28 Nov 2023 14:49:13 +0100 Subject: [PATCH 045/105] German translations (#7864) --- languages/de-DE/Exporters.multids | 2 +- languages/de-DE/Help/commands.tid | 4 ++-- languages/de-DE/Help/server.tid | 2 +- languages/de-DE/Types/image_x-icon.tid | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/de-DE/Exporters.multids b/languages/de-DE/Exporters.multids index 6103f370d..6663dd17b 100644 --- a/languages/de-DE/Exporters.multids +++ b/languages/de-DE/Exporters.multids @@ -3,4 +3,4 @@ title: $:/language/Exporters/ StaticRiver: HTML - Statisch JsonFile: JSON - Format CsvFile: CSV - Format -TidFile: .tid - Format +TidFile: TID - Text Format diff --git a/languages/de-DE/Help/commands.tid b/languages/de-DE/Help/commands.tid index b7de1b86f..55aefa16e 100644 --- a/languages/de-DE/Help/commands.tid +++ b/languages/de-DE/Help/commands.tid @@ -1,7 +1,7 @@ title: $:/language/Help/commands description: Ausführen von Befehlen aus einem Tiddler -Sequentielle Abarbeitung von Befehlen aus einem Tiddler. +Sequentielle Abarbeitung von Befehlen aus einem Tiddler. ``` --commands @@ -9,6 +9,6 @@ Sequentielle Abarbeitung von Befehlen aus einem Tiddler. Beispiele -`--commands "[enlist{$:/build-commands-as-text}]"` +`--commands "[enlist:raw{$:/build-commands-as-text}]"` `--commands "[{$:/build-commands-as-json}jsonindexes[]] :map[{$:/build-commands-as-json}jsonget]"` \ No newline at end of file diff --git a/languages/de-DE/Help/server.tid b/languages/de-DE/Help/server.tid index 94b40acc6..2bfbbdb47 100644 --- a/languages/de-DE/Help/server.tid +++ b/languages/de-DE/Help/server.tid @@ -1,5 +1,5 @@ title: $:/language/Help/server -description: Stellt einen HTTP server für TiddlyWiki zur Verfügung. (Dieser Befehl ist abgekündigt! - Neu ist: "listen") +description: (Dieser Befehl ist abgekündigt! - Neu ist: "listen") -- Stellt einen HTTP server für TiddlyWiki zur Verfügung. TiddlyWiki bringt einen einfachen Web-Server mit. diff --git a/languages/de-DE/Types/image_x-icon.tid b/languages/de-DE/Types/image_x-icon.tid index d75ef6fad..043071d97 100644 --- a/languages/de-DE/Types/image_x-icon.tid +++ b/languages/de-DE/Types/image_x-icon.tid @@ -1,4 +1,4 @@ title: $:/language/Docs/Types/image/x-icon -description: ICO - Piktogramm Format +description: ICO - Piktogramm (Icon) name: image/x-icon group: Bilder From 5dc468f1eae62b5656087cf4106ea60a46690466 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 28 Nov 2023 17:43:57 +0000 Subject: [PATCH 046/105] Fix release note typo Apologies again @oflg --- editions/prerelease/tiddlers/Release 5.3.2.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index ce1338ba0..fcf9a5844 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -165,7 +165,7 @@ joebordes kookma linonetwo mateuszwilczek -oflig +oflg pille1842 pmario rmunn From b08281a20b890b4137fa8fb1e8dd4fecd4bea4ce Mon Sep 17 00:00:00 2001 From: Mateusz Wilczek <36714554+mateuszwilczek@users.noreply.github.com> Date: Wed, 29 Nov 2023 10:01:46 +0100 Subject: [PATCH 047/105] Improve `jsonstringify` and `stringify` operators docs: part 2 (#7748) --- .../jsonstringify Operator (Examples).tid | 11 ++++++++ .../stringify_Operator_(Examples).tid | 6 +++-- .../filters/jsonstringify Operator.tid | 27 +++++++++++++++++-- .../tiddlers/filters/stringify_Operator.tid | 19 ++++++------- .../howtos/Constructing JSON tiddlers.tid | 4 +-- 5 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid diff --git a/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid new file mode 100644 index 000000000..39113ea38 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid @@ -0,0 +1,11 @@ +created: 20230922121858167 +modified: 20230922122333325 +tags: [[Operator Examples]] [[jsonstringify Operator]] +title: jsonstringify Operator (Examples) +type: text/vnd.tiddlywiki + +Compare the encoding of quotes and control characters in the first example with the analogue [[example for the stringify operator|stringify Operator (Examples)]]. +<<.operator-example 1 """[[Backslash \, double quote ", single quote ', tab , line feed +]] +[jsonstringify[]]""">> +<<.operator-example 2 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 without suffix]] +[jsonstringify[]]""">> +<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[jsonstringify:rawunicode[]]""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid b/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid index cc5a51429..4b67993b0 100644 --- a/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid @@ -1,9 +1,11 @@ created: 20161017154944352 -modified: 20230919124059118 +modified: 20230922122319674 tags: [[Operator Examples]] [[stringify Operator]] title: stringify Operator (Examples) type: text/vnd.tiddlywiki -<<.operator-example 1 """[[Title with "double quotes" and single ' and \backslash]] +[stringify[]]""">> +Compare the encoding of quotes and control characters in the first example with the analogue [[example for the jsonstringify operator|jsonstringify Operator (Examples)]]. +<<.operator-example 1 """[[Backslash \, double quote ", single quote ', tab , line feed +]] +[stringify[]]""">> <<.operator-example 2 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 without suffix]] +[stringify[]]""">> <<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[stringify:rawunicode[]]""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid b/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid index 748a851bb..edd48432a 100644 --- a/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid +++ b/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid @@ -1,12 +1,35 @@ caption: jsonstringify created: 20171029155051467 from-version: 5.1.14 -modified: 20230919124826880 +modified: 20230922121404577 +op-input: a [[selection of titles|Title Selection]] +op-output: the input with JSON string encodings applied op-parameter: op-parameter-name: -op-purpose: deprecated, use <<.olink stringify>> instead +op-purpose: apply JSON string encoding to a string, see also the similar <<.olink stringify>> +op-suffix: <<.from-version "5.1.23">> optionally, the keyword `rawunicode` op-suffix-name: R tags: [[Filter Operators]] [[String Operators]] title: jsonstringify Operator type: text/vnd.tiddlywiki +The following substitutions are made: + +|!Character |!Replacement |!Condition | +|`\` |`\\` |Always | +|`"` |`\"` |Always | +|Carriage return (0x0d) |`\r` |Always | +|Line feed (0x0a) |`\n` |Always | +|Backspace (0x08) |`\b` |Always | +|Form field (0x0c) |`\f` |Always | +|Tab (0x09) |`\t` |Always| +|Characters from 0x00 to 0x1f, except listed above |`\u####` where #### is four hex digits |Always | +|Characters from from 0x80 to 0xffff|`\u####` where #### is four hex digits |If `rawunicode` suffix is not present (default) | +|Characters from 0x80 to 0xffff|<<.from-version "5.1.23">> Unchanged |If `rawunicode` suffix is present | + +<<.from-version "5.1.23">> If the suffix `rawunicode` is present, Unicode characters above 0x80 (such as ß, ä, ñ or 🎄) will be passed through unchanged. Without the suffix, they will be substituted with `\u` codes, which was the default behavior before 5.1.23. Characters outside the Basic Multilingual Plane, such as 🎄 and other emojis, will be encoded as a UTF-16 surrogate pair, i.e. with two `\u` sequences. + +<<.note """Mind the differences compared to <<.olink stringify>> in encoding of single quotes and control characters (0x00 to 0x1f). +""">> + +<<.operator-examples "jsonstringify">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/stringify_Operator.tid b/editions/tw5.com/tiddlers/filters/stringify_Operator.tid index 73dabb1c2..6178517f7 100644 --- a/editions/tw5.com/tiddlers/filters/stringify_Operator.tid +++ b/editions/tw5.com/tiddlers/filters/stringify_Operator.tid @@ -1,12 +1,12 @@ caption: stringify created: 20161017153038029 from-version: 5.1.14 -modified: 20230919130847809 +modified: 20230922121406947 op-input: a [[selection of titles|Title Selection]] op-output: the input with ~JavaScript string encodings applied op-parameter: op-parameter-name: -op-purpose: apply ~JavaScript string encoding to a string +op-purpose: apply ~JavaScript string encoding to a string, see also the similar <<.olink jsonstringify>> op-suffix: <<.from-version "5.1.23">> optionally, the keyword `rawunicode` op-suffix-name: R tags: [[Filter Operators]] [[String Operators]] @@ -18,19 +18,16 @@ The following substitutions are made: |!Character |!Replacement |!Condition | |`\` |`\\` |Always | |`"` |`\"` |Always | -|Carriage return (0x0d) |`\r` |Always | +|`'` |`\'` |Always | |Line feed (0x0a) |`\n` |Always | -|Backspace (0x08) |`\b` |Always | -|Form field (0x0c) |`\f` |Always | -|Tab (0x09) |`\t` |Always | -|Characters from 0x00 to 0x1f |`\x##` where ## is two hex digits |Always | +|Carriage return (0x0d) |`\r` |Always | +|Characters from 0x00 to 0x1f, except listed above |`\x##` where ## is two hex digits |Always | |Characters from 0x80 to 0xffff|`\u####` where #### is four hex digits |If `rawunicode` suffix is not present (default) | |Characters from 0x80 to 0xffff|<<.from-version "5.1.23">> Unchanged |If `rawunicode` suffix is present | -<<.from-version "5.1.23">> If the suffix `rawunicode` is present, Unicode characters above 0x80 (such as ß, ä, ñ or 🎄) will be passed through unchanged. Without the suffix, they will be substituted with `\u` codes, which was the default behavior before 5.1.23. +<<.from-version "5.1.23">> If the suffix `rawunicode` is present, Unicode characters above 0x80 (such as ß, ä, ñ or 🎄) will be passed through unchanged. Without the suffix, they will be substituted with `\u` codes, which was the default behavior before 5.1.23. Characters outside the Basic Multilingual Plane, such as 🎄 and other emojis, will be encoded as a UTF-16 surrogate pair, i.e. with two `\u` sequences. -<<.note """Characters outside the Basic Multilingual Plane, such as 🎄 and other emojis, will be encoded as a UTF-16 surrogate pair, i.e. with two `\u` sequences.""">> - -<<.olink jsonstringify>> is considered deprecated, as it duplicates the functionality of <<.op stringify>>. +<<.note """Mind the differences compared to <<.olink jsonstringify>> in encoding of single quotes and control characters (0x00 to 0x1f). +""">> <<.operator-examples "stringify">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/howtos/Constructing JSON tiddlers.tid b/editions/tw5.com/tiddlers/howtos/Constructing JSON tiddlers.tid index ff4c7927c..93d78ac16 100644 --- a/editions/tw5.com/tiddlers/howtos/Constructing JSON tiddlers.tid +++ b/editions/tw5.com/tiddlers/howtos/Constructing JSON tiddlers.tid @@ -1,5 +1,5 @@ created: 20220427174702859 -modified: 20230809113620964 +modified: 20230922122551197 tags: [[JSON in TiddlyWiki]] Learning title: Constructing JSON tiddlers @@ -13,4 +13,4 @@ At a high level, we have several ways to generate JSON data in TiddlyWiki's own * [[jsontiddler Macro]] * [[jsontiddlers Macro]] -When constructing JSON data manually, the [[stringify Operator]] is needed to ensure that any special characters are properly escaped. +When constructing JSON data manually, the [[jsonstringify Operator]] is needed to ensure that any special characters are properly escaped. From fe17f16675431af8ab84e5847736db845c2c6865 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 09:31:19 +0000 Subject: [PATCH 048/105] Fix syncer not exiting when used on CLI Fixes #7867 --- core/modules/syncer.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 12781ad5a..66beaf591 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -189,7 +189,7 @@ Syncer.prototype.readTiddlerInfo = function() { // Record information for known tiddlers var self = this, tiddlers = this.getSyncedTiddlers(); - this.logger.log("Initialising tiddlerInfo for " + tiddlers.length + " tiddlers"); + // this.logger.log("Initialising tiddlerInfo for " + tiddlers.length + " tiddlers"); $tw.utils.each(tiddlers,function(title) { var tiddler = self.wiki.getTiddler(title); if(tiddler) { @@ -302,10 +302,16 @@ Syncer.prototype.getStatus = function(callback) { Synchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date */ Syncer.prototype.syncFromServer = function() { - this.forceSyncFromServer = true; - this.processTaskQueue(); + if(this.canSyncFromServer()) { + this.forceSyncFromServer = true; + this.processTaskQueue(); + } }; +Syncer.prototype.canSyncFromServer = function() { + return !!this.syncadaptor.getUpdatedTiddlers || !!this.syncadaptor.getSkinnyTiddlers; +} + /* Force load a tiddler from the server */ @@ -447,7 +453,7 @@ Syncer.prototype.processTaskQueue = function() { // And trigger a timeout if there is a pending task if(task === true) { this.triggerTimeout(this.taskTimerInterval); - } else { + } else if(this.canSyncFromServer()) { this.triggerTimeout(this.pollTimerInterval); } } From fc1e9b6c434b774159dbbe77b17075526bd6d293 Mon Sep 17 00:00:00 2001 From: Mateusz Wilczek <36714554+mateuszwilczek@users.noreply.github.com> Date: Wed, 29 Nov 2023 11:06:47 +0100 Subject: [PATCH 049/105] Update forum link in update wizard (#7865) * Update forum link in upgrade wizard * Update links to forum in es-ES and de-AT editons --- editions/de-AT/tiddlers/HelloThere.tid | 4 ++-- editions/de-AT/tiddlers/community/Fur_Entwickler.tid | 2 +- editions/es-ES/tiddlers/Forums.tid | 9 ++++----- editions/es-ES/tiddlers/HelloThere.tid | 4 ++-- editions/es-ES/tiddlers/Typography.tid | 2 +- plugins/tiddlywiki/upgrade/UpgradeWizard.tid | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/editions/de-AT/tiddlers/HelloThere.tid b/editions/de-AT/tiddlers/HelloThere.tid index 60c2147f8..aa8bf52e7 100644 --- a/editions/de-AT/tiddlers/HelloThere.tid +++ b/editions/de-AT/tiddlers/HelloThere.tid @@ -21,8 +21,8 @@ Willkommen bei ''~TiddlyWiki'', dem einzigartigen [[nicht-linearen|Philosophy vo Anders, als bei herkömmlichen Online-Diensten, lässt Ihnen ~TiddlyWiki die Freiheit, wo sie ihre Daten speichern. Da ~TiddlyWiki alle Daten als simplen Text speichert, sind Notizen, die Sie heute machen, garantiert in Jahrzehnten noch einfach lesbar.
    - -{{$:/core/images/mail}} ~TiddlyWiki Mailing List + +{{$:/core/images/help}} ~TiddlyWiki Forum {{$:/core/images/twitter}} @~TiddlyWiki on Twitter diff --git a/editions/de-AT/tiddlers/community/Fur_Entwickler.tid b/editions/de-AT/tiddlers/community/Fur_Entwickler.tid index 0c656c8dc..2dbc185d7 100644 --- a/editions/de-AT/tiddlers/community/Fur_Entwickler.tid +++ b/editions/de-AT/tiddlers/community/Fur_Entwickler.tid @@ -7,5 +7,5 @@ type: text/vnd.tiddlywiki Es gibt mehrere Ressourcen für Entwickler, um mehr über das TiddlyWiki Projekt zu erfahren, zu diskutieren und vor allem mitzuhelfen. * [[tiddlywiki.com/dev|https://tiddlywiki.com/dev]] Offizielle Entwickler Doku. -* [[TiddlyWikiDev group|http://groups.google.com/group/TiddlyWikiDev]] Google Diskussionsforum für Entwickler. +* [[TiddlyWikiDev group|https://talk.tiddlywiki.org/c/devs/]] Diskussionsforum für Entwickler. * https://github.com/Jermolene/TiddlyWiki5 .. Github Repository. diff --git a/editions/es-ES/tiddlers/Forums.tid b/editions/es-ES/tiddlers/Forums.tid index 63ecc4339..57af7d0f2 100644 --- a/editions/es-ES/tiddlers/Forums.tid +++ b/editions/es-ES/tiddlers/Forums.tid @@ -12,7 +12,9 @@ Son listas de correo en las que hablamos de ~TiddlyWiki: pedimos ayuda, anunciam Puedes participar a través de la página web asociada, o suscribirte via mail. -!!Usuarios +!! Usuarios + +[[Foro oficial de TiddlyWiki| https://talk.tiddlywiki.org/]] [[Grupo principal de TiddlyWiki| http://groups.google.com/group/TiddlyWiki]] @@ -25,10 +27,7 @@ o síguenos [[en Twitter|http://twitter.com/TiddlyWiki]] si quieres recibir las !! Desarrolladores -[[Grupo de desarrollo de TiddlyWiki|http://groups.google.com/group/TiddlyWikiDev]] - ->No necesitas tener cuenta en Google para acceder al grupo. Suscríbete igualmente enviando un mail a: -*mailto:tiddlywikidev+subscribe@googlegroups.com. +[[Foro de desarrollo de TiddlyWiki|https://talk.tiddlywiki.org/c/devs]] Accede a nuestra [[página de desarrollo|https://github.com/Jermolene/TiddlyWiki5]] en GitHub y haz tu contribución. diff --git a/editions/es-ES/tiddlers/HelloThere.tid b/editions/es-ES/tiddlers/HelloThere.tid index 0b1cea4bb..c08a27e7d 100644 --- a/editions/es-ES/tiddlers/HelloThere.tid +++ b/editions/es-ES/tiddlers/HelloThere.tid @@ -20,8 +20,8 @@ BIenvenido a TiddlyWiki, un bloc de notas [[no lineal|Philosophy of Tiddlers]] Al revés que los servicios online convencionales, TiddlyWiki te deja escoger dónde quieres guardar tus datos, garantizándote que, por más que pase el tiempo, podrás seguir usando en el futuro las notas que tomes hoy.
    - -{{$:/core/images/mail}} ~TiddlyWiki en Google Groups + +{{$:/core/images/mail}} Foro oficial de ~TiddlyWiki {{$:/core/images/video}} ~TiddlyWiki en ~YouTube diff --git a/editions/es-ES/tiddlers/Typography.tid b/editions/es-ES/tiddlers/Typography.tid index 58edf9220..47d3a05ce 100644 --- a/editions/es-ES/tiddlers/Typography.tid +++ b/editions/es-ES/tiddlers/Typography.tid @@ -8,7 +8,7 @@ type: text/vnd.tiddlywiki Se recomienda el uso de las [[macros de documentación|Documentation Macros]] para facilitar las futuras tareas de mantenimiento del texto frente a nuevos cambios y actualizaciones. -Se recomienda precaución en el uso arbitrario de estilos directos de formato (''negrita'', //cursiva// ...etc). Si se puede usar una macro, conviene usarla. Si no existe la macro adecuada, se puede crear o, si no se sabe cómo, pedir su creación en el [[Grupo de Google|http://groups.google.com/group/TiddlyWiki]]. +Se recomienda precaución en el uso arbitrario de estilos directos de formato (''negrita'', //cursiva// ...etc). Si se puede usar una macro, conviene usarla. Si no existe la macro adecuada, se puede crear o, si no se sabe cómo, pedir su creación en el [[Foro de TiddlyWiki|https://talk.tiddlywiki.org/]]. Por el mismo motivo, se aconseja el uso de acentos graves `...` para transcribir fragmentos de código y ~WikiText, pero no para nombres de cosas tales como campos, operadores, variables o widgets. Estas tienen su macro correspondiente. diff --git a/plugins/tiddlywiki/upgrade/UpgradeWizard.tid b/plugins/tiddlywiki/upgrade/UpgradeWizard.tid index 922441bd6..8e398156a 100644 --- a/plugins/tiddlywiki/upgrade/UpgradeWizard.tid +++ b/plugins/tiddlywiki/upgrade/UpgradeWizard.tid @@ -44,7 +44,7 @@ Make sure that you keep a safe copy of your previous ~TiddlyWiki file. Close this browser window to prevent others from being able to access your data. -For help and support, visit [[the TiddlyWiki discussion forum|http://groups.google.com/group/TiddlyWiki]]. +For help and support, visit [[the TiddlyWiki discussion forum|https://talk.tiddlywiki.org]]. From f56f5dcc5655563cda7928aea7f65359857024fd Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 11:23:57 +0000 Subject: [PATCH 050/105] Fix savetiddlers handling of tiddlers with no text field --- core/modules/commands/savetiddlers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/commands/savetiddlers.js b/core/modules/commands/savetiddlers.js index d3b82d726..9c750e204 100644 --- a/core/modules/commands/savetiddlers.js +++ b/core/modules/commands/savetiddlers.js @@ -46,7 +46,7 @@ Command.prototype.execute = function() { type = tiddler.fields.type || "text/vnd.tiddlywiki", contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"}, filename = path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title)); - fs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding); + fs.writeFileSync(filename,tiddler.fields.text || "",contentTypeInfo.encoding); }); return null; }; From 622512c380e5855fb5bba5d01119c2749e8e2618 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 11:24:54 +0000 Subject: [PATCH 051/105] Further reduce syncer logging The rationale is that the deeper logs are only useful for debugging the syncer logic, and are overwhelming for most users --- core/modules/syncer.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 66beaf591..9769d9674 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -189,7 +189,6 @@ Syncer.prototype.readTiddlerInfo = function() { // Record information for known tiddlers var self = this, tiddlers = this.getSyncedTiddlers(); - // this.logger.log("Initialising tiddlerInfo for " + tiddlers.length + " tiddlers"); $tw.utils.each(tiddlers,function(title) { var tiddler = self.wiki.getTiddler(title); if(tiddler) { @@ -236,7 +235,6 @@ Syncer.prototype.isDirty = function() { return false; } var dirtyStatus = checkIsDirty(); - this.logger.log("Dirty status was " + dirtyStatus); return dirtyStatus; }; @@ -266,7 +264,6 @@ Syncer.prototype.storeTiddler = function(tiddlerFields) { adaptorInfo: this.syncadaptor.getTiddlerInfo(tiddler), changeCount: this.wiki.getChangeCount(tiddlerFields.title) }; - this.logger.log("Updating tiddler info in syncer.storeTiddler for " + tiddlerFields.title + " " + JSON.stringify(this.tiddlerInfo[tiddlerFields.title])); }; Syncer.prototype.getStatus = function(callback) { @@ -431,7 +428,6 @@ Syncer.prototype.processTaskQueue = function() { if((!this.syncadaptor.isReady || this.syncadaptor.isReady()) && this.numTasksInProgress === 0) { // Choose the next task to perform var task = this.chooseNextTask(); - // self.logger.log("Chosen next task " + task); // Perform the task if we had one if(typeof task === "object" && task !== null) { this.numTasksInProgress += 1; @@ -557,14 +553,12 @@ SaveTiddlerTask.prototype.run = function(callback) { revision: revision, timestampLastSaved: new Date() }; - // self.syncer.logger.log("Updating tiddler info in SaveTiddlerTask.run for " + self.title + " " + JSON.stringify(self.syncer.tiddlerInfo[self.title])); // Invoke the callback callback(null); },{ tiddlerInfo: self.syncer.tiddlerInfo[self.title] }); } else { - // this.syncer.logger.log(" Not Dispatching 'save' task:",this.title,"tiddler does not exist"); $tw.utils.nextTick(callback(null)); } }; @@ -588,7 +582,6 @@ DeleteTiddlerTask.prototype.run = function(callback) { return callback(err); } // Remove the info stored about this tiddler - // self.syncer.logger.log("Deleting tiddler info in DeleteTiddlerTask.run for " + self.title); delete self.syncer.tiddlerInfo[self.title]; // Invoke the callback callback(null); @@ -642,7 +635,6 @@ SyncFromServerTask.prototype.run = function(callback) { callback(null); }; if(this.syncer.syncadaptor.getUpdatedTiddlers) { - self.syncer.logger.log("Retrieving updated tiddler list"); this.syncer.syncadaptor.getUpdatedTiddlers(self,function(err,updates) { if(err) { self.syncer.displayError($tw.language.getString("Error/RetrievingSkinny"),err); @@ -663,9 +655,7 @@ SyncFromServerTask.prototype.run = function(callback) { return successCallback(); }); } else if(this.syncer.syncadaptor.getSkinnyTiddlers) { - this.syncer.logger.log("Retrieving skinny tiddler list"); this.syncer.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) { - // self.syncer.logger.log("Retrieved skinny tiddler list"); // Check for errors if(err) { self.syncer.displayError($tw.language.getString("Error/RetrievingSkinny"),err); From c282208668ee89af07b81cf93a21ba68430affc0 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 12:06:40 +0000 Subject: [PATCH 052/105] Fix jsonset crash when applied to primitive types See https://talk.tiddlywiki.org/t/final-checks-before-release-of-v5-3-2/8560/7 --- core/modules/filters/json-ops.js | 5 ++++- editions/test/tiddlers/tests/test-json-filters.js | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/modules/filters/json-ops.js b/core/modules/filters/json-ops.js index 75a34e94a..0c58964eb 100644 --- a/core/modules/filters/json-ops.js +++ b/core/modules/filters/json-ops.js @@ -273,7 +273,10 @@ function setDataItem(data,indexes,value) { lastIndex = $tw.utils.parseInt(lastIndex); if(lastIndex < 0) { lastIndex = lastIndex + current.length }; } - current[lastIndex] = value; + // Only set indexes on objects and arrays + if(typeof current === "object") { + current[lastIndex] = value; + } return data; } diff --git a/editions/test/tiddlers/tests/test-json-filters.js b/editions/test/tiddlers/tests/test-json-filters.js index a8903970a..bfb8a4504 100644 --- a/editions/test/tiddlers/tests/test-json-filters.js +++ b/editions/test/tiddlers/tests/test-json-filters.js @@ -124,6 +124,7 @@ describe("json filter tests", function() { }); it("should support the jsonset operator", function() { + expect(wiki.filterTiddlers("[jsonset[a],[aa]]")).toEqual(['"First"','"Second"','"Third"']); expect(wiki.filterTiddlers("[{First}jsonset[]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); expect(wiki.filterTiddlers("[{First}jsonset[],[Antelope]]")).toEqual(['"Antelope"']); expect(wiki.filterTiddlers("[{First}jsonset:number[],[not a number]]")).toEqual(['0']); From 6b47cbed32005382b274525f76fb8323ed2cfdb4 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 14:36:58 +0000 Subject: [PATCH 053/105] Scrollable: write bound value if title of bound tiddler changes Thanks @yaisog --- core/modules/widgets/scrollable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index 58597461b..7733308a8 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -183,7 +183,7 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { "scroll-left": self.outerDomNode.scrollLeft.toString(), "scroll-top": self.outerDomNode.scrollTop.toString() }; - if(!existingTiddler || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { + if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); } }); From c61c34e9df09bab7215a4c0b7a5c04d239341088 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 14:45:34 +0000 Subject: [PATCH 054/105] Debounce scrollable widget scroll handler --- core/modules/widgets/scrollable.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index 7733308a8..c2acc563d 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -176,16 +176,23 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { // After a delay for rendering, scroll to the bound position setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); // Save scroll position on DOM scroll event + var timeout; this.outerDomNode.addEventListener("scroll",function(event) { - var existingTiddler = self.wiki.getTiddler(self.scrollableBind), - newTiddlerFields = { - title: self.scrollableBind, - "scroll-left": self.outerDomNode.scrollLeft.toString(), - "scroll-top": self.outerDomNode.scrollTop.toString() - }; - if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { - self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); + if(timeout) { + window.cancelAnimationFrame(timeout); + timeout = null; } + timeout = window.requestAnimationFrame(function() { + var existingTiddler = self.wiki.getTiddler(self.scrollableBind), + newTiddlerFields = { + title: self.scrollableBind, + "scroll-left": self.outerDomNode.scrollLeft.toString(), + "scroll-top": self.outerDomNode.scrollTop.toString() + }; + if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { + self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); + } + }); }); } }; From f7359671aa827c868b896def60fe2e903dd974e9 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 29 Nov 2023 18:06:54 +0000 Subject: [PATCH 055/105] Defer scrollable widget updating bound tiddler for 100ms See discussion https://talk.tiddlywiki.org/t/5-3-2pre-scroll-binding/8570/3?u=jeremyruston --- core/modules/widgets/scrollable.js | 8 +++++--- editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index c2acc563d..b77d6a12b 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -12,6 +12,8 @@ Scrollable widget /*global $tw: false */ "use strict"; +var DEBOUNCE_INTERVAL = 100; // Delay after last scroll event before updating the bound tiddler + var Widget = require("$:/core/modules/widgets/widget.js").widget; var ScrollableWidget = function(parseTreeNode,options) { @@ -179,10 +181,10 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { var timeout; this.outerDomNode.addEventListener("scroll",function(event) { if(timeout) { - window.cancelAnimationFrame(timeout); + clearTimeout(timeout); timeout = null; } - timeout = window.requestAnimationFrame(function() { + timeout = setTimeout(function() { var existingTiddler = self.wiki.getTiddler(self.scrollableBind), newTiddlerFields = { title: self.scrollableBind, @@ -192,7 +194,7 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); } - }); + },DEBOUNCE_INTERVAL); }); } }; diff --git a/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid b/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid index d31eb6e31..6c52f0025 100644 --- a/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ScrollableWidget.tid @@ -18,7 +18,7 @@ The content of the `<$scrollable>` widget is displayed within a pair of wrapper |fallthrough |See below | |bind |<<.from-version "5.3.2">> Optional title of tiddler to which the scroll position should be bound | -Binding the scroll position to a tiddler automatically copies the scroll coordinates into the `scroll-left` and `scroll-top` fields as scrolling occurs. Conversely, setting those field values will automatically cause the scrollable to scroll if it can. +Binding the scroll position to a tiddler automatically copies the scroll coordinates into the `scroll-left` and `scroll-top` fields after scrolling occurs. Conversely, setting those field values will automatically cause the scrollable to scroll if it can. <$macrocall $name=".note" _="""If a scrollable widget can't handle the `tm-scroll` message because the inner DIV fits within the outer DIV, then by default the message falls through to the parent widget. Setting the ''fallthrough'' attribute to `no` prevents this behaviour."""/> From e60ddf0b0ab668201997b06c64b94577673622a6 Mon Sep 17 00:00:00 2001 From: yaisog Date: Thu, 30 Nov 2023 19:26:26 +0100 Subject: [PATCH 056/105] Handle switching the bound tiddler (#7868) --- core/modules/widgets/scrollable.js | 53 ++++++++++++++++++------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index b77d6a12b..f6cb5e67b 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -177,28 +177,28 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { if(this.scrollableBind) { // After a delay for rendering, scroll to the bound position setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); - // Save scroll position on DOM scroll event - var timeout; - this.outerDomNode.addEventListener("scroll",function(event) { - if(timeout) { - clearTimeout(timeout); - timeout = null; - } - timeout = setTimeout(function() { - var existingTiddler = self.wiki.getTiddler(self.scrollableBind), - newTiddlerFields = { - title: self.scrollableBind, - "scroll-left": self.outerDomNode.scrollLeft.toString(), - "scroll-top": self.outerDomNode.scrollTop.toString() - }; - if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { - self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); - } - },DEBOUNCE_INTERVAL); - }); + // Set up event listener + this.currentListener = this.listenerFunction.bind(this); + this.outerDomNode.addEventListener("scroll", this.currentListener); } }; +ScrollableWidget.prototype.listenerFunction = function(event) { + self = this; + clearTimeout(this.timeout); + this.timeout = setTimeout(function() { + var existingTiddler = self.wiki.getTiddler(self.scrollableBind), + newTiddlerFields = { + title: self.scrollableBind, + "scroll-left": self.outerDomNode.scrollLeft.toString(), + "scroll-top": self.outerDomNode.scrollTop.toString() + }; + if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { + self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); + } + }, DEBOUNCE_INTERVAL); +} + ScrollableWidget.prototype.updateScrollPositionFromBoundTiddler = function() { // Bail if we're running on the fakedom if(!this.outerDomNode.scrollTo) { @@ -243,8 +243,19 @@ ScrollableWidget.prototype.refresh = function(changedTiddlers) { this.refreshSelf(); return true; } - if(changedAttributes.bind || changedTiddlers[this.getAttribute("bind")]) { - this.updateScrollPositionFromBoundTiddler(); + // If the bound tiddler has changed, update the eventListener and update scroll position + if(changedAttributes["bind"]) { + if(this.currentListener) { + this.outerDomNode.removeEventListener("scroll", this.currentListener, false); + } + this.scrollableBind = this.getAttribute("bind"); + this.currentListener = this.listenerFunction.bind(this); + this.outerDomNode.addEventListener("scroll", this.currentListener); + setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); + } + // If a new scroll position was written into the tiddler, update scroll position + if(changedTiddlers[this.getAttribute("bind")]) { + setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); } return this.refreshChildren(changedTiddlers); }; From 4e67aafeb784265a8304f6de976089cdd106e9bf Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Sat, 2 Dec 2023 08:58:35 +0000 Subject: [PATCH 057/105] Scrollable hotfix: Avoid setTimeout See #7869 --- core/modules/widgets/scrollable.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index f6cb5e67b..227c455c3 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -176,7 +176,7 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { // If the scroll position is bound to a tiddler if(this.scrollableBind) { // After a delay for rendering, scroll to the bound position - setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); + this.updateScrollPositionFromBoundTiddler(); // Set up event listener this.currentListener = this.listenerFunction.bind(this); this.outerDomNode.addEventListener("scroll", this.currentListener); @@ -251,13 +251,14 @@ ScrollableWidget.prototype.refresh = function(changedTiddlers) { this.scrollableBind = this.getAttribute("bind"); this.currentListener = this.listenerFunction.bind(this); this.outerDomNode.addEventListener("scroll", this.currentListener); - setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); } - // If a new scroll position was written into the tiddler, update scroll position - if(changedTiddlers[this.getAttribute("bind")]) { - setTimeout(this.updateScrollPositionFromBoundTiddler.bind(this),50); + // Refresh children + var result = this.refreshChildren(changedTiddlers); + // If the bound tiddler has changed, update scroll position + if(changedAttributes["bind"] || changedTiddlers[this.getAttribute("bind")]) { + this.updateScrollPositionFromBoundTiddler(); } - return this.refreshChildren(changedTiddlers); + return result; }; exports.scrollable = ScrollableWidget; From 155db0f6f8a7bf65cdc2030b6f489915a82c13d1 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Mon, 4 Dec 2023 08:13:23 +0000 Subject: [PATCH 058/105] Improve release note --- editions/prerelease/tiddlers/Release 5.3.2.tid | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index fcf9a5844..e1194c06c 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -12,7 +12,9 @@ description: Under development !! Conditional Shortcut Syntax -<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7710">> a new [[shortcut syntax|Conditional Shortcut Syntax]] for concisely expressing if-then-else logic. For example: +<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7710">> a new [[shortcut syntax|Conditional Shortcut Syntax]] for concisely expressing if-then-else logic. This is the first of a new type of wikitext syntax based on tokens delimited with `<%` and `%>`. We plan to introduce other structures using the same format such as a "case" statement. + +These new token-based shortcuts allow a richer structure and expressivity than existing features such as widgets or pragmas. For example: ``` <% if [match[Elephant]] %> @@ -24,9 +26,15 @@ description: Under development <% endif %> ``` +Behind the scenes, the conditional shortcut syntax is rendered as the equivalent [[ListWidgets|ListWidget]]. + !! Explicit Templates for the ListWidget -<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7784">> support for `<$list-template>` and `<$list-empty>` as immediate children of the <<.wid "ListWidget">> widget to specify the list item template and/or the empty template. For example: +<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7784">> support for `<$list-template>` and `<$list-empty>` as immediate children of the <<.wid "ListWidget">> widget to specify the list item template and/or the empty template. + +This new feature is designed to replace a common pattern of using the `emptyMessage` attribute of the ListWidget to render complex wikitext that thus has to be quoted. Working with wikitext within quotes is awkward and error prone. The new structure can be somewhat faster because it allows the empty message to be parsed in advanced of rendering. + +For example: ``` <$list filter=<>> From 2b0675cac5c7e5467d375a71ca112e7f625ebe8b Mon Sep 17 00:00:00 2001 From: Saq Imtiaz Date: Mon, 4 Dec 2023 09:53:24 +0100 Subject: [PATCH 059/105] Docs: fixes typos in conditonal shortcut syntax docs (#7872) * Docs: Conditional Shortcut Syntax corrections * Update Conditional Shortcut Syntax.tid Add a link to Filter Expression tiddler --- .../tiddlers/wikitext/Conditional Shortcut Syntax.tid | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid b/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid index 3ea99433e..8cef3acfb 100644 --- a/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid +++ b/editions/tw5.com/tiddlers/wikitext/Conditional Shortcut Syntax.tid @@ -4,14 +4,14 @@ tags: WikiText title: Conditional Shortcut Syntax type: text/vnd.tiddlywiki -<<.from-version "5.3.2">> The conditional shortcut syntax provides a convenient way to express if-then-else logic within WikiText. It evaluates a filter and considers the condition to be true if there is at least one result (regardless of the value of that result). +<<.from-version "5.3.2">> The conditional shortcut syntax provides a convenient way to express if-then-else logic within WikiText. It evaluates a [[filter expression|Filter Expression]] and considers the condition to be true if there is at least one result (regardless of the value of that result). Within an "if" or "elseif" clause, the variable `condition` contains the value of the first result of evaluating the filter condition. A simple example: <$macrocall $name='wikitext-example-without-html' -src='<% if [{$:/$:/info/url/protocol}match[file:]] %> +src='<% if [{$:/info/url/protocol}match[file:]] %> Loaded from a file URI <% else %> Not loaded from a file URI @@ -21,11 +21,11 @@ src='<% if [{$:/$:/info/url/protocol}match[file:]] %> One or more `<% elseif %>` clauses may be included before the `<% else %>` clause: <$macrocall $name='wikitext-example-without-html' -src='<% if [{$:/$:/info/url/protocol}match[file:]] %> +src='<% if [{$:/info/url/protocol}match[file:]] %> Loaded from a file URI -<% elseif [{$:/$:/info/url/protocol}match[https:]] %> +<% elseif [{$:/info/url/protocol}match[https:]] %> Loaded from an HTTPS URI -<% elseif [{$:/$:/info/url/protocol}match[http:]] %> +<% elseif [{$:/info/url/protocol}match[http:]] %> Loaded from an HTTP URI <% else %> Loaded from an unknown protocol From 5578fa5f942011861d9f18494600197316d0cdeb Mon Sep 17 00:00:00 2001 From: Mateusz Wilczek <36714554+mateuszwilczek@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:24:33 +0100 Subject: [PATCH 060/105] Improve `jsonset` operator docs (#7873) * Update docs of jsonset operator * Move jsonset examples into a separate tiddler * Update jsonset operator docs --- .../tiddlers/filters/examples/jsonset.tid | 59 +++++++++++++ editions/tw5.com/tiddlers/filters/jsonset.tid | 88 +++++-------------- 2 files changed, 83 insertions(+), 64 deletions(-) create mode 100644 editions/tw5.com/tiddlers/filters/examples/jsonset.tid diff --git a/editions/tw5.com/tiddlers/filters/examples/jsonset.tid b/editions/tw5.com/tiddlers/filters/examples/jsonset.tid new file mode 100644 index 000000000..8cd1d1d61 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/jsonset.tid @@ -0,0 +1,59 @@ +created: 20231204112944341 +modified: 20231204115056732 +tags: [[Operator Examples]] [[jsonset Operator]] +title: jsonset Operator (Examples) + +<$let object-a="""{ + "a": "one", + "b": "", + "c": "three", + "d": { + "e": "four", + "f": [ + "five", + "six", + true, + false, + null + ], + "g": { + "x": "max", + "y": "may", + "z": "maize" + } + } +} +""" +object-b="""{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}"""> + +The examples below assume the following JSON object is contained in the variable `object-a`: + +
    <>
    + +<<.operator-example 1 "[jsonset[d],[Jaguar]]">> +<<.operator-example 2 "[jsonset[d],[f],[Panther]]">> +<<.operator-example 3 "[jsonset[d],[f],[-1],[Elephant]]">> +<<.operator-example 4 "[jsonset[d],[f],[-2],[Elephant]]">> +<<.operator-example 5 "[jsonset[d],[f],[-4],[Elephant]]">> +<<.operator-example 6 "[jsonset[Panther]]" "If only a single parameter is specified, it replaces the entire JSON object">> +<<.operator-example 7 "[jsonset[]]" "If only a single blank parameter is specified, no changes are made to the JSON object">> + + +The examples below assume the following JSON object is contained in the variable `object-b`: + +
    <>
    + +<<.operator-example 8 "[jsonset[]]" "If only a single blank parameter is specified, no changes are made to the JSON object">> +<<.operator-example 9 "[jsonset[],[Antelope]]" "If the property to be set is blank, the entire JSON object is replaced">> +<<.operator-example 10 "[jsonset:number[],[not a number]]" "invalid numbers are interpreted as zero">> +<<.operator-example 11 "[jsonset[id],[Antelope]]" "nonexistent top level properties are added to the object">> +<<.operator-example 19 "[jsonset[missing],[id],[Antelope]]" "nonexistent nested properties are are ignored">> +<<.operator-example 12 "[jsonset:notatype[id],[Antelope]]" "invalid type suffix is interpreted as the default string type">> +<<.operator-example 13 "[jsonset:boolean[id],[false]]">> +<<.operator-example 14 "[jsonset:boolean[id],[Antelope]]" "invalid boolean value causes no assignment to be made">> +<<.operator-example 15 "[jsonset:number[id],[42]]">> +<<.operator-example 16 "[jsonset:null[id]]">> +<<.operator-example 17 "[jsonset:array[d],[f],[5]]">> +<<.operator-example 18 "[jsonset:object[d],[f],[5]]">> + +<<.operator-example 20 "[] [] :and[jsonset[b],[two]]" "If the input consists of multiple JSON objects with matching properties, the value is set for all of them">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/jsonset.tid b/editions/tw5.com/tiddlers/filters/jsonset.tid index 81552c7a1..1cfd076c2 100644 --- a/editions/tw5.com/tiddlers/filters/jsonset.tid +++ b/editions/tw5.com/tiddlers/filters/jsonset.tid @@ -1,22 +1,31 @@ +caption: jsonset created: 20230915121010948 -modified: 20230915121010948 +modified: 20231204115203428 +op-input: a selection of JSON objects +op-output: the JSON objects with the specified value assigned to the specified property +op-parameter: one or more indexes of the property to modify, if applicable followed by the value to be assigned +op-purpose: set the value of a property in JSON objects +op-suffix: data type of the value to be assigned to the property tags: [[Filter Operators]] [[JSON Operators]] title: jsonset Operator -caption: jsonset -op-purpose: set the value of a property in JSON strings -op-input: a selection of JSON strings -op-parameter: one or more indexes of the property to retrieve and sometimes a value to assign -op-output: the JSON strings with the specified property assigned -<<.from-version "5.3.2">> See [[JSON in TiddlyWiki]] for background. - -The <<.op jsonset>> operator is used to set a property value in JSON strings. See also the following related operators: +<<.from-version "5.3.2">> The <<.op jsonset>> operator is used to set a property value in JSON strings. See [[JSON in TiddlyWiki]] for background. See also the following related operators: * <<.olink jsonget>> to retrieve the values of a property in JSON data * <<.olink jsontype>> to retrieve the type of a JSON value * <<.olink jsonindexes>> to retrieve the names of the fields of a JSON object, or the indexes of a JSON array * <<.olink jsonextract>> to retrieve a JSON value as a string of JSON +The type of the value to be assigned to the property can be optionally specified with a suffix: + +* ''string'': default, the string is specified as the final operand +* ''boolean'': the boolean value is true if the final operand is the string "true" and false if the final operand is the string "false", any other value for the final string results prevents the property from being assigned +* ''number'': the numeric value is taken from the final operand, invalid numbers are interpreted as zero +* ''json'': the JSON string value is taken from the final operand, invalid JSON prevents the property from being assigned +* ''object'': an empty object is assigned to the property, the final operand is ignored +* ''array'': an empty array is assigned to the property, the final operand is ignored +* ''null'': the special value null is assigned to the property, the final operand is ignored + Properties within a JSON object are identified by a sequence of indexes. In the following example, the value at `[a]` is `one`, and the value at `[d][f][0]` is `five`. ``` @@ -42,63 +51,14 @@ Properties within a JSON object are identified by a sequence of indexes. In the } ``` -The following examples assume that this JSON data is contained in a variable called `jsondata`. +The <<.op jsonset>> operator uses multiple parameters to specify the indexes of the property to set. When used to assign strings (default behaviour if no suffix is specified) the final operand is interpreted as the value to assign. -The <<.op jsonset>> operator uses multiple operands to specify the indexes of the property to set. When used to assign strings the final operand is interpreted as the value to assign. For example: +Negative indexes are counted from the end, so -1 means the last item, -2 the next-to-last item, and so on. -``` -[jsonset[d],[Jaguar]] --> {"a": "one","b": "","c": "three","d": "Jaguar"} -[jsonset[d],[f],[Panther]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": "Panther","g": {"x": "max","y": "may","z": "maize"}}"} -``` +Indexes can be dynamically composed from variables and transclusions, e.g. `[jsonset,{!!field},[0],{CurrentResult}]`. -Negative indexes into an array are counted from the end, so -1 means the last item, -2 the next-to-last item, and so on: +In the special case where only a single parameter is defined, the operator replaces the entire input object with the the value of that parameter. If the single parameter is blank, the operation is ignored and no assignment takes place. -``` -[jsonset[d],[f],[-1],[Elephant]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five","six",true,false,"Elephant"],"g": {"x": "max","y": "may","z": "maize"}}"} -[jsonset[d],[f],[-2],[Elephant]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five","six",true,"Elephant",null],"g": {"x": "max","y": "may","z": "maize"}}"} -[jsonset[d],[f],[-4],[Elephant]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five","Elephant",true,false,null],"g": {"x": "max","y": "may","z": "maize"}}"} -``` +If the input consists of multiple JSON objects with matching properties, the value is set for all of them. -Indexes can be dynamically composed from variables and transclusions: - -``` -[jsonset,{!!field},[0],{CurrentResult}] -``` - -The data type of the value to be assigned to the property can be specified with an optional suffix: - -|!Suffix |!Description | -|''string'' |The string is specified as the final operand | -|''boolean'' |The boolean value is true if the final operand is the string "true" and false if the final operand is the string "false". Any other value for the final string results prevents the property from being assigned | -|''number'' |The numeric value is taken from the final operand. Invalid numbers are interpreted as zero | -|''json'' |The JSON string value is taken from the final operand. Invalid JSON prevents the property from being assigned | -|''object'' |An empty object is assigned to the property. The final operand is not used as a value | -|''array'' |An empty array is assigned to the property. The final operand is not used as a value | -|''null'' |The special value null is assigned to the property. The final operand is not used as a value | - -For example: - -``` -Input string: -{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}} - -[jsonset[]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}} -[jsonset[],[Antelope]] --> "Antelope" -[jsonset:number[],[not a number]] --> 0 -[jsonset[id],[Antelope]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":"Antelope"} -[jsonset:notatype[id],[Antelope]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":"Antelope"} -[jsonset:boolean[id],[false]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":false} -[jsonset:boolean[id],[Antelope]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}} -[jsonset:number[id],[42]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":42} -[jsonset:null[id]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":null} -[jsonset:array[d],[f],[5]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null,[]]}} -[jsonset:object[d],[f],[5]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null,{}]}} -[jsonset[missing],[id],[Antelope]] --> {"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}} -``` - -A subtlety is that the special case of a single operand sets the value of that operand as the new JSON string, entirely replacing the input object. If that operand is blank, the operation is ignored and no assignment takes place. Thus: - -``` -[jsonset[Panther]] --> "Panther" -[jsonset[]] --> {"a": "one","b": "","c": "three","d": "{"e": "four","f": ["five", "six", true, false, null],"g": {"x": "max","y": "may","z": "maize"}}"} -``` +<<.operator-examples "jsonset">> \ No newline at end of file From 4e06c31022c39423041cfc38aa7de818ee23213f Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Thu, 7 Dec 2023 15:34:07 +0700 Subject: [PATCH 061/105] Move list-join example onto single line (#7877) It's a little less readable this way, but avoids the whitespace issue. --- editions/prerelease/tiddlers/Release 5.3.2.tid | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index e1194c06c..4c7bc8874 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -62,18 +62,13 @@ Note that the <<.attr "emptyMessage">> and <<.attr "template">> attributes take You can replace it with: ``` -<$list filter=<> variable="item" join=", "> -<$text text=<>/> - +<$list filter=<> variable="item" join=", "><$text text=<>/> ``` If the joiner text that you need is long and awkward to write in an attribute, you can use the new `<$list-join>` widget. Like `<$list-template>` and `<$list-empty>`, it must be an immediate child of the <<.wid "ListWidget">>: ``` -<$list filter=<> variable="item"> -<$text text=<>/> -<$list-join>, and also let's not forget - +<$list filter=<> variable="item"><$text text=<>/><$list-join>, and also let's not forget ``` !! jsonset operator From c9be572bafb90d2e041f6d7625303bbd2e3e8aa0 Mon Sep 17 00:00:00 2001 From: etardiff <153414521+etardiff@users.noreply.github.com> Date: Sun, 10 Dec 2023 05:01:30 -0500 Subject: [PATCH 062/105] Signing the CLA (#7879) --- licenses/cla-individual.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/licenses/cla-individual.md b/licenses/cla-individual.md index 023ef792e..04fb7a0c3 100644 --- a/licenses/cla-individual.md +++ b/licenses/cla-individual.md @@ -554,4 +554,6 @@ Timur, @T1mL3arn, 2023/10/04 Wang Ke, @Gk0Wk, 2023/10/17 -@frittro, 2023/10/27 \ No newline at end of file +@frittro, 2023/10/27 + +@etardiff, 2023/12/10 From 4a9b3009dd2c1128d4fdd957ed91e5649b25cd9c Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Mon, 11 Dec 2023 15:21:03 +0000 Subject: [PATCH 063/105] Further fix for d1c7f79dd2c138afeb6527236a3fcca23b4a1cf3 The plus sign needs escaping on some regex engines --- plugins/tiddlywiki/jasmine/run-wiki-based-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js b/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js index 93c09c005..439de794d 100644 --- a/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js +++ b/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js @@ -51,7 +51,7 @@ describe("Wiki-based tests", function() { }); function readMultipleTiddlersTiddler(title) { - var rawTiddlers = $tw.wiki.getTiddlerText(title).split(/\r?\n+\r?\n/mg); + var rawTiddlers = $tw.wiki.getTiddlerText(title).split(/\r?\n\+\r?\n/mg); var tiddlers = []; $tw.utils.each(rawTiddlers,function(rawTiddler) { var fields = Object.create(null), From 15e53b8cd1fe4db67389538994ddebe236920655 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Mon, 11 Dec 2023 17:56:11 +0000 Subject: [PATCH 064/105] Revert: #7768 Ensure {{}} doesn't cause a recursion error See https://github.com/Jermolene/TiddlyWiki5/pull/7768#issuecomment-1850578638 --- core/modules/parsers/wikiparser/rules/transcludeblock.js | 3 --- core/modules/parsers/wikiparser/rules/transcludeinline.js | 3 --- editions/prerelease/tiddlers/Release 5.3.2.tid | 1 - 3 files changed, 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index d6dad6df3..c033c2440 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -81,9 +81,6 @@ exports.parse = function() { } return [tiddlerNode]; } else { - // No template or text reference is provided, so we'll use a blank target. Otherwise we'll generate - // a transclude widget that transcludes the current tiddler, often leading to recursion errors - transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: ""}; return [transcludeNode]; } } diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 87529ca8d..3ce9dc78e 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -79,9 +79,6 @@ exports.parse = function() { } return [tiddlerNode]; } else { - // No template or text reference is provided, so we'll use a blank target. Otherwise we'll generate - // a transclude widget that transcludes the current tiddler, often leading to recursion errors - transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: ""}; return [transcludeNode]; } } diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index 4c7bc8874..c3de75b36 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -113,7 +113,6 @@ Improvements to the following translations: ! Bug Fixes -* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7665">> `{{}}` generating a recursion error * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7758">> ordering of Vanilla stylesheets * <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/fa9bfa07a095548eb2f8339b0b1b816d2e6794ef">> missing closing tag in tag-pill-inner macro * <<.link-badge-removed "https://github.com/Jermolene/TiddlyWiki5/issues/7732">> invalid "type" attribute from textarea elements generated by the EditTextWidget From 51862f812851afda0ed3540f8463f51def0d4f9a Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 12 Dec 2023 09:04:37 +0000 Subject: [PATCH 065/105] Update New Release Banner for v5.3.2 --- .../tiddlers/images/New Release Banner.png | Bin 104615 -> 136131 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/editions/tw5.com/tiddlers/images/New Release Banner.png b/editions/tw5.com/tiddlers/images/New Release Banner.png index daa1db0949f711ba9603e0ccd3994c507887c694..bcb9a25cb029c0628d01cf28dda0930b41c3436f 100644 GIT binary patch literal 136131 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
    xG5g#J02-+~658?n>EwFU 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%0AytBfroSD0jk-X=vdj@o8zW8K>-`L-^4?$Mtf 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 literal 104615 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 YKkW=VLUnjm6951J07*qoM6N<$f@BiZb^rhX From 5c283f843b1ad54945bdc3cd1c7fc742a0f7b1b3 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 12 Dec 2023 09:06:38 +0000 Subject: [PATCH 066/105] Add banner details to the release note --- editions/prerelease/tiddlers/Release 5.3.2.tid | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/prerelease/tiddlers/Release 5.3.2.tid index c3de75b36..fa2d0670e 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/prerelease/tiddlers/Release 5.3.2.tid @@ -8,6 +8,11 @@ description: Under development //[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.3.1...master]]// +<<.banner-credits + credit:"""Congratulations to [[catter-fly|https://talk.tiddlywiki.org/u/catter-fly]] for their winning design for the banner for this release (here is the [[competition thread|https://talk.tiddlywiki.org/t/banner-image-competition-for-v5-3-2/8569]]). +""" + url:"https://raw.githubusercontent.com/Jermolene/TiddlyWiki5/51862f812851afda0ed3540f8463f51def0d4f9a/editions/tw5.com/tiddlers/images/New%20Release%20Banner.png" +>> ! Major Improvements !! Conditional Shortcut Syntax From 9d94459c5d5fa6fe4884c9e386c72d5cea3e1f56 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Tue, 12 Dec 2023 15:48:09 +0000 Subject: [PATCH 067/105] Syncer: fix object reference We should be passing the syncer object, not the task object --- core/modules/syncer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 9769d9674..f7627e1ac 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -635,7 +635,7 @@ SyncFromServerTask.prototype.run = function(callback) { callback(null); }; if(this.syncer.syncadaptor.getUpdatedTiddlers) { - this.syncer.syncadaptor.getUpdatedTiddlers(self,function(err,updates) { + this.syncer.syncadaptor.getUpdatedTiddlers(self.syncer,function(err,updates) { if(err) { self.syncer.displayError($tw.language.getString("Error/RetrievingSkinny"),err); return callback(err); From c13c321a6174427dfa350285ae82ea49e12ea924 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 13 Dec 2023 08:10:38 +0000 Subject: [PATCH 068/105] Preparing for release of v5.3.2 --- .../prerelease/tiddlers/Release 5.3.3.tid | 58 +++++++++++++++++++ .../tiddlers/hellothere/HelloThere.tid | 2 +- .../tiddlers/releasenotes}/Release 5.3.2.tid | 7 ++- readme.md | 2 +- 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 editions/prerelease/tiddlers/Release 5.3.3.tid rename editions/{prerelease/tiddlers => tw5.com/tiddlers/releasenotes}/Release 5.3.2.tid (98%) diff --git a/editions/prerelease/tiddlers/Release 5.3.3.tid b/editions/prerelease/tiddlers/Release 5.3.3.tid new file mode 100644 index 000000000..aa2abe17b --- /dev/null +++ b/editions/prerelease/tiddlers/Release 5.3.3.tid @@ -0,0 +1,58 @@ +caption: 5.3.3 +created: 20231213080754563 +modified: 20231213080754563 +tags: ReleaseNotes +title: Release 5.3.3 +type: text/vnd.tiddlywiki +description: Under development + +//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.3.2...master]]// + +! Translation improvements + +Improvements to the following translations: + +* + +! Plugin Improvements + +* + +! Widget Improvements + +* + +! Usability Improvements + +* + +! Hackability Improvements + +* + +! Bug Fixes + +* + +! Node.js Improvements + +* + +! Performance Improvements + +* + +! Developer Improvements + +* + +! Infrastructure 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/tw5.com/tiddlers/hellothere/HelloThere.tid b/editions/tw5.com/tiddlers/hellothere/HelloThere.tid index ddb91a41e..edc7b1d27 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: 20230820112855583 +modified: 20231213080637781 tags: TableOfContents title: HelloThere type: text/vnd.tiddlywiki diff --git a/editions/prerelease/tiddlers/Release 5.3.2.tid b/editions/tw5.com/tiddlers/releasenotes/Release 5.3.2.tid similarity index 98% rename from editions/prerelease/tiddlers/Release 5.3.2.tid rename to editions/tw5.com/tiddlers/releasenotes/Release 5.3.2.tid index fa2d0670e..e2f3637cb 100644 --- a/editions/prerelease/tiddlers/Release 5.3.2.tid +++ b/editions/tw5.com/tiddlers/releasenotes/Release 5.3.2.tid @@ -1,12 +1,13 @@ caption: 5.3.2 -created: 20231016122502955 -modified: 20231016122502955 +created: 20231213080637781 +modified: 20231213080637781 +released: 20231213080637781 tags: ReleaseNotes title: Release 5.3.2 type: text/vnd.tiddlywiki description: Under development -//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.3.1...master]]// +//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.3.1...v5.3.2]]// <<.banner-credits credit:"""Congratulations to [[catter-fly|https://talk.tiddlywiki.org/u/catter-fly]] for their winning design for the banner for this release (here is the [[competition thread|https://talk.tiddlywiki.org/t/banner-image-competition-for-v5-3-2/8569]]). diff --git a/readme.md b/readme.md index 2dad1f1de..f56a2c702 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@

    TiddlyWiki is a complete interactive wiki in JavaScript. It can be used as a single HTML file in the browser or as a powerful Node.js application. It is highly customisable: the entire user interface is itself implemented in hackable WikiText.

    Learn more and see it in action at https://tiddlywiki.com/

    Developer documentation is in progress at https://tiddlywiki.com/dev/

    Join the Community

    Official Forums

    The new official forum for talking about TiddlyWiki: requests for help, announcements of new releases and plugins, debating new features, or just sharing experiences. You can participate via the associated website, or subscribe via email.

    https://talk.tiddlywiki.org/

    Note that talk.tiddlywiki.org is a community run service that we host and maintain ourselves. The modest running costs are covered by community contributions.

    For the convenience of existing users, we also continue to operate the original TiddlyWiki group (hosted on Google Groups since 2005):

    https://groups.google.com/group/TiddlyWiki

    Developer Forums

    There are several resources for developers to learn more about TiddlyWiki and to discuss and contribute to its development.

    Other Forums

    Documentation

    There is also a discussion group specifically for discussing TiddlyWiki documentation improvement initiatives: https://groups.google.com/group/tiddlywikidocs

    -

    Installing TiddlyWiki on Node.js

    1. Install Node.js
      • Linux:
        Debian/Ubuntu:
        apt install nodejs
        May need to be followed up by:
        apt install npm
        Arch Linux
        yay -S tiddlywiki
        (installs node and tiddlywiki)
      • Mac
        brew install node
      • Android
      • Other
    2. Open a command line terminal and type:
      npm install -g tiddlywiki
      If it fails with an error you may need to re-run the command as an administrator:
      sudo npm install -g tiddlywiki (Mac/Linux)
    3. Ensure TiddlyWiki is installed by typing:
      tiddlywiki --version
      • In response, you should see TiddlyWiki report its current version (eg "5.3.1". You may also see other debugging information reported.)
    4. Try it out:
      1. tiddlywiki mynewwiki --init server to create a folder for a new wiki that includes server-related components
      2. tiddlywiki mynewwiki --listen to start TiddlyWiki
      3. Visit http://127.0.0.1:8080/ in your browser
      4. Try editing and creating tiddlers
    5. Optionally, make an offline copy:

    Welcome to TiddlyWiki, a non-linear personal web notebook that anyone can use and keep forever, independently of any corporation.