mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-02-21 17:39:51 +00:00
Compare commits
12 Commits
background
...
further-re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfaa8f30bd | ||
|
|
48626ceded | ||
|
|
6f31d3e7d6 | ||
|
|
9d53e9b875 | ||
|
|
5e37367aa4 | ||
|
|
2db71cd14f | ||
|
|
037ad2d0da | ||
|
|
b713d13c5a | ||
|
|
bb05bd8817 | ||
|
|
42a908e1c9 | ||
|
|
70689a6de4 | ||
|
|
64ee20edd2 |
@@ -143,7 +143,14 @@ exports.parseParameterDefinition = function(paramString,options) {
|
||||
var paramInfo = {name: paramMatch[1]},
|
||||
defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5];
|
||||
if(defaultValue !== undefined) {
|
||||
paramInfo["default"] = defaultValue;
|
||||
// Check for an MVV reference ((varname))
|
||||
var mvvDefaultMatch = /^\(\(([^)|]+)\)\)$/.exec(defaultValue);
|
||||
if(mvvDefaultMatch) {
|
||||
paramInfo.defaultType = "multivalue-variable";
|
||||
paramInfo.defaultVariable = mvvDefaultMatch[1];
|
||||
} else {
|
||||
paramInfo["default"] = defaultValue;
|
||||
}
|
||||
}
|
||||
params.push(paramInfo);
|
||||
// Look for the next parameter
|
||||
@@ -247,6 +254,46 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) {
|
||||
return node;
|
||||
};
|
||||
|
||||
/*
|
||||
Look for an MVV (multi-valued variable) reference as a transclusion, i.e. ((varname)) or ((varname params))
|
||||
Returns null if not found, or a parse tree node of type "transclude" with isMVV: true
|
||||
*/
|
||||
exports.parseMVVReferenceAsTransclusion = function(source,pos) {
|
||||
var node = {
|
||||
type: "transclude",
|
||||
isMVV: true,
|
||||
start: pos,
|
||||
attributes: {},
|
||||
orderedAttributes: []
|
||||
};
|
||||
// Define our regexps
|
||||
var reVarName = /([^\s>"'=:)]+)/g;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double opening parenthesis
|
||||
var token = $tw.utils.parseTokenString(source,pos,"((");
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
pos = token.end;
|
||||
// Get the variable name
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,reVarName);
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(node,"$variable",token.match[1]);
|
||||
pos = token.end;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double closing parenthesis
|
||||
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
|
||||
*/
|
||||
@@ -321,19 +368,20 @@ exports.parseMacroParameterAsAttribute = function(source,pos) {
|
||||
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];
|
||||
// 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 {
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation && isNewStyleSeparator) {
|
||||
pos = macroInvocation.end;
|
||||
// Look for an MVV reference value
|
||||
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
|
||||
if(mvvReference && isNewStyleSeparator) {
|
||||
pos = mvvReference.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
node.value = mvvReference;
|
||||
node.isMVV = true;
|
||||
} else {
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue && isNewStyleSeparator) {
|
||||
@@ -341,6 +389,14 @@ exports.parseMacroParameterAsAttribute = function(source,pos) {
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
} 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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -471,19 +527,20 @@ exports.parseAttribute = function(source,pos) {
|
||||
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];
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
} else {
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation) {
|
||||
pos = macroInvocation.end;
|
||||
// Look for an MVV reference value
|
||||
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
|
||||
if(mvvReference) {
|
||||
pos = mvvReference.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
node.value = mvvReference;
|
||||
node.isMVV = true;
|
||||
} else {
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue) {
|
||||
@@ -491,8 +548,16 @@ exports.parseAttribute = function(source,pos) {
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
} else {
|
||||
node.type = "string";
|
||||
node.value = "true";
|
||||
// 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 {
|
||||
node.type = "string";
|
||||
node.value = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ Instantiate parse rule
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*))?\)(\s*\r?\n)?/mg;
|
||||
this.matchRegExp = /\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*(?:\)\)[^)]*)*))?\)(\s*\r?\n)?/mg;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
95
core/modules/parsers/wikiparser/rules/mvvdisplayinline.js
Normal file
95
core/modules/parsers/wikiparser/rules/mvvdisplayinline.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/*\
|
||||
title: $:/core/modules/parsers/wikiparser/rules/mvvdisplayinline.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki rule for inline display of multi-valued variables and filter results.
|
||||
|
||||
Variable display: ((varname)) or ((varname||separator))
|
||||
Filter display: (((filter))) or (((filter||separator)))
|
||||
|
||||
The default separator is ", " (comma space).
|
||||
|
||||
\*/
|
||||
|
||||
"use strict";
|
||||
|
||||
exports.name = "mvvdisplayinline";
|
||||
exports.types = {inline: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
};
|
||||
|
||||
exports.findNextMatch = function(startPos) {
|
||||
var source = this.parser.source;
|
||||
var nextStart = startPos;
|
||||
while((nextStart = source.indexOf("((",nextStart)) >= 0) {
|
||||
if(source.charAt(nextStart + 2) === "(") {
|
||||
// Filter mode: (((filter))) or (((filter||sep)))
|
||||
var match = /^\(\(\(([\s\S]+?)\)\)\)/.exec(source.substring(nextStart));
|
||||
if(match) {
|
||||
// Check for separator: split on last || before )))
|
||||
var inner = match[1];
|
||||
var sepIndex = inner.lastIndexOf("||");
|
||||
if(sepIndex >= 0) {
|
||||
this.nextMatch = {
|
||||
type: "filter",
|
||||
filter: inner.substring(0,sepIndex),
|
||||
separator: inner.substring(sepIndex + 2),
|
||||
start: nextStart,
|
||||
end: nextStart + match[0].length
|
||||
};
|
||||
} else {
|
||||
this.nextMatch = {
|
||||
type: "filter",
|
||||
filter: inner,
|
||||
separator: ", ",
|
||||
start: nextStart,
|
||||
end: nextStart + match[0].length
|
||||
};
|
||||
}
|
||||
return nextStart;
|
||||
}
|
||||
} else {
|
||||
// Variable mode: ((varname)) or ((varname||sep))
|
||||
var match = /^\(\(([^()|]+?)(?:\|\|([^)]*))?\)\)/.exec(source.substring(nextStart));
|
||||
if(match) {
|
||||
this.nextMatch = {
|
||||
type: "variable",
|
||||
varName: match[1],
|
||||
separator: match[2] !== undefined ? match[2] : ", ",
|
||||
start: nextStart,
|
||||
end: nextStart + match[0].length
|
||||
};
|
||||
return nextStart;
|
||||
}
|
||||
}
|
||||
nextStart += 2;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/*
|
||||
Parse the most recent match
|
||||
*/
|
||||
exports.parse = function() {
|
||||
var match = this.nextMatch;
|
||||
this.nextMatch = null;
|
||||
this.parser.pos = match.end;
|
||||
var filter, sep = match.separator;
|
||||
if(match.type === "variable") {
|
||||
filter = "[(" + match.varName + ")join[" + sep + "]]";
|
||||
} else {
|
||||
filter = match.filter + " +[join[" + sep + "]]";
|
||||
}
|
||||
return [{
|
||||
type: "text",
|
||||
attributes: {
|
||||
text: {name: "text", type: "filtered", filter: filter}
|
||||
},
|
||||
orderedAttributes: [
|
||||
{name: "text", type: "filtered", filter: filter}
|
||||
]
|
||||
}];
|
||||
};
|
||||
@@ -61,7 +61,9 @@ ParametersWidget.prototype.execute = function() {
|
||||
if(name.substr(0,2) === "$$") {
|
||||
name = name.substr(1);
|
||||
}
|
||||
var value = pointer.getTransclusionParameter(name,index,self.getAttribute(attr.name,""));
|
||||
var defaultValue = (self.multiValuedAttributes && self.multiValuedAttributes[attr.name])
|
||||
|| self.getAttribute(attr.name,"");
|
||||
var value = pointer.getTransclusionParameter(name,index,defaultValue);
|
||||
self.setVariable(name,value);
|
||||
});
|
||||
// Assign any metaparameters
|
||||
@@ -80,7 +82,8 @@ ParametersWidget.prototype.execute = function() {
|
||||
if(name.substr(0,2) === "$$") {
|
||||
name = name.substr(1);
|
||||
}
|
||||
var value = self.getAttribute(attr.name,"");
|
||||
var value = (self.multiValuedAttributes && self.multiValuedAttributes[attr.name])
|
||||
|| self.getAttribute(attr.name,"");
|
||||
self.setVariable(name,value);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -158,8 +158,10 @@ Collect string parameters
|
||||
TranscludeWidget.prototype.collectStringParameters = function() {
|
||||
var self = this;
|
||||
this.stringParametersByName = Object.create(null);
|
||||
this.multiValuedParametersByName = Object.create(null);
|
||||
if(!this.legacyMode) {
|
||||
$tw.utils.each(this.attributes,function(value,name) {
|
||||
var attrName = name; // Save original attribute name for MVV lookup
|
||||
if(name.charAt(0) === "$") {
|
||||
if(name.charAt(1) === "$") {
|
||||
// Attributes starting $$ represent parameters starting with a single $
|
||||
@@ -170,6 +172,9 @@ TranscludeWidget.prototype.collectStringParameters = function() {
|
||||
}
|
||||
}
|
||||
self.stringParametersByName[name] = value;
|
||||
if(self.multiValuedAttributes && self.multiValuedAttributes[attrName]) {
|
||||
self.multiValuedParametersByName[name] = self.multiValuedAttributes[attrName];
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -313,7 +318,16 @@ TranscludeWidget.prototype.parseTransclusionTarget = function(parseAsInline) {
|
||||
if(name.charAt(0) === "$") {
|
||||
name = "$" + name;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"])
|
||||
if(param.defaultType === "multivalue-variable") {
|
||||
// Construct MVV attribute for the default
|
||||
var mvvNode = {type: "transclude", isMVV: true, attributes: {}, orderedAttributes: []};
|
||||
$tw.utils.addAttributeToParseTreeNode(mvvNode,"$variable",param.defaultVariable);
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],{
|
||||
name: name, type: "macro", isMVV: true, value: mvvNode
|
||||
});
|
||||
} else {
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"]);
|
||||
}
|
||||
});
|
||||
} else if(srcVariable && !srcVariable.isFunctionDefinition) {
|
||||
// For macros and ordinary variables, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
|
||||
@@ -364,7 +378,11 @@ TranscludeWidget.prototype.getOrderedTransclusionParameters = function() {
|
||||
// Collect the parameters
|
||||
for(var name in this.stringParametersByName) {
|
||||
var value = this.stringParametersByName[name];
|
||||
result.push({name: name, value: value});
|
||||
var param = {name: name, value: value};
|
||||
if(this.multiValuedParametersByName[name]) {
|
||||
param.multiValue = this.multiValuedParametersByName[name];
|
||||
}
|
||||
result.push(param);
|
||||
}
|
||||
// Sort numerical parameter names first
|
||||
result.sort(function(a,b) {
|
||||
@@ -394,10 +412,16 @@ Fetch the value of a parameter
|
||||
*/
|
||||
TranscludeWidget.prototype.getTransclusionParameter = function(name,index,defaultValue) {
|
||||
if(name in this.stringParametersByName) {
|
||||
if(this.multiValuedParametersByName[name]) {
|
||||
return this.multiValuedParametersByName[name];
|
||||
}
|
||||
return this.stringParametersByName[name];
|
||||
} else {
|
||||
var name = "" + index;
|
||||
if(name in this.stringParametersByName) {
|
||||
if(this.multiValuedParametersByName[name]) {
|
||||
return this.multiValuedParametersByName[name];
|
||||
}
|
||||
return this.stringParametersByName[name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,19 +381,31 @@ filterFn: only include attributes where filterFn(name) returns true
|
||||
Widget.prototype.computeAttributes = function(options) {
|
||||
options = options || {};
|
||||
var changedAttributes = {},
|
||||
self = this;
|
||||
self = this,
|
||||
newMultiValuedAttributes = Object.create(null);
|
||||
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
|
||||
if(options.filterFn) {
|
||||
if(!options.filterFn(name)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var value = self.computeAttribute(attribute);
|
||||
if(self.attributes[name] !== value) {
|
||||
var value = self.computeAttribute(attribute),
|
||||
multiValue = null;
|
||||
if($tw.utils.isArray(value)) {
|
||||
multiValue = value;
|
||||
newMultiValuedAttributes[name] = multiValue;
|
||||
value = value[0] || "";
|
||||
}
|
||||
var changed = (self.attributes[name] !== value);
|
||||
if(!changed && multiValue && self.multiValuedAttributes) {
|
||||
changed = !$tw.utils.isArrayEqual(self.multiValuedAttributes[name] || [], multiValue);
|
||||
}
|
||||
if(changed) {
|
||||
self.attributes[name] = value;
|
||||
changedAttributes[name] = true;
|
||||
}
|
||||
});
|
||||
this.multiValuedAttributes = newMultiValuedAttributes;
|
||||
return changedAttributes;
|
||||
};
|
||||
|
||||
@@ -431,7 +443,7 @@ Widget.prototype.computeAttribute = function(attribute,options) {
|
||||
});
|
||||
// Invoke the macro
|
||||
var variableInfo = this.getVariableInfo(macroName,{params: params});
|
||||
if(options.asList) {
|
||||
if(options.asList || attribute.isMVV) {
|
||||
value = variableInfo.resultList;
|
||||
} else {
|
||||
value = variableInfo.text;
|
||||
|
||||
@@ -122,15 +122,15 @@ tags: $:/tags/Macro
|
||||
\whitespace trim
|
||||
\procedure keyboard-driven-input-actions()
|
||||
<%if [<event-key-descriptor>match[((input-accept))]] %>
|
||||
<<inputAcceptActions>>
|
||||
<$transclude $variable=inputAcceptActions $fillignore=yes />
|
||||
<%elseif [<event-key-descriptor>match[((input-accept-variant))]] %>
|
||||
<<inputAcceptVariantActions>>
|
||||
<$transclude $variable=inputAcceptVariantActions $fillignore=yes />
|
||||
<%elseif [<event-key-descriptor>match[((input-up))]] %>
|
||||
<<input-next-actions-before>>
|
||||
<$transclude $variable=input-next-actions-before $fillignore=yes />
|
||||
<%elseif [<event-key-descriptor>match[((input-down))]] %>
|
||||
<<input-next-actions-after>>
|
||||
<$transclude $variable=input-next-actions-after $fillignore=yes />
|
||||
<%elseif [<event-key-descriptor>match[((input-cancel))]] %>
|
||||
<<inputCancelActions>>
|
||||
<$transclude $variable=inputCancelActions $fillignore=yes />
|
||||
<%endif%>
|
||||
\end keyboard-driven-input-actions
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
title: MultiValuedVariables/AttributeFirstValue
|
||||
description: ((var)) on non-MVV-aware widget attribute returns first value only
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
<$text text=((items))/>
|
||||
</$let>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core</p>
|
||||
+
|
||||
@@ -0,0 +1,19 @@
|
||||
title: MultiValuedVariables/DefaultParameterMVV
|
||||
description: Procedure default parameter value using ((var)) syntax to provide MVV default
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
\procedure showItems(itemList:((defaults)))
|
||||
<$text text={{{ [(itemList)join[-]] }}}/>
|
||||
\end
|
||||
<$let defaults={{{ [all[tiddlers]sort[]] }}}>
|
||||
<<showItems>>
|
||||
</$let>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core-ExpectedResult-Output</p>
|
||||
+
|
||||
@@ -0,0 +1,16 @@
|
||||
title: MultiValuedVariables/InlineDisplay
|
||||
description: ((var)) in inline wikitext displays MVV with default comma-space separator
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
((items))
|
||||
</$let>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core, ExpectedResult, Output</p>
|
||||
+
|
||||
@@ -0,0 +1,16 @@
|
||||
title: MultiValuedVariables/InlineDisplaySeparator
|
||||
description: ((var||separator)) in inline wikitext displays MVV with custom separator
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
((items||:))
|
||||
</$let>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core:ExpectedResult:Output</p>
|
||||
+
|
||||
@@ -0,0 +1,14 @@
|
||||
title: MultiValuedVariables/InlineFilterDisplay
|
||||
description: (((filter))) in inline wikitext displays filter results with default comma-space separator
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
((([all[tiddlers]sort[]])))
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core, ExpectedResult, Output</p>
|
||||
+
|
||||
@@ -0,0 +1,14 @@
|
||||
title: MultiValuedVariables/InlineFilterDisplaySeparator
|
||||
description: (((filter||separator))) in inline wikitext displays filter results with custom separator
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
((([all[tiddlers]sort[]]||:)))
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core:ExpectedResult:Output</p>
|
||||
+
|
||||
@@ -0,0 +1,19 @@
|
||||
title: MultiValuedVariables/TranscludeParameter
|
||||
description: Multi-valued variable passed as procedure parameter via ((var)) syntax
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
\procedure showItems(itemList)
|
||||
<$text text={{{ [(itemList)join[-]] }}}/>
|
||||
\end
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
<$transclude $variable="showItems" itemList=((items))/>
|
||||
</$let>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core-ExpectedResult-Output</p>
|
||||
+
|
||||
@@ -0,0 +1,17 @@
|
||||
title: MultiValuedVariables/TranscludeParameterFunction
|
||||
description: Multi-valued variable passed as function parameter via ((var)) in $transclude
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
\function showItems(itemList) [(itemList)sort[]join[-]]
|
||||
<$let items={{{ [all[tiddlers]] }}}>
|
||||
<$transclude $variable="showItems" itemList=((items))/>
|
||||
</$let>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>$:/core-ExpectedResult-Output</p>
|
||||
+
|
||||
@@ -22,6 +22,6 @@ There is also a single line form for shorter functions:
|
||||
\function <function-name>(<param-name>[:<param-default-value>],<param-name>[:<param-default-value>]...) <single-line-definition-text>
|
||||
```
|
||||
|
||||
The first line of the definition specifies the function name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the function. The lines that follow contain the text of the function (i.e. the snippet represented by the function name), until `\end` appears on a line by itself:
|
||||
The first line of the definition specifies the function name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the function. <<.from-version "5.4.0">> The default value can also be a [[multi-valued variable reference|Multi-Valued Variables]] using the `((var))` syntax (e.g. `\function show(items:((defaults)))`). The lines that follow contain the text of the function (i.e. the snippet represented by the function name), until `\end` appears on a line by itself:
|
||||
|
||||
See [[Functions]] for more details.
|
||||
@@ -22,7 +22,7 @@ There is also a single line form for shorter procedures:
|
||||
\procedure <procedure-name>(<param-name>[:<param-default-value>],<param-name>[:<param-default-value>]...) <single-line-definition-text>
|
||||
```
|
||||
|
||||
The first line of the definition specifies the procedure name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the procedure. The lines that follow contain the text of the procedure text (i.e. the snippet represented by the procedure name), until `\end` appears on a line by itself:
|
||||
The first line of the definition specifies the procedure name and any parameters. Each parameter has a name and, optionally, a default value that is used if no value is supplied on a particular call to the procedure. <<.from-version "5.4.0">> The default value can also be a [[multi-valued variable reference|Multi-Valued Variables]] using the `((var))` syntax (e.g. `\procedure show(items:((defaults)))`). The lines that follow contain the text of the procedure text (i.e. the snippet represented by the procedure name), until `\end` appears on a line by itself:
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
title: $:/changenotes/5.4.0/#8258
|
||||
description: Add ability to serialize WikiText AST nodes back to wikitext strings
|
||||
description: Core plugin to serialize syntax trees back to strings
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: feature
|
||||
@@ -7,32 +7,8 @@ change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8258
|
||||
github-contributors: linonetwo
|
||||
|
||||
This PR introduces a new utility `$tw.utils.serializeWikitextParseTree()` that can convert WikiText Abstract Syntax Tree (AST) nodes back into wikitext strings.
|
||||
This is an internal change that will only be of direct interest to plugin developers but will form the basis of future user-facing features. For example:
|
||||
|
||||
There is also a utility `serializeAttribute` for a single attribute node, like an attribute of a widget.
|
||||
|
||||
!! Use Cases
|
||||
|
||||
* Programmatically manipulating wikitext content by modifying the AST, and use this to write it back
|
||||
* Programmatically manipulating wikitext content by modifying the syntax tree and deserializing it back to wikitext
|
||||
* Building WYSIWYG editors
|
||||
* Creating wikitext formatters and linters
|
||||
|
||||
!! Implementation
|
||||
|
||||
* New core plugin `tiddlywiki/wikitext-serialize` containing most of the logic
|
||||
* Separate serialize handlers for each WikiText rule as `module-type: wikiruleserializer`
|
||||
* Test suite with tag `$:/tags/wikitext-serialize-test-spec`
|
||||
* It uses each parser's name as rule (`nextMatch.rule.name`), each AST node that needs serialization has a `type` property matching the rule name
|
||||
** HTML tags and widgets are handled by the `html` serializer
|
||||
|
||||
!! Example Usage
|
||||
|
||||
```javascript
|
||||
// Parse a tiddler's wikitext to AST
|
||||
var parseTree = $tw.wiki.parseTiddler("MyTiddler").tree;
|
||||
|
||||
// Serialize AST back to wikitext string
|
||||
var wikitextString = $tw.utils.serializeWikitextParseTree(parseTree).trimEnd();
|
||||
```
|
||||
|
||||
This feature offers new tools for JS plugin developers. It is not a user-facing change.
|
||||
* Creating WikiText formatters and linters
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#8702/impacts/darkmode-info-tiddler
|
||||
changenote: $:/changenotes/5.4.0/#8702
|
||||
created: 20250901000000000
|
||||
modified: 20250901000000000
|
||||
tags: $:/tags/ImpactNote
|
||||
description: `$:/info/darkmode` has been superseded by `$:/info/browser/darkmode`
|
||||
impact-type: deprecation
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#8702/impacts/palette-pluginisation
|
||||
changenote: $:/changenotes/5.4.0/#8702
|
||||
created: 20250901000000000
|
||||
modified: 20250901000000000
|
||||
tags: $:/tags/ImpactNote
|
||||
description: Existing colour palettes have been moved to a new "palettes-legacy" plugin
|
||||
impact-type: pluginisation
|
||||
|
||||
Add the plugin to your wiki in order to continue using the legacy palettes.
|
||||
@@ -1,27 +0,0 @@
|
||||
title: $:/changenotes/5.4.0/#8702
|
||||
description: Colour handling improvements
|
||||
release: 5.4.0-disabled because this PR is not yet merged
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8702
|
||||
github-contributors: Jermolene
|
||||
|
||||
This PR brings several new features for end users:
|
||||
|
||||
* Automatically switching between a dark and light palette as the operating system setting changes (and to do so without making the wiki dirty)
|
||||
* Customisation options for palettes. For example, users might choose a base hue, with the colours of the palette automatically adapting to it
|
||||
* A generalisation of the dark vs. light mechanism to allow an arbitrary number of distinct schemes that are dynamically selected. For example, a palette that has a different scheme for night, morning, day and evening that automatically change with the time of day
|
||||
|
||||
There are also new capabilities for palette authors:
|
||||
|
||||
* Inheritance for palettes, making it easy to create chains of variants of a base palette
|
||||
* Self contained palettes that can contain both dark and light variants (or variants for any other custom scheme)
|
||||
|
||||
To make all of these new features possible, this PR also includes some useful new general purpose mechanisms and features:
|
||||
|
||||
* Background actions that are triggered whenever there is a change to the results of a specified filter
|
||||
* Several new filter operators for manipulating colour values. The underlying functionality comes from the [[color.js|https://colorjs.io/]] library
|
||||
* New media query tracking mechanism that can track the results of any CSS media query (not just dark mode), storing the results in a shadow `$:/info/...` tiddler
|
||||
* New `changecount` filter operator
|
||||
* New `:apply` filter run prefix (to be replaced by the `:let` filter run prefix in [[#8972|https://github.com/TiddlyWiki/TiddlyWiki5/pull/8972]]))
|
||||
@@ -4,7 +4,7 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8972 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9614
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8972 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9614 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9645
|
||||
github-contributors: Jermolene saqimtiaz
|
||||
|
||||
This PR introduces a new filter run prefix `:let` that assigns the result of the filter run to a variable that is made available for the remaining filter runs of the filter expression. It solves the problem that previously it was impossible to compute values for filter operator parameters; parameters could only be a literal string, text reference or variable reference.
|
||||
|
||||
@@ -7,36 +7,19 @@ 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:
|
||||
This PR extends the handling of macro/procedure/function invocationsmade via the `<<..>>` shortcut syntax to allow dynamic parameters instead of just 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:
|
||||
|
||||
```
|
||||
<<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:
|
||||
The extended syntax allows parameter values to be passed as transclusions, filter expressions or nested invocations in three 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.
|
||||
See [[Calls]] for more details and examples.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
change-category: internal
|
||||
change-category: developer
|
||||
change-type: enhancement
|
||||
created: 20260120153052332
|
||||
description: Adds a destroy method for widgets allowing for clean up of resources when a widget is removed.
|
||||
|
||||
@@ -4,5 +4,5 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: performance
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9118
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9119
|
||||
github-contributors: Leilei332
|
||||
|
||||
@@ -4,5 +4,5 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: deprecation
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9118
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9131
|
||||
github-contributors: Leilei332
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
title: $:/changenotes/5.4.0/#9177
|
||||
description: Add Display Field to list-tagged-draggable and list-links-draggable
|
||||
description: Add Display Field to list-tagged-draggable and list-links-draggable macros
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: usability
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9177
|
||||
github-contributors: kookma
|
||||
|
||||
|
||||
@@ -7,4 +7,4 @@ change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9235 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9325
|
||||
github-contributors: Leilei332
|
||||
|
||||
Removes nested `<span class="tc-keyboard">` element in core search field.
|
||||
Removes nested `<span class="tc-keyboard">` element in core search field.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
change-category: usability
|
||||
change-category: hackability
|
||||
change-type: enhancement
|
||||
created: 20251115012214040
|
||||
description: list-links-draggable defaults to currentTiddler if tiddler parameter is missing
|
||||
|
||||
@@ -4,7 +4,7 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9287
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9287 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9657
|
||||
github-contributors: Jermolene
|
||||
|
||||
Doing so enables us to filter and group changes. For example, we could show all the breaking changes between two releases.
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Set modal's mask-closable attribute to yes by default
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: usability
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9313
|
||||
github-contributors: Leilei332
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Add the prevailing mimetype for CSV parser
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: internal
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9445
|
||||
github-contributors: EvidentlyCube
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Import UI now conditionally displays file-type-specific import opti
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
change-category: usability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9465
|
||||
github-contributors: linonetwo
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@ tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9570
|
||||
github-contributors: jermolene
|
||||
github-contributors: Jermolene
|
||||
|
||||
Fixes issue whereby transcluding a _canonical_uri tiddler with a missing image did not assign the progress classes `tc-image-loading`, `tc-image-loaded` and `tc-image-error`.
|
||||
@@ -3,7 +3,7 @@ created: 20260106174849522
|
||||
modified: 20260106174849522
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: usability
|
||||
change-category: hackability
|
||||
description: The button classes of Editor toolbar buttons can now be evaluated as filter expressions
|
||||
release: 5.4.0
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9585
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
change-category: widget
|
||||
change-type: enhancement
|
||||
created: 20260125124838970
|
||||
description: adds support for pointer capture and enabling/disabling the widget
|
||||
description: Adds support for pointer capture and enabling/disabling to the EventCatcherWidget.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9609
|
||||
modified: 20260125202924515
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
change-category: usability
|
||||
change-category: hackability
|
||||
change-type: enhancement
|
||||
created: 20260124121646761
|
||||
description: The simple toc macro now supports a level parameter
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
change-category: usability
|
||||
change-category: widget
|
||||
change-type: bugfix
|
||||
created: 20260125195754439
|
||||
description: Refresh widget if "default" parameter input value is changed
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
change-category: usability
|
||||
change-category: hackability
|
||||
change-type: enhancement
|
||||
created: 20260126125300
|
||||
description: Add start- and endactions to link-widget, list-links-draggable and list-tagged-draggable macros
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Add "Cascade Details" to the Advanced tab of the Tiddler Info panel
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
change-category: usability
|
||||
github-links: https://github.com/Jermolene/TiddlyWiki5/pull/9634 https://github.com/Jermolene/TiddlyWiki5/pull/9643
|
||||
github-contributors: DesignThinkerer
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ description: Background actions and media query tracking
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: enhancement
|
||||
change-category: internal
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9641
|
||||
github-contributors: Jermolene
|
||||
|
||||
Introduces[[Background Actions]] that are triggered whenever there is a change to the results of a specified filter.
|
||||
Introduces [[Background Actions]] that are triggered whenever there is a change to the results of a specified filter.
|
||||
|
||||
Building on that, it also introduces a new [[Media Query Tracker Mechanism]] that can track the results of any CSS media query (not just dark mode), storing the results in a shadow `$:/info/...` tiddler
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ type: text/vnd.tiddlywiki
|
||||
description: Under development
|
||||
|
||||
\procedure release-introduction()
|
||||
Release v5.4.0 is an important release because it deliberately and forensically loosens backwards compatibility where needed to allow significant new features and fundamental improvements to be made.
|
||||
Release v5.4.0 deliberately and forensically loosens backwards compatibility to clear the path for significant new features and fundamental improvements to be made in the future.
|
||||
|
||||
''Please note that this release note is not yet fully completed, please see the change history on ~GitHub for the full list of changes included in this release.''
|
||||
''Please note that there are some changes that do not yet change notes, please see the change history on ~GitHub for the full list of changes.''
|
||||
|
||||
See the [[project plan|https://github.com/orgs/TiddlyWiki/projects/4]] for full details.
|
||||
\end release-introduction
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Draft title internationalization
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: internal
|
||||
change-category: translation
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8891
|
||||
github-contributors: Leilei332
|
||||
|
||||
|
||||
@@ -53,3 +53,13 @@ Impact note fields:
|
||||
* `description` - a brief description of the impact
|
||||
* `impact-type` - the type of impact; see [[here|Release Notes and Changes]] for valid values
|
||||
* `text` - description of the impact if required
|
||||
|
||||
! Summary Lists
|
||||
|
||||
Summary sections are curated via lists stored in fields on the tiddler `$:/tw5.com/releases/info/summary-lists`.
|
||||
|
||||
Each field is named `<section>/<release>` and contains a list of change note tiddler titles, for example:
|
||||
|
||||
* `highlights/5.4.0`
|
||||
* `big-bug-fixes/5.4.0`
|
||||
* `clearing-the-decks/5.4.0`
|
||||
|
||||
@@ -1,35 +1,67 @@
|
||||
title: $:/tw5.com/releases/info/
|
||||
|
||||
category-order: translation plugin usability theme hackability widget filters performance nodejs internal developer
|
||||
categories/internal/caption: Internal
|
||||
categories/translation/caption: Translation
|
||||
categories/plugin/caption: Plugin
|
||||
categories/widget/caption: Widget
|
||||
categories/usability/caption: Usability
|
||||
categories/theme/caption: Theme
|
||||
categories/hackability/caption: Hackability
|
||||
categories/nodejs/caption: Node.js
|
||||
categories/performance/caption: Performance
|
||||
categories/developer/caption: Developer
|
||||
categories/filters/caption: Filters
|
||||
change-types/bugfix/caption: Bugfix
|
||||
category-order: translation usability hackability widget filters plugin theme nodejs developer internal
|
||||
change-type-order: feature enhancement performance bugfix deprecation security
|
||||
impact-type-order: compatibility-break deprecation pluginisation
|
||||
tab-order: [[Summary]] [[By Type]] [[By Category]] [[Impacts]]
|
||||
categories/developer/singular: Developer
|
||||
categories/developer/plural: Developer
|
||||
categories/filters/singular: Filters
|
||||
categories/filters/plural: Filters
|
||||
categories/hackability/singular: Hackability
|
||||
categories/hackability/plural: Hackability
|
||||
categories/internal/singular: Internal
|
||||
categories/internal/plural: Internal
|
||||
categories/nodejs/singular: Node.js
|
||||
categories/nodejs/plural: Node.js
|
||||
categories/plugin/singular: Plugin
|
||||
categories/plugin/plural: Plugins
|
||||
categories/theme/singular: Theme
|
||||
categories/theme/plural: Theming
|
||||
categories/translation/singular: Translation
|
||||
categories/translation/plural: Translation
|
||||
categories/usability/singular: Usability
|
||||
categories/usability/plural: Usability
|
||||
categories/widget/singular: Widget
|
||||
categories/widget/plural: Widgets
|
||||
change-types/bugfix/singular: Bugfix
|
||||
change-types/bugfix/colour: #ffe246
|
||||
change-types/feature/caption: Feature
|
||||
change-types/feature/colour: #91ba66
|
||||
change-types/enhancement/caption: Enhancement
|
||||
change-types/enhancement/colour: #cba5ff
|
||||
change-types/deprecation/caption: Deprecation
|
||||
change-types/bugfix/plural: Bugfixes
|
||||
change-types/deprecation/singular: Deprecation
|
||||
change-types/deprecation/colour: #ff9d6c
|
||||
change-types/security/caption: Security
|
||||
change-types/security/colour: #ff6666
|
||||
change-types/performance/caption: Performance
|
||||
change-types/deprecation/plural: Deprecations
|
||||
change-types/enhancement/singular: Enhancement
|
||||
change-types/enhancement/colour: #cba5ff
|
||||
change-types/enhancement/plural: Enhancements
|
||||
change-types/feature/singular: Feature
|
||||
change-types/feature/colour: #91ba66
|
||||
change-types/feature/plural: Features
|
||||
change-types/performance/singular: Performance
|
||||
change-types/performance/colour: #c2c7ff
|
||||
impact-types/deprecation/caption: Deprecation
|
||||
impact-types/deprecation/colour/foreground: #882222
|
||||
impact-types/deprecation/colour/background: #ffdddd
|
||||
impact-types/compatibility-break/caption: Compatibility Break
|
||||
impact-types/compatibility-break/colour/foreground: #228822
|
||||
change-types/performance/plural: Performance
|
||||
change-types/security/singular: Security
|
||||
change-types/security/colour: #ff6666
|
||||
change-types/security/plural: Security
|
||||
impact-types/compatibility-break/singular: Compatibility Break
|
||||
impact-types/compatibility-break/colour/background: #ddffdd
|
||||
impact-types/pluginisation/caption: Pluginisation
|
||||
impact-types/pluginisation/colour/foreground: #222288
|
||||
impact-types/compatibility-break/colour/foreground: #228822
|
||||
impact-types/compatibility-break/plural: Compatibility Breaks
|
||||
impact-types/deprecation/singular: Deprecation
|
||||
impact-types/deprecation/colour/background: #ffdddd
|
||||
impact-types/deprecation/colour/foreground: #882222
|
||||
impact-types/deprecation/plural: Deprecations
|
||||
impact-types/pluginisation/singular: Pluginisation
|
||||
impact-types/pluginisation/colour/background: #ddddff
|
||||
impact-types/pluginisation/colour/foreground: #222288
|
||||
impact-types/pluginisation/plural: Pluginisations
|
||||
categories/translation/colour: #7ec8e3
|
||||
categories/usability/colour: #f4a261
|
||||
categories/hackability/colour: #9b8ec4
|
||||
categories/performance/colour: #87ceeb
|
||||
categories/widget/colour: #e78ac3
|
||||
categories/filters/colour: #8cc56d
|
||||
categories/plugin/colour: #f0c674
|
||||
categories/theme/colour: #d4a76a
|
||||
categories/nodejs/colour: #77bb66
|
||||
categories/developer/colour: #6baed6
|
||||
categories/internal/colour: #b0b0b0
|
||||
|
||||
@@ -48,69 +48,318 @@ tags: $:/tags/Global
|
||||
</span>
|
||||
\end impact-pill
|
||||
|
||||
\procedure change-list()
|
||||
\procedure release-section-toggle(state,default)
|
||||
\whitespace trim
|
||||
<div class="doc-release-note">
|
||||
<$list filter="[enlist{$:/tw5.com/releases/info/category-order}]" variable="category">
|
||||
<%if [tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] :filter[{!!change-category}match<category>] %>
|
||||
<div class="doc-release-note-heading">
|
||||
<h2 class="doc-change-note-category">
|
||||
<$text text={{{ [[$:/tw5.com/releases/info/categories/]addsuffix<category>addsuffix[/caption]get[text]] }}} />
|
||||
</h2>
|
||||
</div>
|
||||
<$list filter="[tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] :filter[{!!change-category}match<category>sort[description]]" variable="change">
|
||||
<div class="doc-change-note-item">
|
||||
<h3 class="doc-change-note-heading">
|
||||
<$link
|
||||
to="Release Notes and Changes"
|
||||
class="doc-link-badge"
|
||||
style.backgroundColor={{{ [<change>get[change-type]addprefix[$:/tw5.com/releases/info/change-types/]addsuffix[/colour]get[text]] }}}
|
||||
>
|
||||
<$text text={{{ [<change>get[change-type]addprefix[$:/tw5.com/releases/info/change-types/]addsuffix[/caption]get[text]] }}}/>
|
||||
</$link> <$transclude $tiddler=<<change>> $field="description" $mode="inline"/></h3>
|
||||
<div class="doc-change-note-info-list">
|
||||
<$list filter="[tag[$:/tags/ImpactNote]] :filter[{!!changenote}match<change>] +[sort[description]]" variable="impact" counter="impactCount">
|
||||
<div class="doc-change-note-info-list-item-caption">
|
||||
<%if [<impactCount>match[1]] %>
|
||||
Impact:
|
||||
<%endif%>
|
||||
</div>
|
||||
<div class="doc-change-note-info-list-item-description">
|
||||
<div class="doc-change-note-info-list-item-description-summary">
|
||||
<$transclude $variable="impact-pill" $mode="inline" impact-type={{{ [<impact>get[impact-type]] }}}/>
|
||||
<$text text=": "/>
|
||||
<$transclude $tiddler=<<impact>> $field="description" $mode="inline"/>
|
||||
</div>
|
||||
<div class="doc-change-note-info-list-item-description-details">
|
||||
<$transclude $tiddler=<<impact>> $field="text" $mode="block"/>
|
||||
</div>
|
||||
</div>
|
||||
</$list>
|
||||
<div class="doc-change-note-info-list-item-caption">
|
||||
<$text text="GitHub: "/>
|
||||
</div>
|
||||
<div class="doc-change-note-info-list-item-description">
|
||||
<$list filter="[<change>get[github-links]enlist-input[]]" variable="link">
|
||||
<a
|
||||
href=<<link>>
|
||||
class="doc-github-link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{{$:/core/images/github}}
|
||||
</a>
|
||||
</$list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="doc-change-note-description">
|
||||
<$transclude $tiddler=<<change>> $mode="block"/>
|
||||
</div>
|
||||
</div>
|
||||
</$list>
|
||||
<%endif%>
|
||||
<$reveal type="nomatch" state=<<state>> text="open" default=<<default>> tag="span">
|
||||
<$action-setfield $tiddler=<<state>> $field="text" $value="open"/>
|
||||
<span class="doc-release-section-toggle">{{$:/core/images/right-arrow}}</span>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<state>> text="open" default=<<default>> tag="span">
|
||||
<$action-setfield $tiddler=<<state>> $field="text" $value="close"/>
|
||||
<span class="doc-release-section-toggle">{{$:/core/images/down-arrow}}</span>
|
||||
</$reveal>
|
||||
\end release-section-toggle
|
||||
|
||||
\procedure change-note-type-badge()
|
||||
\whitespace trim
|
||||
<$link
|
||||
to="Release Notes and Changes"
|
||||
class="doc-link-badge"
|
||||
style.backgroundColor={{{ [<change>get[change-type]addprefix[$:/tw5.com/releases/info/change-types/]addsuffix[/colour]get[text]] }}}
|
||||
>
|
||||
<$text text={{{ [<change>get[change-type]addprefix[$:/tw5.com/releases/info/change-types/]addsuffix[/singular]get[text]] }}}/>
|
||||
</$link>
|
||||
\end change-note-type-badge
|
||||
|
||||
\procedure change-note-category-badge()
|
||||
\whitespace trim
|
||||
<$link
|
||||
to="Release Notes and Changes"
|
||||
class="doc-link-badge"
|
||||
style.backgroundColor={{{ [<change>get[change-category]addprefix[$:/tw5.com/releases/info/categories/]addsuffix[/colour]get[text]] }}}
|
||||
>
|
||||
<$text text={{{ [<change>get[change-category]addprefix[$:/tw5.com/releases/info/categories/]addsuffix[/singular]get[text]] }}}/>
|
||||
</$link>
|
||||
\end change-note-category-badge
|
||||
|
||||
\procedure change-note-heading()
|
||||
\whitespace trim
|
||||
<h3 class="doc-change-note-heading"
|
||||
style.backgroundColor={{{ [<change>get[change-type]addprefix[$:/tw5.com/releases/info/change-types/]addsuffix[/colour]get[text]addsuffix[40]] }}}
|
||||
>
|
||||
<%if [<show-type-badge>!match[no]] %><<change-note-type-badge>><%endif%>
|
||||
<%if [<show-category-badge>match[yes]] %><<change-note-category-badge>><%endif%>
|
||||
<%if [<show-tiddler-link>match[yes]] %><$link to=<<change>> class="doc-change-note-description-link"><$transclude $tiddler=<<change>> $field="description" $mode="inline"/></$link><%else%><$transclude $tiddler=<<change>> $field="description" $mode="inline"/><%endif%>
|
||||
</h3>
|
||||
\end change-note-heading
|
||||
|
||||
\procedure change-note-impacts()
|
||||
\whitespace trim
|
||||
<$list filter="[tag[$:/tags/ImpactNote]] :filter[{!!changenote}match<change>] +[sort[description]]" variable="impact" counter="impactCount">
|
||||
<div class="doc-change-note-info-list-item-caption">
|
||||
<%if [<impactCount>match[1]] %>Impact:<%endif%>
|
||||
</div>
|
||||
<div class="doc-change-note-info-list-item-description">
|
||||
<div class="doc-change-note-info-list-item-description-summary">
|
||||
<$transclude $variable="impact-pill" $mode="inline" impact-type={{{ [<impact>get[impact-type]] }}}/>
|
||||
<$text text=": "/>
|
||||
<%if [<show-tiddler-link>match[yes]] %><$link to=<<impact>> class="doc-change-note-description-link"><$transclude $tiddler=<<impact>> $field="description" $mode="inline"/></$link><%else%><$transclude $tiddler=<<impact>> $field="description" $mode="inline"/><%endif%>
|
||||
</div>
|
||||
<div class="doc-change-note-info-list-item-description-details">
|
||||
<$transclude $tiddler=<<impact>> $field="text" $mode="block"/>
|
||||
</div>
|
||||
</div>
|
||||
</$list>
|
||||
\end change-note-impacts
|
||||
|
||||
\procedure change-note-github-links()
|
||||
\whitespace trim
|
||||
<div class="doc-change-note-info-list-item-caption">
|
||||
<$text text="GitHub: "/>
|
||||
</div>
|
||||
<div class="doc-change-note-info-list-item-description">
|
||||
<$list filter="[<change>get[github-links]enlist-input[]]" variable="link">
|
||||
<a href=<<link>> class="doc-github-link" target="_blank" rel="noopener noreferrer">
|
||||
{{$:/core/images/github}}
|
||||
</a>
|
||||
</$list>
|
||||
</div>
|
||||
\end change-list
|
||||
\end change-note-github-links
|
||||
|
||||
\procedure change-note-info()
|
||||
\whitespace trim
|
||||
<div class="doc-change-note-info-list">
|
||||
<%if [<show-change-impacts>!match[no]] %><<change-note-impacts>><%endif%>
|
||||
<<change-note-github-links>>
|
||||
</div>
|
||||
\end change-note-info
|
||||
|
||||
\procedure change-note-description()
|
||||
\whitespace trim
|
||||
<div class="doc-change-note-description">
|
||||
<$transclude $tiddler=<<change>> $mode="block"/>
|
||||
</div>
|
||||
\end change-note-description
|
||||
|
||||
\procedure change-note-item()
|
||||
\whitespace trim
|
||||
<div class="doc-change-note-item">
|
||||
<<change-note-heading>>
|
||||
<<change-note-info>>
|
||||
<<change-note-description>>
|
||||
</div>
|
||||
\end change-note-item
|
||||
|
||||
\procedure change-note-list(filter)
|
||||
\whitespace trim
|
||||
<$list
|
||||
filter=<<filter>>
|
||||
variable="change"
|
||||
emptyMessage="<div class='doc-change-note-empty'>No curated changes yet.</div>"
|
||||
>
|
||||
<<change-note-item>>
|
||||
</$list>
|
||||
\end change-note-list
|
||||
|
||||
\procedure summary-tab()
|
||||
\whitespace trim
|
||||
These are significant improvements that will benefit a broad range of users, and are recommended for everyone to explore.
|
||||
<$let show-type-badge="yes" show-category-badge="yes" show-change-impacts="yes" show-tiddler-link="yes"
|
||||
summaryListField={{{ [<release>addprefix[highlights/]] }}}
|
||||
>
|
||||
<$macrocall $name="change-note-list" filter="[[$:/tw5.com/releases/info/summary-lists]get<summaryListField>enlist-input[]]"/>
|
||||
</$let>
|
||||
\end summary-tab
|
||||
|
||||
\procedure release-tab-search(stateTiddler)
|
||||
\whitespace trim
|
||||
<div class="doc-release-tab-search">
|
||||
<$edit-text tiddler=<<stateTiddler>> tag="input" placeholder="Search..." default=""/>
|
||||
</div>
|
||||
\end release-tab-search
|
||||
|
||||
\procedure change-type-section()
|
||||
\whitespace trim
|
||||
<$let changeTypeState={{{ [<release>addprefix[$:/state/release/change-type/]addsuffix[/]addsuffix<change-type>] }}}>
|
||||
<div class="doc-release-section">
|
||||
<$button class="tc-btn-invisible doc-release-section-summary"
|
||||
style.backgroundColor={{{ [[$:/tw5.com/releases/info/change-types/]addsuffix<change-type>addsuffix[/colour]get[text]addsuffix[40]] }}}
|
||||
>
|
||||
<$macrocall $name="release-section-toggle" state=<<changeTypeState>>/>
|
||||
<span class="doc-release-section-summary-text">
|
||||
<$text text={{{ [[$:/tw5.com/releases/info/change-types/]addsuffix<change-type>addsuffix[/plural]get[text]] }}} />
|
||||
<$text text=" "/><span class="doc-release-section-count">(<$text text={{{ [tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] :filter[{!!change-type}match<change-type>] +[count[]] }}}/>)</span>
|
||||
</span>
|
||||
</$button>
|
||||
<$reveal type="match" state=<<changeTypeState>> text="open" tag="div" class="doc-release-section-body">
|
||||
<$let typeFilter="[tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] :filter[{!!change-type}match<change-type>] +[sort[description]]">
|
||||
<$macrocall $name="change-note-list" filter=<<typeFilter>>/>
|
||||
</$let>
|
||||
</$reveal>
|
||||
</div>
|
||||
</$let>
|
||||
\end change-type-section
|
||||
|
||||
\procedure change-types-tab()
|
||||
\whitespace trim
|
||||
<$let show-type-badge="no" show-category-badge="yes" show-change-impacts="yes" show-tiddler-link="yes"
|
||||
searchState={{{ [<release>addprefix[$:/state/release/search/change-types/]] }}}
|
||||
>
|
||||
<$macrocall $name="release-tab-search" stateTiddler=<<searchState>>/>
|
||||
<$let searchText={{{ [<searchState>get[text]] }}}>
|
||||
<%if [<searchText>!match[]] %>
|
||||
<div class="doc-release-search-count">
|
||||
<$let count={{{ [tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] +[search:title,description,text,github-contributors,github-links<searchText>] +[count[]] }}}>
|
||||
<$text text={{{ [<count>addsuffix[ ]] }}}/>result<$text text={{{ [<count>!match[1]then[s]] }}}/>
|
||||
</$let>
|
||||
</div>
|
||||
<$macrocall $name="change-note-list" filter="[tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] +[search:title,description,text,github-contributors,github-links<searchText>] +[sort[description]]"/>
|
||||
<%else%>
|
||||
<$list filter="[enlist{$:/tw5.com/releases/info/change-type-order}]" variable="change-type">
|
||||
<<change-type-section>>
|
||||
</$list>
|
||||
<%endif%>
|
||||
</$let>
|
||||
</$let>
|
||||
\end change-types-tab
|
||||
|
||||
\procedure change-category-section()
|
||||
\whitespace trim
|
||||
<$let changeCategoryState={{{ [<release>addprefix[$:/state/release/change-category/]addsuffix[/]addsuffix<category>] }}}>
|
||||
<div class="doc-release-section">
|
||||
<$button class="tc-btn-invisible doc-release-section-summary"
|
||||
style.backgroundColor={{{ [[$:/tw5.com/releases/info/categories/]addsuffix<category>addsuffix[/colour]get[text]addsuffix[40]] }}}
|
||||
>
|
||||
<$macrocall $name="release-section-toggle" state=<<changeCategoryState>>/>
|
||||
<span class="doc-release-section-summary-text">
|
||||
<$text text={{{ [[$:/tw5.com/releases/info/categories/]addsuffix<category>addsuffix[/plural]get[text]] }}} />
|
||||
<$text text=" "/><span class="doc-release-section-count">(<$text text={{{ [tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] :filter[{!!change-category}match<category>] +[count[]] }}}/>)</span>
|
||||
</span>
|
||||
</$button>
|
||||
<$reveal type="match" state=<<changeCategoryState>> text="open" tag="div" class="doc-release-section-body">
|
||||
<$let categoryFilter="[tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] :filter[{!!change-category}match<category>] +[sort[description]]">
|
||||
<$macrocall $name="change-note-list" filter=<<categoryFilter>>/>
|
||||
</$let>
|
||||
</$reveal>
|
||||
</div>
|
||||
</$let>
|
||||
\end change-category-section
|
||||
|
||||
\procedure change-categories-tab()
|
||||
\whitespace trim
|
||||
<$let show-type-badge="yes" show-category-badge="no" show-change-impacts="yes" show-tiddler-link="yes"
|
||||
searchState={{{ [<release>addprefix[$:/state/release/search/change-categories/]] }}}
|
||||
>
|
||||
<$macrocall $name="release-tab-search" stateTiddler=<<searchState>>/>
|
||||
<$let searchText={{{ [<searchState>get[text]] }}}>
|
||||
<%if [<searchText>!match[]] %>
|
||||
<div class="doc-release-search-count">
|
||||
<$let count={{{ [tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] +[search:title,description,text,github-contributors,github-links<searchText>] +[count[]] }}}>
|
||||
<$text text={{{ [<count>addsuffix[ ]] }}}/>result<$text text={{{ [<count>!match[1]then[s]] }}}/>
|
||||
</$let>
|
||||
</div>
|
||||
<$macrocall $name="change-note-list" filter="[tag[$:/tags/ChangeNote]] :filter[{!!release}match<release>] +[search:title,description,text,github-contributors,github-links<searchText>] +[sort[description]]"/>
|
||||
<%else%>
|
||||
<$list filter="[enlist{$:/tw5.com/releases/info/category-order}]" variable="category">
|
||||
<<change-category-section>>
|
||||
</$list>
|
||||
<%endif%>
|
||||
</$let>
|
||||
</$let>
|
||||
\end change-categories-tab
|
||||
|
||||
\procedure impact-change-note()
|
||||
\whitespace trim
|
||||
<$let change={{{ [<impact>get[changenote]] }}} show-change-impacts="no">
|
||||
<<change-note-item>>
|
||||
</$let>
|
||||
\end impact-change-note
|
||||
|
||||
\procedure impact-note-item()
|
||||
\whitespace trim
|
||||
<div class="doc-impact-note-item">
|
||||
<h3 class="doc-impact-note-heading"
|
||||
style.backgroundColor={{{ [<impact>get[impact-type]addprefix[$:/tw5.com/releases/info/impact-types/]addsuffix[/colour/background]get[text]] }}}
|
||||
>
|
||||
<$transclude $variable="impact-pill" $mode="inline" impact-type={{{ [<impact>get[impact-type]] }}}/>
|
||||
<$text text=": "/>
|
||||
<%if [<show-tiddler-link>match[yes]] %><$link to=<<impact>> class="doc-change-note-description-link"><$transclude $tiddler=<<impact>> $field="description" $mode="inline"/></$link><%else%><$transclude $tiddler=<<impact>> $field="description" $mode="inline"/><%endif%>
|
||||
</h3>
|
||||
<div class="doc-impact-note-details">
|
||||
<$transclude $tiddler=<<impact>> $field="text" $mode="block"/>
|
||||
</div>
|
||||
<<impact-change-note>>
|
||||
</div>
|
||||
\end impact-note-item
|
||||
|
||||
\procedure impact-type-section()
|
||||
\whitespace trim
|
||||
<$let impactTypeState={{{ [<release>addprefix[$:/state/release/impact-type/]addsuffix[/]addsuffix<impact-type>] }}}>
|
||||
<div class="doc-release-section">
|
||||
<$button class="tc-btn-invisible doc-release-section-summary"
|
||||
style.backgroundColor={{{ [[$:/tw5.com/releases/info/impact-types/]addsuffix<impact-type>addsuffix[/colour/background]get[text]] }}}
|
||||
>
|
||||
<$macrocall $name="release-section-toggle" state=<<impactTypeState>>/>
|
||||
<span class="doc-release-section-summary-text">
|
||||
<$text text={{{ [[$:/tw5.com/releases/info/impact-types/]addsuffix<impact-type>addsuffix[/plural]get[text]] }}} />
|
||||
<$text text=" "/><span class="doc-release-section-count">(<$text text={{{ [tag[$:/tags/ImpactNote]] :filter[{!!impact-type}match<impact-type>] :filter[{!!changenote}get[release]match<release>] +[count[]] }}}/>)</span>
|
||||
</span>
|
||||
</$button>
|
||||
<$reveal type="match" state=<<impactTypeState>> text="open" tag="div" class="doc-release-section-body">
|
||||
<$list
|
||||
filter="[tag[$:/tags/ImpactNote]] :filter[{!!impact-type}match<impact-type>] :filter[{!!changenote}get[release]match<release>] +[sort[description]]"
|
||||
variable="impact"
|
||||
>
|
||||
<<impact-note-item>>
|
||||
</$list>
|
||||
</$reveal>
|
||||
</div>
|
||||
</$let>
|
||||
\end impact-type-section
|
||||
|
||||
\procedure impacts-tab()
|
||||
\whitespace trim
|
||||
<$let show-tiddler-link="yes"
|
||||
searchState={{{ [<release>addprefix[$:/state/release/search/impacts/]] }}}
|
||||
>
|
||||
<$macrocall $name="release-tab-search" stateTiddler=<<searchState>>/>
|
||||
<$let searchText={{{ [<searchState>get[text]] }}}>
|
||||
<%if [<searchText>!match[]] %>
|
||||
<div class="doc-release-search-count">
|
||||
<$let count={{{ [tag[$:/tags/ImpactNote]] :filter[{!!changenote}get[release]match<release>] +[search:title,description,text<searchText>] +[count[]] }}}>
|
||||
<$text text={{{ [<count>addsuffix[ ]] }}}/>result<$text text={{{ [<count>!match[1]then[s]] }}}/>
|
||||
</$let>
|
||||
</div>
|
||||
<$list filter="[tag[$:/tags/ImpactNote]] :filter[{!!changenote}get[release]match<release>] +[search:title,description,text<searchText>] +[sort[description]]" variable="impact">
|
||||
<<impact-note-item>>
|
||||
</$list>
|
||||
<%else%>
|
||||
<$list filter="[enlist{$:/tw5.com/releases/info/impact-type-order}]" variable="impact-type">
|
||||
<<impact-type-section>>
|
||||
</$list>
|
||||
<%endif%>
|
||||
</$let>
|
||||
</$let>
|
||||
\end impacts-tab
|
||||
|
||||
\procedure credits-tab()
|
||||
\whitespace trim
|
||||
<div class="doc-release-credits">
|
||||
A warm thank you to the developers who have contributed to this release:
|
||||
<<acknowledgements>>
|
||||
</div>
|
||||
\end credits-tab
|
||||
|
||||
\procedure release-tabs()
|
||||
\whitespace trim
|
||||
<$macrocall
|
||||
$name="tabs"
|
||||
tabsList="[enlist{$:/tw5.com/releases/info/tab-order}]"
|
||||
default="Summary"
|
||||
class="doc-release-tabs"
|
||||
template="$:/tw5.com/releases/tab-template"
|
||||
/>
|
||||
\end release-tabs
|
||||
|
||||
\procedure acknowledgements()
|
||||
<ol class="doc-github-contributors">
|
||||
@@ -136,21 +385,13 @@ See <<github-release-changes-link>> and [[other releases|TiddlyWiki Releases]].
|
||||
|
||||
<<banner-credits>>
|
||||
|
||||
! Introduction
|
||||
|
||||
<$transclude $variable="release-introduction" $mode="block"/>
|
||||
|
||||
! Changes
|
||||
<<release-tabs>>
|
||||
|
||||
<$transclude $variable="change-list" $mode="inline"/>
|
||||
! Credits
|
||||
|
||||
<!-- Acknowledgement list -->
|
||||
|
||||
! Acknowledgements
|
||||
|
||||
A warm thank you to the developers who have contributed to this release:
|
||||
|
||||
<<acknowledgements>>
|
||||
<<credits-tab>>
|
||||
|
||||
</$let>
|
||||
\end releasenote
|
||||
|
||||
@@ -5,6 +5,72 @@ type: text/vnd.tiddlywiki
|
||||
.doc-release-note {
|
||||
}
|
||||
|
||||
.tc-tab-set.doc-release-tabs {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.doc-release-tab-search {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
||||
.doc-release-tab-search input {
|
||||
width: 100%;
|
||||
padding: 0.5em;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 0.25em;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.doc-release-search-count {
|
||||
font-size: 0.85em;
|
||||
color: #888;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.doc-release-section {
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 0.5em;
|
||||
margin: 0.75em 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.doc-release-section-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5em 0.75em;
|
||||
font-weight: 600;
|
||||
background: #f1f1f1;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
border-radius: 0.5em 0.5em 0 0;
|
||||
}
|
||||
|
||||
.doc-release-section-toggle {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.doc-release-section-summary-text {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.doc-release-section-count {
|
||||
font-weight: normal;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.doc-release-credits {
|
||||
margin: 0.75em 0;
|
||||
}
|
||||
|
||||
.doc-release-section-body {
|
||||
padding: 0.5em 0.75em;
|
||||
}
|
||||
|
||||
.doc-release-note-heading {
|
||||
}
|
||||
|
||||
@@ -84,3 +150,56 @@ type: text/vnd.tiddlywiki
|
||||
padding: 0.25em;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.doc-impact-note-item {
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 0.5em;
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.doc-impact-note-heading {
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.25em 0;
|
||||
padding: 0.25em 0.5em;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
.doc-impact-note-item > .doc-change-note-item {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.doc-impact-note-details {
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.doc-impact-note-change {
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.doc-impact-note-change-caption {
|
||||
text-transform: uppercase;
|
||||
font-size: 0.7em;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.doc-impact-note-change-link {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.doc-change-note-description-link {
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dotted;
|
||||
}
|
||||
|
||||
.doc-change-note-description-link:hover {
|
||||
text-decoration-style: solid;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
title: $:/tw5.com/releases/info/summary-lists
|
||||
type: text/vnd.tiddlywiki
|
||||
highlights/5.4.0: [[$:/changenotes/5.4.0/#9055]] [[$:/changenotes/5.4.0/#8972]] [[$:/changenotes/5.4.0/#9641]] [[$:/changenotes/5.4.0/#8258]]
|
||||
@@ -0,0 +1,12 @@
|
||||
title: $:/tw5.com/releases/tab-template
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<%if [<currentTab>match[Summary]] %>
|
||||
<<summary-tab>>
|
||||
<%elseif [<currentTab>match[By Type]] %>
|
||||
<<change-types-tab>>
|
||||
<%elseif [<currentTab>match[By Category]] %>
|
||||
<<change-categories-tab>>
|
||||
<%elseif [<currentTab>match[Impacts]] %>
|
||||
<<impacts-tab>>
|
||||
<%endif%>
|
||||
@@ -0,0 +1,6 @@
|
||||
title: $:/tw5.com/releases/ViewTemplate/body/changenote
|
||||
|
||||
\whitespace trim
|
||||
<$let change=<<currentTiddler>> show-type-badge="yes" show-category-badge="yes" show-change-impacts="yes">
|
||||
<<change-note-item>>
|
||||
</$let>
|
||||
@@ -0,0 +1,6 @@
|
||||
title: $:/tw5.com/releases/ViewTemplateBodyFilters
|
||||
tags: $:/tags/ViewTemplateBodyFilter
|
||||
list-before:
|
||||
|
||||
[tag[$:/tags/ChangeNote]then[$:/tw5.com/releases/ViewTemplate/body/changenote]]
|
||||
[tag[$:/tags/ImpactNote]then[$:/tw5.com/releases/ViewTemplate/body/impactnote]]
|
||||
@@ -0,0 +1,6 @@
|
||||
title: $:/tw5.com/releases/ViewTemplate/body/impactnote
|
||||
|
||||
\whitespace trim
|
||||
<$let impact=<<currentTiddler>> show-tiddler-link="yes">
|
||||
<<impact-note-item>>
|
||||
</$let>
|
||||
@@ -8,4 +8,6 @@ type: text/vnd.tiddlywiki
|
||||
|!how declared|!behaviour|
|
||||
|\define|Textual substitution of parameters is performed on the body text. No further processing takes place. The result after textual substitution is used as the attribute's value|
|
||||
|<<.wlink SetWidget>>, <<.wlink LetWidget>>, <<.wlink VarsWidget>>, \procedure, \widget|Body text is retrieved as-is and used as the attribute's value.|
|
||||
|\function|When a function (e.g. `.myfun`) is invoked as `<div class=<<.myfun>>/>`, it is a synonym for `<div class={{{[function[.myfun]]}}}/>`. As with any filtered transclusion (i.e. triple curly braces), all results except the first are discarded. That first result is used as the attribute's value. Note that functions are recursively processed even when invoked in this form. In other words a filter expression in a function can invoke another function and the processing will continue|
|
||||
|\function|When a function (e.g. `.myfun`) is invoked as `<div class=<<.myfun>>/>`, it is a synonym for `<div class={{{[function[.myfun]]}}}/>`. As with any filtered transclusion (i.e. triple curly braces), all results except the first are discarded. That first result is used as the attribute's value. Note that functions are recursively processed even when invoked in this form. In other words a filter expression in a function can invoke another function and the processing will continue|
|
||||
|
||||
<<.from-version "5.4.0">> Using the [[multi-valued variable attribute|Multi-Valued Variable Attribute Values]] syntax `((var))` instead of `<<var>>` passes the complete list of values to the attribute rather than just the first value. This is primarily useful for passing [[multi-valued variables|Multi-Valued Variables]] to procedure and function parameters via the TranscludeWidget.
|
||||
@@ -59,14 +59,57 @@ For example:
|
||||
```
|
||||
\function myfunc(tiddlers) [(tiddlers)sort[]]
|
||||
|
||||
<$let varname={{{ [all[tiddlers]limit[50]] }}}>
|
||||
<$let varname={{{ [all[tiddlers]limit[50]] }}}>
|
||||
<$text text={{{ [function[myfunc],(varname)] +[join[-]] }}}/>
|
||||
</$let>
|
||||
```
|
||||
|
||||
! Examples
|
||||
!! Passing Multi-Valued Variables to Procedures and Functions
|
||||
|
||||
For example:
|
||||
<<.from-version "5.4.0">> Multi-valued variables can be passed to procedures and functions using the `((var))` syntax in [[widget attributes|Multi-Valued Variable Attribute Values]]. This is the multi-valued counterpart of the `<<var>>` syntax:
|
||||
|
||||
```
|
||||
\procedure showItems(itemList)
|
||||
<$text text={{{ [(itemList)join[-]] }}}/>
|
||||
\end
|
||||
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
<$transclude $variable="showItems" itemList=((items))/>
|
||||
</$let>
|
||||
```
|
||||
|
||||
The `((var))` syntax can also be used in procedure and function parameter defaults:
|
||||
|
||||
```
|
||||
\procedure showItems(itemList:((defaults)))
|
||||
<$text text={{{ [(itemList)join[-]] }}}/>
|
||||
\end
|
||||
```
|
||||
|
||||
! Displaying Multi-Valued Variables
|
||||
|
||||
<<.from-version "5.4.0">> Multi-valued variables can be displayed inline in wikitext using the `((var))` syntax. The values are joined with a comma and space by default:
|
||||
|
||||
```
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
((items))
|
||||
</$let>
|
||||
```
|
||||
|
||||
A custom separator can be specified using the `||` delimiter:
|
||||
|
||||
```
|
||||
((items||:))
|
||||
```
|
||||
|
||||
A similar syntax with triple round brackets is available for displaying the results of a filter expression:
|
||||
|
||||
```
|
||||
((( [all[tiddlers]sort[]] )))
|
||||
((( [all[tiddlers]sort[]] ||: )))
|
||||
```
|
||||
|
||||
! Examples
|
||||
|
||||
```
|
||||
<$let varname={{{ [all[tiddlers]sort[]] }}}>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
created: 20250208120000000
|
||||
modified: 20250208120000000
|
||||
tags: WikiText [[Widget Attributes]]
|
||||
title: Multi-Valued Variable Attribute Values
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.4.0">> Multi-valued variable attribute values are indicated with double round brackets around the variable name. This passes the complete list of values of a [[multi-valued variable|Multi-Valued Variables]] to the attribute, rather than just the first value.
|
||||
|
||||
```
|
||||
<$transclude $variable="myproc" items=((myvar))/>
|
||||
```
|
||||
|
||||
This is the multi-valued counterpart to the [[Variable Attribute Values]] syntax `<<var>>`, which only returns the first value for backwards compatibility. The relationship mirrors the existing convention in filter operands where `<var>` returns a single value and `(var)` returns all values.
|
||||
|
||||
! Non-MVV-Aware Attributes
|
||||
|
||||
When `((var))` is used on a widget attribute that does not support multi-valued variables (such as the `text` attribute of the TextWidget), only the first value is used:
|
||||
|
||||
```
|
||||
<$text text=((myvar))/>
|
||||
```
|
||||
|
||||
! Passing Multi-Valued Variables to Procedures
|
||||
|
||||
The primary use case for this syntax is passing multi-valued variables through the `$transclude` pipeline to procedures and functions:
|
||||
|
||||
```
|
||||
\procedure showItems(itemList)
|
||||
<$text text={{{ [(itemList)join[-]] }}}/>
|
||||
\end
|
||||
|
||||
<$let items={{{ [all[tiddlers]sort[]] }}}>
|
||||
<$transclude $variable="showItems" itemList=((items))/>
|
||||
</$let>
|
||||
```
|
||||
|
||||
In this example, the complete list of tiddler titles stored in `items` is passed to the `itemList` parameter of the `showItems` procedure.
|
||||
@@ -62,6 +62,28 @@ or, when used with a template, `{{{ [tag[mechanism]]||TemplateTitle }}}` expands
|
||||
|
||||
<<.tip "Install the //Internals// plugin to enable the display of the generated widget tree in the preview pane of the editor">>
|
||||
|
||||
!! Multi-Valued Variable Display
|
||||
|
||||
<<.from-version "5.4.0">> The `((var))` syntax can be used inline to display the values of a [[multi-valued variable|Multi-Valued Variables]], joined with a comma and space by default:
|
||||
|
||||
```
|
||||
((myvar))
|
||||
((myvar||:))
|
||||
```
|
||||
|
||||
The optional `||` delimiter specifies a custom separator string.
|
||||
|
||||
!! Inline Filter Display
|
||||
|
||||
<<.from-version "5.4.0">> The `(((filter)))` syntax displays the results of a filter expression inline, joined with a comma and space by default:
|
||||
|
||||
```
|
||||
((( [all[tiddlers]sort[]] )))
|
||||
((( [all[tiddlers]sort[]] ||: )))
|
||||
```
|
||||
|
||||
The optional `||` delimiter specifies a custom separator string. This is the inline display counterpart to the filtered transclusion `{{{ }}}` syntax.
|
||||
|
||||
---
|
||||
|
||||
See also:
|
||||
|
||||
@@ -11,6 +11,7 @@ Attributes of [[HTML elements|HTML in WikiText]] and widgets can be specified in
|
||||
* [[a transclusion of a macro/variable|Variable Attribute Values]]
|
||||
* [[as the result of a filter expression|Filtered Attribute Values]]
|
||||
* <<.from-version "5.3.0">> [[as the result of performing filter and variable substitutions on the given string|Substituted Attribute Values]]
|
||||
* <<.from-version "5.4.0">> [[as a multi-valued variable reference|Multi-Valued Variable Attribute Values]]
|
||||
|
||||
|attribute type|syntax|h
|
||||
|literal |single, double or triple quotes or no quotes for values without spaces |
|
||||
@@ -18,9 +19,10 @@ Attributes of [[HTML elements|HTML in WikiText]] and widgets can be specified in
|
||||
|variable |double angle brackets around a macro or variable invocation |
|
||||
|filtered |triple curly braces around a filter expression|
|
||||
|substituted|single or triple backticks around the text to be processed for substitutions|
|
||||
|multi-valued variable |double round brackets around a variable name |
|
||||
|
||||
|
||||
<$list filter="[[Literal Attribute Values]] [[Transcluded Attribute Values]] [[Variable Attribute Values]] [[Filtered Attribute Values]] [[Substituted Attribute Values]]">
|
||||
<$list filter="[[Literal Attribute Values]] [[Transcluded Attribute Values]] [[Variable Attribute Values]] [[Filtered Attribute Values]] [[Substituted Attribute Values]] [[Multi-Valued Variable Attribute Values]]">
|
||||
<$link><h1><$text text=<<currentTiddler>>/></h1></$link>
|
||||
<$transclude mode="block"/>
|
||||
</$list>
|
||||
|
||||
@@ -58,7 +58,7 @@ js.configs.recommended,
|
||||
"array-callback-return": "off",
|
||||
"@stylistic/array-element-newline": "off",
|
||||
"arrow-body-style": "error",
|
||||
"@stylistic/arrow-parens": ["error", "as-needed"],
|
||||
"@stylistic/arrow-parens": ["error", "always"],
|
||||
"@stylistic/arrow-spacing": ["error", {
|
||||
after: true,
|
||||
before: true,
|
||||
|
||||
Reference in New Issue
Block a user