mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-02-16 15:09:50 +00:00
Compare commits
19 Commits
dynamic-ma
...
default-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82fc2f24b2 | ||
|
|
b6106ee4d9 | ||
|
|
d2faad2c58 | ||
|
|
f41ed1c88c | ||
|
|
73cd48cada | ||
|
|
3b84a7042c | ||
|
|
3f81e3651e | ||
|
|
c4d0b61827 | ||
|
|
adf9853ce4 | ||
|
|
5f03d1e6ac | ||
|
|
0ffb4d988b | ||
|
|
f2fbcf60a2 | ||
|
|
8276f66edf | ||
|
|
b6859c5a2d | ||
|
|
beb6839a35 | ||
|
|
f3e9beb1e1 | ||
|
|
2a1c607450 | ||
|
|
9b56734451 | ||
|
|
2f8d53d3f7 |
21
boot/boot.js
21
boot/boot.js
@@ -316,25 +316,8 @@ $tw.utils.htmlDecode = function(s) {
|
||||
return s.toString().replace(/</mg,"<").replace(/ /mg,"\xA0").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
||||
};
|
||||
|
||||
/*
|
||||
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
|
||||
*/
|
||||
$tw.utils.getLocationHash = function() {
|
||||
const href = window.location.href,
|
||||
idx = href.indexOf("#");
|
||||
|
||||
if(idx === -1) {
|
||||
return "#";
|
||||
}
|
||||
|
||||
const afterHash = href.substring(idx + 1);
|
||||
if(afterHash.startsWith("#") || afterHash.startsWith("%23")) {
|
||||
// Special case: ignore location hash if it itself starts with a #
|
||||
return "#";
|
||||
}
|
||||
return href.substring(idx);
|
||||
};
|
||||
|
||||
/** @deprecated Use window.location.hash instead. */
|
||||
$tw.utils.getLocationHash = () => window.location.hash;
|
||||
|
||||
/** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */
|
||||
$tw.utils.pad = function(value,length = 2) {
|
||||
|
||||
@@ -42,8 +42,6 @@ function Server(options) {
|
||||
}
|
||||
// Setup the default required plugins
|
||||
this.requiredPlugins = this.get("required-plugins").split(',');
|
||||
// Initialise CORS
|
||||
this.corsEnable = this.get("cors-enable") === "yes";
|
||||
// Initialise CSRF
|
||||
this.csrfDisable = this.get("csrf-disable") === "yes";
|
||||
// Initialize Gzip compression
|
||||
@@ -263,13 +261,6 @@ Server.prototype.requestHandler = function(request,response,options) {
|
||||
state.urlInfo = url.parse(request.url);
|
||||
state.queryParameters = querystring.parse(state.urlInfo.query);
|
||||
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
|
||||
// Enable CORS
|
||||
if(this.corsEnable) {
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Headers", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "*");
|
||||
response.setHeader("Access-Control-Expose-Headers", "*");
|
||||
}
|
||||
state.sendResponse = sendResponse.bind(self,request,response);
|
||||
// Get the principals authorized to access this resource
|
||||
state.authorizationType = options.authorizationType || this.methodMappings[request.method] || "readers";
|
||||
@@ -294,12 +285,6 @@ Server.prototype.requestHandler = function(request,response,options) {
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
// Reply to OPTIONS
|
||||
if(this.corsEnable && request.method === "OPTIONS") {
|
||||
response.writeHead(204);
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
// Find the route that matches this path
|
||||
var route = self.findMatchingRoute(request,state);
|
||||
// Optionally output debug info
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*\
|
||||
title: $:/core-server/modules/utils/escapecss.js
|
||||
type: application/javascript
|
||||
module-type: utils-node
|
||||
|
||||
Provides CSS.escape() functionality.
|
||||
|
||||
\*/
|
||||
|
||||
"use strict";
|
||||
|
||||
exports.escapeCSS = (function() {
|
||||
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||
|
||||
/* eslint-disable */
|
||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||
return function(value) {
|
||||
if (arguments.length == 0) {
|
||||
throw new TypeError('`CSS.escape` requires an argument.');
|
||||
}
|
||||
var string = String(value);
|
||||
var length = string.length;
|
||||
var index = -1;
|
||||
var codeUnit;
|
||||
var result = '';
|
||||
var firstCodeUnit = string.charCodeAt(0);
|
||||
while (++index < length) {
|
||||
codeUnit = string.charCodeAt(index);
|
||||
// Note: there’s no need to special-case astral symbols, surrogate
|
||||
// pairs, or lone surrogates.
|
||||
|
||||
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
||||
// (U+FFFD).
|
||||
if (codeUnit == 0x0000) {
|
||||
result += '\uFFFD';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||
// U+007F, […]
|
||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
||||
// If the character is the first character and is in the range [0-9]
|
||||
// (U+0030 to U+0039), […]
|
||||
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||
// If the character is the second character and is in the range [0-9]
|
||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||
(
|
||||
index == 1 &&
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||
firstCodeUnit == 0x002D
|
||||
)
|
||||
) {
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
||||
result += '\\' + codeUnit.toString(16) + ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is the first character and is a `-` (U+002D), and
|
||||
// there is no second character, […]
|
||||
index == 0 &&
|
||||
length == 1 &&
|
||||
codeUnit == 0x002D
|
||||
) {
|
||||
result += '\\' + string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the character is not handled by one of the above rules and is
|
||||
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
||||
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||
if (
|
||||
codeUnit >= 0x0080 ||
|
||||
codeUnit == 0x002D ||
|
||||
codeUnit == 0x005F ||
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||
) {
|
||||
// the character itself
|
||||
result += string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, the escaped character.
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character
|
||||
result += '\\' + string.charAt(index);
|
||||
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/* eslint-enable */
|
||||
})();
|
||||
@@ -30,6 +30,7 @@ Error/DeserializeOperator/MissingOperand: Filter Error: Missing operand for 'des
|
||||
Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserializer provided as operand for the 'deserialize' operator
|
||||
Error/Filter: Filter error
|
||||
Error/FilterSyntax: Syntax error in filter expression
|
||||
Error/FilterPragma: Filter Error: Unknown filter pragma
|
||||
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
|
||||
Error/IsFilterOperator: Filter Error: Unknown parameter for the 'is' filter operator
|
||||
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
|
||||
|
||||
@@ -3,6 +3,7 @@ title: $:/language/Search/
|
||||
DefaultResults/Caption: List
|
||||
Filter/Caption: Filter
|
||||
Filter/Hint: Search via a [[filter expression|https://tiddlywiki.com/static/Filters.html]]
|
||||
Filter/AllowDuplicates: Allow duplicate results
|
||||
Filter/Matches: //<small><<resultCount>> matches</small>//
|
||||
Matches: //<small><<resultCount>> matches</small>//
|
||||
Matches/All: All matches:
|
||||
|
||||
@@ -146,14 +146,16 @@ exports.parseFilter = function(filterString) {
|
||||
match;
|
||||
var whitespaceRegExp = /(\s+)/mg,
|
||||
// Groups:
|
||||
// 1 - entire filter run prefix
|
||||
// 2 - filter run prefix itself
|
||||
// 3 - filter run prefix suffixes
|
||||
// 4 - opening square bracket following filter run prefix
|
||||
// 5 - double quoted string following filter run prefix
|
||||
// 6 - single quoted string following filter run prefix
|
||||
// 7 - anything except for whitespace and square brackets
|
||||
operandRegExp = /((?:\+|\-|~|(?:=>?)|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
||||
// 1 - pragma
|
||||
// 2 - pragma suffix
|
||||
// 3 - entire filter run prefix
|
||||
// 4 - filter run prefix name
|
||||
// 5 - filter run prefix suffixes
|
||||
// 6 - opening square bracket following filter run prefix
|
||||
// 7 - double quoted string following filter run prefix
|
||||
// 8 - single quoted string following filter run prefix
|
||||
// 9 - anything except for whitespace and square brackets
|
||||
operandRegExp = /(?:::(\w+)(?:\:(\w+))?(?=\s|$)|((?:\+|\-|~|(?:=>?)|:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+)))/mg;
|
||||
while(p < filterString.length) {
|
||||
// Skip any whitespace
|
||||
whitespaceRegExp.lastIndex = p;
|
||||
@@ -170,18 +172,23 @@ exports.parseFilter = function(filterString) {
|
||||
};
|
||||
match = operandRegExp.exec(filterString);
|
||||
if(match && match.index === p) {
|
||||
// If there is a filter run prefix
|
||||
if(match[1]) {
|
||||
operation.prefix = match[1];
|
||||
// If there is a filter pragma
|
||||
operation.pragma = match[1];
|
||||
operation.suffix = match[2];
|
||||
p = match.index + match[0].length;
|
||||
} else if(match[3]) {
|
||||
// If there is a filter run prefix
|
||||
operation.prefix = match[3];
|
||||
p = p + operation.prefix.length;
|
||||
// Name for named prefixes
|
||||
if(match[2]) {
|
||||
operation.namedPrefix = match[2];
|
||||
if(match[4]) {
|
||||
operation.namedPrefix = match[4];
|
||||
}
|
||||
// Suffixes for filter run prefix
|
||||
if(match[3]) {
|
||||
if(match[5]) {
|
||||
operation.suffixes = [];
|
||||
$tw.utils.each(match[3].split(":"),function(subsuffix) {
|
||||
$tw.utils.each(match[5].split(":"),function(subsuffix) {
|
||||
operation.suffixes.push([]);
|
||||
$tw.utils.each(subsuffix.split(","),function(entry) {
|
||||
entry = $tw.utils.trim(entry);
|
||||
@@ -193,7 +200,7 @@ exports.parseFilter = function(filterString) {
|
||||
}
|
||||
}
|
||||
// Opening square bracket
|
||||
if(match[4]) {
|
||||
if(match[6]) {
|
||||
p = parseFilterOperation(operation.operators,filterString,p);
|
||||
} else {
|
||||
p = match.index + match[0].length;
|
||||
@@ -203,9 +210,9 @@ exports.parseFilter = function(filterString) {
|
||||
p = parseFilterOperation(operation.operators,filterString,p);
|
||||
}
|
||||
// Quoted strings and unquoted title
|
||||
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
|
||||
if(match[7] || match[8] || match[9]) { // Double quoted string, single quoted string or unquoted title
|
||||
operation.operators.push(
|
||||
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
|
||||
{operator: "title", operands: [{text: match[7] || match[8] || match[9]}]}
|
||||
);
|
||||
}
|
||||
results.push(operation);
|
||||
@@ -230,8 +237,8 @@ exports.getFilterRunPrefixes = function() {
|
||||
return this.filterRunPrefixes;
|
||||
}
|
||||
|
||||
exports.filterTiddlers = function(filterString,widget,source) {
|
||||
var fn = this.compileFilter(filterString);
|
||||
exports.filterTiddlers = function(filterString,widget,source,options) {
|
||||
var fn = this.compileFilter(filterString,options);
|
||||
try {
|
||||
const fnResult = fn.call(this,source,widget);
|
||||
return fnResult;
|
||||
@@ -241,17 +248,21 @@ exports.filterTiddlers = function(filterString,widget,source) {
|
||||
};
|
||||
|
||||
/*
|
||||
Compile a filter into a function with the signature fn(source,widget) where:
|
||||
Compile a filter into a function with the signature fn(source,widget,options) where:
|
||||
source: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)
|
||||
widget: an optional widget node for retrieving the current tiddler etc.
|
||||
options: optional hashmap of options
|
||||
options.defaultFilterRunPrefix: the default filter run prefix to use when none is specified
|
||||
*/
|
||||
exports.compileFilter = function(filterString) {
|
||||
exports.compileFilter = function(filterString,options) {
|
||||
var defaultFilterRunPrefix = (options || {}).defaultFilterRunPrefix || "or";
|
||||
var cacheKey = filterString + "|" + defaultFilterRunPrefix;
|
||||
if(!this.filterCache) {
|
||||
this.filterCache = Object.create(null);
|
||||
this.filterCacheCount = 0;
|
||||
}
|
||||
if(this.filterCache[filterString] !== undefined) {
|
||||
return this.filterCache[filterString];
|
||||
if(this.filterCache[cacheKey] !== undefined) {
|
||||
return this.filterCache[cacheKey];
|
||||
}
|
||||
var filterParseTree;
|
||||
try {
|
||||
@@ -330,7 +341,8 @@ exports.compileFilter = function(filterString) {
|
||||
regexp: operator.regexp
|
||||
},{
|
||||
wiki: self,
|
||||
widget: widget
|
||||
widget: widget,
|
||||
defaultFilterRunPrefix: defaultFilterRunPrefix
|
||||
});
|
||||
if($tw.utils.isArray(results)) {
|
||||
accumulator = self.makeTiddlerIterator(results);
|
||||
@@ -351,29 +363,45 @@ exports.compileFilter = function(filterString) {
|
||||
var filterRunPrefixes = self.getFilterRunPrefixes();
|
||||
// Wrap the operator functions in a wrapper function that depends on the prefix
|
||||
operationFunctions.push((function() {
|
||||
var options = {wiki: self, suffixes: operation.suffixes || []};
|
||||
switch(operation.prefix || "") {
|
||||
case "": // No prefix means that the operation is unioned into the result
|
||||
return filterRunPrefixes["or"](operationSubFunction, options);
|
||||
case "=": // The results of the operation are pushed into the result without deduplication
|
||||
return filterRunPrefixes["all"](operationSubFunction, options);
|
||||
case "-": // The results of this operation are removed from the main result
|
||||
return filterRunPrefixes["except"](operationSubFunction, options);
|
||||
case "+": // This operation is applied to the main results so far
|
||||
return filterRunPrefixes["and"](operationSubFunction, options);
|
||||
case "~": // This operation is unioned into the result only if the main result so far is empty
|
||||
return filterRunPrefixes["else"](operationSubFunction, options);
|
||||
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
|
||||
return filterRunPrefixes["let"](operationSubFunction, options);
|
||||
default:
|
||||
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
|
||||
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
|
||||
} else {
|
||||
if(operation.pragma) {
|
||||
switch(operation.pragma) {
|
||||
case "defaultprefix":
|
||||
defaultFilterRunPrefix = operation.suffix || "or";
|
||||
break;
|
||||
default:
|
||||
return function(results,source,widget) {
|
||||
results.clear();
|
||||
results.push($tw.language.getString("Error/FilterRunPrefix"));
|
||||
results.push($tw.language.getString("Error/FilterPragma"));
|
||||
};
|
||||
}
|
||||
}
|
||||
return function(results,source,widget) {
|
||||
// Dummy response
|
||||
};
|
||||
} else {
|
||||
var options = {wiki: self, suffixes: operation.suffixes || []};
|
||||
switch(operation.prefix || "") {
|
||||
case "": // Use the default filter run prefix if none is specified
|
||||
return filterRunPrefixes[defaultFilterRunPrefix](operationSubFunction, options);
|
||||
case "=": // The results of the operation are pushed into the result without deduplication
|
||||
return filterRunPrefixes["all"](operationSubFunction, options);
|
||||
case "-": // The results of this operation are removed from the main result
|
||||
return filterRunPrefixes["except"](operationSubFunction, options);
|
||||
case "+": // This operation is applied to the main results so far
|
||||
return filterRunPrefixes["and"](operationSubFunction, options);
|
||||
case "~": // This operation is unioned into the result only if the main result so far is empty
|
||||
return filterRunPrefixes["else"](operationSubFunction, options);
|
||||
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
|
||||
return filterRunPrefixes["let"](operationSubFunction, options);
|
||||
default:
|
||||
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
|
||||
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
|
||||
} else {
|
||||
return function(results,source,widget) {
|
||||
results.clear();
|
||||
results.push($tw.language.getString("Error/FilterRunPrefix"));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
})());
|
||||
});
|
||||
@@ -412,7 +440,7 @@ exports.compileFilter = function(filterString) {
|
||||
this.filterCache = Object.create(null);
|
||||
this.filterCacheCount = 0;
|
||||
}
|
||||
this.filterCache[filterString] = fnMeasured;
|
||||
this.filterCache[cacheKey] = fnMeasured;
|
||||
this.filterCacheCount++;
|
||||
return fnMeasured;
|
||||
};
|
||||
|
||||
@@ -16,6 +16,8 @@ exports.enlist = function(source,operator,options) {
|
||||
var allowDuplicates = false;
|
||||
switch(operator.suffix) {
|
||||
case "raw":
|
||||
// Intentional fallthrough
|
||||
case "all":
|
||||
allowDuplicates = true;
|
||||
break;
|
||||
case "dedupe":
|
||||
|
||||
@@ -13,7 +13,9 @@ Filter operator returning those input titles that pass a subfilter
|
||||
Export our filter function
|
||||
*/
|
||||
exports.filter = function(source,operator,options) {
|
||||
var filterFn = options.wiki.compileFilter(operator.operand),
|
||||
var suffixes = operator.suffixes || [],
|
||||
defaultFilterRunPrefix = (suffixes[0] || [options.defaultFilterRunPrefix] || [])[0] || "or",
|
||||
filterFn = options.wiki.compileFilter(operator.operand,{defaultFilterRunPrefix}),
|
||||
results = [],
|
||||
target = operator.prefix !== "!";
|
||||
source(function(tiddler,title) {
|
||||
|
||||
@@ -58,7 +58,7 @@ exports.split = makeStringBinaryOperator(
|
||||
);
|
||||
|
||||
exports["enlist-input"] = makeStringBinaryOperator(
|
||||
function(a,o,s) {return $tw.utils.parseStringArray("" + a,(s === "raw"));}
|
||||
function(a,o,s) {return $tw.utils.parseStringArray("" + a,(s === "raw" || s === "all"));}
|
||||
);
|
||||
|
||||
exports.join = makeStringReducingOperator(
|
||||
|
||||
@@ -13,7 +13,9 @@ Filter operator returning its operand evaluated as a filter
|
||||
Export our filter function
|
||||
*/
|
||||
exports.subfilter = function(source,operator,options) {
|
||||
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
|
||||
var suffixes = operator.suffixes || [],
|
||||
defaultFilterRunPrefix = (suffixes[0] || [options.defaultFilterRunPrefix] || [])[0] || "or";
|
||||
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source,{defaultFilterRunPrefix});
|
||||
if(operator.prefix === "!") {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
|
||||
@@ -107,14 +107,13 @@ exports.parseStringLiteral = function(source,pos) {
|
||||
type: "string",
|
||||
start: pos
|
||||
};
|
||||
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')|\[\[((?:[^\]]|\](?!\]))*)\]\]/g;
|
||||
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')/g;
|
||||
reString.lastIndex = pos;
|
||||
var match = reString.exec(source);
|
||||
if(match && match.index === pos) {
|
||||
node.value = match[1] !== undefined ? match[1] :(
|
||||
match[2] !== undefined ? match[2] : (
|
||||
match[3] !== undefined ? match[3] : match[4]
|
||||
));
|
||||
match[2] !== undefined ? match[2] : match[3]
|
||||
);
|
||||
node.end = pos + match[0].length;
|
||||
return node;
|
||||
} else {
|
||||
@@ -174,7 +173,7 @@ exports.parseMacroParameter = function(source,pos) {
|
||||
start: pos
|
||||
};
|
||||
// Define our regexp
|
||||
const reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[((?:[^\]]|\](?!\]))*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y;
|
||||
const reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for the parameter
|
||||
@@ -207,152 +206,28 @@ exports.parseMacroParameter = function(source,pos) {
|
||||
Look for a macro invocation. Returns null if not found, or {type: "transclude", attributes:, start:, end:}
|
||||
*/
|
||||
exports.parseMacroInvocationAsTransclusion = function(source,pos) {
|
||||
var node = {
|
||||
type: "transclude",
|
||||
start: pos,
|
||||
attributes: {},
|
||||
orderedAttributes: []
|
||||
};
|
||||
// Define our regexps
|
||||
var reVarName = /([^\s>"'=:]+)/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double opening angle bracket
|
||||
var token = $tw.utils.parseTokenString(source,pos,"<<");
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
pos = token.end;
|
||||
// Get the variable name for the macro
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,reVarName);
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(node,"$variable",token.match[1]);
|
||||
pos = token.end;
|
||||
// Check that the tag is terminated by a space or >>
|
||||
if(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === ">" && source.charAt(pos + 1) === ">") ) {
|
||||
return null;
|
||||
}
|
||||
// Process attributes
|
||||
pos = $tw.utils.parseMacroParametersAsAttributes(node,source,pos);
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double closing angle bracket
|
||||
token = $tw.utils.parseTokenString(source,pos,">>");
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
node.end = token.end;
|
||||
return node;
|
||||
};
|
||||
|
||||
/*
|
||||
Parse macro parameters as attributes. Returns the position after the last attribute
|
||||
*/
|
||||
exports.parseMacroParametersAsAttributes = function(node,source,pos) {
|
||||
var position = 0,
|
||||
attribute = $tw.utils.parseMacroParameterAsAttribute(source,pos);
|
||||
while(attribute) {
|
||||
if(!attribute.name) {
|
||||
attribute.name = (position++) + "";
|
||||
attribute.isPositional = true;
|
||||
}
|
||||
node.orderedAttributes.push(attribute);
|
||||
node.attributes[attribute.name] = attribute;
|
||||
pos = attribute.end;
|
||||
// Get the next attribute
|
||||
attribute = $tw.utils.parseMacroParameterAsAttribute(source,pos);
|
||||
}
|
||||
node.end = pos;
|
||||
return pos;
|
||||
};
|
||||
|
||||
/*
|
||||
Parse a macro parameter as an attribute. Returns null if not found, otherwise returns {name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}, with the name being optional
|
||||
*/
|
||||
exports.parseMacroParameterAsAttribute = function(source,pos) {
|
||||
var node = {
|
||||
start: pos
|
||||
};
|
||||
// Define our regexps
|
||||
var reAttributeName = /([^\/\s>"'`=:]+)/g,
|
||||
reUnquotedAttribute = /((?:(?:>(?!>))|[^\s>"'])+)/g,
|
||||
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g,
|
||||
reIndirectValue = /\{\{([^\}]+)\}\}/g,
|
||||
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Get the attribute name and the separator token
|
||||
var nameToken = $tw.utils.parseTokenRegExp(source,pos,reAttributeName),
|
||||
namePos = nameToken && $tw.utils.skipWhiteSpace(source,nameToken.end),
|
||||
separatorToken = nameToken && $tw.utils.parseTokenRegExp(source,namePos,/=|:/g),
|
||||
isNewStyleSeparator = false; // If there is no separator then we don't allow new style values
|
||||
// If we have a name and a separator then we have a named attribute
|
||||
if(nameToken && separatorToken) {
|
||||
node.name = nameToken.match[1];
|
||||
// key value separator is `=` or `:`
|
||||
node.assignmentOperator = separatorToken.match[0];
|
||||
pos = separatorToken.end;
|
||||
isNewStyleSeparator = (node.assignmentOperator === "=");
|
||||
}
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a string literal
|
||||
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
|
||||
if(stringLiteral) {
|
||||
pos = stringLiteral.end;
|
||||
node.type = "string";
|
||||
node.value = stringLiteral.value;
|
||||
// Mark the value as having been quoted in the source
|
||||
node.quoted = true;
|
||||
} else {
|
||||
// Look for a filtered value
|
||||
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
|
||||
if(filteredValue && isNewStyleSeparator) {
|
||||
pos = filteredValue.end;
|
||||
node.type = "filtered";
|
||||
node.filter = filteredValue.match[1];
|
||||
} else {
|
||||
// Look for an indirect value
|
||||
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
|
||||
if(indirectValue && isNewStyleSeparator) {
|
||||
pos = indirectValue.end;
|
||||
node.type = "indirect";
|
||||
node.textReference = indirectValue.match[1];
|
||||
} else {
|
||||
// Look for a unquoted value
|
||||
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
|
||||
if(unquotedValue) {
|
||||
pos = unquotedValue.end;
|
||||
node.type = "string";
|
||||
node.value = unquotedValue.match[1];
|
||||
} else {
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation && isNewStyleSeparator) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
} else {
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue && isNewStyleSeparator) {
|
||||
pos = substitutedValue.end;
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
} else {
|
||||
}
|
||||
}
|
||||
var node = $tw.utils.parseMacroInvocation(source,pos);
|
||||
if(node) {
|
||||
var positionalName = 0,
|
||||
transclusion = {
|
||||
type: "transclude",
|
||||
start: node.start,
|
||||
end: node.end
|
||||
};
|
||||
$tw.utils.addAttributeToParseTreeNode(transclusion,"$variable",node.name);
|
||||
$tw.utils.each(node.params,function(param) {
|
||||
var name = param.name;
|
||||
if(name) {
|
||||
if(name.charAt(0) === "$") {
|
||||
name = "$" + name;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: name,type: "string", value: param.value, start: param.start, end: param.end});
|
||||
} else {
|
||||
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: (positionalName++) + "",type: "string", value: param.value, start: param.start, end: param.end});
|
||||
}
|
||||
}
|
||||
});
|
||||
return transclusion;
|
||||
}
|
||||
// Bail if we don't have a value
|
||||
if(!node.type) {
|
||||
return null;
|
||||
}
|
||||
// Update the end position
|
||||
node.end = pos;
|
||||
return node;
|
||||
};
|
||||
|
||||
@@ -421,7 +296,7 @@ exports.parseFilterVariable = function(source) {
|
||||
};
|
||||
|
||||
/*
|
||||
Look for an HTML attribute definition. Returns null if not found, otherwise returns {name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}
|
||||
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}
|
||||
*/
|
||||
exports.parseAttribute = function(source,pos) {
|
||||
var node = {
|
||||
@@ -479,7 +354,7 @@ exports.parseAttribute = function(source,pos) {
|
||||
node.value = unquotedValue.match[1];
|
||||
} else {
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
var macroInvocation = $tw.utils.parseMacroInvocation(source,pos);
|
||||
if(macroInvocation) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
@@ -500,7 +375,6 @@ exports.parseAttribute = function(source,pos) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If there is no equals sign or colon, then this is an attribute with no value, defaulting to "true"
|
||||
node.type = "string";
|
||||
node.value = "true";
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ exports.parse = function() {
|
||||
var paramString = this.match[2],
|
||||
params = [];
|
||||
if(paramString !== "") {
|
||||
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[((?:[^\]]|\](?!\]))*)\]\]|([^"'\s]+)))?/mg,
|
||||
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))?/mg,
|
||||
paramMatch = reParam.exec(paramString);
|
||||
while(paramMatch) {
|
||||
// Save the parameter details
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/escapecss.js
|
||||
type: application/javascript
|
||||
module-type: utils-browser
|
||||
module-type: utils
|
||||
|
||||
Provides CSS.escape() functionality.
|
||||
|
||||
@@ -9,6 +9,92 @@ Provides CSS.escape() functionality.
|
||||
|
||||
"use strict";
|
||||
|
||||
// TODO -- resolve this construction
|
||||
exports.escapeCSS = (function() {
|
||||
return window.CSS.escape;
|
||||
// use browser's native CSS.escape() function if available
|
||||
if ($tw.browser && window.CSS && window.CSS.escape) {
|
||||
return window.CSS.escape;
|
||||
}
|
||||
|
||||
// otherwise, a utility method is provided
|
||||
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||
|
||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||
return function(value) {
|
||||
if (arguments.length == 0) {
|
||||
throw new TypeError('`CSS.escape` requires an argument.');
|
||||
}
|
||||
var string = String(value);
|
||||
var length = string.length;
|
||||
var index = -1;
|
||||
var codeUnit;
|
||||
var result = '';
|
||||
var firstCodeUnit = string.charCodeAt(0);
|
||||
while (++index < length) {
|
||||
codeUnit = string.charCodeAt(index);
|
||||
// Note: there’s no need to special-case astral symbols, surrogate
|
||||
// pairs, or lone surrogates.
|
||||
|
||||
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
||||
// (U+FFFD).
|
||||
if (codeUnit == 0x0000) {
|
||||
result += '\uFFFD';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||
// U+007F, […]
|
||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
||||
// If the character is the first character and is in the range [0-9]
|
||||
// (U+0030 to U+0039), […]
|
||||
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||
// If the character is the second character and is in the range [0-9]
|
||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||
(
|
||||
index == 1 &&
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||
firstCodeUnit == 0x002D
|
||||
)
|
||||
) {
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
||||
result += '\\' + codeUnit.toString(16) + ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is the first character and is a `-` (U+002D), and
|
||||
// there is no second character, […]
|
||||
index == 0 &&
|
||||
length == 1 &&
|
||||
codeUnit == 0x002D
|
||||
) {
|
||||
result += '\\' + string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the character is not handled by one of the above rules and is
|
||||
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
||||
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||
if (
|
||||
codeUnit >= 0x0080 ||
|
||||
codeUnit == 0x002D ||
|
||||
codeUnit == 0x005F ||
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||
) {
|
||||
// the character itself
|
||||
result += string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, the escaped character.
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character
|
||||
result += '\\' + string.charAt(index);
|
||||
|
||||
}
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -37,7 +37,6 @@ Object.defineProperty(TW_Node.prototype, 'TEXT_NODE', {
|
||||
var TW_TextNode = function(text) {
|
||||
bumpSequenceNumber(this);
|
||||
this.textContent = text + "";
|
||||
this.children = [];
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(TW_TextNode.prototype,TW_Node.prototype);
|
||||
|
||||
@@ -62,8 +62,8 @@ SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
var paramObject = Object.create(null);
|
||||
// Add names/values pairs if present
|
||||
if(this.actionNames && this.actionValues) {
|
||||
var names = this.wiki.filterTiddlers(this.actionNames,this),
|
||||
values = this.wiki.filterTiddlers(this.actionValues,this);
|
||||
var names = this.wiki.filterTiddlers(this.actionNames,this,{defaultFilterRunPrefix: "all"}),
|
||||
values = this.wiki.filterTiddlers(this.actionValues,this,{defaultFilterRunPrefix: "all"});
|
||||
$tw.utils.each(names,function(name,index) {
|
||||
paramObject[name] = values[index] || "";
|
||||
});
|
||||
|
||||
@@ -56,10 +56,10 @@ Invoke the action associated with this widget
|
||||
*/
|
||||
SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
var tiddler = this.wiki.getTiddler(this.actionTiddler),
|
||||
names, values = this.wiki.filterTiddlers(this.actionValues,this);
|
||||
names, values = this.wiki.filterTiddlers(this.actionValues,this,{defaultFilterRunPrefix: "all"});
|
||||
if(this.actionFields) {
|
||||
var additions = {};
|
||||
names = this.wiki.filterTiddlers(this.actionFields,this);
|
||||
names = this.wiki.filterTiddlers(this.actionFields,this,{defaultFilterRunPrefix: "all"});
|
||||
$tw.utils.each(names,function(fieldname,index) {
|
||||
additions[fieldname] = values[index] || "";
|
||||
});
|
||||
@@ -68,7 +68,7 @@ SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event
|
||||
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,{title: this.actionTiddler},modificationFields,additions));
|
||||
} else if(this.actionIndexes) {
|
||||
var data = this.wiki.getTiddlerData(this.actionTiddler,Object.create(null));
|
||||
names = this.wiki.filterTiddlers(this.actionIndexes,this);
|
||||
names = this.wiki.filterTiddlers(this.actionIndexes,this,{defaultFilterRunPrefix: "all"});
|
||||
$tw.utils.each(names,function(name,index) {
|
||||
data[name] = values[index] || "";
|
||||
});
|
||||
|
||||
@@ -72,8 +72,8 @@ GenesisWidget.prototype.execute = function() {
|
||||
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);
|
||||
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this,{defaultFilterRunPrefix: "all"});
|
||||
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this,{defaultFilterRunPrefix: "all"});
|
||||
$tw.utils.each(this.attributeNames,function(varname,index) {
|
||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],varname,self.attributeValues[index] || "");
|
||||
});
|
||||
@@ -103,8 +103,8 @@ 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);
|
||||
attributeNames = this.wiki.filterTiddlers(filterNames,this,{defaultFilterRunPrefix: "all"}),
|
||||
attributeValues = this.wiki.filterTiddlers(filterValues,this,{defaultFilterRunPrefix: "all"});
|
||||
if($tw.utils.count(changedAttributes) > 0 || !$tw.utils.isArrayEqual(this.attributeNames,attributeNames) || !$tw.utils.isArrayEqual(this.attributeValues,attributeValues)) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
|
||||
@@ -7,6 +7,7 @@ This widget allows defining multiple variables at once, while allowing
|
||||
the later variables to depend upon the earlier ones.
|
||||
|
||||
```
|
||||
\define helloworld() Hello world!
|
||||
<$let currentTiddler="target" value={{!!value}} currentTiddler="different">
|
||||
{{!!value}} will be different from <<value>>
|
||||
</$let>
|
||||
@@ -55,7 +56,7 @@ LetWidget.prototype.computeAttributes = function() {
|
||||
});
|
||||
// Run through again, setting variables and looking for differences
|
||||
$tw.utils.each(this.currentValueFor,function(value,name) {
|
||||
if(self.attributes[name] === undefined || !$tw.utils.isArrayEqual(self.attributes[name],value)) {
|
||||
if(!$tw.utils.isArrayEqual(self.attributes[name],value)) {
|
||||
self.attributes[name] = value;
|
||||
self.setVariable(name,value);
|
||||
changedAttributes[name] = true;
|
||||
@@ -67,7 +68,7 @@ LetWidget.prototype.computeAttributes = function() {
|
||||
LetWidget.prototype.getVariableInfo = function(name,options) {
|
||||
// Special handling: If this variable exists in this very $let, we can
|
||||
// use it, but only if it's been staged.
|
||||
if($tw.utils.hop(this.currentValueFor,name)) {
|
||||
if ($tw.utils.hop(this.currentValueFor,name)) {
|
||||
var value = this.currentValueFor[name];
|
||||
return {
|
||||
text: value[0] || "",
|
||||
|
||||
@@ -82,8 +82,8 @@ SelectWidget.prototype.handleChangeEvent = function(event) {
|
||||
if(this.selectMultiple == false) {
|
||||
var value = this.getSelectDomNode().value;
|
||||
} else {
|
||||
var value = this.getSelectValues();
|
||||
value = $tw.utils.stringifyList(value);
|
||||
var value = this.getSelectValues()
|
||||
value = $tw.utils.stringifyList(value);
|
||||
}
|
||||
this.wiki.setText(this.selectTitle,this.selectField,this.selectIndex,value);
|
||||
// Trigger actions
|
||||
@@ -118,21 +118,12 @@ SelectWidget.prototype.setSelectValue = function() {
|
||||
}
|
||||
}
|
||||
// Assign it to the select element if it's different than the current value
|
||||
if(this.selectMultiple) {
|
||||
if (this.selectMultiple) {
|
||||
value = value === undefined ? "" : value;
|
||||
var select = this.getSelectDomNode();
|
||||
var child,
|
||||
values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);
|
||||
var values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);
|
||||
for(var i=0; i < select.children.length; i++){
|
||||
child=select.children[i];
|
||||
if(child.children.length === 0){
|
||||
child.selected = values.indexOf(child.value) !== -1;
|
||||
} else {
|
||||
// grouped options
|
||||
for(var y=0; y < child.children.length; y++){
|
||||
child.children[y].selected = values.indexOf(child.children[y].value) !== -1;
|
||||
}
|
||||
}
|
||||
select.children[i].selected = values.indexOf(select.children[i].value) !== -1
|
||||
}
|
||||
} else {
|
||||
var domNode = this.getSelectDomNode();
|
||||
@@ -156,14 +147,14 @@ SelectWidget.prototype.getSelectValues = function() {
|
||||
select = this.getSelectDomNode();
|
||||
result = [];
|
||||
options = select && select.options;
|
||||
for(var i=0; i<options.length; i++) {
|
||||
for (var i=0; i<options.length; i++) {
|
||||
opt = options[i];
|
||||
if(opt.selected) {
|
||||
if (opt.selected) {
|
||||
result.push(opt.value || opt.text);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
@@ -192,7 +183,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
SelectWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
// If we're using a different tiddler/field/index then completely refresh ourselves
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tooltip || changedAttributes.default || changedAttributes.tabindex || changedAttributes.disabled) {
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tooltip || changedAttributes.tabindex || changedAttributes.disabled) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -12,7 +12,7 @@ Widget to set multiple variables at once from a list of names and a list of valu
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var SetMultipleVariablesWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -24,52 +24,52 @@ SetMultipleVariablesWidget.prototype = new Widget();
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
SetMultipleVariablesWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
SetMultipleVariablesWidget.prototype.execute = function() {
|
||||
// Setup our variables
|
||||
this.setVariables();
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets();
|
||||
// Setup our variables
|
||||
this.setVariables();
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
|
||||
SetMultipleVariablesWidget.prototype.setVariables = function() {
|
||||
// Set the variables
|
||||
var self = this,
|
||||
filterNames = this.getAttribute("$names",""),
|
||||
filterValues = this.getAttribute("$values","");
|
||||
this.variableNames = [];
|
||||
this.variableValues = [];
|
||||
if(filterNames && filterValues) {
|
||||
this.variableNames = this.wiki.filterTiddlers(filterNames,this);
|
||||
this.variableValues = this.wiki.filterTiddlers(filterValues,this);
|
||||
$tw.utils.each(this.variableNames,function(varname,index) {
|
||||
self.setVariable(varname,self.variableValues[index]);
|
||||
});
|
||||
}
|
||||
// Set the variables
|
||||
var self = this,
|
||||
filterNames = this.getAttribute("$names",""),
|
||||
filterValues = this.getAttribute("$values","");
|
||||
this.variableNames = [];
|
||||
this.variableValues = [];
|
||||
if(filterNames && filterValues) {
|
||||
this.variableNames = this.wiki.filterTiddlers(filterNames,this,{defaultFilterRunPrefix: "all"});
|
||||
this.variableValues = this.wiki.filterTiddlers(filterValues,this,{defaultFilterRunPrefix: "all"});
|
||||
$tw.utils.each(this.variableNames,function(varname,index) {
|
||||
self.setVariable(varname,self.variableValues[index]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Refresh the widget by ensuring our attributes are up to date
|
||||
*/
|
||||
SetMultipleVariablesWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var filterNames = this.getAttribute("$names",""),
|
||||
filterValues = this.getAttribute("$values",""),
|
||||
variableNames = this.wiki.filterTiddlers(filterNames,this),
|
||||
variableValues = this.wiki.filterTiddlers(filterValues,this);
|
||||
if(!$tw.utils.isArrayEqual(this.variableNames,variableNames) || !$tw.utils.isArrayEqual(this.variableValues,variableValues)) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
var filterNames = this.getAttribute("$names",""),
|
||||
filterValues = this.getAttribute("$values",""),
|
||||
variableNames = this.wiki.filterTiddlers(filterNames,this,{defaultFilterRunPrefix: "all"}),
|
||||
variableValues = this.wiki.filterTiddlers(filterValues,this,{defaultFilterRunPrefix: "all"});
|
||||
if(!$tw.utils.isArrayEqual(this.variableNames,variableNames) || !$tw.utils.isArrayEqual(this.variableValues,variableValues)) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
};
|
||||
|
||||
exports["setmultiplevariables"] = SetMultipleVariablesWidget;
|
||||
|
||||
@@ -414,21 +414,7 @@ Widget.prototype.computeAttribute = function(attribute,options) {
|
||||
value = [value];
|
||||
}
|
||||
} else if(attribute.type === "macro") {
|
||||
// Get the macro name
|
||||
var macroName = attribute.value.attributes["$variable"].value;
|
||||
// Collect macro parameters
|
||||
var params = [];
|
||||
$tw.utils.each(attribute.value.orderedAttributes,function(attr) {
|
||||
var param = {
|
||||
value: self.computeAttribute(attr)
|
||||
};
|
||||
if(attr.name && !attr.isPositional) {
|
||||
param.name = attr.name;
|
||||
}
|
||||
params.push(param);
|
||||
});
|
||||
// Invoke the macro
|
||||
var variableInfo = this.getVariableInfo(macroName,{params: params});
|
||||
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
|
||||
if(options.asList) {
|
||||
value = variableInfo.resultList;
|
||||
} else {
|
||||
|
||||
@@ -96,13 +96,24 @@ caption: {{$:/language/Search/Filter/Caption}}
|
||||
</$list>
|
||||
</div>
|
||||
|
||||
<div class="tc-advanced-search-options">
|
||||
<$checkbox tiddler="$:/config/Search/AllowDuplicates" field="text" checked="yes" unchecked="no" default="yes">
|
||||
<$text text=" "/><<lingo Filter/AllowDuplicates>>
|
||||
</$checkbox>
|
||||
</div>
|
||||
|
||||
<$reveal state="$:/temp/advancedsearch" type="nomatch" text="" tag="div" class="tc-search-results">
|
||||
<$set name="resultCount" value="<$count filter={{$:/temp/advancedsearch}}/>">
|
||||
<$let
|
||||
filter-allow-duplicates="::defaultprefix:all [subfilter{$:/temp/advancedsearch}]"
|
||||
filter-deduplicate="::defaultprefix:or [subfilter{$:/temp/advancedsearch}]"
|
||||
currentFilter={{{ [{$:/config/Search/AllowDuplicates}match[yes]then<filter-allow-duplicates>else<filter-deduplicate>] }}}
|
||||
resultCount={{{ [subfilter<currentFilter>count[]] }}}
|
||||
>
|
||||
<p><<lingo Filter/Matches>></p>
|
||||
<$list filter={{$:/temp/advancedsearch}}>
|
||||
<$list filter="[subfilter<currentFilter>]">
|
||||
<span class={{{[<currentTiddler>addsuffix[-primaryList]] -[[$:/temp/advancedsearch/selected-item]get[text]] :and[then[]else[tc-list-item-selected]] }}}>
|
||||
<$transclude tiddler="$:/core/ui/ListItemTemplate"/>
|
||||
</span>
|
||||
</$list>
|
||||
</$set>
|
||||
</$let>
|
||||
</$reveal>
|
||||
|
||||
@@ -15,7 +15,7 @@ caption: {{$:/language/SideBar/Open/Caption}}
|
||||
|
||||
\define droppable-item(button)
|
||||
\whitespace trim
|
||||
<$droppable actions=<<drop-actions>> enable=<<tv-enable-drag-and-drop>> tag="div">
|
||||
<$droppable actions=<<drop-actions>> enable=<<tv-allow-drag-and-drop>> tag="div">
|
||||
<<placeholder>>
|
||||
<div>
|
||||
$button$
|
||||
|
||||
2
core/wiki/config/SearchAllowDuplicates.tid
Normal file
2
core/wiki/config/SearchAllowDuplicates.tid
Normal file
@@ -0,0 +1,2 @@
|
||||
title: $:/config/Search/AllowDuplicates
|
||||
text: yes
|
||||
@@ -92,7 +92,7 @@ tags: $:/tags/Macro
|
||||
</$set>
|
||||
\end
|
||||
|
||||
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"",displayField:"title")
|
||||
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"",displayField:"caption")
|
||||
\whitespace trim
|
||||
<span class="tc-tagged-draggable-list">
|
||||
<$set name="tag" value=<<__tag__>>>
|
||||
@@ -115,6 +115,7 @@ tags: $:/tags/Macro
|
||||
<$view field="title"/>
|
||||
</$transclude>
|
||||
</$let>
|
||||
<$view field="title"/>
|
||||
</$link>
|
||||
</$transclude>
|
||||
</$genesis>
|
||||
|
||||
@@ -21,7 +21,7 @@ second-search-filter: [subfilter<tagListFilter>is[system]search:title<userInput>
|
||||
|
||||
<!-- clean up temporary tiddlers, so the next "pick" starts with a clean input -->
|
||||
<!-- This could probably be optimized / removed if we would use different temp-tiddlers
|
||||
(future improvement because keeping track is complex for humans)
|
||||
(future improvement because keeping track is comlex for humans)
|
||||
-->
|
||||
\procedure delete-tag-state-tiddlers()
|
||||
<$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
|
||||
@@ -111,7 +111,6 @@ The second ESC tries to close the "draft tiddler"
|
||||
refreshTitle=<<refreshTitle>>
|
||||
selectionStateTitle=<<tagSelectionState>>
|
||||
inputAcceptActions=<<add-tag-actions>>
|
||||
inputAcceptVariantActions=<<save-tiddler-actions>>
|
||||
inputCancelActions=<<clear-tags-actions>>
|
||||
tag="input"
|
||||
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
created: 20150220191009000
|
||||
modified: 20150602092431500
|
||||
title: $:/editions/tw5.com/railroad/call-parameter-value
|
||||
title: $:/editions/tw5.com/railroad/macro-parameter-value
|
||||
type: text/vnd.tiddlywiki.railroad
|
||||
|
||||
( '"""' [:{/'tout sauf """'/}] '"""'
|
||||
| '"' [:{/'tout sauf "'/}] '"'
|
||||
| "'" [:{/"tout sauf '"/}] "'"
|
||||
| "[[" [:{/"tout sauf ]"/}] "]]"
|
||||
| "`" [:{/"tout sauf `"/}] "`"
|
||||
| "```" [:{/"tout sauf ```"/}] "```"
|
||||
| {/"""tout sauf ' " ou espacevierge"""/}
|
||||
)
|
||||
|
||||
@@ -25,4 +25,4 @@ The <<.place param-nom>> is a sequence of letters (`A`--`Z`, `a`--`z`), digits (
|
||||
|
||||
The <<.place valeur>> is specified as follows<<dp>>
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/call-parameter-value}}/>
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/macro-parameter-value}}/>
|
||||
|
||||
@@ -33,7 +33,7 @@ parametre.nom [: [:espace] ":" [:espace] defaut ]
|
||||
|
||||
La valeur par <<.place défaut>> d'un paramètre est spécifiée comme suit<<:>>
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/call-parameter-value}}/>
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/macro-parameter-value}}/>
|
||||
|
||||
La définition de la <<.place suite>> se fait comme suit<<:>>
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
title: Filters/DefaultFilterRunPrefixPragma
|
||||
description: Test Default Filter Run Prefix Pragma
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\procedure mysubfilter() 1 1 +[join[Y]]
|
||||
|
||||
(<$text text={{{ ::defaultprefix:all 1 1 [subfilter<mysubfilter>] +[join[X]] }}}/>)
|
||||
|
||||
(<$text text={{{ 1 1 ::defaultprefix:all 1 1 +[join[X]] }}}/>)
|
||||
|
||||
(<$text text={{{ ::nonexistent X }}}/>)
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>(1X1X1Y1)</p><p>(1X1X1)</p><p>(Filter Error: Unknown filter pragma)</p>
|
||||
22
editions/test/tiddlers/tests/data/filters/Filter.tid
Normal file
22
editions/test/tiddlers/tests/data/filters/Filter.tid
Normal file
@@ -0,0 +1,22 @@
|
||||
title: Filters/Filter
|
||||
description: Test filter operator
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\procedure test-filter() 1 1 +[join[X]] +[!match<currentTiddler>]
|
||||
|
||||
(<$text text={{{ [filter<test-filter>] +[join[ ]] }}}/>)
|
||||
|
||||
(<$text text={{{ [filter:all<test-filter>] +[join[ ]] }}}/>)
|
||||
|
||||
+
|
||||
title: 1X1
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>($:/core 1X1 ExpectedResult Output)</p><p>($:/core ExpectedResult Output)</p>
|
||||
20
editions/test/tiddlers/tests/data/filters/Subfilter.tid
Normal file
20
editions/test/tiddlers/tests/data/filters/Subfilter.tid
Normal file
@@ -0,0 +1,20 @@
|
||||
title: Filters/Subfilter
|
||||
description: Test subfilter operator
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\procedure test-data() 1 2 1 3 3 4
|
||||
|
||||
(<$text text={{{ [subfilter<test-data>] +[join[ ]] }}}/>)
|
||||
|
||||
(<$text text={{{ [subfilter:all<test-data>] +[join[ ]] }}}/>)
|
||||
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>(2 1 3 4)</p><p>(1 2 1 3 3 4)</p>
|
||||
@@ -1,26 +0,0 @@
|
||||
title: Macros/Dynamic/Attribute
|
||||
description: Attribute macrocall with dynamic paramters
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\define mamacromamacro(param:"red")
|
||||
It is $param$
|
||||
\end
|
||||
|
||||
<$text text=<<mamacromamacro>>/>
|
||||
-
|
||||
<$text text=<<mamacromamacro param={{{ [[a]addprefix[b]] }}}>>/>
|
||||
-
|
||||
<$text text=<<mamacromamacro param>>/>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>It is red
|
||||
-
|
||||
It is ba
|
||||
-
|
||||
It is param
|
||||
</p>
|
||||
@@ -1,23 +0,0 @@
|
||||
title: Macros/Dynamic/Standalone
|
||||
description: Standalone macrocall with dynamic paramters
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\define mamacro(one:"red",two:"green")
|
||||
It is $one$ and $two$ or <<__one__>> and <<__two__>>.
|
||||
\end
|
||||
|
||||
<<mamacro>>
|
||||
|
||||
<<mamacro one={{{ [[b]addprefix[a]] }}}>>
|
||||
|
||||
|
||||
<<mamacro one>>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>It is red and green or red and green.</p><p>It is ab and green or ab and green.</p><p>It is one and green or one and green.</p>
|
||||
@@ -1,9 +0,0 @@
|
||||
tags: $:/tags/wikitext-serialize-test-spec
|
||||
title: Serialize/DynamicMacroMixed
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<mymacro static:"value" dynamic={{reference}} filter={{{ [tag[test]] }}}>>
|
||||
|
||||
<$macrocall $name="mymacro" static="value" dynamic=<<inner>>/>
|
||||
|
||||
<<mymacro `substituted $(var)$`>>
|
||||
@@ -1,9 +0,0 @@
|
||||
tags: $:/tags/wikitext-serialize-test-spec
|
||||
title: Serialize/DynamicMacroParams
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<mymacro param={{Something}}>>
|
||||
|
||||
<<mymacro param={{{ [<myvar>addprefix[https:]] }}}>>
|
||||
|
||||
<$macrocall $name="outermacro" inner=<<innermacro arg="value">>/>
|
||||
@@ -1,7 +0,0 @@
|
||||
tags: $:/tags/wikitext-serialize-test-spec
|
||||
title: Serialize/DynamicWidgetAttribute
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<div class=<<mymacro param={{Something}}>>>content</div>
|
||||
|
||||
<$button actions=<<myactions target={{!!title}}>>/>
|
||||
@@ -7,7 +7,3 @@ type: text/vnd.tiddlywiki
|
||||
<<.def "macro calls">>
|
||||
|
||||
<<alert "primary" "primary alert" width:"60%">>
|
||||
|
||||
<<john one:val1 two:val2 three:"quoted value">>
|
||||
|
||||
<<test unquoted:value quoted:"value" number:123>>
|
||||
|
||||
@@ -3,5 +3,3 @@ title: Serialize/MacroCallInline
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
These are macro calls in a line: <<name "value" "value2">> and <<.def "macro calls">> <<alert "primary" "primary alert" width:"60%">>
|
||||
|
||||
Testing unquoted parameters: <<john one:val1 two:val2>> and <<test param:value other:"quoted">>.
|
||||
|
||||
@@ -235,307 +235,11 @@ describe("HTML tag new parser tests", function() {
|
||||
expect(parser.parseTag("< $mytag attrib1='something' attrib2=else thing>",0)).toEqual(
|
||||
null
|
||||
);
|
||||
expect(parser.parseTag("<$mytag attrib3=<<myMacro one:two three:'four and five'>>>", 0)).toEqual(
|
||||
{
|
||||
"type": "mytag",
|
||||
"start": 0,
|
||||
"attributes": {
|
||||
"attrib3": {
|
||||
"start": 7,
|
||||
"name": "attrib3",
|
||||
"type": "macro",
|
||||
"value": {
|
||||
"type": "transclude",
|
||||
"start": 16,
|
||||
"attributes": {
|
||||
"$variable": {
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
"one": {
|
||||
"start": 25,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 33
|
||||
},
|
||||
"three": {
|
||||
"start": 33,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 55
|
||||
}
|
||||
},
|
||||
"orderedAttributes": [
|
||||
{
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
{
|
||||
"start": 25,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 33
|
||||
},
|
||||
{
|
||||
"start": 33,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 55
|
||||
}
|
||||
],
|
||||
"end": 57
|
||||
},
|
||||
"end": 57
|
||||
}
|
||||
},
|
||||
"orderedAttributes": [
|
||||
{
|
||||
"start": 7,
|
||||
"name": "attrib3",
|
||||
"type": "macro",
|
||||
"value": {
|
||||
"type": "transclude",
|
||||
"start": 16,
|
||||
"attributes": {
|
||||
"$variable": {
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
"one": {
|
||||
"start": 25,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 33
|
||||
},
|
||||
"three": {
|
||||
"start": 33,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 55
|
||||
}
|
||||
},
|
||||
"orderedAttributes": [
|
||||
{
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
{
|
||||
"start": 25,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 33
|
||||
},
|
||||
{
|
||||
"start": 33,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 55
|
||||
}
|
||||
],
|
||||
"end": 57
|
||||
},
|
||||
"end": 57
|
||||
}
|
||||
],
|
||||
"tag": "$mytag",
|
||||
"end": 58
|
||||
}
|
||||
expect(parser.parseTag("<$mytag attrib3=<<myMacro one:two three:'four and five'>>>",0)).toEqual(
|
||||
{ type : "mytag", start : 0, attributes : { attrib3 : { type : "macro", start : 7, name : "attrib3", value : { type : "macrocall", start : 16, params : [ { type : "macro-parameter", start : 25, value : "two", name : "one", end : 33 }, { type : "macro-parameter", start : 33, value : "four and five", name : "three", end : 55 } ], name : "myMacro", end : 57 }, end : 57 } }, orderedAttributes: [ { type : "macro", start : 7, name : "attrib3", value : { type : "macrocall", start : 16, params : [ { type : "macro-parameter", start : 25, value : "two", name : "one", end : 33 }, { type : "macro-parameter", start : 33, value : "four and five", name : "three", end : 55 } ], name : "myMacro", end : 57 }, end : 57 } ], tag : "$mytag", end : 58 }
|
||||
);
|
||||
expect(parser.parseTag("<$mytag attrib1='something' attrib2=else thing attrib3=<<myMacro one:two three:'four and five'>>>",0)).toEqual(
|
||||
{
|
||||
"type": "mytag",
|
||||
"start": 0,
|
||||
"attributes": {
|
||||
"attrib1": {
|
||||
"start": 7,
|
||||
"name": "attrib1",
|
||||
"type": "string",
|
||||
"value": "something",
|
||||
"end": 27
|
||||
},
|
||||
"attrib2": {
|
||||
"start": 27,
|
||||
"name": "attrib2",
|
||||
"type": "string",
|
||||
"value": "else",
|
||||
"end": 40
|
||||
},
|
||||
"thing": {
|
||||
"start": 40,
|
||||
"name": "thing",
|
||||
"type": "string",
|
||||
"value": "true",
|
||||
"end": 47
|
||||
},
|
||||
"attrib3": {
|
||||
"start": 47,
|
||||
"name": "attrib3",
|
||||
"type": "macro",
|
||||
"value": {
|
||||
"type": "transclude",
|
||||
"start": 55,
|
||||
"attributes": {
|
||||
"$variable": {
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
"one": {
|
||||
"start": 64,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 72
|
||||
},
|
||||
"three": {
|
||||
"start": 72,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 94
|
||||
}
|
||||
},
|
||||
"orderedAttributes": [
|
||||
{
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
{
|
||||
"start": 64,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 72
|
||||
},
|
||||
{
|
||||
"start": 72,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 94
|
||||
}
|
||||
],
|
||||
"end": 96
|
||||
},
|
||||
"end": 96
|
||||
}
|
||||
},
|
||||
"orderedAttributes": [
|
||||
{
|
||||
"start": 7,
|
||||
"name": "attrib1",
|
||||
"type": "string",
|
||||
"value": "something",
|
||||
"end": 27
|
||||
},
|
||||
{
|
||||
"start": 27,
|
||||
"name": "attrib2",
|
||||
"type": "string",
|
||||
"value": "else",
|
||||
"end": 40
|
||||
},
|
||||
{
|
||||
"start": 40,
|
||||
"name": "thing",
|
||||
"type": "string",
|
||||
"value": "true",
|
||||
"end": 47
|
||||
},
|
||||
{
|
||||
"start": 47,
|
||||
"name": "attrib3",
|
||||
"type": "macro",
|
||||
"value": {
|
||||
"type": "transclude",
|
||||
"start": 55,
|
||||
"attributes": {
|
||||
"$variable": {
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
"one": {
|
||||
"start": 64,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 72
|
||||
},
|
||||
"three": {
|
||||
"start": 72,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 94
|
||||
}
|
||||
},
|
||||
"orderedAttributes": [
|
||||
{
|
||||
"name": "$variable",
|
||||
"type": "string",
|
||||
"value": "myMacro"
|
||||
},
|
||||
{
|
||||
"start": 64,
|
||||
"name": "one",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "two",
|
||||
"end": 72
|
||||
},
|
||||
{
|
||||
"start": 72,
|
||||
"name": "three",
|
||||
"assignmentOperator": ":",
|
||||
"type": "string",
|
||||
"value": "four and five",
|
||||
"quoted": true,
|
||||
"end": 94
|
||||
}
|
||||
],
|
||||
"end": 96
|
||||
},
|
||||
"end": 96
|
||||
}
|
||||
],
|
||||
"tag": "$mytag",
|
||||
"end": 97
|
||||
}
|
||||
{ type : "mytag", start : 0, attributes : { attrib1 : { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, attrib2 : { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, thing : { type : "string", start : 40, name : "thing", value : "true", end : 47 }, attrib3 : { type : "macro", start : 47, name : "attrib3", value : { type : "macrocall", start : 55, params : [ { type : "macro-parameter", start : 64, value : "two", name : "one", end : 72 }, { type : "macro-parameter", start : 72, value : "four and five", name : "three", end : 94 } ], name : "myMacro", end : 96 }, end : 96 } }, orderedAttributes: [ { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, { type : "string", start : 40, name : "thing", value : "true", end : 47 }, { type : "macro", start : 47, name : "attrib3", value : { type : "macrocall", start : 55, params : [ { type : "macro-parameter", start : 64, value : "two", name : "one", end : 72 }, { type : "macro-parameter", start : 72, value : "four and five", name : "three", end : 94 } ], name : "myMacro", end : 96 }, end : 96 } ], tag : "$mytag", end : 97 }
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ describe("WikiText parser tests", function() {
|
||||
);
|
||||
expect(parse("text <<john one:val1 two: 'val \"2\"' three: \"val '3'\" four: \"\"\"val 4\"5'\"\"\" five: [[val 5]] >>")).toEqual(
|
||||
|
||||
[{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","assignmentOperator":":","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","assignmentOperator":":","type":"string","value":"val \"2\"","quoted":true,"start":20,"end":35},"three":{"name":"three","assignmentOperator":":","type":"string","value":"val '3'","quoted":true,"start":35,"end":52},"four":{"name":"four","assignmentOperator":":","type":"string","value":"val 4\"5'","quoted":true,"start":52,"end":73},"five":{"name":"five","assignmentOperator":":","type":"string","value":"val 5","quoted":true,"start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","assignmentOperator":":","type":"string","value":"val1","start":11,"end":20},{"name":"two","assignmentOperator":":","type":"string","value":"val \"2\"","quoted":true,"start":20,"end":35},{"name":"three","assignmentOperator":":","type":"string","value":"val '3'","quoted":true,"start":35,"end":52},{"name":"four","assignmentOperator":":","type":"string","value":"val 4\"5'","quoted":true,"start":52,"end":73},{"name":"five","assignmentOperator":":","type":"string","value":"val 5","quoted":true,"start":73,"end":89}]}],"start":0,"end":92}]
|
||||
[{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}]
|
||||
|
||||
);
|
||||
expect(parse("ignored << carrots <<john>>")).toEqual(
|
||||
@@ -287,7 +287,7 @@ describe("WikiText parser tests", function() {
|
||||
);
|
||||
expect(parse("text <<outie one:'my <<innie>>' >>")).toEqual(
|
||||
|
||||
[{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","assignmentOperator":":","type":"string","value":"my <<innie>>","quoted":true,"start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","assignmentOperator":":","type":"string","value":"my <<innie>>","quoted":true,"start":12,"end":31}]}],"start":0,"end":34}]
|
||||
[{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <<innie>>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <<innie>>","start":12,"end":31}]}],"start":0,"end":34}]
|
||||
|
||||
);
|
||||
|
||||
@@ -301,7 +301,7 @@ describe("WikiText parser tests", function() {
|
||||
);
|
||||
expect(parse("<<john one:val1 two: 'val \"2\"' three: \"val '3'\" four: \"\"\"val 4\"5'\"\"\" five: [[val 5]] >>")).toEqual(
|
||||
|
||||
[{"type":"transclude","start":0,"end":87,"rule":"macrocallblock","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","assignmentOperator":":","type":"string","value":"val1","start":6,"end":15},"two":{"name":"two","assignmentOperator":":","type":"string","value":"val \"2\"","quoted":true,"start":15,"end":30},"three":{"name":"three","assignmentOperator":":","type":"string","value":"val '3'","quoted":true,"start":30,"end":47},"four":{"name":"four","assignmentOperator":":","type":"string","value":"val 4\"5'","quoted":true,"start":47,"end":68},"five":{"name":"five","assignmentOperator":":","type":"string","value":"val 5","quoted":true,"start":68,"end":84}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","assignmentOperator":":","type":"string","value":"val1","start":6,"end":15},{"name":"two","assignmentOperator":":","type":"string","value":"val \"2\"","quoted":true,"start":15,"end":30},{"name":"three","assignmentOperator":":","type":"string","value":"val '3'","quoted":true,"start":30,"end":47},{"name":"four","assignmentOperator":":","type":"string","value":"val 4\"5'","quoted":true,"start":47,"end":68},{"name":"five","assignmentOperator":":","type":"string","value":"val 5","quoted":true,"start":68,"end":84}],"isBlock":true}]
|
||||
[{"type":"transclude","start":0,"end":87,"rule":"macrocallblock","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":6,"end":15},"two":{"name":"two","type":"string","value":"val \"2\"","start":15,"end":30},"three":{"name":"three","type":"string","value":"val '3'","start":30,"end":47},"four":{"name":"four","type":"string","value":"val 4\"5'","start":47,"end":68},"five":{"name":"five","type":"string","value":"val 5","start":68,"end":84}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":6,"end":15},{"name":"two","type":"string","value":"val \"2\"","start":15,"end":30},{"name":"three","type":"string","value":"val '3'","start":30,"end":47},{"name":"four","type":"string","value":"val 4\"5'","start":47,"end":68},{"name":"five","type":"string","value":"val 5","start":68,"end":84}],"isBlock":true}]
|
||||
|
||||
);
|
||||
expect(parse("<< carrots\n\n<<john>>")).toEqual(
|
||||
@@ -321,12 +321,12 @@ describe("WikiText parser tests", function() {
|
||||
);
|
||||
expect(parse("<<multiline arg:\"\"\"\n\nwikitext\n\"\"\" >>")).toEqual(
|
||||
|
||||
[{"type":"transclude","start":0,"end":36,"rule":"macrocallblock","attributes":{"$variable":{"name":"$variable","type":"string","value":"multiline"},"arg":{"name":"arg","assignmentOperator":":","type":"string","value":"\n\nwikitext\n","quoted":true,"start":11,"end":33}},"orderedAttributes":[{"name":"$variable","type":"string","value":"multiline"},{"name":"arg","assignmentOperator":":","type":"string","value":"\n\nwikitext\n","quoted":true,"start":11,"end":33}],"isBlock":true}]
|
||||
[{"type":"transclude","start":0,"end":36,"rule":"macrocallblock","attributes":{"$variable":{"name":"$variable","type":"string","value":"multiline"},"arg":{"name":"arg","type":"string","value":"\n\nwikitext\n","start":11,"end":33}},"orderedAttributes":[{"name":"$variable","type":"string","value":"multiline"},{"name":"arg","type":"string","value":"\n\nwikitext\n","start":11,"end":33}],"isBlock":true}]
|
||||
|
||||
);
|
||||
expect(parse("<<outie one:'my <<innie>>' >>")).toEqual(
|
||||
|
||||
[ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", assignmentOperator: ":", type:"string", value: "my <<innie>>", quoted: true, start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", assignmentOperator: ":", type:"string", value: "my <<innie>>", quoted: true, start: 7, end: 26} ], end: 29, isBlock: true } ]
|
||||
[ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <<innie>>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <<innie>>", start: 7, end: 26} ], end: 29, isBlock: true } ]
|
||||
|
||||
);
|
||||
});
|
||||
@@ -334,23 +334,23 @@ describe("WikiText parser tests", function() {
|
||||
it("should parse tricky macrocall parameters", function() {
|
||||
expect(parse("<<john pa>am>>")).toEqual(
|
||||
|
||||
[{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"pa>am","start":6,"end":12,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"pa>am","start":6,"end":12,"isPositional":true}],"isBlock":true,"rule":"macrocallblock"}]
|
||||
[{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"pa>am","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"pa>am","start":6,"end":12}],"isBlock":true,"rule":"macrocallblock"}]
|
||||
|
||||
);
|
||||
expect(parse("<<john param> >>")).toEqual(
|
||||
|
||||
[{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"param>","start":6,"end":13,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param>","start":6,"end":13,"isPositional":true}],"isBlock":true,"rule":"macrocallblock"}]
|
||||
[{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"param>","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param>","start":6,"end":13}],"isBlock":true,"rule":"macrocallblock"}]
|
||||
|
||||
);
|
||||
expect(parse("<<john param>>>")).toEqual(
|
||||
|
||||
[{"type":"element","rule":"parseblock","tag":"p","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12,"isPositional":true}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}]
|
||||
[{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}]
|
||||
|
||||
);
|
||||
// equals signs should be allowed
|
||||
expect(parse("<<john var>=4 >>")).toEqual(
|
||||
|
||||
[{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"var>=4","start":6,"end":13,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"var>=4","start":6,"end":13,"isPositional":true}],"isBlock":true,"rule":"macrocallblock"}]
|
||||
[{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"var>=4","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"var>=4","start":6,"end":13}],"isBlock":true,"rule":"macrocallblock"}]
|
||||
|
||||
);
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ tags: Filters
|
||||
title: Dominant Append
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: Description and link to new escape hatches
|
||||
|
||||
[[Filters]] manipulate [[sets of titles|Title Selection]] in which no title may appear more than once. Furthermore, they often need to append one such set to another.
|
||||
|
||||
This is done in such a way that, if a title would be duplicated, the earlier copy of that title is discarded. The titles being appended are dominant.
|
||||
|
||||
@@ -4,22 +4,22 @@ tags: Learning
|
||||
title: TaskManagementExample
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TiddlyWiki5 can be used as a simple task management system without further customisation.<br>The idea is that tasks be tagged `task`, with those that are completed also tagged `done`. In this way it is straightforward to generate task lists.
|
||||
TiddlyWiki5 can be used as a simple task management system without further customisation. The idea is that tasks be tagged `task`, with those that are completed also tagged `done`. In this way it is straightforward to generate task lists.
|
||||
|
||||
<<.tip """There is [[an enhanced version of this demo|TaskManagementExample (Draggable)]] that adds the ability to drag and drop the tasks to re-order them.""">>
|
||||
|
||||
! Outstanding tasks
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""<$list filter="[!has[draft.of]tag[task]!tag[done]sort[created]]">
|
||||
<$checkbox tag="done"> <$link/></$checkbox><br>
|
||||
<$list filter="[!has[draft.of]tag[task]!tag[done]sort[created]]">
|
||||
|
||||
<$checkbox tag="done"> <$link/></$checkbox>
|
||||
|
||||
</$list>
|
||||
"""/>
|
||||
|
||||
! Completed tasks
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox><br>
|
||||
<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
|
||||
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
|
||||
|
||||
</$list>
|
||||
"""/>
|
||||
|
||||
@@ -4,24 +4,20 @@ tags: Learning
|
||||
title: TaskManagementExample (Draggable)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This is a version of the TaskManagementExample enhanced with the ability to drag and drop the task list to re-order them.<br>The list uses a the itemTemplate [[TaskManagementExampleDraggableTemplate]] tiddler, which you will also need to experiment yourself.
|
||||
This is a version of the TaskManagementExample enhanced with the ability to drag and drop the task list to re-order them.
|
||||
|
||||
! Outstanding tasks
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""//Drag the tasks to re-order them//
|
||||
//Drag the tasks to re-order them//
|
||||
|
||||
<<list-tagged-draggable tag:"task" subFilter:"!has[draft.of]!tag[done]" itemTemplate:"TaskManagementExampleDraggableTemplate" emptyMessage:"You don't have any active tasks">>
|
||||
"""/>
|
||||
|
||||
! Completed tasks
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""//(Listed in reverse order of completion)//
|
||||
//(Listed in reverse order of completion)//
|
||||
|
||||
<$list filter="[!has[draft.of]tag[task]tag[done]sort[modified]]">
|
||||
<div>
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
|
||||
</div>
|
||||
</$list>
|
||||
"""/>
|
||||
|
||||
@@ -4,36 +4,35 @@ tags: Features
|
||||
title: DateFormat
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
The default representation of dates is a compact string such as <<.value "<$view field='modified' format='text'/>">>. The associated template is `[UTC]YYYY0MM0DD0hh0mm0ss0XXX`. For example, the <<.field created>> and <<.field modified>> fields are stored like this.
|
||||
The default representation of dates is a compact string such as <<.value 20211002153802059>>. The associated template is `[UTC]YYYY0MM0DD0hh0mm0ss0XXX`. For example, the <<.field created>> and <<.field modified>> fields are stored like this.
|
||||
|
||||
The display format for this string can be controlled with a template. For example, transcluding the <<.field modified>> field automatically applies a template to display the date as "{{!!modified}}". A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget:
|
||||
The display format for this string can be controlled with a template. For example, transcluding the <<.field modified>> field automatically applies a template to display the date as <<.value "Sat Oct 02 2021 17:40:50 GMT+0200 (Central European Summer Time)">>. A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget:
|
||||
|
||||
`<$view field=modified format=date template="DDth mmm YYYY 0hh:0mm:0ss" />`
|
||||
|
||||
The date string is processed with the following substitutions:
|
||||
|
||||
|!Token |!Substituted Value |
|
||||
|`[UTC]`|Time-shift the represented date to UTC. Must be at very start of format string |
|
||||
|`YYYY` |Full year |
|
||||
|`YY` |Two-digit year |
|
||||
|`wYYYY` |Full year with respect to week number |
|
||||
|`aYYYY` |<<.from-version "5.1.23">> Full year but negative dates are displayed as positive |
|
||||
|`wYY` |Two digit year with respect to week number |
|
||||
|`{era:BCE||CE}` |<<.from-version "5.1.23">> Displays a different string for years that are negative, zero or positive (see below) |
|
||||
|`MMM` |Month in full (e.g. "July") |
|
||||
|`mmm` |Short month (e.g. "Jul") |
|
||||
|`MM` |Month number |
|
||||
|`0MM` |Adds leading zero |
|
||||
|`ddddd` |<<.from-version "5.2.0">> Day of year (1 to 365, or 366 for leap years) |
|
||||
|`0ddddd` |<<.from-version "5.2.0">> Zero padded day of year (001 to 365, or 366 for leap years) |
|
||||
|`DDD` |Day of week in full (e.g. "Monday") |
|
||||
|`ddd` |Short day of week (e.g. "Mon") |
|
||||
|`DDD` |Day of week in full (eg, "Monday") |
|
||||
|`ddd` |Short day of week (eg, "Mon") |
|
||||
|`dddd` |<<.from-version "5.2.0">> Weekday number from 1 through 7, beginning with Monday and ending with Sunday |
|
||||
|`DD` |Day of month |
|
||||
|`0DD` |Adds a leading zero |
|
||||
|`DDth` |Adds a suffix |
|
||||
|`WW` |ISO-8601 week number of year |
|
||||
|`0WW` |Adds a leading zero |
|
||||
|`MMM` |Month in full (eg, "July") |
|
||||
|`mmm` |Short month (eg, "Jul") |
|
||||
|`MM` |Month number |
|
||||
|`0MM` |Adds leading zero |
|
||||
|`YYYY` |Full year |
|
||||
|`YY` |Two digit year |
|
||||
|`wYYYY` |Full year with respect to week number |
|
||||
|`aYYYY` |<<.from-version "5.1.23">> Full year but negative dates are displayed as positive |
|
||||
|`wYY` |Two digit year with respect to week number |
|
||||
|`{era:BCE||CE}` |<<.from-version "5.1.23">> Displays a different string for years that are negative, zero or positive (see below) |
|
||||
|`hh` |Hours |
|
||||
|`0hh` |Adds a leading zero |
|
||||
|`hh12` |Hours in 12 hour clock |
|
||||
@@ -44,12 +43,12 @@ The date string is processed with the following substitutions:
|
||||
|`0ss` |Seconds with leading zero |
|
||||
|`XXX` |Milliseconds |
|
||||
|`0XXX` |Milliseconds with leading zero |
|
||||
|`am` or `pm` |Lower case am/pm indicator |
|
||||
|`am` or `pm` |Lower case AM/PM indicator |
|
||||
|`AM` or `PM` |Upper case AM/PM indicator |
|
||||
|`TZD` |Timezone offset from UTC (e.g. "+01:00", "-05:00"…) |
|
||||
|`TZD` |Timezone offset |
|
||||
|`TIMESTAMP` |<<.from-version "5.2.4">> Number of milliseconds since the [[ECMAScript epoch|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#the_ecmascript_epoch_and_timestamps]], 1 January 1970. |
|
||||
|`\x` |Used to escape a character that would otherwise have special meaning |
|
||||
|
||||
|`[UTC]`|Time-shift the represented date to UTC. Must be at very start of format string|
|
||||
|
||||
Note that other text is passed through unchanged, allowing commas, colons or other separators to be used.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ op-output: the titles stored as a [[title list|Title List]] at <<.place L>>
|
||||
op-parameter: a [[title list|Title List]]
|
||||
op-parameter-name: L
|
||||
op-purpose: select titles from the parameter interpreted as a [[title list|Title List]]
|
||||
op-suffix: <<.from-version "5.1.20">> `dedupe` (the default) to remove duplicates, `raw` to leave duplicates untouched
|
||||
op-suffix: <<.from-version "5.1.20">> `dedupe` (the default) to remove duplicates, `all` (or `raw`) to leave duplicates untouched
|
||||
op-suffix-name: D
|
||||
tags: [[Filter Operators]] [[Field Operators]] [[Selection Constructors]] [[Negatable Operators]]
|
||||
title: enlist Operator
|
||||
|
||||
@@ -4,7 +4,7 @@ modified: 20201102221854719
|
||||
op-input: a [[selection of titles|Title Selection]]
|
||||
op-output: the titles stored as a [[title list|Title List]] in each input title
|
||||
op-purpose: select titles by interpreting each input title as a [[title list|Title List]]
|
||||
op-suffix: `dedupe` (the default) to remove duplicates, `raw` to leave duplicates untouched
|
||||
op-suffix: `dedupe` (the default) to remove duplicates, `all` (or `raw`) to leave duplicates untouched
|
||||
op-suffix-name: D
|
||||
tags: [[Filter Operators]] [[String Operators]]
|
||||
title: enlist-input Operator
|
||||
|
||||
@@ -6,13 +6,15 @@ type: text/vnd.tiddlywiki
|
||||
<<.operator-example 2 "[!days:created[-800]]" "tiddlers created more than 800 days ago">>
|
||||
The filter can be used to highlight new items in a list. For example:
|
||||
<$macrocall
|
||||
$name="wikitext-example-without-html"
|
||||
src="""<ul>
|
||||
$name="wikitext-example-without-html" src=
|
||||
"""
|
||||
<ul>
|
||||
<$list filter="[tag[ReleaseNotes]!<currentTiddler>!sort[modified]]">
|
||||
<li>
|
||||
<$link><$view field="title"/></$link>
|
||||
<$list filter="[<currentTiddler>days[-180]]"> @@color:red;^^new^^@@</$list>
|
||||
<$list filter="[<currentTiddler>days[-500]!days[-180]]"> @@color:black;^^recent^^@@</$list>
|
||||
<$list filter="[<currentTiddler>days[-180]]"> @@color:red;^^new^^@@</$list>
|
||||
<$list filter="[<currentTiddler>days[-500]!days[-180]]"> @@color:black;^^recent^^@@</$list>
|
||||
</li>
|
||||
</$list>
|
||||
</ul>"""/>
|
||||
</ul>
|
||||
"""/>
|
||||
|
||||
@@ -12,6 +12,8 @@ tags: [[Filter Operators]] [[Negatable Operators]]
|
||||
title: filter Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: Description of new parameter
|
||||
|
||||
<<.from-version "5.1.23">> The <<.op filter>> operator runs a subfilter for each input title, and returns those input titles for which the subfilter returns a non-empty result (in other words the result is not an empty list). The results of the subfilter are thrown away.
|
||||
|
||||
Simple filter operations can be concatenated together directly (eg `[tag[HelloThere]search[po]]`) but this doesn't work when the filtering operations require intermediate results to be computed. The <<.op filter>> operator can be used to filter on an intermediate result which is discarded. To take the same example but to also filter by those tiddlers whose text field is longer than 1000 characters:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: function
|
||||
created: 20220909111836951
|
||||
modified: 20260130210336084
|
||||
modified: 20230419103154328
|
||||
op-input: a [[selection of titles|Title Selection]] passed as input to the function <<.place F>>
|
||||
op-output: the [[selection of titles|Title Selection]] returned from the function <<.place F>>
|
||||
op-parameter: first parameter is the [[function name|Functions]], subsequent parameters are passed to the function by position
|
||||
@@ -10,7 +10,7 @@ tags: [[Filter Operators]]
|
||||
title: function Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.3.0">> The <<.op function>> operator applies a named [[function|Functions]] to the input titles, and returns the results from the function. The function is called once with all of the input titles (in contrast, the [[filter Operator]] calls its function separately for each input title).
|
||||
<<.from-version "5.3.0">> The <<.op function>> operator applies a named [[function|Functions]] to the input titles, and returns the results from the function. The function is invoked once with all of the input titles (in contrast, the [[filter Operator]] invokes its function separately for each input title).
|
||||
|
||||
The first parameter of the <<.op function>> operator specifies the name of the function to be called. Subsequent parameters are passed to the function.
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ tags: [[Filter Operators]] [[Field Operators]] [[Selection Constructors]] [[Nega
|
||||
title: subfilter Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: Description of new parameter
|
||||
|
||||
<<.from-version "5.1.18">> Note that the <<.op subfilter>> operator was introduced in version 5.1.18 and is not available in earlier versions.
|
||||
|
||||
<<.tip " Literal filter parameters cannot contain square brackets but you can work around the issue by using a variable:">>
|
||||
|
||||
@@ -4,6 +4,8 @@ tags: [[Filter Syntax]]
|
||||
title: Filter Expression
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: Update railroad diagram
|
||||
|
||||
A <<.def "filter expression">> is the outermost level of the [[filter syntax|Filter Syntax]]. It consists of [[filter runs|Filter Run]] with optional [[filter run prefixes|Filter Run Prefix]]. Multiple filter runs are separated by [[whitespace|Filter Whitespace]].
|
||||
|
||||
<$railroad text="""
|
||||
|
||||
11
editions/tw5.com/tiddlers/filters/syntax/Filter Pragma.tid
Normal file
11
editions/tw5.com/tiddlers/filters/syntax/Filter Pragma.tid
Normal file
@@ -0,0 +1,11 @@
|
||||
created: 20260122212128206
|
||||
modified: 20260122212128206
|
||||
tags: [[Filter Expression]]
|
||||
title: Filter Pragma
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: High level pragma docs & railroad diagram
|
||||
|
||||
A <<.def "filter pragma">> is a special instruction embedded within a filter expression that affects the behavior of subsequent filter operations. Filter pragmas are similar to wikitext pragmas and are used to control aspects of filter evaluation. They do not appear at the start of a filter, but can be placed between other filter runs.
|
||||
|
||||
The `::defaultprefix` pragma sets the default filter run prefix for the remainder of the filter expression. This allows users to control deduplication behavior without having to specify prefixes for each individual operation.
|
||||
@@ -4,6 +4,8 @@ tags: [[Filter Expression]]
|
||||
title: Filter Run Prefix
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: Link to how the default filter run prefix can be specified
|
||||
|
||||
There are 2 types of filter run prefixes that are interchangeable; [[named prefixes|Named Filter Run Prefix]] and [[shortcut prefixes|Shortcut Filter Run Prefix]].
|
||||
|
||||
<$railroad text="""
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
created: 20260122212128206
|
||||
modified: 20260122212128206
|
||||
tags: [[Filter Pragma]]
|
||||
title: defaultprefix Filter Pragma
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TODO:docs-default-prefix-for-subfilter: Purpose and docs of new pragma
|
||||
|
||||
A <<.def "defaultprefix filter pragma">> is used to set the default [[Filter Run Prefix]] for the remainder of the filter expression. This allows users to control deduplication behavior without having to specify prefixes for each individual operation.
|
||||
|
||||
Any of the [[named prefixes|Named Filter Run Prefix]] can be specified as the default prefix, but `all` is the most commonly used value to disable deduplication.
|
||||
|
||||
|
||||
@@ -16,13 +16,12 @@ Functions are usually defined with the [[Pragma: \function]]:
|
||||
\end
|
||||
```
|
||||
|
||||
Functions can be called in several ways:
|
||||
Functions can be invoked in several ways:
|
||||
|
||||
* Using the [[Calls]] syntax:
|
||||
** Directly transclude functions with the syntax `<<myfun param:"value">>`
|
||||
** Assign functions to widget attributes with the syntax `<div class=<<myfun param:"value">>>`
|
||||
* Call functions via the [[function Operator]] with the syntax `[function[myfun],[value],...]`
|
||||
* Directly call functions whose names contain a period as custom filter operators with the syntax `[my.fun[value]]` or `[.myfun[value]]`
|
||||
* Directly transclude functions with the syntax `<<myfun param:"value">>`
|
||||
* Assign functions to widget attributes with the syntax `<div class=<<myfun param:"value">>>`
|
||||
* Invoke functions via the [[function Operator]] with the syntax `[function[myfun],[value],...]`
|
||||
* Directly invoke functions whose names contain a period as custom filter operators with the syntax `[my.fun[value]]` or `[.myfun[value]]`
|
||||
|
||||
!! How Functions Work
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
created: 20240310165023000
|
||||
modified: 20260125212303316
|
||||
tags: [[Call Syntax]]
|
||||
title: Call Syntax
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.preamble """What follows is a formal presentation of the syntax of the WikiText syntax for procedure/function/macro calls, using [[railroad diagrams|Railroad Diagrams]].""">>
|
||||
|
||||
!! callee-name
|
||||
|
||||
<$railroad text="""
|
||||
"<<" [[ callee-name |Calls]] [: [[whitespace|"Filter Whitespace"]] [:{param-value}] ]">>"
|
||||
"""/>
|
||||
|
||||
* The <<.place callee-name>> is a sequence of non-whitespace characters other than `(` or `>`.
|
||||
|
||||
* <<.place whitespace>> denotes a sequence of [[whitespace characters|Filter Whitespace]].
|
||||
|
||||
!!! param-value
|
||||
|
||||
Each ''individual'' <<.place param-value>> has the following syntax:
|
||||
|
||||
<$railroad text="""
|
||||
\start none
|
||||
\end none
|
||||
(
|
||||
value
|
||||
|
|
||||
param-name [:space] (
|
||||
":" [:space] value [: space]
|
||||
|
|
||||
"=" [:space] new-value [: space]
|
||||
)
|
||||
)
|
||||
"""/>
|
||||
|
||||
* The <<.place param-name>> is a sequence of letters (`A`--`Z`, `a`--`z`), digits (`0`--`9`), hyphens (`-`) and underscores (`_`).
|
||||
|
||||
* The <<.place value>> is specified as follows:
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/call-parameter-value}}/>
|
||||
|
||||
* <<.from-version 5.4.0>> The <<.place new-value>> can either be a plain <<.place value>> or a full <<.place callee-name>> call, allowing for dynamic parameter values.
|
||||
@@ -1,7 +1,31 @@
|
||||
created: 20150221105732000
|
||||
modified: 20260125212303316
|
||||
tags: $:/deprecated
|
||||
modified: 20150221222352000
|
||||
tags: [[Macro Syntax]] $:/deprecated
|
||||
title: Macro Call Syntax
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.deprecated-since "5.3.0" "Call Syntax">>
|
||||
<<.deprecated-since "5.3.0" "Procedure Call Syntax">>
|
||||
|
||||
----------
|
||||
|
||||
<<.preamble """What follows is a formal presentation of the syntax of the WikiText syntax for macro calls, using [[railroad diagrams|Railroad Diagrams]]. A [[simpler overview|Macro Calls in WikiText]] is also available.""">>
|
||||
|
||||
<$railroad text="""
|
||||
"<<" name [: space [:{param-value}] ]">>"
|
||||
"""/>
|
||||
|
||||
<<.place space>> denotes a sequence of [[whitespace characters|Filter Whitespace]].
|
||||
|
||||
The [[macro|Macros]]'s <<.place name>> is a sequence of non-whitespace characters other than `(` or `>`.
|
||||
|
||||
Each individual <<.place param-value>> has the following syntax:
|
||||
|
||||
<$railroad text="""
|
||||
[: param-name [:space] ":" [:space] ] value [: space]
|
||||
"""/>
|
||||
|
||||
The <<.place param-name>> is a sequence of letters (`A`--`Z`, `a`--`z`), digits (`0`--`9`), hyphens (`-`) and underscores (`_`).
|
||||
|
||||
The <<.place value>> is specified as follows:
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/macro-parameter-value}}/>
|
||||
|
||||
@@ -37,7 +37,7 @@ param-name [: [:space] ":" [:space] default ]
|
||||
|
||||
The optional <<.place default>> value of a parameter is specified as follows:
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/call-parameter-value}}/>
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/macro-parameter-value}}/>
|
||||
|
||||
The <<.place rest>> of the definition has the following syntax:
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
created: 20150220191009000
|
||||
modified: 20260125212303316
|
||||
title: $:/editions/tw5.com/railroad/call-parameter-value
|
||||
modified: 20150221111554000
|
||||
title: $:/editions/tw5.com/railroad/macro-parameter-value
|
||||
type: text/vnd.tiddlywiki.railroad
|
||||
|
||||
( '"""' [:{/'anything but """'/}] '"""'
|
||||
| '"' [:{/'anything but "'/}] '"'
|
||||
| "'" [:{/"anything but '"/}] "'"
|
||||
| "[[" [:{/"anything but ]"/}] "]]"
|
||||
| "`" [:{/"anything but `"/}] "`"
|
||||
| "```" [:{/"anything but ```"/}] "```"
|
||||
| {/"""anything but ' " or whitespace"""/}
|
||||
)
|
||||
@@ -1,6 +1,33 @@
|
||||
created: 20240310165023000
|
||||
modified: 20260125212303316
|
||||
modified: 20240310172648116
|
||||
tags: [[Procedure Syntax]]
|
||||
title: Procedure Call Syntax
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.deprecated-since "5.4.0" "Call Syntax">>
|
||||
<<.preamble """What follows is a formal presentation of the syntax of the WikiText syntax for procedure calls, using [[railroad diagrams|Railroad Diagrams]].""">>
|
||||
|
||||
!! procedure-name
|
||||
|
||||
<$railroad text="""
|
||||
"<<" [[ procedure-name |Procedures]] [: [[whitespace|"Filter Whitespace"]] [:{param-value}] ]">>"
|
||||
"""/>
|
||||
|
||||
* The [[procedure's|Procedures]] <<.place procedure-name>> is a sequence of non-whitespace characters other than `(` or `>`.
|
||||
|
||||
* <<.place whitespace>> denotes a sequence of [[whitespace characters|Filter Whitespace]].
|
||||
|
||||
!!! param-value
|
||||
|
||||
Each ''individual'' <<.place param-value>> has the following syntax:
|
||||
|
||||
<$railroad text="""
|
||||
\start none
|
||||
\end none
|
||||
[: param-name [:[[whitespace|"Filter Whitespace"]]] ":" [:[[whitespace|"Filter Whitespace"]]] ] value [: [[whitespace|"Filter Whitespace"]] ]
|
||||
"""/>
|
||||
|
||||
* The <<.place param-name>> is a sequence of letters (`A`--`Z`, `a`--`z`), digits (`0`--`9`), hyphens (`-`) and underscores (`_`).
|
||||
|
||||
* The <<.place value>> is specified as follows:
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/macro-parameter-value}}/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
created: 20240310165023000
|
||||
modified: 20240310175033730
|
||||
tags: [[Call Syntax]]
|
||||
tags: [[Procedure Syntax]]
|
||||
title: Procedure Definition Syntax
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -73,7 +73,7 @@ Each ''individual'' <<.place parameter>> has the following syntax:
|
||||
|
||||
* <<.place default>> is an optional value of a parameter is specified as follows:
|
||||
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/call-parameter-value}}/>
|
||||
<$railroad text={{$:/editions/tw5.com/railroad/macro-parameter-value}}/>
|
||||
|
||||
!! body
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
Plain text description can be found at [[Procedures]]
|
||||
|
||||
<<list-links filter:"[tag[Call Syntax]]">>
|
||||
<<list-links filter:"[tag[Procedure Syntax]]">>
|
||||
|
||||
<<.tip "The railroad boxes in the linked tiddlers can be used to navigate.">>
|
||||
|
||||
@@ -1,7 +1,56 @@
|
||||
caption: Procedure Calls
|
||||
created: 20221007130006705
|
||||
modified: 20260125212303316
|
||||
modified: 20230419103154329
|
||||
tags: WikiText Procedures
|
||||
title: Procedure Calls
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.deprecated-since "5.4.0" "Calls">>
|
||||
!! Introduction
|
||||
|
||||
This tiddler describes the different ways in which [[procedure|Procedures]] can be called.
|
||||
|
||||
!! Procedure Call Transclusion Shortcut
|
||||
|
||||
To call a [[procedure|Procedures]], place `<<`double angle brackets`>>` around the name and any parameter values.
|
||||
|
||||
```
|
||||
<<my-procedure param:"This is the parameter value">>
|
||||
```
|
||||
|
||||
By default, parameters are listed in the same order as in the procedure definition. A parameter can be labelled with its name and a colon to allow them to be listed in a different order.
|
||||
|
||||
If no value is specified for a parameter, the default value given for that parameter in the [[procedure definition|Procedure Definitions]] is used instead. (If no default value was defined, the parameter is blank).
|
||||
|
||||
Each parameter value can be enclosed in `'`single quotes`'`, `"`double quotes`"`, `"""`triple double quotes`"""` or `[[`double square brackets`]]`. Triple double quotes allow a value to contain almost anything. If a value contains no spaces or single or double quotes, it requires no delimiters.
|
||||
|
||||
See the discussion about [[parser modes|WikiText parser mode: macro examples]]
|
||||
|
||||
!! Procedure Calls with <<.wlink TranscludeWidget>> Widget
|
||||
|
||||
The shortcut syntax expands to the <<.wlink TranscludeWidget>> widget with the `$variable` attribute specifying the name of the procedure to transclude.
|
||||
|
||||
```
|
||||
<$transclude $variable="my-procedure" param="This is the parameter value"/>
|
||||
```
|
||||
|
||||
The widget itself offers greater flexibility than the shortcut syntax, including the ability to specify dynamic parameter values.
|
||||
|
||||
!! Assigning Procedure Calls to Attribute Values
|
||||
|
||||
The text of a procedure can be directly assigned to an attribute of a widget or HTML element. The result of the procedure is not wikified, which means that [[parameter handling|Procedure Parameter Handling]] does not take place.
|
||||
|
||||
```
|
||||
<div class=<<myclasses>>>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
!! Using Procedure Calls in Filters
|
||||
|
||||
Procedure calls can be used in filters. The text is not wikified which again means that the parameters will be ignored.
|
||||
|
||||
```
|
||||
<$list filter="[<my-procedure>]">
|
||||
...
|
||||
</$list>
|
||||
```
|
||||
@@ -33,6 +33,6 @@ Procedures are implemented as a special kind of [[variable|Variables]]. The only
|
||||
!! Using Procedures
|
||||
|
||||
* [[Procedure Definitions]] describes how to create procedures
|
||||
* [[Calls]] describes how to use procedures
|
||||
* [[Procedure Calls]] describes how to use procedures
|
||||
* [[Procedure Parameter Handling]] describes how procedure parameters work
|
||||
* [[Call Syntax]] is a formal syntax description using railroad diagrams
|
||||
* [[Procedure Syntax]] is a formal syntax description using railroad diagrams
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
caption: Calls
|
||||
created: 20221007130006705
|
||||
modified: 20260125212303316
|
||||
tags: WikiText Procedures Functions Macros
|
||||
title: Calls
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! Introduction
|
||||
|
||||
This tiddler describes the different ways in which [[procedures|Procedures]], [[functions|Functions]] and [[macros|Macros]] can be called. See [[Call Syntax]] for a formal description of the syntax.
|
||||
|
||||
!! Call Transclusion Shortcut
|
||||
|
||||
To perform a call, place `<<`double angle brackets`>>` around the callee name and any parameter values.
|
||||
|
||||
```
|
||||
<<my-procedure param="This is the parameter value">>
|
||||
```
|
||||
|
||||
By default, parameters are interpreted as being in the same order as in the definition. A parameter value can be labelled with its name and an equals sign to allow them to be listed in a different order.
|
||||
|
||||
If no value is specified for a parameter, the default value given for that parameter in the [[procedure definition|Procedure Definitions]], [[function definition|Function Definitions]] or [[macro definition|Macro Definitions]] is used instead. (If no default value was defined, the parameter is blank).
|
||||
|
||||
Each parameter value can be enclosed in `'`single quotes`'`, `"`double quotes`"`, `"""`triple double quotes`"""` or `[[`double square brackets`]]`. Triple double quotes allow a value to contain almost anything. If a value contains no spaces or single or double quotes, it requires no delimiters. [[Substituted Attribute Values]] enclosed in single or triple back quotes are also supported.
|
||||
|
||||
See the discussion about [[parser modes|WikiText parser mode: macro examples]]
|
||||
|
||||
!! Calls with <<.wlink TranscludeWidget>> Widget
|
||||
|
||||
The shortcut syntax expands to the <<.wlink TranscludeWidget>> widget with the `$variable` attribute specifying the name of the procedure to transclude.
|
||||
|
||||
```
|
||||
<$transclude $variable="my-procedure" param="This is the parameter value"/>
|
||||
```
|
||||
|
||||
The widget itself offers greater flexibility than the shortcut syntax, including the ability to override it with a custom widget.
|
||||
|
||||
!! Assigning Results of Calls to Attribute Values
|
||||
|
||||
The text returned from a call can be directly assigned to an attribute of a widget or HTML element. The result of the call is not wikified, which means that [[parameter handling|Procedure Parameter Handling]] does not take place.
|
||||
|
||||
```
|
||||
<div class=<<myclasses>>>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
!! Using Calls in Filters
|
||||
|
||||
Calls can be used in filters. The text is not wikified which again means that the parameters will be ignored.
|
||||
|
||||
```
|
||||
<$list filter="[<my-procedure>]">
|
||||
...
|
||||
</$list>
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#8093
|
||||
description: Fixes SelectWidget does not work with multiple options organised into group - issue #8092
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/issues/8093 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9616
|
||||
github-contributors: buggyj saqimtiaz
|
||||
|
||||
Fixed SelectWidget does not work with multiple options organised into group.
|
||||
@@ -1,42 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#9055
|
||||
description: Dynamic parameters for macro/procedure/function calls
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9055
|
||||
github-contributors: Jermolene
|
||||
|
||||
This PR extends the handling of macro/procedure/function made via the `<<..>>` syntax to allow parameters to be specified dynamically instead of just as static strings. To indicate the new syntax the colon that usually separates a parameter name from its value is replaced by an equals sign.
|
||||
|
||||
For example, by it is now possible to do things like this:
|
||||
|
||||
```
|
||||
<<mymacro param={{Something}}>>
|
||||
```
|
||||
|
||||
Or even this:
|
||||
|
||||
```
|
||||
<div class=<<mymacro param={{Something}}>>>
|
||||
```
|
||||
|
||||
Or this:
|
||||
|
||||
```
|
||||
<div class=<<mymacro param={{{ [<myvar>addprefix[https:] }}}>>>
|
||||
```
|
||||
|
||||
Parameters can also be specified for the inner call:
|
||||
|
||||
```
|
||||
<div class=<<mymacro param={{{ [<innermacro p={{Something}}>addprefix[https:] }}}>>>
|
||||
```
|
||||
|
||||
The extended syntax can be used in three different settings:
|
||||
|
||||
* As a standalone construction
|
||||
* As a widget attribute value
|
||||
* As a filter operand value
|
||||
|
||||
In all cases, it is now possible to use an equals sign instead of a colon to allow parameter values to be passed as a transclusion, filter expression or nested call.
|
||||
@@ -1,17 +0,0 @@
|
||||
change-category: nodejs
|
||||
change-type: feature
|
||||
created: 20260120154012282
|
||||
description: Allows server routes to be prioritized via ordering.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9206
|
||||
modified: 20260120160656948
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9206
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This PR adds support for an info property to server route module exports. The info object may include a priority field, which determines the route’s order of precedence.
|
||||
|
||||
Priorities are numeric and follow a descending order: routes with higher priority values are processed first, similar to how saver modules are prioritized.
|
||||
|
||||
To maintain backward compatibility with existing code, any module that omits info or info.priority is assigned a default priority of 100. Core server routes have been updated to explicitly use this default value of 100.
|
||||
@@ -1,13 +0,0 @@
|
||||
change-category: nodejs
|
||||
change-type: feature
|
||||
created: 20260120154249928
|
||||
description: Allows server routes to support multiple HTTP methods.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9207
|
||||
modified: 20260120160159661
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9207
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Allows server routes to support multiple HTTP methods by introducing an `exports.methods` array.
|
||||
@@ -1,13 +0,0 @@
|
||||
change-category: widget
|
||||
change-type: deprecation
|
||||
created: 20260120154533983
|
||||
description: The deprecated events and actions-* atrributes for the eventcatcher widget have been removed.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9259
|
||||
modified: 20260120160236297
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9259
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Deprecates and removes the `events` and `actions-*` attributes for the $eventcatcher widget.
|
||||
@@ -1,8 +0,0 @@
|
||||
changenote: $:/changenotes/5.4.0/#9259
|
||||
created: 20260120154817011
|
||||
description: Deprecated events and actons-* attributes from the eventcatcher widget
|
||||
impact-type: deprecation
|
||||
modified: 20260120154900978
|
||||
tags: $:/tags/ImpactNote
|
||||
title: $:/changenotes/5.4.0/#9259/impacts/deprecate-eventcatcher-attributes
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -1,29 +0,0 @@
|
||||
change-category: hackability
|
||||
change-type: feature
|
||||
created: 20260120154445701
|
||||
description: Adds info tiddlers for viewport dimensions that are updated on window resize.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9260
|
||||
modified: 20260120160515462
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9260
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Adds info tiddlers for viewport dimensions that are updated on window resize.
|
||||
|
||||
!! Example: Main and a user-created window with windowID my-window
|
||||
|
||||
|Window | Info tiddler | Meaning |h
|
||||
|system/main |`$:/info/browser/window/system/main/outer/width` | Full browser window including chrome, tabs, toolbars |
|
||||
|system/main |`$:/info/browser/window/system/main/outer/height` | Full browser window including chrome, tabs, toolbars |
|
||||
|system/main |`$:/info/browser/window/system/main/inner/width` | Viewport width including scrollbars |
|
||||
|system/main |`$:/info/browser/window/system/main/inner/height` | Viewport height including scrollbars |
|
||||
|system/main |`$:/info/browser/window/system/main/client/width` | Content width excluding scrollbars |
|
||||
|system/main |`$:/info/browser/window/system/main/client/height` | Content height excluding scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/outer/width` | Full browser window including chrome, tabs, toolbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/outer/height` | Full browser window including chrome, tabs, toolbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/inner/width` | Viewport width including scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/inner/height` | Viewport height including scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/client/width` | Content width excluding scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/client/height` | Content height excluding scrollbars |
|
||||
@@ -1,10 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#9277
|
||||
description: Added an option to enable CORS
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: feature
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9277
|
||||
github-contributors: kixam
|
||||
|
||||
Added an option to the TiddlyWiki5 server to enable CORS (ie. don't check `same-origin`). It is meant for advanced users, do not use it unless you understand the full consequences.
|
||||
@@ -1,7 +1,17 @@
|
||||
title: $:/changenotes/5.4.0/#9337/impacts/math-filters
|
||||
title: $:/changenotes/5.4.0/#9337/compatibility-break/math-filters
|
||||
changenote: $:/changenotes/5.4.0/#9337
|
||||
created: 20251112152513384
|
||||
modified: 20251209160312626
|
||||
created - 20251112152513384
|
||||
modified - 20251112152513384
|
||||
tags: $:/tags/ImpactNote
|
||||
description: filter output changes for some math filter operators when input list is empty
|
||||
impact-type: compatibility-break
|
||||
description: filter output with empty input changes for some math filter operators
|
||||
impact-type: compatibility-break
|
||||
|
||||
These math operators will now output an empty list when the input list is empty:
|
||||
|
||||
* sum[] - previously returned 0
|
||||
* product[] - previously returned 1
|
||||
* maxall[] - previously returned -Infinity
|
||||
* minall[] - previously returned Infinity
|
||||
* average[] - previously returned NaN
|
||||
* variance[] - previously returned NaN
|
||||
* standard-deviation[] - previously returned NaN
|
||||
@@ -4,8 +4,7 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: translation
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9375 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9576
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9375
|
||||
github-contributors: BramChen
|
||||
|
||||
* change camel-case hint text for chinese translations
|
||||
* add alerts ARIA message
|
||||
* change camel-case hint text for chinese translations
|
||||
@@ -1,10 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#9494
|
||||
description: Fix LetWidget to always set all staged variables on first render
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9494
|
||||
github-contributors: yaisog
|
||||
|
||||
This PR corrects a bug where the LetWidget did not set variables if their value was the empty output of a filtered transclusion.
|
||||
34
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9595.tid
Normal file
34
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9595.tid
Normal file
@@ -0,0 +1,34 @@
|
||||
title: $:/changenotes/5.4.0/#9595
|
||||
description: Easier avoidance of deduplication in filters
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: filters
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9595
|
||||
github-contributors: Jermolene
|
||||
|
||||
Resolves a long-standing issue with filters where there has been no easy way to avoid deduplication of results during filter evaluation. There are two distinct new capabilities.
|
||||
|
||||
First, there is a new filter pragma `::defaultprefix` that sets the default filter run prefix for the remainder of the filter expression. Filter pragmas are a new concept akin to wikitext pragmas, allowing special instructions to be embedded in filter expressions.
|
||||
|
||||
The `::defaultprefix` pragma takes as its first parameter the desired default filter run prefix, followed by any number of filter operations to which it applies. The default prefix `all` can be used to disable deduplication for the subsequent operations (`or` is the default prefix that performs deduplication).
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
::defaultprefix:all 1 2 2 1 4 +[join[ ]]
|
||||
```
|
||||
|
||||
Returns `1 2 2 1 4`.
|
||||
|
||||
Contrast to the result without the pragma which returns `2 1 4`:
|
||||
|
||||
```
|
||||
1 2 2 1 4 +[join[ ]]
|
||||
```
|
||||
|
||||
Second, there is a new parameter to the `subfilter` and `filter` operators to specify the default filter run prefix to use when the filter is evaluated. This overrides any default set with the `::defaultprefix` pragma.
|
||||
|
||||
```
|
||||
[subfilter:all<my-subfilter>]
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#9600
|
||||
description: Fix Ctrl-Enter not working in EditTemplate tag name input
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9600
|
||||
github-contributors: yaisog
|
||||
|
||||
The tag name input now calls `<<save-tiddler-actions>>` from the EditTemplate when Ctrl-Enter (or whichever key is assigned to input-accept-variant) is pressed.
|
||||
@@ -1,12 +0,0 @@
|
||||
change-category: usability
|
||||
change-type: bugfix
|
||||
created: 20260125195754439
|
||||
description: Refresh widget if "default" parameter input value is changed
|
||||
github-contributors: pmario
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9217
|
||||
modified: 20260125195754439
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9217
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -4,7 +4,7 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: deprecation
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9251 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9622
|
||||
github-contributors: Leilei332 saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9251
|
||||
github-contributors: Leilei332
|
||||
|
||||
Deprecate some utility functions. Some of them are moved to [[$:/core/modules/utils/deprecated.js]].
|
||||
@@ -1,10 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#9475
|
||||
description: Split escapecss.js into two platforms
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: performance
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9475
|
||||
github-contributors: Leilei332
|
||||
|
||||
Split [[$:/core/modules/utils/escapecss.js]] for two platforms: one for the browser, the other for Node.js. The `CSS.escape` polyfill is moved to `core-server`.
|
||||
@@ -5,16 +5,8 @@ tags: Releases
|
||||
title: TiddlyWiki Releases
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Here are the details of recent releases of TiddlyWiki5. See [[TiddlyWiki5 Versioning]] for details of how releases are named.
|
||||
|
||||
* An overview about all TW versions can be found at the [[TiddlyWiki Archive]].
|
||||
|
||||
* If you are using Node.js, you can also install ''prior'' versions like this:
|
||||
|
||||
*> npm install -g tiddlywiki@5.3.0
|
||||
|
||||
* BetaReleases and AlphaReleases are listed separately
|
||||
Here are the details of recent releases of TiddlyWiki5. See [[TiddlyWiki5 Versioning]] for details of how releases are named, and [[Release Notes and Changes]] for details of how release notes are constructed.
|
||||
|
||||
<$list filter="[tag[ReleaseNotes]!sort[created]limit[1]]">
|
||||
<$macrocall $name="tabs" tabsList="[tag[ReleaseNotes]!sort[created]]" default={{!!title}} class="tc-vertical" template="ReleaseTemplate" />
|
||||
</$list>
|
||||
</$list>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
title: Improvements to Macro Calls in v5.4.0
|
||||
tags: v5.4.0
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""\define testmacro(one)
|
||||
Result: $one$.
|
||||
\end testmacro
|
||||
|
||||
<<testmacro one={{{ [[There]addprefix[Hello]] }}}>>
|
||||
"""/>
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""\function testfunction(one)
|
||||
[<one>addprefix[Hello]]
|
||||
\end testfunction
|
||||
|
||||
<<testfunction one={{{ [[re]addprefix[The]] }}}>>
|
||||
"""/>
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""\define testmacro(one)
|
||||
Result: $one$.
|
||||
\end testmacro
|
||||
|
||||
<$text text=<<testmacro one={{{ [[There]addprefix[Hello]] }}}>>/>
|
||||
"""/>
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src="""\function testfunction(one)
|
||||
[<one>addprefix[Hello]]
|
||||
\end testfunction
|
||||
|
||||
<$text text=<<testfunction one={{{ [[re]addprefix[The]] }}}>>/>
|
||||
"""/>
|
||||
|
||||
<$macrocall $name='wikitext-example'
|
||||
src="""\define innermacro(one)
|
||||
:$one$:$one$:
|
||||
\end innermacro
|
||||
|
||||
\define mymacro(param)
|
||||
|$param$|$param$|
|
||||
\end mymacro
|
||||
|
||||
<div class=<<mymacro param={{{ [<innermacro one={{$:/palette}}>addprefix[The palette named ]] }}}>>>
|
||||
Content
|
||||
</div>
|
||||
"""/>
|
||||
@@ -1,52 +0,0 @@
|
||||
created: 20230726145210484
|
||||
modified: 20260130210336084
|
||||
tags: [[Variable Usage]]
|
||||
title: Behaviour of called variables depends on how the variable was declared
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define m1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\procedure p1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\function f1(a1) "$a1$" "-" [<__a1__>] ="-" [<a1>] :and[join[ ]]
|
||||
|
||||
Called in normal wikitext context: `<$transclude $variable=myvar/>` or `<<myvar>>`
|
||||
|
||||
{{Behaviour of variables called via normal wikitext}}
|
||||
|
||||
Called via widget attribute: `<div class=<<myvar>>/>`
|
||||
|
||||
{{Behaviour of variables called via widget attributes}}
|
||||
|
||||
Called via filter operator parameter: `[<myvar>]`
|
||||
|
||||
{{Behaviour of variables called via filter operator parameter}}
|
||||
|
||||
Called via function call in a filter expression: `[function[.myfun]]`
|
||||
|
||||
{{Behaviour of variables called via filter expression function call}}
|
||||
|
||||
!! Examples
|
||||
|
||||
Below is an example macro, procedure and function definition. All three forms of parameter substitution `$a1$`, `<<__a1__>>`, and `<<a1>>` are included in each definition. The output helps illustrate when each form of substitution will or will not have affect.
|
||||
|
||||
```
|
||||
\define m1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\procedure p1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\function f1(a1) $a1$ "-" [<__a1__>] ="-" [<a1>] :and[join[ ]]
|
||||
```
|
||||
|
||||
| !Variable transclusion|!output |
|
||||
| `<<m1 foo>>`|<<m1 foo>>|
|
||||
| `<<p1 foo>>`|<<p1 foo>>|
|
||||
| `<<f1 foo>>`|<<f1 foo>>|
|
||||
| !Widget attribute|!output |
|
||||
| `<$text text=<<m1 foo>>/>`|<$text text=<<m1 foo>>/>|
|
||||
| `<$text text=<<p1 foo>>/>`|<$text text=<<p1 foo>>/>|
|
||||
| `<$text text=<<f1 foo>>/>`|<$text text=<<f1 foo>>/>|
|
||||
| !Filter operator parameter|!output |
|
||||
| `[<m1 foo>]`|<$text text={{{[<m1 foo>]}}}/>|
|
||||
| `[<p1 foo>]`|<$text text={{{[<p1 foo>]}}}/>|
|
||||
| `[<f1 foo>]`|<$text text={{{[<f1 foo>]}}}/>|
|
||||
| !Function call in filter expression|!output |
|
||||
| `[function[m1],[foo]]`|<$text text={{{[function[m1],[foo]]}}}/>|
|
||||
| `[function[p1],[foo]]`|<$text text={{{[function[p1],[foo]]}}}/>|
|
||||
| `[function[f1],[foo]]`|<$text text={{{[function[f1],[foo]]}}}/>|
|
||||
@@ -1,6 +1,52 @@
|
||||
created: 20230726145210484
|
||||
modified: 20260130210336084
|
||||
title: Behaviour of called variables depends on how the variable was declared
|
||||
modified: 20240619211734149
|
||||
tags: [[Variable Usage]]
|
||||
title: Behaviour of invoked variables depends on how the variable was declared
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
See [[Behaviour of called variables depends on how the variable was declared]].
|
||||
\define m1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\procedure p1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\function f1(a1) "$a1$" "-" [<__a1__>] ="-" [<a1>] :and[join[ ]]
|
||||
|
||||
Invoked in normal wikitext context: `<$transclude $variable=myvar/>` or `<<myvar>>`
|
||||
|
||||
{{Behaviour of variables invoked via normal wikitext}}
|
||||
|
||||
Invoked via widget attribute: `<div class=<<myvar>>/>`
|
||||
|
||||
{{Behaviour of variables invoked via widget attributes}}
|
||||
|
||||
Invoked via filter operator parameter: `[<myvar>]`
|
||||
|
||||
{{Behaviour of variables invoked via filter operator parameter}}
|
||||
|
||||
Invoked via function call in a filter expression: `[function[.myfun]]`
|
||||
|
||||
{{Behaviour of variables invoked via filter expression function call}}
|
||||
|
||||
!! Examples
|
||||
|
||||
Below is an example macro, procedure and function definition. All three forms of parameter substitution `$a1$`, `<<__a1__>>`, and `<<a1>>` are included in each definition. The output helps illustrate when each form of substitution will or will not have affect.
|
||||
|
||||
```
|
||||
\define m1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\procedure p1(a1) $a1$ - <<__a1__>> - <<a1>>
|
||||
\function f1(a1) $a1$ "-" [<__a1__>] ="-" [<a1>] :and[join[ ]]
|
||||
```
|
||||
|
||||
| !Variable transclusion|!output |
|
||||
| `<<m1 foo>>`|<<m1 foo>>|
|
||||
| `<<p1 foo>>`|<<p1 foo>>|
|
||||
| `<<f1 foo>>`|<<f1 foo>>|
|
||||
| !Widget attribute|!output |
|
||||
| `<$text text=<<m1 foo>>/>`|<$text text=<<m1 foo>>/>|
|
||||
| `<$text text=<<p1 foo>>/>`|<$text text=<<p1 foo>>/>|
|
||||
| `<$text text=<<f1 foo>>/>`|<$text text=<<f1 foo>>/>|
|
||||
| !Filter operator parameter|!output |
|
||||
| `[<m1 foo>]`|<$text text={{{[<m1 foo>]}}}/>|
|
||||
| `[<p1 foo>]`|<$text text={{{[<p1 foo>]}}}/>|
|
||||
| `[<f1 foo>]`|<$text text={{{[<f1 foo>]}}}/>|
|
||||
| !Function call in filter expression|!output |
|
||||
| `[function[m1],[foo]]`|<$text text={{{[function[m1],[foo]]}}}/>|
|
||||
| `[function[p1],[foo]]`|<$text text={{{[function[p1],[foo]]}}}/>|
|
||||
| `[function[f1],[foo]]`|<$text text={{{[function[f1],[foo]]}}}/>|
|
||||
@@ -6,5 +6,5 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
|tc-first-col-min-width|k
|
||||
|!how declared|!behaviour|
|
||||
|\define, <<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|Every function is a variable, but only variables defined using \function are callable using the <<.olink function>> filter operator. Attempts to use a non-function variable is the same as if the function doesn't exist. The behavior in this case is like the identity function. All filter input is passed unchanged to the output.|
|
||||
|\define, <<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|Every function is a variable, but only variables defined using \function are invokable using the <<.olink function>> filter operator. Attempts to use a non-function variable is the same as if the function doesn't exist. The behavior in this case is like the identity function. All filter input is passed unchanged to the output.|
|
||||
|\function|The body text of the function is treated as a filter expression and evaluated. This filter expression can itself contain a function call. Filter expressions can be factored out into functions arbitrarily deep.|
|
||||
@@ -1,7 +1,58 @@
|
||||
caption: Macro Calls
|
||||
created: 20150220182252000
|
||||
modified: 20230419103154328
|
||||
tags: WikiText Macros
|
||||
title: Macro Calls
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.deprecated-since "5.4.0" "Calls">>
|
||||
!! Introduction
|
||||
|
||||
This tiddler describes the different ways in which [[macros|Macros]] can be called.
|
||||
|
||||
!! Macro Call Transclusion Shortcut
|
||||
|
||||
To call a [[macro|Macros]], place `<<`double angle brackets`>>` around the name and any parameter values.
|
||||
|
||||
```
|
||||
<<mymacro param:"This is the parameter value">>
|
||||
```
|
||||
|
||||
By default, parameters are listed in the same order as in the macro's definition. A parameter can be labelled with its name and a colon to allow them to be listed in a different order.
|
||||
|
||||
If no value is specified for a parameter, the default value given for that parameter in the [[macro definition|Macro Definitions]] is used instead. (If no default value was defined, the parameter is blank).
|
||||
|
||||
Each parameter value can be enclosed in `'`single quotes`'`, `"`double quotes`"`, `"""`triple double quotes`"""` or `[[`double square brackets`]]`. Triple double quotes allow a value to contain almost anything. If a value contains no spaces or single or double quotes, it requires no delimiters.
|
||||
|
||||
A more formal [[presentation|Macro Call Syntax]] of this syntax is also available.
|
||||
|
||||
See some [[examples|Macro Calls in WikiText (Examples)]] and discussion about [[parser modes|WikiText parser mode: macro examples]].
|
||||
|
||||
!! Macro Calls with <<.wlink TranscludeWidget>> Widget
|
||||
|
||||
The shortcut syntax expands to the <<.wlink TranscludeWidget>> widget with the `$variable` attribute specifying the name of the macro to transclude.
|
||||
|
||||
```
|
||||
<$transclude $variable="mymacro" param="This is the parameter value"/>
|
||||
```
|
||||
|
||||
The widget itself offers greater flexibility than the shortcut syntax, including the ability to specify parameter values.
|
||||
|
||||
!! Assigning Macro Calls to Attribute Values
|
||||
|
||||
The result of a macro can be directly assigned to an attribute of a widget or HTML element. The result of the macro is not wikified, but the [[parameter substitution|Macro Parameter Handling]] is performed.
|
||||
|
||||
```
|
||||
<div class=<<myclasses "Horizontal">>>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
!! Using Macro Calls in Filters
|
||||
|
||||
Macro calls can be used in filters:
|
||||
|
||||
```
|
||||
<$list filter="[<mymacro param:'value'>]">
|
||||
...
|
||||
</$list>
|
||||
```
|
||||
@@ -104,7 +104,7 @@ js.configs.recommended,
|
||||
"init-declarations": "off",
|
||||
"@stylistic/jsx-quotes": "error",
|
||||
"@stylistic/key-spacing": "off",
|
||||
"@stylistic/keyword-spacing": ["warn", {
|
||||
"@stylistic/keyword-spacing": ["error", {
|
||||
before: true,
|
||||
after: false,
|
||||
overrides: {
|
||||
@@ -114,7 +114,6 @@ js.configs.recommended,
|
||||
return: { after: true },
|
||||
throw: { after: true },
|
||||
try: { after: true },
|
||||
const: { after: true }
|
||||
},
|
||||
}],
|
||||
"@stylistic/line-comment-position": "off",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
title: $:/language/
|
||||
|
||||
Alerts: 警报信息
|
||||
AboveStory/ClassicPlugin/Warning: 您似乎要加载为 ~TiddlyWiki 经典版设计的插件。请注意,[[这些插件无法运行于 TiddlyWiki 5.x.x 版|https://tiddlywiki.com/#TiddlyWikiClassic]]。检测到 ~TiddlyWiki 经典版插件:
|
||||
BinaryWarning/Prompt: 此条目包含二进制数据
|
||||
ClassicWarning/Hint: 此条目以经典版 TiddlyWiki 标记格式撰写,不完全兼容新版 TiddlyWiki 的格式,详细信息请参阅:https://tiddlywiki.com/static/Upgrading。
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
title: $:/language/
|
||||
|
||||
Alerts: 警示訊息
|
||||
AboveStory/ClassicPlugin/Warning: 您似乎要載入為 ~TiddlyWiki 經典版設計的插件。請注意,[[這些插件無法運行於 TiddlyWiki 5.x.x 版|https://tiddlywiki.com/#TiddlyWikiClassic]]。偵測到 ~TiddlyWiki 經典版插件:
|
||||
BinaryWarning/Prompt: 此條目包含二進位資料
|
||||
ClassicWarning/Hint: 此條目以經典版 TiddlyWiki 標記格式撰寫,不完全相容新版 TiddlyWiki 的格式,詳細資訊請參閱:https://tiddlywiki.com/static/Upgrading。
|
||||
|
||||
@@ -18,7 +18,7 @@ exports.serialize = function (node) {
|
||||
if(node.orderedAttributes) {
|
||||
node.orderedAttributes.forEach(function (attribute) {
|
||||
if(attribute.name !== "$variable") {
|
||||
result += " " + $tw.utils.serializeAttribute(attribute);
|
||||
result += " " + $tw.utils.serializeAttribute(attribute,{assignmentSymbol:":"});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,27 +62,14 @@ exports.serializeAttribute = function(node,options) {
|
||||
}
|
||||
// If name is number, means it is a positional attribute and name is omitted
|
||||
var positional = parseInt(node.name) >= 0,
|
||||
// Use the original assignment operator if available, otherwise default to '='
|
||||
assign = positional ? "" : (node.assignmentOperator || "="),
|
||||
// `=` in a widget and might be `:` in a macro
|
||||
assign = positional ? "" : (options.assignmentSymbol || "="),
|
||||
attributeString = positional ? "" : node.name;
|
||||
if(node.type === "string") {
|
||||
if(node.value === "true") {
|
||||
return attributeString;
|
||||
}
|
||||
// For macro parameters (using ':' separator), preserve unquoted values
|
||||
// For widget attributes (using '=' separator), always use quotes
|
||||
if(assign === ":" && !node.quoted) {
|
||||
attributeString += assign + node.value;
|
||||
} else if(assign === "") {
|
||||
// Positional parameter
|
||||
if(!node.quoted) {
|
||||
attributeString += node.value;
|
||||
} else {
|
||||
attributeString += '"' + node.value + '"';
|
||||
}
|
||||
} else {
|
||||
attributeString += assign + '"' + node.value + '"';
|
||||
}
|
||||
attributeString += assign + '"' + node.value + '"';
|
||||
} else if(node.type === "filtered") {
|
||||
attributeString += assign + "{{{" + node.filter + "}}}";
|
||||
} else if(node.type === "indirect") {
|
||||
@@ -90,36 +77,11 @@ exports.serializeAttribute = function(node,options) {
|
||||
} else if(node.type === "substituted") {
|
||||
attributeString += assign + "`" + node.rawValue + "`";
|
||||
} else if(node.type === "macro") {
|
||||
if(node.value && typeof node.value === "object") {
|
||||
if(node.value.type === "transclude") {
|
||||
// Handle the transclude-based macro call structure
|
||||
var macroName = node.value.attributes && node.value.attributes["$variable"] ?
|
||||
node.value.attributes["$variable"].value : "";
|
||||
if(!macroName) {
|
||||
return null;
|
||||
}
|
||||
var params = [];
|
||||
if(node.value.orderedAttributes) {
|
||||
node.value.orderedAttributes.forEach(function(attr) {
|
||||
if(attr.name !== "$variable") {
|
||||
var paramStr = exports.serializeAttribute(attr);
|
||||
if(paramStr) {
|
||||
params.push(paramStr);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
attributeString += assign + "<<" + macroName + (params.length > 0 ? " " + params.join(" ") : "") + ">>";
|
||||
} else if(node.value.type === "macrocall") {
|
||||
// Handle the classical macrocall structure for backwards compatibility
|
||||
var params = node.value.params.map(function(param) {
|
||||
return param.value;
|
||||
}).join(" ");
|
||||
attributeString += assign + "<<" + node.value.name + " " + params + ">>";
|
||||
} else {
|
||||
// Unsupported macro structure
|
||||
return null;
|
||||
}
|
||||
if(node.value && typeof node.value === "object" && node.value.type === "macrocall") {
|
||||
var params = node.value.params.map(function(param) {
|
||||
return param.value;
|
||||
}).join(" ");
|
||||
attributeString += assign + "<<" + node.value.name + " " + params + ">>";
|
||||
} else {
|
||||
// Unsupported macro structure
|
||||
return null;
|
||||
|
||||
@@ -940,6 +940,10 @@ button.tc-btn-invisible.tc-remove-tag-button {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.tc-advanced-search .tc-advanced-search-options input {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.tc-search a svg {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
|
||||
Reference in New Issue
Block a user