mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-02-19 08:29:50 +00:00
Compare commits
30 Commits
revised-js
...
improved-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
995ab34ee0 | ||
|
|
8d1e6b5d23 | ||
|
|
1df4c29d73 | ||
|
|
81e4745c56 | ||
|
|
87597ea273 | ||
|
|
4e9267ea58 | ||
|
|
dd66fcc759 | ||
|
|
8ebb9ef442 | ||
|
|
81ac987484 | ||
|
|
0a00da6db9 | ||
|
|
53d229592d | ||
|
|
166a156584 | ||
|
|
c5d3d4c26e | ||
|
|
51bdf60ee8 | ||
|
|
50f54ba6ca | ||
|
|
1a0ab68dec | ||
|
|
bb67f96562 | ||
|
|
a981f8ccfe | ||
|
|
859d15a446 | ||
|
|
debfd42d51 | ||
|
|
fe365354d0 | ||
|
|
d825f1c875 | ||
|
|
fe74a776e9 | ||
|
|
93e1a632b8 | ||
|
|
9b7edfc1a7 | ||
|
|
3b2c64a85b | ||
|
|
35b9faaa89 | ||
|
|
11b258a14b | ||
|
|
c8ad385947 | ||
|
|
c1f6e02d14 |
13
boot/boot.js
13
boot/boot.js
@@ -1230,13 +1230,16 @@ $tw.Wiki = function(options) {
|
|||||||
this.getTiddler = function(title) {
|
this.getTiddler = function(title) {
|
||||||
if(title) {
|
if(title) {
|
||||||
var t = tiddlers[title];
|
var t = tiddlers[title];
|
||||||
if(t instanceof $tw.Tiddler) {
|
if(t !== undefined) {
|
||||||
return t;
|
return t;
|
||||||
} else if(title !== undefined && shadowTiddlers[title]) {
|
} else {
|
||||||
return shadowTiddlers[title].tiddler;
|
var s = shadowTiddlers[title];
|
||||||
|
if(s !== undefined) {
|
||||||
|
return s.tiddler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get an array of all tiddler titles
|
// Get an array of all tiddler titles
|
||||||
@@ -2416,7 +2419,7 @@ $tw.boot.initStartup = function(options) {
|
|||||||
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
|
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
|
||||||
$tw.utils.registerFileType("application/octet-stream","base64",".octet-stream");
|
$tw.utils.registerFileType("application/octet-stream","base64",".octet-stream");
|
||||||
// Create the wiki store for the app
|
// Create the wiki store for the app
|
||||||
$tw.wiki = new $tw.Wiki();
|
$tw.wiki = new $tw.Wiki($tw.safeMode && {enableIndexers: []});
|
||||||
// Install built in tiddler fields modules
|
// Install built in tiddler fields modules
|
||||||
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
|
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
|
||||||
// Install the tiddler deserializer modules
|
// Install the tiddler deserializer modules
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ Adds tiddler filtering methods to the $tw.Wiki object.
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* Maximum permitted filter recursion depth */
|
||||||
|
var MAX_FILTER_DEPTH = 300;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parses an operation (i.e. a run) within a filter string
|
Parses an operation (i.e. a run) within a filter string
|
||||||
operators: Array of array of operator nodes into which results should be inserted
|
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
|
// 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) {
|
if(!source) {
|
||||||
source = self.each;
|
source = self.each;
|
||||||
} else if(typeof source === "object") { // Array or hashmap
|
} else if(typeof source === "object") { // Array or hashmap
|
||||||
@@ -338,9 +341,15 @@ exports.compileFilter = function(filterString) {
|
|||||||
widget = $tw.rootWidget;
|
widget = $tw.rootWidget;
|
||||||
}
|
}
|
||||||
var results = new $tw.utils.LinkedList();
|
var results = new $tw.utils.LinkedList();
|
||||||
$tw.utils.each(operationFunctions,function(operationFunction) {
|
self.filterRecursionCount = (self.filterRecursionCount || 0) + 1;
|
||||||
operationFunction(results,source,widget);
|
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();
|
return results.toArray();
|
||||||
});
|
});
|
||||||
if(this.filterCacheCount >= 2000) {
|
if(this.filterCacheCount >= 2000) {
|
||||||
@@ -350,9 +359,9 @@ exports.compileFilter = function(filterString) {
|
|||||||
this.filterCache = Object.create(null);
|
this.filterCache = Object.create(null);
|
||||||
this.filterCacheCount = 0;
|
this.filterCacheCount = 0;
|
||||||
}
|
}
|
||||||
this.filterCache[filterString] = compiled;
|
this.filterCache[filterString] = fnMeasured;
|
||||||
this.filterCacheCount++;
|
this.filterCacheCount++;
|
||||||
return compiled;
|
return fnMeasured;
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ WikiParser.prototype.loadRemoteTiddler = function(url) {
|
|||||||
*/
|
*/
|
||||||
WikiParser.prototype.setupRules = function(proto,configPrefix) {
|
WikiParser.prototype.setupRules = function(proto,configPrefix) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if(!$tw.safemode) {
|
if(!$tw.safeMode) {
|
||||||
$tw.utils.each(proto,function(object,name) {
|
$tw.utils.each(proto,function(object,name) {
|
||||||
if(self.wiki.getTiddlerText(configPrefix + name,"enable") !== "enable") {
|
if(self.wiki.getTiddlerText(configPrefix + name,"enable") !== "enable") {
|
||||||
delete proto[name];
|
delete proto[name];
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ var TW_TextNode = function(text) {
|
|||||||
this.textContent = text + "";
|
this.textContent = text + "";
|
||||||
};
|
};
|
||||||
|
|
||||||
TW_TextNode.prototype = Object.create(TW_Node.prototype);
|
Object.setPrototypeOf(TW_TextNode,TW_Node.prototype);
|
||||||
|
|
||||||
Object.defineProperty(TW_TextNode.prototype, "nodeType", {
|
Object.defineProperty(TW_TextNode.prototype, "nodeType", {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -67,7 +67,7 @@ var TW_Element = function(tag,namespace) {
|
|||||||
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
|
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
|
||||||
};
|
};
|
||||||
|
|
||||||
TW_Element.prototype = Object.create(TW_Node.prototype);
|
Object.setPrototypeOf(TW_Element,TW_Node.prototype);
|
||||||
|
|
||||||
Object.defineProperty(TW_Element.prototype, "style", {
|
Object.defineProperty(TW_Element.prototype, "style", {
|
||||||
get: function() {
|
get: function() {
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ Logger.prototype.log = function(/* args */) {
|
|||||||
this.saveBufferLogger.buffer = this.saveBufferLogger.buffer.slice(-this.saveBufferLogger.saveLimit);
|
this.saveBufferLogger.buffer = this.saveBufferLogger.buffer.slice(-this.saveBufferLogger.saveLimit);
|
||||||
}
|
}
|
||||||
if(console !== undefined && console.log !== undefined) {
|
if(console !== undefined && console.log !== undefined) {
|
||||||
return Function.apply.call(console.log, console, [$tw.utils.terminalColour(this.colour),this.componentName + ":"].concat(Array.prototype.slice.call(arguments,0)).concat($tw.utils.terminalColour()));
|
var logMessage = [$tw.utils.terminalColour(this.colour) + this.componentName + ":"].concat(Array.prototype.slice.call(arguments,0));
|
||||||
|
logMessage[logMessage.length-1] += $tw.utils.terminalColour();
|
||||||
|
return Function.apply.call(console.log, console, logMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,12 +12,26 @@ Parse tree utility functions.
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add attribute to parse tree node
|
||||||
|
Can be invoked as (node,name,value) or (node,attr)
|
||||||
|
*/
|
||||||
exports.addAttributeToParseTreeNode = function(node,name,value) {
|
exports.addAttributeToParseTreeNode = function(node,name,value) {
|
||||||
var attribute = {name: name, type: "string", value: value};
|
var attribute = typeof name === "object" ? name : {name: name, type: "string", value: value};
|
||||||
|
name = attribute.name;
|
||||||
node.attributes = node.attributes || {};
|
node.attributes = node.attributes || {};
|
||||||
|
node.orderedAttributes = node.orderedAttributes || [];
|
||||||
node.attributes[name] = attribute;
|
node.attributes[name] = attribute;
|
||||||
if(node.orderedAttributes) {
|
var foundIndex = -1;
|
||||||
|
$tw.utils.each(node.orderedAttributes,function(attr,index) {
|
||||||
|
if(attr.name === name) {
|
||||||
|
foundIndex = index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(foundIndex === -1) {
|
||||||
node.orderedAttributes.push(attribute);
|
node.orderedAttributes.push(attribute);
|
||||||
|
} else {
|
||||||
|
node.orderedAttributes[foundIndex] = attribute;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -66,14 +66,14 @@ CheckboxWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
CheckboxWidget.prototype.getValue = function() {
|
CheckboxWidget.prototype.getValue = function() {
|
||||||
var tiddler = this.wiki.getTiddler(this.checkboxTitle);
|
var tiddler = this.wiki.getTiddler(this.checkboxTitle);
|
||||||
if(tiddler || this.checkboxFilter) {
|
if(tiddler || this.checkboxFilter) {
|
||||||
if(this.checkboxTag) {
|
if(tiddler && this.checkboxTag) {
|
||||||
if(this.checkboxInvertTag === "yes") {
|
if(this.checkboxInvertTag === "yes") {
|
||||||
return !tiddler.hasTag(this.checkboxTag);
|
return !tiddler.hasTag(this.checkboxTag);
|
||||||
} else {
|
} else {
|
||||||
return tiddler.hasTag(this.checkboxTag);
|
return tiddler.hasTag(this.checkboxTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.checkboxField || this.checkboxIndex) {
|
if(tiddler && (this.checkboxField || this.checkboxIndex)) {
|
||||||
// Same logic applies to fields and indexes
|
// Same logic applies to fields and indexes
|
||||||
var value;
|
var value;
|
||||||
if(this.checkboxField) {
|
if(this.checkboxField) {
|
||||||
@@ -206,11 +206,18 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
|
|||||||
}
|
}
|
||||||
// Set the list field (or index) if specified
|
// Set the list field (or index) if specified
|
||||||
if(this.checkboxListField || this.checkboxListIndex) {
|
if(this.checkboxListField || this.checkboxListIndex) {
|
||||||
var listContents, oldPos, newPos;
|
var fieldContents, listContents, oldPos, newPos;
|
||||||
if(this.checkboxListField) {
|
if(this.checkboxListField) {
|
||||||
listContents = tiddler.getFieldList(this.checkboxListField);
|
fieldContents = tiddler ? tiddler.fields[this.checkboxListField] : undefined;
|
||||||
} else {
|
} else {
|
||||||
listContents = $tw.utils.parseStringArray(this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex) || "") || [];
|
fieldContents = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex);
|
||||||
|
}
|
||||||
|
if($tw.utils.isArray(fieldContents)) {
|
||||||
|
// Make a copy so we can modify it without changing original that's refrenced elsewhere
|
||||||
|
listContents = fieldContents.slice(0);
|
||||||
|
} else {
|
||||||
|
listContents = $tw.utils.parseStringArray(fieldContents) || [];
|
||||||
|
// No need to copy since parseStringArray returns a fresh array, not refrenced elsewhere
|
||||||
}
|
}
|
||||||
oldPos = notValue ? listContents.indexOf(notValue) : -1;
|
oldPos = notValue ? listContents.indexOf(notValue) : -1;
|
||||||
newPos = value ? listContents.indexOf(value) : -1;
|
newPos = value ? listContents.indexOf(value) : -1;
|
||||||
|
|||||||
63
core/modules/widgets/error.js
Normal file
63
core/modules/widgets/error.js
Normal 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;
|
||||||
|
|
||||||
|
})();
|
||||||
108
core/modules/widgets/genesis.js
Normal file
108
core/modules/widgets/genesis.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/genesis.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Genesis widget for dynamically creating widgets
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var GenesisWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.parentDomNode = parent;
|
||||||
|
this.computeAttributes({filterFn: function(name) {
|
||||||
|
// Only compute our own attributes which start with a single dollar
|
||||||
|
return name.charAt(0) === "$" && name.charAt(1) !== "$";
|
||||||
|
}});
|
||||||
|
this.execute();
|
||||||
|
this.renderChildren(parent,nextSibling);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compute the internal state of the widget
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype.execute = function() {
|
||||||
|
var self = this;
|
||||||
|
// Collect attributes
|
||||||
|
this.genesisType = this.getAttribute("$type","element");
|
||||||
|
this.genesisRemappable = this.getAttribute("$remappable","yes") === "yes";
|
||||||
|
this.genesisNames = this.getAttribute("$names","");
|
||||||
|
this.genesisValues = this.getAttribute("$values","");
|
||||||
|
// Construct parse tree
|
||||||
|
var isElementWidget = this.genesisType.charAt(0) !== "$",
|
||||||
|
nodeType = isElementWidget ? "element" : this.genesisType.substr(1),
|
||||||
|
nodeTag = isElementWidget ? this.genesisType : undefined;
|
||||||
|
var parseTreeNodes = [{
|
||||||
|
type: nodeType,
|
||||||
|
tag: nodeTag,
|
||||||
|
attributes: {},
|
||||||
|
orderedAttributes: [],
|
||||||
|
children: this.parseTreeNode.children || [],
|
||||||
|
isNotRemappable: !this.genesisRemappable
|
||||||
|
}];
|
||||||
|
// Apply explicit attributes
|
||||||
|
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
|
||||||
|
var name = attribute.name;
|
||||||
|
if(name.charAt(0) === "$") {
|
||||||
|
if(name.charAt(1) === "$") {
|
||||||
|
// Double $$ is changed to a single $
|
||||||
|
name = name.substr(1);
|
||||||
|
} else {
|
||||||
|
// Single dollar is ignored
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],$tw.utils.extend({},attribute,{name: name}));
|
||||||
|
});
|
||||||
|
// Apply attributes in $names/$values
|
||||||
|
this.attributeNames = [];
|
||||||
|
this.attributeValues = [];
|
||||||
|
if(this.genesisNames && this.genesisValues) {
|
||||||
|
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this);
|
||||||
|
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this);
|
||||||
|
$tw.utils.each(this.attributeNames,function(varname,index) {
|
||||||
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],varname,self.attributeValues[index] || "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Construct the child widgets
|
||||||
|
this.makeChildWidgets(parseTreeNodes);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
var changedAttributes = this.computeAttributes(),
|
||||||
|
filterNames = this.getAttribute("$names",""),
|
||||||
|
filterValues = this.getAttribute("$values",""),
|
||||||
|
attributeNames = this.wiki.filterTiddlers(filterNames,this),
|
||||||
|
attributeValues = this.wiki.filterTiddlers(filterValues,this);
|
||||||
|
if($tw.utils.count(changedAttributes) > 0 || !$tw.utils.isArrayEqual(this.attributeNames,attributeNames) || !$tw.utils.isArrayEqual(this.attributeValues,attributeValues)) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return this.refreshChildren(changedTiddlers);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.genesis = GenesisWidget;
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -39,7 +39,10 @@ Compute the internal state of the widget
|
|||||||
ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
||||||
var widgetPointer = this;
|
var widgetPointer = this;
|
||||||
// Got to flush all the accumulated variables
|
// Got to flush all the accumulated variables
|
||||||
this.variables = new this.variablesConstructor();
|
this.variables = Object.create(null);
|
||||||
|
if(this.parentWidget) {
|
||||||
|
Object.setPrototypeOf(this.variables,this.parentWidget.variables);
|
||||||
|
}
|
||||||
// Get our parameters
|
// Get our parameters
|
||||||
this.filter = this.getAttribute("filter");
|
this.filter = this.getAttribute("filter");
|
||||||
// Compute the filter
|
// Compute the filter
|
||||||
|
|||||||
@@ -51,11 +51,9 @@ LetWidget.prototype.computeAttributes = function() {
|
|||||||
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
|
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
|
||||||
var value = self.computeAttribute(attribute),
|
var value = self.computeAttribute(attribute),
|
||||||
name = attribute.name;
|
name = attribute.name;
|
||||||
if(name.charAt(0) !== "$") {
|
// Now that it's prepped, we're allowed to look this variable up
|
||||||
// Now that it's prepped, we're allowed to look this variable up
|
// when defining later variables
|
||||||
// when defining later variables
|
self.currentValueFor[name] = value;
|
||||||
self.currentValueFor[name] = value;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
// Run through again, setting variables and looking for differences
|
// Run through again, setting variables and looking for differences
|
||||||
$tw.utils.each(this.currentValueFor,function(value,name) {
|
$tw.utils.each(this.currentValueFor,function(value,name) {
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ Widget base class
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"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
|
Create a widget object for a parse tree node
|
||||||
parseTreeNode: reference to the parse tree node to be rendered
|
parseTreeNode: reference to the parse tree node to be rendered
|
||||||
@@ -38,9 +41,10 @@ Widget.prototype.initialise = function(parseTreeNode,options) {
|
|||||||
this.parseTreeNode = parseTreeNode;
|
this.parseTreeNode = parseTreeNode;
|
||||||
this.wiki = options.wiki;
|
this.wiki = options.wiki;
|
||||||
this.parentWidget = options.parentWidget;
|
this.parentWidget = options.parentWidget;
|
||||||
this.variablesConstructor = function() {};
|
this.variables = Object.create(null);
|
||||||
this.variablesConstructor.prototype = this.parentWidget ? this.parentWidget.variables : {};
|
if(this.parentWidget) {
|
||||||
this.variables = new this.variablesConstructor();
|
Object.setPrototypeOf(this.variables,this.parentWidget.variables);
|
||||||
|
}
|
||||||
this.document = options.document;
|
this.document = options.document;
|
||||||
this.attributes = {};
|
this.attributes = {};
|
||||||
this.children = [];
|
this.children = [];
|
||||||
@@ -357,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
|
Make child widgets correspondng to specified parseTreeNodes
|
||||||
*/
|
*/
|
||||||
@@ -364,21 +382,29 @@ Widget.prototype.makeChildWidgets = function(parseTreeNodes,options) {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
this.children = [];
|
this.children = [];
|
||||||
var self = this;
|
var self = this;
|
||||||
// Create set variable widgets for each variable
|
// Check for too much recursion
|
||||||
$tw.utils.each(options.variables,function(value,name) {
|
if(this.getAncestorCount() > MAX_WIDGET_TREE_DEPTH) {
|
||||||
var setVariableWidget = {
|
this.children.push(this.makeChildWidget({type: "error", attributes: {
|
||||||
type: "set",
|
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
|
||||||
attributes: {
|
}}));
|
||||||
name: {type: "string", value: name},
|
} else {
|
||||||
value: {type: "string", value: value}
|
// Create set variable widgets for each variable
|
||||||
},
|
$tw.utils.each(options.variables,function(value,name) {
|
||||||
children: parseTreeNodes
|
var setVariableWidget = {
|
||||||
};
|
type: "set",
|
||||||
parseTreeNodes = [setVariableWidget];
|
attributes: {
|
||||||
});
|
name: {type: "string", value: name},
|
||||||
$tw.utils.each(parseTreeNodes || (this.parseTreeNode && this.parseTreeNode.children),function(childNode) {
|
value: {type: "string", value: value}
|
||||||
self.children.push(self.makeChildWidget(childNode));
|
},
|
||||||
});
|
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));
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ caption: {{$:/language/EditTemplate/Body/Preview/Type/Output}}
|
|||||||
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]] [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!has[draft.of]]
|
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]] [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!has[draft.of]]
|
||||||
<$set name="tv-tiddler-preview" value="yes">
|
<$set name="tv-tiddler-preview" value="yes">
|
||||||
|
|
||||||
<$transclude />
|
<$transclude tiddler={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/ViewTemplateBodyFilter]!is[draft]get[text]] :and[!is[blank]else[$:/core/ui/ViewTemplate/body/default]] }}} />
|
||||||
|
|
||||||
</$set>
|
</$set>
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
created: 20160504080001125
|
|
||||||
modified: 20160504080318928
|
|
||||||
title: $:/core/ui/TagTemplate
|
|
||||||
type: text/vnd.tiddlywiki
|
|
||||||
|
|
||||||
\define tag-styles()
|
|
||||||
background-color:$(backgroundColor)$;
|
|
||||||
fill:$(foregroundColor)$;
|
|
||||||
color:$(foregroundColor)$;
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define tag-body-inner(colour,fallbackTarget,colourA,colourB)
|
|
||||||
<$set name="foregroundColor" value=<<contrastcolour target:"""$colour$""" fallbackTarget:"""$fallbackTarget$""" colourA:"""$colourA$""" colourB:"""$colourB$""">>>
|
|
||||||
<$set name="backgroundColor" value="""$colour$""">
|
|
||||||
<$button popup=<<qualify "$:/state/popup/tag">> class="tc-btn-invisible tc-tag-label" style=<<tag-styles>>>
|
|
||||||
<$transclude tiddler={{!!icon}}/> <$view field="fr-title"><$view field="title" format="text" /></$view>
|
|
||||||
</$button>
|
|
||||||
<$reveal state=<<qualify "$:/state/popup/tag">> type="popup" position="below" animate="yes"><div class="tc-drop-down"><$transclude tiddler="$:/core/ui/ListItemTemplate"/>
|
|
||||||
<hr>
|
|
||||||
<$list filter="[all[current]tagging[]]" template="$:/core/ui/ListItemTemplate"/>
|
|
||||||
</div>
|
|
||||||
</$reveal>
|
|
||||||
</$set>
|
|
||||||
</$set>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define tag-body(colour,palette)
|
|
||||||
<span class="tc-tag-list-item">
|
|
||||||
<$macrocall $name="tag-body-inner" colour="""$colour$""" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}}/>
|
|
||||||
</span>
|
|
||||||
\end
|
|
||||||
|
|
||||||
<$macrocall $name="tag-body" colour={{!!color}} palette={{$:/palette}}/>
|
|
||||||
113
editions/fr-FR/tiddlers/system/$__core_macros_list.tid
Normal file
113
editions/fr-FR/tiddlers/system/$__core_macros_list.tid
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
created: 20220830224607117
|
||||||
|
modified: 20220830224638865
|
||||||
|
tags: $:/tags/Macro
|
||||||
|
title: $:/core/macros/list
|
||||||
|
|
||||||
|
\define list-links(filter,type:"ul",subtype:"li",class:"",emptyMessage)
|
||||||
|
\whitespace trim
|
||||||
|
<$type$ class="$class$">
|
||||||
|
<$list filter="$filter$" emptyMessage=<<__emptyMessage__>>>
|
||||||
|
<$subtype$>
|
||||||
|
<$link to={{!!title}}>
|
||||||
|
<$let tv-wikilinks="no">
|
||||||
|
<$transclude field="caption">
|
||||||
|
<$view field="title"/>
|
||||||
|
</$transclude>
|
||||||
|
</$let>
|
||||||
|
</$link>
|
||||||
|
</$subtype$>
|
||||||
|
</$list>
|
||||||
|
</$type$>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define list-links-draggable-drop-actions()
|
||||||
|
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate)
|
||||||
|
\whitespace trim
|
||||||
|
<span class="tc-links-draggable-list">
|
||||||
|
<$vars targetTiddler="""$tiddler$""" targetField="""$field$""">
|
||||||
|
<$type$ class="$class$">
|
||||||
|
<$list filter="[list[$tiddler$!!$field$]]" emptyMessage=<<__emptyMessage__>>>
|
||||||
|
<$droppable actions=<<list-links-draggable-drop-actions>> tag="""$subtype$""" enable=<<tv-enable-drag-and-drop>>>
|
||||||
|
<div class="tc-droppable-placeholder"/>
|
||||||
|
<div>
|
||||||
|
<$transclude tiddler="""$itemTemplate$""">
|
||||||
|
<$link to={{!!title}}>
|
||||||
|
<$let tv-wikilinks="no">
|
||||||
|
<$transclude field="caption">
|
||||||
|
<$view field="title"/>
|
||||||
|
</$transclude>
|
||||||
|
</$let>
|
||||||
|
</$link>
|
||||||
|
</$transclude>
|
||||||
|
</div>
|
||||||
|
</$droppable>
|
||||||
|
</$list>
|
||||||
|
<$tiddler tiddler="">
|
||||||
|
<$droppable actions=<<list-links-draggable-drop-actions>> tag="div" enable=<<tv-enable-drag-and-drop>>>
|
||||||
|
<div class="tc-droppable-placeholder">
|
||||||
|
{{$:/core/images/blank}}
|
||||||
|
</div>
|
||||||
|
<div style="height:0.5em;"/>
|
||||||
|
</$droppable>
|
||||||
|
</$tiddler>
|
||||||
|
</$type$>
|
||||||
|
</$vars>
|
||||||
|
</span>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define list-tagged-draggable-drop-actions(tag)
|
||||||
|
\whitespace trim
|
||||||
|
<!-- Save the current ordering of the tiddlers with this tag -->
|
||||||
|
<$set name="order" filter="[<__tag__>tagging[]]">
|
||||||
|
<!-- Remove any list-after or list-before fields from the tiddlers with this tag -->
|
||||||
|
<$list filter="[<__tag__>tagging[]]">
|
||||||
|
<$action-deletefield $field="list-before"/>
|
||||||
|
<$action-deletefield $field="list-after"/>
|
||||||
|
</$list>
|
||||||
|
<!-- Save the new order to the Tag Tiddler -->
|
||||||
|
<$action-listops $tiddler=<<__tag__>> $field="list" $filter="+[enlist<order>] +[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||||
|
<!-- Make sure the newly added item has the right tag -->
|
||||||
|
<!-- Removing this line makes dragging tags within the dropdown work as intended -->
|
||||||
|
<!--<$action-listops $tiddler=<<actionTiddler>> $tags=<<__tag__>>/>-->
|
||||||
|
<!-- Using the following 5 lines as replacement makes dragging titles from outside into the dropdown apply the tag -->
|
||||||
|
<$list filter="[<actionTiddler>!contains:tags<__tag__>]">
|
||||||
|
<$fieldmangler tiddler=<<actionTiddler>>>
|
||||||
|
<$action-sendmessage $message="tm-add-tag" $param=<<__tag__>>/>
|
||||||
|
</$fieldmangler>
|
||||||
|
</$list>
|
||||||
|
</$set>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"")
|
||||||
|
\whitespace trim
|
||||||
|
<span class="tc-tagged-draggable-list">
|
||||||
|
<$set name="tag" value=<<__tag__>>>
|
||||||
|
<$list filter="[<__tag__>tagging[]$subFilter$]" emptyMessage=<<__emptyMessage__>> storyview=<<__storyview__>>>
|
||||||
|
<$elementTag$ class="tc-menu-list-item">
|
||||||
|
<$droppable actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" enable=<<tv-enable-drag-and-drop>>>
|
||||||
|
<$elementTag$ class="tc-droppable-placeholder"/>
|
||||||
|
<$elementTag$>
|
||||||
|
<$transclude tiddler="""$itemTemplate$""">
|
||||||
|
<$link to={{!!title}}>
|
||||||
|
<$view field="fr-title">
|
||||||
|
<$view field="title"/>
|
||||||
|
</$view>
|
||||||
|
</$link>
|
||||||
|
</$transclude>
|
||||||
|
</$elementTag$>
|
||||||
|
</$droppable>
|
||||||
|
</$elementTag$>
|
||||||
|
</$list>
|
||||||
|
<$tiddler tiddler="">
|
||||||
|
<$droppable actions="""<$macrocall $name="list-tagged-draggable-drop-actions" tag=<<__tag__>>/>""" enable=<<tv-enable-drag-and-drop>>>
|
||||||
|
<$elementTag$ class="tc-droppable-placeholder"/>
|
||||||
|
<$elementTag$ style="height:0.5em;">
|
||||||
|
</$elementTag$>
|
||||||
|
</$droppable>
|
||||||
|
</$tiddler>
|
||||||
|
</$set>
|
||||||
|
</span>
|
||||||
|
\end
|
||||||
39
editions/fr-FR/tiddlers/system/$__core_macros_tag.tid
Normal file
39
editions/fr-FR/tiddlers/system/$__core_macros_tag.tid
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
created: 20220830190922373
|
||||||
|
modified: 20220830191056761
|
||||||
|
tags: $:/tags/Macro
|
||||||
|
title: $:/core/macros/tag
|
||||||
|
|
||||||
|
\define tag-pill-styles()
|
||||||
|
background-color:$(backgroundColor)$;
|
||||||
|
fill:$(foregroundColor)$;
|
||||||
|
color:$(foregroundColor)$;
|
||||||
|
\end
|
||||||
|
|
||||||
|
<!-- This has no whitespace trim to avoid modifying $actions$. Closing tags omitted for brevity. -->
|
||||||
|
\define tag-pill-inner(tag,icon,colour,fallbackTarget,colourA,colourB,element-tag,element-attributes,actions)
|
||||||
|
<$vars
|
||||||
|
foregroundColor=<<contrastcolour target:"""$colour$""" fallbackTarget:"""$fallbackTarget$""" colourA:"""$colourA$""" colourB:"""$colourB$""">>
|
||||||
|
backgroundColor="""$colour$"""
|
||||||
|
><$element-tag$
|
||||||
|
$element-attributes$
|
||||||
|
class="tc-tag-label tc-btn-invisible"
|
||||||
|
style=<<tag-pill-styles>>
|
||||||
|
>$actions$<$transclude tiddler="""$icon$"""/><$view tiddler=<<__tag__>> field="fr-title" format="text"><$view tiddler=<<__tag__>> field="title" format="text" /></$view></$element-tag$>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define tag-pill-body(tag,icon,colour,palette,element-tag,element-attributes,actions)
|
||||||
|
<$macrocall $name="tag-pill-inner" tag=<<__tag__>> icon="""$icon$""" colour="""$colour$""" fallbackTarget={{$palette$##tag-background}} colourA={{$palette$##foreground}} colourB={{$palette$##background}} element-tag="""$element-tag$""" element-attributes="""$element-attributes$""" actions="""$actions$"""/>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define tag-pill(tag,element-tag:"span",element-attributes:"",actions:"")
|
||||||
|
\whitespace trim
|
||||||
|
<span class="tc-tag-list-item" data-tag-title=<<__tag__>>>
|
||||||
|
<$let currentTiddler=<<__tag__>>>
|
||||||
|
<$macrocall $name="tag-pill-body" tag=<<__tag__>> icon={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}} colour={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}} palette={{$:/palette}} element-tag="""$element-tag$""" element-attributes="""$element-attributes$""" actions="""$actions$"""/>
|
||||||
|
</$let>
|
||||||
|
</span>
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define tag(tag)
|
||||||
|
{{$tag$||$:/core/ui/TagTemplate}}
|
||||||
|
\end
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
created: 20220830194301860
|
||||||
|
modified: 20220830194658750
|
||||||
|
title: $:/core/ui/TagPickerTagTemplate
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$button class=<<button-classes>> tag="a" tooltip={{$:/language/EditTemplate/Tags/Add/Button/Hint}}>
|
||||||
|
<$list filter="[<saveTiddler>minlength[1]]">
|
||||||
|
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="[<tag>]"/>
|
||||||
|
</$list>
|
||||||
|
<$set name="currentTiddlerCSSEscaped" value={{{ [<saveTiddler>escapecss[]] }}}>
|
||||||
|
<$action-sendmessage $message="tm-focus-selector" $param=<<get-tagpicker-focus-selector>> preventScroll="true"/>
|
||||||
|
</$set>
|
||||||
|
<<delete-tag-state-tiddlers>>
|
||||||
|
<$list filter="[<refreshTitle>minlength[1]]">
|
||||||
|
<$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
|
||||||
|
</$list>
|
||||||
|
<<actions>>
|
||||||
|
<$set name="backgroundColor" value={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}>
|
||||||
|
<$wikify name="foregroundColor" text="""<$macrocall $name="contrastcolour" target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>""">
|
||||||
|
<span class="tc-tag-label tc-btn-invisible" style=<<tag-pill-styles>>>
|
||||||
|
{{||$:/core/ui/TiddlerIcon}}<$view field="fr-title" format="text"><$view field="title" format="text"/></$view>
|
||||||
|
</span>
|
||||||
|
</$wikify>
|
||||||
|
</$set>
|
||||||
|
</$button>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
caption: 5.2.4
|
caption: 5.2.4
|
||||||
created: 20220802100223020
|
created: 20220924141149286
|
||||||
modified: 20220802100223020
|
modified: 20220924141149286
|
||||||
tags: ReleaseNotes
|
tags: ReleaseNotes
|
||||||
title: Release 5.2.4
|
title: Release 5.2.4
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
@@ -11,9 +11,17 @@ type: text/vnd.tiddlywiki
|
|||||||
|
|
||||||
*
|
*
|
||||||
|
|
||||||
! Translation improvements
|
! Translation improvement
|
||||||
|
|
||||||
*
|
Improvements to the following translations:
|
||||||
|
|
||||||
|
* Chinese
|
||||||
|
* Japanese
|
||||||
|
|
||||||
|
Improvements to the translation features of TiddlyWiki:
|
||||||
|
|
||||||
|
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6882">> the [[Translators Edition|Translate TiddlyWiki into your language]] to add an option to display the original English text underneath the text area
|
||||||
|
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/6933">> "delete" button text in $:/AdvancedSearch so that it is translatable
|
||||||
|
|
||||||
! Accessibility Improvements
|
! Accessibility Improvements
|
||||||
|
|
||||||
@@ -21,11 +29,14 @@ type: text/vnd.tiddlywiki
|
|||||||
|
|
||||||
! Usability Improvements
|
! Usability Improvements
|
||||||
|
|
||||||
*
|
* <<.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
|
! 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
|
! Filter improvements
|
||||||
|
|
||||||
@@ -33,7 +44,11 @@ type: text/vnd.tiddlywiki
|
|||||||
|
|
||||||
! Hackability Improvements
|
! 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
|
! Bug Fixes
|
||||||
|
|
||||||
@@ -45,15 +60,29 @@ type: text/vnd.tiddlywiki
|
|||||||
|
|
||||||
! Node.js Improvements
|
! Node.js Improvements
|
||||||
|
|
||||||
*
|
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6947">> console logging to avoid spaces and `<empty string>` message
|
||||||
|
|
||||||
! Performance Improvements
|
! 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
|
! 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:
|
[[@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 """
|
<<.contributors """
|
||||||
|
bestony
|
||||||
|
BramChen
|
||||||
|
flibbles
|
||||||
|
fu-sen
|
||||||
|
Marxsal
|
||||||
|
oflg
|
||||||
|
pmario
|
||||||
|
rmunn
|
||||||
|
roma0104
|
||||||
|
tw-FRed
|
||||||
|
twMat
|
||||||
|
xcazin
|
||||||
""">>
|
""">>
|
||||||
|
|||||||
15
editions/test/tiddlers/tests/data/filters/Recursion.tid
Normal file
15
editions/test/tiddlers/tests/data/filters/Recursion.tid
Normal 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>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
title: Genesis/DollarSigns
|
||||||
|
description: Usage of genesis widget with attributes starting with dollar signs
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$genesis $type="$let" myvar="Kitten">(<$text text=<<myvar>>/>)</$genesis>
|
||||||
|
<$genesis $type="$let" $$myvar="Kitten">(<$text text=<<$myvar>>/>)</$genesis>
|
||||||
|
+
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>(Kitten)(Kitten)</p>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
title: Genesis/MultipleAttributes
|
||||||
|
description: Usage of genesis widget with multiple attributes
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$genesis $type="$let" $names="myvar other" $values="Kitten Donkey" myvar={{{ Shark }}}>(<$text text=<<myvar>>/>|<$text text=<<other>>/>)</$genesis>
|
||||||
|
<$genesis $type="$let" $names="$myvar $other" $values="Kitten Donkey" $$myvar="Shark">(<$text text=<<$myvar>>/>|<$text text=<<$other>>/>)</$genesis>
|
||||||
|
+
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>(Kitten|Donkey)(Kitten|Donkey)</p>
|
||||||
14
editions/test/tiddlers/tests/data/genesis-widget/Simple.tid
Normal file
14
editions/test/tiddlers/tests/data/genesis-widget/Simple.tid
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
title: Genesis/Simple
|
||||||
|
description: Simple usage of genesis widget
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$genesis $type="div">Mouse</$genesis>
|
||||||
|
<$genesis $type="div" class="tc-thing" label="Squeak">Mouse</$genesis>
|
||||||
|
+
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p><div>Mouse</div><div class="tc-thing" label="Squeak">Mouse</div></p>
|
||||||
13
editions/test/tiddlers/tests/data/transclude/Recursion.tid
Normal file
13
editions/test/tiddlers/tests/data/transclude/Recursion.tid
Normal 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>
|
||||||
@@ -234,6 +234,38 @@ Tests the checkbox widget thoroughly.
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// https://github.com/Jermolene/TiddlyWiki5/issues/6871
|
||||||
|
const listModeTestsWithListField = (
|
||||||
|
listModeTests
|
||||||
|
.filter(data => data.widgetText.includes("listField='colors'"))
|
||||||
|
.map(data => {
|
||||||
|
const newData = {
|
||||||
|
...data,
|
||||||
|
tiddlers: data.tiddlers.map(tiddler => ({...tiddler, list: tiddler.colors, colors: undefined})),
|
||||||
|
widgetText: data.widgetText.replace("listField='colors'", "listField='list'"),
|
||||||
|
expectedChange: {
|
||||||
|
"Colors": { list: data.expectedChange.Colors.colors.split(' ') }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return newData;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const listModeTestsWithTagsField = (
|
||||||
|
listModeTests
|
||||||
|
.filter(data => data.widgetText.includes("listField='colors'"))
|
||||||
|
.map(data => {
|
||||||
|
const newData = {
|
||||||
|
...data,
|
||||||
|
tiddlers: data.tiddlers.map(tiddler => ({...tiddler, tags: tiddler.colors, colors: undefined})),
|
||||||
|
widgetText: data.widgetText.replace("listField='colors'", "listField='tags'"),
|
||||||
|
expectedChange: {
|
||||||
|
"Colors": { tags: data.expectedChange.Colors.colors.split(' ') }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return newData;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const indexListModeTests = listModeTests.map(data => {
|
const indexListModeTests = listModeTests.map(data => {
|
||||||
const newData = {...data};
|
const newData = {...data};
|
||||||
const newName = data.testName.replace('list mode', 'index list mode');
|
const newName = data.testName.replace('list mode', 'index list mode');
|
||||||
@@ -453,6 +485,8 @@ Tests the checkbox widget thoroughly.
|
|||||||
const checkboxTestData = fieldModeTests.concat(
|
const checkboxTestData = fieldModeTests.concat(
|
||||||
indexModeTests,
|
indexModeTests,
|
||||||
listModeTests,
|
listModeTests,
|
||||||
|
listModeTestsWithListField,
|
||||||
|
listModeTestsWithTagsField,
|
||||||
indexListModeTests,
|
indexListModeTests,
|
||||||
filterModeTests,
|
filterModeTests,
|
||||||
);
|
);
|
||||||
@@ -495,7 +529,7 @@ Tests the checkbox widget thoroughly.
|
|||||||
for (const fieldName of Object.keys(change)) {
|
for (const fieldName of Object.keys(change)) {
|
||||||
const expectedValue = change[fieldName];
|
const expectedValue = change[fieldName];
|
||||||
const fieldValue = tiddler.fields[fieldName];
|
const fieldValue = tiddler.fields[fieldName];
|
||||||
expect(fieldValue).toBe(expectedValue);
|
expect(fieldValue).toEqual(expectedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
created: 20220721200137586
|
created: 20220721200137586
|
||||||
modified: 20220721200137586
|
modified: 20220819200137586
|
||||||
tags: [[Table of Contents]]
|
tags: [[Table of Contents]]
|
||||||
title: Code of Conduct
|
title: Code of Conduct
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
@@ -17,6 +17,7 @@ These principles guide technical and non-technical decisions, and help contribut
|
|||||||
* We recognise that the motivation for sharing and helping is usually for appreciation, and not financial gain, and so we take care to acknowledge and ''thank the people who enrich the community by sharing what they have created''
|
* We recognise that the motivation for sharing and helping is usually for appreciation, and not financial gain, and so we take care to acknowledge and ''thank the people who enrich the community by sharing what they have created''
|
||||||
* While we are united in our interest in TiddlyWiki, we differ in every other conceivable way. We choose to focus on what unites us, and ''avoid unnecessarily mixing contentious topics like religion and politics''
|
* While we are united in our interest in TiddlyWiki, we differ in every other conceivable way. We choose to focus on what unites us, and ''avoid unnecessarily mixing contentious topics like religion and politics''
|
||||||
* We treat each other with respect, and start with the assumption that ''others are acting in good faith''
|
* We treat each other with respect, and start with the assumption that ''others are acting in good faith''
|
||||||
|
* We avoid discriminatory language
|
||||||
* We try to use our strength as a community to help others
|
* We try to use our strength as a community to help others
|
||||||
* We avoid responding when angry or upset because we try to de-escalate conflict
|
* We avoid responding when angry or upset because we try to de-escalate conflict
|
||||||
* We make sure we critique ideas, not people
|
* We make sure we critique ideas, not people
|
||||||
@@ -27,4 +28,6 @@ These principles guide technical and non-technical decisions, and help contribut
|
|||||||
|
|
||||||
Our discussions are in English. It is not the first language of many people in the community, nor do we all share the same cultural background and reference points. So we take care to use language that is clear and unambigous, and avoid cultural references or jokes that will not be widely understood.
|
Our discussions are in English. It is not the first language of many people in the community, nor do we all share the same cultural background and reference points. So we take care to use language that is clear and unambigous, and avoid cultural references or jokes that will not be widely understood.
|
||||||
|
|
||||||
|
It is not acceptable to make jokes or other comments that discriminate by race, gender, sexuality, or other protected characteristic.
|
||||||
|
|
||||||
As an inclusive community, we are committed to making sure that TiddlyWiki is an accessible tool that understands the needs of people with disabilities.
|
As an inclusive community, we are committed to making sure that TiddlyWiki is an accessible tool that understands the needs of people with disabilities.
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
created: 20141230182901899
|
created: 20141230182901899
|
||||||
modified: 20210106151027090
|
modified: 20220226205227090
|
||||||
tags: [[Community Editions]] [[Community Plugins]]
|
tags: [[Community Editions]] [[Community Plugins]]
|
||||||
title: "GSD5" by Roma Hicks
|
title: "GSD5" by Roma Hicks
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
url: http://gsd5.tiddlyspot.com/
|
url: http://gsd5.tiddlyhost.com/
|
||||||
|
|
||||||
An adaptation of the [[TiddlyWiki powered GTD® system formerly known as MonkeyGTD|http://mgsd.tiddlyspot.com/]] for TiddlyWiki version 5.
|
An adaptation of the [[TiddlyWiki powered GTD® system formerly known as MonkeyGTD|http://mgsd.tiddlyspot.com/]] for TiddlyWiki version 5.
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
created: 20131129090249275
|
created: 20131129090249275
|
||||||
modified: 20200507203622933
|
modified: 20220819041016415
|
||||||
tags: [[Working with TiddlyWiki]]
|
tags: [[Working with TiddlyWiki]]
|
||||||
title: GettingStarted
|
title: GettingStarted
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
The easiest way to use TiddlyWiki is to sign up for a free account with [[Tiddlyhost]], an independently run community service:
|
The easiest way to use ~TiddlyWiki is to sign up for a free account with [[Tiddlyhost|https://tiddlyhost.com/]], an independently run community service. If you find Tiddlyhost useful, please consider [[donation or sponsorship|https://tiddlyhost.com/donate]].
|
||||||
|
|
||||||
https://tiddlyhost.com/
|
Click here to download an empty copy of ~TiddlyWiki: {{$:/editions/tw5.com/snippets/download-empty-button}}
|
||||||
|
|
||||||
If you find Tiddlyhost useful, please consider [[donation or sponsorship|https://tiddlyhost.com/donate]].
|
|
||||||
|
|
||||||
Click here to download an empty copy of TiddlyWiki: {{$:/editions/tw5.com/snippets/download-empty-button}}
|
|
||||||
|
|
||||||
The next step is to choose a method for saving changes. There's a wide variety of methods available, with different features and limitations. Click on the badge for a method to see more information about it. You can also click on one of the platform filters to restrict the listing to methods that work with that platform.
|
The next step is to choose a method for saving changes. There's a wide variety of methods available, with different features and limitations. Click on the badge for a method to see more information about it. You can also click on one of the platform filters to restrict the listing to methods that work with that platform.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
created: 20220909094340097
|
||||||
|
modified: 20220909094340097
|
||||||
|
title: Hidden Setting: Sync System Tiddlers From Server
|
||||||
|
tags: [[Hidden Settings]]
|
||||||
|
|
||||||
|
<<.from-version "5.1.23">> Determines whether system tiddlers are synced from the server under Node.js. (Note that this is a one-way setting; system tiddlers are always synced //to// the server).
|
||||||
|
|
||||||
|
* `no` -- system tiddlers are not synced from the server (default)
|
||||||
|
* `yes` -- system tiddlers are synced from the server
|
||||||
|
|
||||||
|
Engaging sync of system tiddlers means that tiddlers such as $:/StoryList and $:/HistoryList get synced, which can lead to unexpected outcomes when multiple users are connected to the same server at the same time (it means that the story sequence is synced between all the users).
|
||||||
|
|
||||||
|
$:/config/SyncSystemTiddlersFromServer
|
||||||
@@ -22,7 +22,7 @@ The new tiddler message is usually generated with the ButtonWidget or ActionSend
|
|||||||
|
|
||||||
! Examples
|
! Examples
|
||||||
|
|
||||||
To make a button that creates new tiddlers tagged "task", create a tiddler called "TaskTemplate" with that tag, and then make your button like this:
|
To make a button that creates new tiddlers tagged "task", create a tiddler called "~TaskTemplate" with that tag, and then make your button like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
<$button message="tm-new-tiddler" param="TaskTemplate">New Task</$button>
|
<$button message="tm-new-tiddler" param="TaskTemplate">New Task</$button>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
created: 20140912140651119
|
created: 20140912140651119
|
||||||
modified: 20220401151525812
|
modified: 20220812144516626
|
||||||
saving-browser: Firefox Chrome Edge [[Internet Explorer]] Safari Opera [[Standalone App]]
|
saving-browser: Firefox Chrome Edge [[Internet Explorer]] Safari Opera [[Standalone App]]
|
||||||
saving-os: Windows Mac Linux Android iOS
|
saving-os: Windows Mac Linux Android iOS
|
||||||
tags: [[Working with TiddlyWiki]]
|
tags: [[Working with TiddlyWiki]]
|
||||||
@@ -34,7 +34,7 @@ type: text/vnd.tiddlywiki
|
|||||||
\end
|
\end
|
||||||
<$vars stateTiddler=<<qualify "$:/state/gettingstarted">> >
|
<$vars stateTiddler=<<qualify "$:/state/gettingstarted">> >
|
||||||
|
|
||||||
Available methods for saving changes with TiddlyWiki:
|
Available methods for saving changes with ~TiddlyWiki:
|
||||||
|
|
||||||
<div class="tc-wrapper-flex">
|
<div class="tc-wrapper-flex">
|
||||||
<div class="tc-saving-sidebar">
|
<div class="tc-saving-sidebar">
|
||||||
|
|||||||
@@ -46,21 +46,17 @@ open the ''example edition'' in a new window
|
|||||||
|
|
||||||
<$macrocall $name="copy-to-clipboard-above-right" src=<<__src__>>/>
|
<$macrocall $name="copy-to-clipboard-above-right" src=<<__src__>>/>
|
||||||
|
|
||||||
```
|
<$codeblock code=<<__src__>>/>
|
||||||
$src$
|
|
||||||
```
|
|
||||||
|
|
||||||
That renders as:
|
That renders as:
|
||||||
|
|
||||||
$$$text/vnd.tiddlywiki
|
<$macrocall $name="__src__"/>
|
||||||
$src$
|
|
||||||
$$$
|
|
||||||
|
|
||||||
... and the underlying HTML is:
|
... and the underlying HTML is:
|
||||||
|
|
||||||
$$$text/vnd.tiddlywiki>text/html
|
<$wikify name="html" text=<<__src__>> output="html">
|
||||||
$src$
|
<$codeblock code=<<html>>/>
|
||||||
$$$
|
</$wikify>
|
||||||
</div>
|
</div>
|
||||||
\end
|
\end
|
||||||
|
|
||||||
@@ -69,15 +65,12 @@ $$$
|
|||||||
|
|
||||||
<$macrocall $name="copy-to-clipboard-above-right" src=<<__src__>>/>
|
<$macrocall $name="copy-to-clipboard-above-right" src=<<__src__>>/>
|
||||||
|
|
||||||
```
|
<$codeblock code=<<__src__>>/>
|
||||||
$src$
|
|
||||||
```
|
|
||||||
|
|
||||||
That renders as:
|
That renders as:
|
||||||
|
|
||||||
$$$text/vnd.tiddlywiki
|
<$macrocall $name="__src__"/>
|
||||||
$src$
|
|
||||||
$$$
|
|
||||||
</div>
|
</div>
|
||||||
\end
|
\end
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
created: 20181002131215403
|
created: 20181002131215403
|
||||||
modified: 2020031109590546
|
modified: 20220909094340097
|
||||||
tags: [[WebServer API]]
|
tags: [[WebServer API]]
|
||||||
title: WebServer API: Get All Tiddlers
|
title: WebServer API: Get All Tiddlers
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
@@ -17,6 +17,8 @@ Parameters:
|
|||||||
|
|
||||||
In order to avoid denial of service attacks with malformed filters in the default configuration the only filter that is accepted is the default filter "[all[tiddlers]!is[system]sort[title]]"; attempts to use any other filter will result in an HTTP 403 error.
|
In order to avoid denial of service attacks with malformed filters in the default configuration the only filter that is accepted is the default filter "[all[tiddlers]!is[system]sort[title]]"; attempts to use any other filter will result in an HTTP 403 error.
|
||||||
|
|
||||||
|
<<.note "System tiddlers will not be returned by this API unless the [[Hidden Setting: Sync System Tiddlers From Server]] is explicitly switched on by setting $:/config/SyncSystemTiddlersFromServer to `yes`">>
|
||||||
|
|
||||||
To enable a particular filter, create a tiddler with the title "$:/config/Server/ExternalFilters/" concatenated with the filter text, and the text field set to "yes". For example, the TiddlyWeb plugin includes the following shadow tiddler to enable the filter that it requires:
|
To enable a particular filter, create a tiddler with the title "$:/config/Server/ExternalFilters/" concatenated with the filter text, and the text field set to "yes". For example, the TiddlyWeb plugin includes the following shadow tiddler to enable the filter that it requires:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
17
editions/tw5.com/tiddlers/widgets/ErrorWidget.tid
Normal file
17
editions/tw5.com/tiddlers/widgets/ErrorWidget.tid
Normal 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 |
|
||||||
29
editions/tw5.com/tiddlers/widgets/GenesisWidget.tid
Normal file
29
editions/tw5.com/tiddlers/widgets/GenesisWidget.tid
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
caption: genesis
|
||||||
|
created: 20220924140702430
|
||||||
|
modified: 20220924140702430
|
||||||
|
tags: Widgets
|
||||||
|
title: GenesisWidget
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
! Introduction
|
||||||
|
|
||||||
|
<<.from-version "5.2.4">> The <<.wlink GenesisWidget>> widget 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.
|
||||||
|
|
||||||
|
! Content and Attributes
|
||||||
|
|
||||||
|
The content of the <<.wlink GenesisWidget>> widget is used as the content of the dynamically created widget.
|
||||||
|
|
||||||
|
|!Attribute |!Description |
|
||||||
|
|$type |The type of widget or element to create (an initial `$` indicates a widget, otherwise an HTML element will be created) |
|
||||||
|
|$names |An optional filter evaluating to the names of a list of attributes to be applied to the widget |
|
||||||
|
|$values |An optional filter evaluating to the values corresponding to the list of names specified in `$names` |
|
||||||
|
|//{other attributes starting with $}// |Other attributes starting with a single dollar sign are reserved for future use |
|
||||||
|
|//{attributes starting with $$}// |Attributes starting with two dollar signs are appplied as attributes to the output widget, but with the attribute name changed to use a single dollar sign |
|
||||||
|
|//{attributes not starting with $}// |Any other attributes that do not start with a dollar are applied as attributes to the output widget |
|
||||||
|
|
||||||
|
Note that attributes explicitly specified take precedence over attributes with the same name specified in the `$names` filter.
|
||||||
|
|
||||||
|
! Examples
|
||||||
|
|
||||||
|
<$macrocall $name='wikitext-example-without-html'
|
||||||
|
src='<$genesis $type="div" class="tc-thing" label="Squeak">Mouse</$genesis>'/>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
title: LetWidget
|
title: LetWidget
|
||||||
created: 20211028115900000
|
created: 20211028115900000
|
||||||
|
modified: 20221001094658854
|
||||||
tags: Widgets
|
tags: Widgets
|
||||||
caption: let
|
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.
|
The content of the <<.wid let>> widget is the scope for the value assigned to the variable.
|
||||||
|
|
||||||
|!Attribute |!Description |
|
|!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.
|
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
|
! Examples
|
||||||
|
|
||||||
Consider a case where you need to set multiple variables, where some depend on the evaluation of others.
|
Consider a case where you need to set multiple variables, where some depend on the evaluation of others.
|
||||||
|
|||||||
@@ -497,3 +497,5 @@ Nolan Darilek, @NDarilek, 2022/06/21
|
|||||||
Keiichi Shiga (🎈 BALLOON | FU-SEN), @fu-sen. 2022/07/07
|
Keiichi Shiga (🎈 BALLOON | FU-SEN), @fu-sen. 2022/07/07
|
||||||
|
|
||||||
Nathaniel Knight, @nathanielknight, 2022/07/26
|
Nathaniel Knight, @nathanielknight, 2022/07/26
|
||||||
|
|
||||||
|
HuanCheng Bai, @bestony, 2022/09/17
|
||||||
|
|||||||
@@ -3,121 +3,13 @@ tags: $:/tags/EditPreview
|
|||||||
list-after: $:/core/ui/EditTemplate/body/preview/output
|
list-after: $:/core/ui/EditTemplate/body/preview/output
|
||||||
caption: parse tree
|
caption: parse tree
|
||||||
|
|
||||||
\whitespace trim
|
\define preview(mode)
|
||||||
|
<$wikify name="preview-text" text={{!!text}} type={{!!type}} mode="$mode$" output="parsetree">
|
||||||
\procedure preview-node-properties(node)
|
<pre>
|
||||||
<$let excludeProperties="text type tag children attributes orderedAttributes">
|
<code>
|
||||||
<$list filter="[<node>jsonindexes[]] -[subfilter<excludeProperties>] +[limit[1]]" variable="ignore">
|
<$text text=<<preview-text>>/>
|
||||||
<table>
|
</code>
|
||||||
<tbody>
|
</pre>
|
||||||
<$list filter="[<node>jsonindexes[]] -[subfilter<excludeProperties>] +[sort[]]" variable="index">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<$text text=<<index>>/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<$text text={{{ [<node>jsonget<index>] }}}/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</$list>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</$list>
|
|
||||||
</$let>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-attribute-string(attribute)
|
|
||||||
<$text text={{{ [<attribute>jsonget[value]] }}}/>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-attribute-indirect(attribute)
|
|
||||||
{{<$text text={{{ [<attribute>jsonget[textReference]] }}}/>}}
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-attribute-macro(attribute)
|
|
||||||
<<
|
|
||||||
<$text text={{{ [<attribute>jsonget[value],[name]] }}}/>
|
|
||||||
<$list filter="[<attribute>jsonindexes[value],[params]]" variable="index">
|
|
||||||
|
|
||||||
<$list filter="[<attribute>jsonget[value],[params],<index>,[name]]" variable="ignore">
|
|
||||||
<$text text={{{ [<attribute>jsonget[value],[params],<index>,[name]] }}}/>
|
|
||||||
:
|
|
||||||
</$list>
|
|
||||||
<$text text={{{ [<attribute>jsonget[value],[params],<index>,[value]] }}}/>
|
|
||||||
</$list>
|
|
||||||
>>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-attributes(node)
|
|
||||||
<$list filter="[<node>jsonindexes[attributes]limit[1]]" variable="ignore">
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<$list filter="[<node>jsonindexes[attributes]sort[]]" variable="index">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<$text text=<<index>>/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<$let type={{{ [<node>jsonget[attributes],<index>,[type]] }}}>
|
|
||||||
<$transclude $variable={{{ [<type>match[string]then[preview-node-attribute-string]] :else[<type>match[indirect]then[preview-node-attribute-indirect]] :else[<type>match[macro]then[preview-node-attribute-macro]] }}} attribute={{{ [<node>jsonget[attributes],<index>] }}}/>
|
|
||||||
</$let>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</$list>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</$list>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-children(node)
|
|
||||||
<div style="padding:4px 4px 0 4px;">
|
|
||||||
<$transclude $variable="preview-node-properties" node=<<node>>/>
|
|
||||||
<$transclude $variable="preview-node-attributes" node=<<node>>/>
|
|
||||||
<$transclude $variable="preview-node-list" nodeList={{{ [<node>jsonget[children]] }}}/>
|
|
||||||
</div>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-title-widget(node)
|
|
||||||
<div style="border:2px solid red;margin:4px;">
|
|
||||||
<div style="background:red;color:white;padding:4px;">
|
|
||||||
<$<$text text={{{ [<node>jsonget[type]] }}}/>>
|
|
||||||
</div>
|
|
||||||
<$transclude $variable="preview-node-children" node=<<node>>/>
|
|
||||||
</div>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-title-element(node)
|
|
||||||
<div style="border:2px solid purple;margin:4px;">
|
|
||||||
<div style="background:purple;color:white;padding:4px;">
|
|
||||||
<<$text text={{{ [<node>jsonget[tag]] }}}/>>
|
|
||||||
</div>
|
|
||||||
<$transclude $variable="preview-node-children" node=<<node>>/>
|
|
||||||
</div>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-title-text(node)
|
|
||||||
<div style="border:2px solid green;margin:4px;">
|
|
||||||
<div style="background:green;color:white;padding:4px;">
|
|
||||||
<span style="color:#ff0;font-weight:bold;">"</span><span style="white-space:pre-wrap;"><$text text={{{ [<node>jsonget[text]] }}}/></span><span style="color:#ff0;font-weight:bold;">"</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node(node)
|
|
||||||
<$let type={{{ [<node>jsonget[type]] }}}>
|
|
||||||
<$transclude $variable={{{ [<type>match[element]then[preview-node-title-element]] :else[<type>match[text]then[preview-node-title-text]] :else[[preview-node-title-widget]] }}} node=<<node>>/>
|
|
||||||
</$let>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview-node-list(nodeList)
|
|
||||||
<$list filter="[<nodeList>jsonindexes[]]" variable="index">
|
|
||||||
<$transclude $variable="preview-node" node={{{ [<nodeList>jsonget<index>] }}}/>
|
|
||||||
</$list>
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure preview(mode)
|
|
||||||
<$wikify name="preview-json" text={{!!text}} type={{!!type}} mode=<<mode>> output="parsetree">
|
|
||||||
<$transclude $variable="preview-node-list" nodeList=<<preview-json>>/>
|
|
||||||
</$wikify>
|
</$wikify>
|
||||||
\end
|
\end
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5
|
|||||||
/*global $tw: true */
|
/*global $tw: true */
|
||||||
"use strict";
|
"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";
|
exports.name = "jasmine";
|
||||||
// Ensure this startup module is executed in the right order.
|
// Ensure this startup module is executed in the right order.
|
||||||
|
|||||||
93
plugins/tiddlywiki/jasmine/run-wiki-based-tests.js
Normal file
93
plugins/tiddlywiki/jasmine/run-wiki-based-tests.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/jasmine/run-wiki-based-tests.js
|
||||||
|
type: application/javascript
|
||||||
|
tags: [[$:/tags/test-spec]]
|
||||||
|
|
||||||
|
Tests the wiki based tests
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var TEST_WIKI_TIDDLER_FILTER = "[type[text/vnd.tiddlywiki-multiple]tag[$:/tags/wiki-test-spec]]";
|
||||||
|
|
||||||
|
var widget = require("$:/core/modules/widgets/widget.js");
|
||||||
|
|
||||||
|
describe("Wiki-based tests", function() {
|
||||||
|
|
||||||
|
// Step through the test tiddlers
|
||||||
|
var tests = $tw.wiki.filterTiddlers(TEST_WIKI_TIDDLER_FILTER);
|
||||||
|
$tw.utils.each(tests,function(title) {
|
||||||
|
var tiddler = $tw.wiki.getTiddler(title);
|
||||||
|
it(tiddler.fields.title + ": " + tiddler.fields.description, function() {
|
||||||
|
// Add our tiddlers
|
||||||
|
var wiki = new $tw.Wiki();
|
||||||
|
wiki.addTiddlers(readMultipleTiddlersTiddler(title));
|
||||||
|
// Complain if we don't have the ouput and expected results
|
||||||
|
if(!wiki.tiddlerExists("Output")) {
|
||||||
|
throw "Missing 'Output' tiddler";
|
||||||
|
}
|
||||||
|
if(!wiki.tiddlerExists("ExpectedResult")) {
|
||||||
|
throw "Missing 'ExpectedResult' tiddler";
|
||||||
|
}
|
||||||
|
// Construct the widget node
|
||||||
|
var text = "{{Output}}\n\n";
|
||||||
|
var widgetNode = createWidgetNode(parseText(text,wiki),wiki);
|
||||||
|
// Render the widget node to the DOM
|
||||||
|
var wrapper = renderWidgetNode(widgetNode);
|
||||||
|
// Clear changes queue
|
||||||
|
wiki.clearTiddlerEventQueue();
|
||||||
|
// Run the actions if provided
|
||||||
|
if(wiki.tiddlerExists("Actions")) {
|
||||||
|
widgetNode.invokeActionString(wiki.getTiddlerText("Actions"));
|
||||||
|
refreshWidgetNode(widgetNode,wrapper);
|
||||||
|
}
|
||||||
|
// Test the rendering
|
||||||
|
expect(wrapper.innerHTML).toBe(wiki.getTiddlerText("ExpectedResult"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function readMultipleTiddlersTiddler(title) {
|
||||||
|
var rawTiddlers = $tw.wiki.getTiddlerText(title).split("\n+\n");
|
||||||
|
var tiddlers = [];
|
||||||
|
$tw.utils.each(rawTiddlers,function(rawTiddler) {
|
||||||
|
var fields = Object.create(null),
|
||||||
|
split = rawTiddler.split(/\r?\n\r?\n/mg);
|
||||||
|
if(split.length >= 1) {
|
||||||
|
fields = $tw.utils.parseFields(split[0],fields);
|
||||||
|
}
|
||||||
|
if(split.length >= 2) {
|
||||||
|
fields.text = split.slice(1).join("\n\n");
|
||||||
|
}
|
||||||
|
tiddlers.push(fields);
|
||||||
|
});
|
||||||
|
return tiddlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWidgetNode(parser,wiki) {
|
||||||
|
return wiki.makeWidget(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseText(text,wiki,options) {
|
||||||
|
return wiki.parseText("text/vnd.tiddlywiki",text,options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderWidgetNode(widgetNode) {
|
||||||
|
$tw.fakeDocument.setSequenceNumber(0);
|
||||||
|
var wrapper = $tw.fakeDocument.createElement("div");
|
||||||
|
widgetNode.render(wrapper,null);
|
||||||
|
// console.log(require("util").inspect(wrapper,{depth: 8}));
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshWidgetNode(widgetNode,wrapper) {
|
||||||
|
widgetNode.refresh(widgetNode.wiki.changedTiddlers,wrapper);
|
||||||
|
// console.log(require("util").inspect(wrapper,{depth: 8}));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user