1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-26 04:43:42 +00:00

Compare commits

..

6 Commits

Author SHA1 Message Date
jeremy@jermolene.com
995ab34ee0 First commit 2022-10-01 10:04:42 +01:00
jeremy@jermolene.com
8d1e6b5d23 Test plugin should run tests in shadow tiddlers
Missed off #6961, preventing the tests introduced there from running
2022-10-01 10:03:50 +01:00
jeremy@jermolene.com
1df4c29d73 Relax the restriction on the let widget being unable to create variables starting with a dollar 2022-10-01 09:47:26 +01:00
jeremy@jermolene.com
81e4745c56 Update release note contributors list 2022-09-24 14:23:36 +01:00
jeremy@jermolene.com
87597ea273 Update release note 2022-09-24 14:20:30 +01:00
Jeremy Ruston
4e9267ea58 Introduce genesis widget (#6961)
* Initial Commit

* Fix version number

* Fix docs date
2022-09-24 14:07:42 +01:00
10 changed files with 189 additions and 32 deletions

View File

@@ -12,6 +12,9 @@ Adds tiddler filtering methods to the $tw.Wiki object.
/*global $tw: false */
"use strict";
/* Maximum permitted filter recursion depth */
var MAX_FILTER_DEPTH = 300;
/*
Parses an operation (i.e. a run) within a filter string
operators: Array of array of operator nodes into which results should be inserted
@@ -328,7 +331,7 @@ exports.compileFilter = function(filterString) {
})());
});
// Return a function that applies the operations to a source iterator of tiddler titles
var compiled = $tw.perf.measure("filter: " + filterString,function filterFunction(source,widget) {
var fnMeasured = $tw.perf.measure("filter: " + filterString,function filterFunction(source,widget) {
if(!source) {
source = self.each;
} else if(typeof source === "object") { // Array or hashmap
@@ -338,9 +341,15 @@ exports.compileFilter = function(filterString) {
widget = $tw.rootWidget;
}
var results = new $tw.utils.LinkedList();
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,widget);
});
self.filterRecursionCount = (self.filterRecursionCount || 0) + 1;
if(self.filterRecursionCount < MAX_FILTER_DEPTH) {
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,widget);
});
} else {
results.push("/**-- Excessive filter recursion --**/");
}
self.filterRecursionCount = self.filterRecursionCount - 1;
return results.toArray();
});
if(this.filterCacheCount >= 2000) {
@@ -350,9 +359,9 @@ exports.compileFilter = function(filterString) {
this.filterCache = Object.create(null);
this.filterCacheCount = 0;
}
this.filterCache[filterString] = compiled;
this.filterCache[filterString] = fnMeasured;
this.filterCacheCount++;
return compiled;
return fnMeasured;
};
})();

View File

@@ -0,0 +1,63 @@
/*\
title: $:/core/modules/widgets/error.js
type: application/javascript
module-type: widget
Error widget
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var ErrorWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
ErrorWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ErrorWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
var message = this.getAttribute("$message","Unknown error"),
domNode = this.document.createElement("span");
domNode.appendChild(this.document.createTextNode(message));
domNode.className = "tc-error";
parent.insertBefore(domNode,nextSibling);
this.domNodes.push(domNode);
};
/*
Compute the internal state of the widget
*/
ErrorWidget.prototype.execute = function() {
// Nothing to do for a text node
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ErrorWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["$message"]) {
this.refreshSelf();
return true;
} else {
return false;
}
};
exports.error = ErrorWidget;
})();

View File

@@ -51,11 +51,9 @@ LetWidget.prototype.computeAttributes = function() {
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
var value = self.computeAttribute(attribute),
name = attribute.name;
if(name.charAt(0) !== "$") {
// Now that it's prepped, we're allowed to look this variable up
// when defining later variables
self.currentValueFor[name] = value;
}
// Now that it's prepped, we're allowed to look this variable up
// when defining later variables
self.currentValueFor[name] = value;
});
// Run through again, setting variables and looking for differences
$tw.utils.each(this.currentValueFor,function(value,name) {

View File

@@ -12,6 +12,9 @@ Widget base class
/*global $tw: false */
"use strict";
/* Maximum permitted depth of the widget tree for recursion detection */
var MAX_WIDGET_TREE_DEPTH = 1000;
/*
Create a widget object for a parse tree node
parseTreeNode: reference to the parse tree node to be rendered
@@ -358,6 +361,20 @@ Widget.prototype.assignAttributes = function(domNode,options) {
}
};
/*
Get the number of ancestor widgets for this widget
*/
Widget.prototype.getAncestorCount = function() {
if(this.ancestorCount === undefined) {
if(this.parentWidget) {
this.ancestorCount = this.parentWidget.getAncestorCount() + 1;
} else {
this.ancestorCount = 0;
}
}
return this.ancestorCount;
};
/*
Make child widgets correspondng to specified parseTreeNodes
*/
@@ -365,21 +382,29 @@ Widget.prototype.makeChildWidgets = function(parseTreeNodes,options) {
options = options || {};
this.children = [];
var self = this;
// Create set variable widgets for each variable
$tw.utils.each(options.variables,function(value,name) {
var setVariableWidget = {
type: "set",
attributes: {
name: {type: "string", value: name},
value: {type: "string", value: value}
},
children: parseTreeNodes
};
parseTreeNodes = [setVariableWidget];
});
$tw.utils.each(parseTreeNodes || (this.parseTreeNode && this.parseTreeNode.children),function(childNode) {
self.children.push(self.makeChildWidget(childNode));
});
// Check for too much recursion
if(this.getAncestorCount() > MAX_WIDGET_TREE_DEPTH) {
this.children.push(this.makeChildWidget({type: "error", attributes: {
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
}}));
} else {
// Create set variable widgets for each variable
$tw.utils.each(options.variables,function(value,name) {
var setVariableWidget = {
type: "set",
attributes: {
name: {type: "string", value: name},
value: {type: "string", value: value}
},
children: parseTreeNodes
};
parseTreeNodes = [setVariableWidget];
});
// Create the child widgets
$tw.utils.each(parseTreeNodes || (this.parseTreeNode && this.parseTreeNode.children),function(childNode) {
self.children.push(self.makeChildWidget(childNode));
});
}
};
/*

View File

@@ -1,6 +1,6 @@
caption: 5.2.4
created: 20220802100223020
modified: 20220902201505817
created: 20220924141149286
modified: 20220924141149286
tags: ReleaseNotes
title: Release 5.2.4
type: text/vnd.tiddlywiki
@@ -31,9 +31,11 @@ Improvements to the translation features of TiddlyWiki:
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/d62a16ee464fb9984b766b48504829a1a3eb143b">> problem with long presses on tiddler links triggering a preview on iOS/iPadOS
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6910">> consistency of button and input elements across browsers
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/d825f1c875f5e46158c9c41c8c66471138c162d1">> edit preview to use the [[View Template Body Cascade]]
! Widget Improvements
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6961">> new GenesisWidget that allows the dynamic construction of another widget, where the name and attributes of the new widget can be dynamically determined, without needing to be known in advance
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/127f660c91020dcbb43897d954066b31af729e74">> EditTextWidget to remove the default text "Type the text for the tiddler 'foo'"
! Filter improvements
@@ -43,6 +45,10 @@ Improvements to the translation features of TiddlyWiki:
! Hackability Improvements
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6936">> new operators for reading and formatting JSON data: [[jsonget Operator]], [[jsonindexes Operator]], [[jsontype Operator]] and [[format Operator]]
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/c5d3d4c26e8fe27f272dda004aec27d6b66c4f60">> safe mode to disable wiki store indexers
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/166a1565843878083fb1eba47c73b8e67b78400d">> safe mode to prevent globally disabling parser rules
! Bug Fixes
@@ -54,21 +60,29 @@ Improvements to the translation features of TiddlyWiki:
! Node.js Improvements
*
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6947">> console logging to avoid spaces and `<empty string>` message
! Performance Improvements
*
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/53d229592df76c6dd607e40be5bea4d5e063c48e">> performance of `wiki.getTiddler()`
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/81ac9874846b3ead275f67010fcfdb49f3d2f43c">> performance of variable prototype chain handling
! 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 """
bestony
BramChen
flibbles
fu-sen
Marxsal
oflg
pmario
rmunn
roma0104
tw-FRed
twMat
xcazin
""">>

View File

@@ -0,0 +1,15 @@
title: Filters/Recursion
description: Filter recursion detection
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\define myfilter() [subfilter<myfilter>]
<$text text={{{ [subfilter<myfilter>] }}}/>
+
title: ExpectedResult
<p>/**-- Excessive filter recursion --**/</p>

View File

@@ -0,0 +1,13 @@
title: Transclude/Recursion
description: Transclusion recursion detection
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$transclude $tiddler="Output"/>
+
title: ExpectedResult
<p><span class="tc-error">Recursive transclusion error in transclude widget</span></p>

View File

@@ -0,0 +1,17 @@
caption: error
created: 20220909111836951
modified: 20220909111836951
tags: Widgets
title: ErrorWidget
type: text/vnd.tiddlywiki
<<.from-version "5.3.0">> The <<.wlink ErrorWidget>> widget is used by the core to display error messages such as the recursion errors reported by the <<.wlink TranscludeWidget>> widget.
The <<.wlink ErrorWidget>> does not provide any useful functionality to end users. It is only required by the core for technical reasons.
! Content and Attributes
The content of the <<.wlink ErrorWidget>> widget is ignored.
|!Attribute |!Description |
|$message |The error message |

View File

@@ -1,5 +1,6 @@
title: LetWidget
created: 20211028115900000
modified: 20221001094658854
tags: Widgets
caption: let
@@ -12,10 +13,12 @@ caption: let
The content of the <<.wid let>> widget is the scope for the value assigned to the variable.
|!Attribute |!Description |
|//{attributes not starting with $}// |Each attribute name specifies a variable name. The attribute value is assigned to the variable |
|//{attributes}// |Each attribute name specifies a variable name. The attribute value is assigned to the variable |
Attributes are evaluated in the order they are written. Attributes with the same name are allowed. Each time a duplicate attribute is encountered, it will replace the existing value set by the earlier duplicate.
<<.note """<<.from-version "5.2.4">> There is no longer any restriction on using variable names that start with the $ character.""">>
! Examples
Consider a case where you need to set multiple variables, where some depend on the evaluation of others.

View File

@@ -12,7 +12,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5
/*global $tw: true */
"use strict";
var TEST_TIDDLER_FILTER = "[type[application/javascript]tag[$:/tags/test-spec]]";
var TEST_TIDDLER_FILTER = "[all[tiddlers+shadows]type[application/javascript]tag[$:/tags/test-spec]]";
exports.name = "jasmine";
// Ensure this startup module is executed in the right order.