From ff1437e4396d5e9b00d1244048d38834945f7119 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Sat, 14 Oct 2023 09:44:18 +0100 Subject: [PATCH] Fix refreshing of transcluded functions (#7698) * Passing test * Failing test * Fix test It still fails, but now fails correctly * Fix refreshing transcluded functions (#7755) We store the previous result of the filter function and recalculate it when the transclude widget needs to be refreshed, refreshing the widget if the result is different. --------- Co-authored-by: Jeremy Ruston <174761+Jermolene@users.noreply.github.com> Co-authored-by: Robin Munn --- core/modules/widgets/transclude.js | 25 ++++++++++++----- .../data/transclude/Variable-Refreshing.tid | 27 +++++++++++++++++++ .../tests/data/transclude/Variable-Static.tid | 15 +++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid create mode 100644 editions/test/tiddlers/tests/data/transclude/Variable-Static.tid diff --git a/core/modules/widgets/transclude.js b/core/modules/widgets/transclude.js index ac467a2c8..d30ab1fa7 100755 --- a/core/modules/widgets/transclude.js +++ b/core/modules/widgets/transclude.js @@ -109,6 +109,7 @@ TranscludeWidget.prototype.collectAttributes = function() { this.recursionMarker = this.getAttribute("recursionMarker","yes"); } else { this.transcludeVariable = this.getAttribute("$variable"); + this.transcludeVariableIsFunction = false; this.transcludeType = this.getAttribute("$type"); this.transcludeOutput = this.getAttribute("$output","text/html"); this.transcludeTitle = this.getAttribute("$tiddler",this.getVariable("currentTiddler")); @@ -184,7 +185,9 @@ TranscludeWidget.prototype.getTransclusionTarget = function() { if(this.transcludeVariable) { // Transcluding a variable var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}); + this.transcludeVariableIsFunction = variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition; text = variableInfo.text; + this.transcludeFunctionResult = text; return { text: variableInfo.text, type: this.transcludeType @@ -219,21 +222,24 @@ TranscludeWidget.prototype.parseTransclusionTarget = function(parseAsInline) { // Transcluding a variable var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}), srcVariable = variableInfo && variableInfo.srcVariable; + if(srcVariable && srcVariable.isFunctionDefinition) { + this.transcludeVariableIsFunction = true; + this.transcludeFunctionResult = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || ""; + } if(variableInfo.text) { if(srcVariable && srcVariable.isFunctionDefinition) { - var result = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || ""; parser = { tree: [{ type: "text", - text: result + text: this.transcludeFunctionResult }], - source: result, + source: this.transcludeFunctionResult, type: "text/vnd.tiddlywiki" }; if(parseAsInline) { parser.tree[0] = { type: "text", - text: result + text: this.transcludeFunctionResult }; } else { parser.tree[0] = { @@ -241,7 +247,7 @@ TranscludeWidget.prototype.parseTransclusionTarget = function(parseAsInline) { tag: "p", children: [{ type: "text", - text: result + text: this.transcludeFunctionResult }] } } @@ -430,12 +436,19 @@ TranscludeWidget.prototype.parserNeedsRefresh = function() { return (this.sourceText === undefined || parserInfo.sourceText !== this.sourceText || parserInfo.parserType !== this.parserType) }; +TranscludeWidget.prototype.functionNeedsRefresh = function() { + var oldResult = this.transcludeFunctionResult; + var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}); + var newResult = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || ""; + return oldResult !== newResult; +} + /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ TranscludeWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(($tw.utils.count(changedAttributes) > 0) || (!this.transcludeVariable && changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { + if(($tw.utils.count(changedAttributes) > 0) || (this.transcludeVariableIsFunction && this.functionNeedsRefresh()) || (!this.transcludeVariable && changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { this.refreshSelf(); return true; } else { diff --git a/editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid b/editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid new file mode 100644 index 000000000..c1867c2fc --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid @@ -0,0 +1,27 @@ +title: Transclude/Variable/Refreshing +description: Transcluding and refreshing a function +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\function list-join(filter, sep:", ") [subfilterjoin] + +<$tiddler tiddler="TestData"> + +<> + + + ++ +title: TestData + + ++ +title: Actions + +<$action-setfield $tiddler="TestData" items={{{ [range[10]join[ ]] }}}/> ++ +title: ExpectedResult + +

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Variable-Static.tid b/editions/test/tiddlers/tests/data/transclude/Variable-Static.tid new file mode 100644 index 000000000..4158569c6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Variable-Static.tid @@ -0,0 +1,15 @@ +title: Transclude/Variable/Static +description: Transcluding a function +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output +items: 1 2 3 4 5 6 7 8 9 10 + +\function list-join(filter, sep:", ") [subfilterjoin] + +<> ++ +title: ExpectedResult + +

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

\ No newline at end of file