1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-02-14 05:59:48 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Jeremy Ruston
88619fc215 Add changenote 2025-12-29 21:09:17 +00:00
Jeremy Ruston
dfc5e9e6e5 Initial Commit 2025-12-29 21:01:38 +00:00
202 changed files with 3181 additions and 3772 deletions

View File

@@ -1,62 +0,0 @@
---
name: Bug report
about: Create a report to help us improve TiddlyWiki 5
title: "[Report] "
type: report
---
<!-- Remove elements, that you do not need -->
<!-- Add screenshots where needed -->
**Problem Description**
<!-- Describe your problem: A clear and concise description of what your problem is -->
**To Reproduce**
Steps to reproduce the behavior:
1. At https://tiddlywiki.com
2. Click on ...
3. Scroll down to ...
4. See ...
**Expected behavior**
As a user,
<!-- As a developer, -->
I would expect ...
**TiddlyWiki Configuration**
<!-- Please complete the following information -->
- Report created with: [Wiki Information](https://tiddlywiki.com/#%24%3A%2Fcore%2Fui%2FControlPanel%2FWikiInformation)
<!-- Your report comes here -->
<!-- or -->
<!-- Add it manually -->
- Version: <!-- e.g. v5.3.8 -->
- Saving mechanism: <!-- e.g. Node.js, TiddlyDesktop, TiddlyHost etc -->
- Plugins installed: <!-- e.g. Freelinks, TiddlyMap ... other 3rd party plugins -->
**Desktop**
<!-- Please complete the following information -->
- OS: <!-- e.g. iOS -->
- Browser: <!-- e.g. chrome, safari, FireFox -- Version: -->
**Smartphone**
<!-- Please complete the following information -->
- Device: <!-- e.g. iPhone6 -->
- OS: <!-- e.g. iOS8.1 -->
- Browser: <!-- e.g. stock browser, safari, FireFox -- Version: -->
**Additional context**
<!-- Add any other context about the problem here. -->

68
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: Bug report
description: Create a report to help us improve TiddlyWiki 5
title: "[BUG] "
type: bug
body:
- type: textarea
id: Describe
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: Expected
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: false
- type: textarea
id: Reproduce
attributes:
label: To Reproduce
description: "Steps to reproduce the behavior:"
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: false
- type: textarea
id: Screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
placeholder: Drag image here to upload screenshot!
validations:
required: false
- type: textarea
id: Configuration
attributes:
label: TiddlyWiki Configuration
description: please complete the following information
placeholder: |
- Version [e.g. v5.1.24]
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
- Plugins installed [e.g. Freelinks, TiddlyMap]
### Desktop (please complete the following information):
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
### Smartphone (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
validations:
required: true
- type: textarea
id: Context
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

@@ -4,23 +4,18 @@ about: Suggest an idea for TiddlyWiki 5
title: "[IDEA]"
labels: ''
assignees: ''
type: idea
type: feature
---
**Is your idea related to a problem? Please describe.**
A clear and concise description of what the problem is. Eg:
As a user, I would like [...]
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -316,25 +316,8 @@ $tw.utils.htmlDecode = function(s) {
return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/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) {

View File

@@ -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

View File

@@ -1,30 +0,0 @@
/*\
title: $:/core-modules/modules/utils/base64.js
type: application/javascript
module-type: utils-node
Base64 UTF-8 utlity functions.
\*/
"use strict";
const{ TextEncoder, TextDecoder } = require("node:util");
exports.btoa = binstr => Buffer.from(binstr, "binary").toString("base64");
exports.atob = b64 => Buffer.from(b64, "base64").toString("binary");
function base64ToBytes(base64) {
const binString = exports.atob(base64);
return Uint8Array.from(binString, m => m.codePointAt(0));
};
function bytesToBase64(bytes) {
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
return exports.btoa(binString);
};
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));

View File

@@ -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: theres 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 */
})();

View File

@@ -5,4 +5,3 @@ TiddlyWiki incorporates code from these fine OpenSource projects:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]]
* [[diff-match-patch-es by antfu|https://github.com/antfu/diff-match-patch-es]]

View File

@@ -1,6 +1,5 @@
title: $:/language/
Alerts: Alerts
AboveStory/ClassicPlugin/Warning: It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:
BinaryWarning/Prompt: This tiddler contains binary data
ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details.

View File

@@ -14,31 +14,31 @@ Export our filter function
*/
exports.sort = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,false,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,false);
return results;
};
exports.nsort = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,true,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,true);
return results;
};
exports.sortan = function(source, operator, options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results, operator.operands[0] || "title", operator.prefix === "!",false,false,true,operator.operands[1]);
options.wiki.sortTiddlers(results, operator.operand || "title", operator.prefix === "!",false,false,true);
return results;
};
exports.sortcs = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,false,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,false);
return results;
};
exports.nsortcs = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,true,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,true);
return results;
};

View File

@@ -37,14 +37,14 @@ exports.trim = function(source,operator,options) {
operand = (operator.operand || ""),
fnCalc;
if(suffix === "prefix") {
fnCalc = function(a,b) {return [$tw.utils.trimPrefix(a,b)];};
fnCalc = function(a,b) {return [$tw.utils.trimPrefix(a,b)];}
} else if(suffix === "suffix") {
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];};
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];}
} else {
if(operand === "") {
fnCalc = function(a) {return [$tw.utils.trim(a)];};
fnCalc = function(a) {return [$tw.utils.trim(a)];}
} else {
fnCalc = function(a,b) {return [$tw.utils.trimSuffix($tw.utils.trimPrefix(a,b),b)];};
fnCalc = function(a,b) {return [$tw.utils.trimSuffix($tw.utils.trimPrefix(a,b),b)];}
}
}
source(function(tiddler,title) {
@@ -71,53 +71,107 @@ exports.join = makeStringReducingOperator(
},null
);
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
exports.levenshtein = makeStringBinaryOperator(
function(a,b) {
const diffs = dmp.diffMain(a,b);
return [dmp.diffLevenshtein(diffs).toString()];
var dmpObject = new dmp.diff_match_patch(),
diffs = dmpObject.diff_main(a,b);
return [dmpObject.diff_levenshtein(diffs) + ""];
}
);
// this function is adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
function diffLineWordMode(text1,text2,mode) {
var a = $tw.utils.diffPartsToChars(text1,text2,mode);
var dmpObject = new dmp.diff_match_patch();
var a = diffPartsToChars(text1,text2,mode);
var lineText1 = a.chars1;
var lineText2 = a.chars2;
var lineArray = a.lineArray;
var diffs = dmp.diffMain(lineText1,lineText2,false);
dmp.diffCharsToLines(diffs,lineArray);
var diffs = dmpObject.diff_main(lineText1,lineText2,false);
dmpObject.diff_charsToLines_(diffs,lineArray);
return diffs;
}
function diffPartsToChars(text1,text2,mode) {
var lineArray = [];
var lineHash = {};
lineArray[0] = '';
function diff_linesToPartsMunge_(text,mode) {
var chars = '';
var lineStart = 0;
var lineEnd = -1;
var lineArrayLength = lineArray.length,
regexpResult;
var searchRegexp = /\W+/g;
while(lineEnd < text.length - 1) {
if(mode === "words") {
regexpResult = searchRegexp.exec(text);
lineEnd = searchRegexp.lastIndex;
if(regexpResult === null) {
lineEnd = text.length;
}
lineEnd = --lineEnd;
} else {
lineEnd = text.indexOf('\n', lineStart);
if(lineEnd == -1) {
lineEnd = text.length - 1;
}
}
var line = text.substring(lineStart, lineEnd + 1);
if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) {
chars += String.fromCharCode(lineHash[line]);
} else {
if(lineArrayLength == maxLines) {
line = text.substring(lineStart);
lineEnd = text.length;
}
chars += String.fromCharCode(lineArrayLength);
lineHash[line] = lineArrayLength;
lineArray[lineArrayLength++] = line;
}
lineStart = lineEnd + 1;
}
return chars;
}
var maxLines = 40000;
var chars1 = diff_linesToPartsMunge_(text1,mode);
maxLines = 65535;
var chars2 = diff_linesToPartsMunge_(text2,mode);
return {chars1: chars1, chars2: chars2, lineArray: lineArray};
};
exports.makepatches = function(source,operator,options) {
var suffix = operator.suffix || "",
var dmpObject = new dmp.diff_match_patch(),
suffix = operator.suffix || "",
result = [];
source(function(tiddler,title) {
let diffs, patches;
if(suffix === "lines" || suffix === "words") {
diffs = diffLineWordMode(title,operator.operand,suffix);
patches = dmp.patchMake(title,diffs);
} else {
patches = dmp.patchMake(title,operator.operand);
}
Array.prototype.push.apply(result,[dmp.patchToText(patches)]);
});
source(function(tiddler,title) {
var diffs, patches;
if(suffix === "lines" || suffix === "words") {
diffs = diffLineWordMode(title,operator.operand,suffix);
patches = dmpObject.patch_make(title,diffs);
} else {
patches = dmpObject.patch_make(title,operator.operand);
}
Array.prototype.push.apply(result,[dmpObject.patch_toText(patches)]);
});
return result;
};
exports.applypatches = makeStringBinaryOperator(
function(a,b) {
let patches;
var dmpObject = new dmp.diff_match_patch(),
patches;
try {
patches = dmp.patchFromText(b);
patches = dmpObject.patch_fromText(b);
} catch(e) {
}
if(patches) {
return [dmp.patchApply(patches,a)[0]];
return [dmpObject.patch_apply(patches,a)[0]];
} else {
return [a];
}
@@ -225,7 +279,7 @@ exports.pad = function(source,operator,options) {
}
});
return results;
};
}
exports.charcode = function(source,operator,options) {
var chars = [];

View File

@@ -11,16 +11,17 @@ The image parser parses an image into an embeddable HTML element
var ImageParser = function(type,text,options) {
var element = {
type: "image",
attributes: {}
};
type: "element",
tag: "img",
attributes: {}
};
if(options._canonical_uri) {
element.attributes.source = {type: "string", value: options._canonical_uri};
element.attributes.src = {type: "string", value: options._canonical_uri};
} else if(text) {
if(type === "image/svg+xml" || type === ".svg") {
element.attributes.source = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
element.attributes.src = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
} else {
element.attributes.source = {type: "string", value: "data:" + type + ";base64," + text};
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
}
this.tree = [element];

View File

@@ -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";
}

View File

@@ -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

View File

@@ -18,6 +18,7 @@ exports.synchronous = true;
// Default story and history lists
var PAGE_TITLE_TITLE = "$:/core/wiki/title";
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
var ROOT_STYLESHEET_TITLE = "$:/core/ui/RootStylesheet";
var PAGE_TEMPLATE_TITLE = "$:/core/ui/RootTemplate";
// Time (in ms) that we defer refreshing changes to draft tiddlers
@@ -44,22 +45,13 @@ exports.startup = function() {
publishTitle();
}
});
// Set up the styles
$tw.styleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_STYLESHEET_TITLE,{document: $tw.fakeDocument});
$tw.styleContainer = $tw.fakeDocument.createElement("style");
$tw.styleWidgetNode.render($tw.styleContainer,null);
$tw.styleWidgetNode.assignedStyles = $tw.styleContainer.textContent;
$tw.styleElement = document.createElement("style");
$tw.styleElement.innerHTML = $tw.styleWidgetNode.assignedStyles;
document.head.insertBefore($tw.styleElement,document.head.firstChild);
var styleParser = $tw.wiki.parseTiddler(ROOT_STYLESHEET_TITLE,{parseAsInline: true}),
styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: document});
styleWidgetNode.render(document.head,null);
$tw.wiki.addEventListener("change",$tw.perf.report("styleRefresh",function(changes) {
if($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {
var newStyles = $tw.styleContainer.textContent;
if(newStyles !== $tw.styleWidgetNode.assignedStyles) {
$tw.styleWidgetNode.assignedStyles = newStyles;
$tw.styleElement.innerHTML = $tw.styleWidgetNode.assignedStyles;
}
}
styleWidgetNode.refresh(changes,document.head,null);
}));
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
$tw.perf.report("mainRender",function() {
@@ -68,7 +60,7 @@ exports.startup = function() {
$tw.utils.addClass($tw.pageContainer,"tc-page-container-wrapper");
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
$tw.pageWidgetNode.render($tw.pageContainer,null);
$tw.hooks.invokeHook("th-page-refreshed");
$tw.hooks.invokeHook("th-page-refreshed");
})();
// Remove any splash screen elements
var removeList = document.querySelectorAll(".tc-remove-when-wiki-loaded");

View File

@@ -63,24 +63,16 @@ exports.startup = function() {
$tw.eventBus.emit("window:closed",{windowID});
},false);
// Set up the styles
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
document: $tw.fakeDocument,
variables: variables,
importPageMacros: true}),
styleContainer = $tw.fakeDocument.createElement("style");
styleWidgetNode.render(styleContainer,null);
var styleElement = srcDocument.createElement("style");
styleElement.innerHTML = styleContainer.textContent;
srcDocument.head.insertBefore(styleElement,srcDocument.head.firstChild);
var styleParser = $tw.wiki.parseTiddler("$:/core/ui/RootStylesheet",{parseAsInline: true}),
styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: srcDocument});
styleWidgetNode.render(srcDocument.head,null);
// Render the text of the tiddler
var parser = $tw.wiki.parseTiddler(template),
widgetNode = $tw.wiki.makeWidget(parser,{document: srcDocument, parentWidget: $tw.rootWidget, variables: variables});
widgetNode.render(srcDocument.body,srcDocument.body.firstChild);
// Function to handle refreshes
refreshHandler = function(changes) {
if(styleWidgetNode.refresh(changes,styleContainer,null)) {
styleElement.innerHTML = styleContainer.textContent;
}
styleWidgetNode.refresh(changes);
widgetNode.refresh(changes);
};
$tw.wiki.addEventListener("change",refreshHandler);

View File

@@ -1,31 +0,0 @@
/*\
title: $:/core/modules/utils/base64.js
type: application/javascript
module-type: utils-browser
Base64 utility functions
\*/
"use strict";
/*
Base64 utility functions that work in either browser or Node.js
*/
exports.btoa = binstr => window.btoa(binstr);
exports.atob = b64 => window.atob(b64);
function base64ToBytes(base64) {
const binString = exports.atob(base64);
return Uint8Array.from(binString, m => m.codePointAt(0));
};
function bytesToBase64(bytes) {
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
return exports.btoa(binString);
};
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));

View File

@@ -44,15 +44,15 @@ exports.domMatchesSelector = (node,selector) => node.matches(selector);
exports.hasClass = (el,className) => el.classList && el.classList.contains(className);
exports.addClass = function(el,className) {
el.classList && className && el.classList.add(className);
el.classList && el.classList.add(className);
};
exports.removeClass = function(el,className) {
el.classList && className && el.classList.remove(className);
el.classList && el.classList.remove(className);
};
exports.toggleClass = function(el,className,status) {
el.classList && className && el.classList.toggle(className, status);
el.classList && el.classList.toggle(className, status);
};
exports.getLocationPath = () => window.location.origin + window.location.pathname;

File diff suppressed because one or more lines are too long

View File

@@ -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: theres 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;
};
})();

View File

@@ -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);

View File

@@ -55,7 +55,7 @@ Return the dflt (default) parameter if str is not a base-10 number.
exports.getInt = function(str,deflt) {
var i = parseInt(str,10);
return isNaN(i) ? deflt : i;
};
}
/*
Repeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string
@@ -69,12 +69,12 @@ exports.replaceString = function(text,search,replace) {
exports.trimPrefix = function(str,unwanted) {
if(typeof str === "string" && typeof unwanted === "string") {
if(unwanted === "") {
return str.replace(/^\s\s*/, "");
return str.replace(/^\s\s*/, '');
} else {
// Safely regexp-escape the unwanted text
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
var regex = new RegExp("^(" + unwanted + ")+");
return str.replace(regex, "");
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('^(' + unwanted + ')+');
return str.replace(regex, '');
}
} else {
return str;
@@ -84,12 +84,12 @@ exports.trimPrefix = function(str,unwanted) {
exports.trimSuffix = function(str,unwanted) {
if(typeof str === "string" && typeof unwanted === "string") {
if(unwanted === "") {
return str.replace(/\s\s*$/, "");
return str.replace(/\s\s*$/, '');
} else {
// Safely regexp-escape the unwanted text
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
var regex = new RegExp("(" + unwanted + ")+$");
return str.replace(regex, "");
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('(' + unwanted + ')+$');
return str.replace(regex, '');
}
} else {
return str;
@@ -101,14 +101,14 @@ Convert a string to sentence case (ie capitalise first letter)
*/
exports.toSentenceCase = function(str) {
return (str || "").replace(/^\S/, function(c) {return c.toUpperCase();});
};
}
/*
Convert a string to title case (ie capitalise each initial letter)
*/
exports.toTitleCase = function(str) {
return (str || "").replace(/(^|\s)\S/g, function(c) {return c.toUpperCase();});
};
}
/*
Find the line break preceding a given position in a string
@@ -358,8 +358,8 @@ exports.formatDateString = function(date,template) {
}],
[/^TZD/, function() {
var tz = date.getTimezoneOffset(),
atz = Math.abs(tz);
return (tz < 0 ? "+" : "-") + $tw.utils.pad(Math.floor(atz / 60)) + ":" + $tw.utils.pad(atz % 60);
atz = Math.abs(tz);
return (tz < 0 ? '+' : '-') + $tw.utils.pad(Math.floor(atz / 60)) + ':' + $tw.utils.pad(atz % 60);
}],
[/^wYY/, function() {
return $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);
@@ -568,9 +568,9 @@ exports.unescapeLineBreaks = function(s) {
exports.escape = function(ch) {
var charCode = ch.charCodeAt(0);
if(charCode <= 0xFF) {
return "\\x" + $tw.utils.pad(charCode.toString(16).toUpperCase());
return '\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());
} else {
return "\\u" + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
return '\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
}
};
@@ -587,11 +587,11 @@ exports.stringify = function(s, rawUnicode) {
*/
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
return (s || "")
.replace(/\\/g, "\\\\") // backslash
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // double quote character
.replace(/'/g, "\\'") // single quote character
.replace(/\r/g, "\\r") // carriage return
.replace(/\n/g, "\\n") // line feed
.replace(/\r/g, '\\r') // carriage return
.replace(/\n/g, '\\n') // line feed
.replace(regex, exports.escape); // non-ASCII characters
};
@@ -601,15 +601,15 @@ exports.jsonStringify = function(s, rawUnicode) {
// See http://www.json.org/
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
return (s || "")
.replace(/\\/g, "\\\\") // backslash
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // double quote character
.replace(/\r/g, "\\r") // carriage return
.replace(/\n/g, "\\n") // line feed
.replace(/\x08/g, "\\b") // backspace
.replace(/\x0c/g, "\\f") // formfeed
.replace(/\t/g, "\\t") // tab
.replace(/\r/g, '\\r') // carriage return
.replace(/\n/g, '\\n') // line feed
.replace(/\x08/g, '\\b') // backspace
.replace(/\x0c/g, '\\f') // formfeed
.replace(/\t/g, '\\t') // tab
.replace(regex,function(s) {
return "\\u" + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
return '\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
}); // non-ASCII characters
};
@@ -617,7 +617,7 @@ exports.jsonStringify = function(s, rawUnicode) {
Escape the RegExp special characters with a preceding backslash
*/
exports.escapeRegExp = function(s) {
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, "\\$&");
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
};
/*
@@ -700,7 +700,7 @@ exports.parseTextReference = function(textRef) {
}
} else {
// If we couldn't parse it
result.title = textRef;
result.title = textRef
}
return result;
};
@@ -759,17 +759,60 @@ Cryptographic hash function as used by sha256 filter operator
options.length .. number of characters returned defaults to 64
*/
exports.sha256 = function(str, options) {
options = options || {};
options = options || {}
return $tw.sjcl.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(str)).substr(0,options.length || 64);
}
/*
Base64 utility functions that work in either browser or Node.js
*/
if(typeof window !== 'undefined') {
exports.btoa = function(binstr) { return window.btoa(binstr); }
exports.atob = function(b64) { return window.atob(b64); }
} else {
exports.btoa = function(binstr) {
return Buffer.from(binstr, 'binary').toString('base64');
}
exports.atob = function(b64) {
return Buffer.from(b64, 'base64').toString('binary');
}
}
exports.base64ToBytes = function(base64) {
const binString = exports.atob(base64);
return Uint8Array.from(binString, (m) => m.codePointAt(0));
};
exports.bytesToBase64 = function(bytes) {
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
return exports.btoa(binString);
};
exports.base64EncodeUtf8 = function(str) {
if ($tw.browser) {
return exports.bytesToBase64(new TextEncoder().encode(str));
} else {
const buff = Buffer.from(str, "utf-8");
return buff.toString("base64");
}
};
exports.base64DecodeUtf8 = function(str) {
if ($tw.browser) {
return new TextDecoder().decode(exports.base64ToBytes(str));
} else {
const buff = Buffer.from(str, "base64");
return buff.toString("utf-8");
}
};
/*
Decode a base64 string
*/
exports.base64Decode = function(string64,binary,urlsafe) {
const encoded = urlsafe ? string64.replace(/_/g,"/").replace(/-/g,"+") : string64;
if(binary) return $tw.utils.atob(encoded);
else return $tw.utils.base64DecodeUtf8(encoded);
const encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
if(binary) return exports.atob(encoded)
else return exports.base64DecodeUtf8(encoded);
};
/*
@@ -777,10 +820,10 @@ Encode a string to base64
*/
exports.base64Encode = function(string64,binary,urlsafe) {
let encoded;
if(binary) encoded = $tw.utils.btoa(string64);
else encoded = $tw.utils.base64EncodeUtf8(string64);
if(binary) encoded = exports.btoa(string64);
else encoded = exports.base64EncodeUtf8(string64);
if(urlsafe) {
encoded = encoded.replace(/\+/g,"-").replace(/\//g,"_");
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
}
return encoded;
};
@@ -914,56 +957,3 @@ exports.makeCompareFunction = function(type,options) {
};
return (types[type] || types[options.defaultType] || types.number);
};
/*
Split text into parts (lines or words) for diff operations
Adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
*/
exports.diffPartsToChars = function(text1,text2,mode) {
const lineArray = [""],
lineHash = Object.create(null);
function diff_linesToPartsMunge_(text,mode) {
let chars = "",
lineStart = 0,
lineEnd = -1,
lineArrayLength = lineArray.length,
regexpResult;
const searchRegexp = /\W+/g;
while(lineEnd < text.length - 1) {
if(mode === "words") {
regexpResult = searchRegexp.exec(text);
lineEnd = searchRegexp.lastIndex;
if(regexpResult === null) {
lineEnd = text.length;
}
lineEnd = --lineEnd;
} else {
lineEnd = text.indexOf("\n", lineStart);
if(lineEnd === -1) {
lineEnd = text.length - 1;
}
}
let line = text.substring(lineStart, lineEnd + 1);
if(line in lineHash) {
chars += String.fromCharCode(lineHash[line]);
} else {
if(lineArrayLength === maxLines) {
line = text.substring(lineStart);
lineEnd = text.length;
}
chars += String.fromCharCode(lineArrayLength);
lineHash[line] = lineArrayLength;
lineArray[lineArrayLength++] = line;
}
lineStart = lineEnd + 1;
}
return chars;
}
let maxLines = 40000;
const chars1 = diff_linesToPartsMunge_(text1,mode);
maxLines = 65535;
const chars2 = diff_linesToPartsMunge_(text2,mode);
return {chars1, chars2, lineArray};
};

View File

@@ -9,8 +9,6 @@ Button widget
"use strict";
const ALLOWED_SELECTED_ARIA_ATTR = ["aria-checked", "aria-selected", "aria-pressed"];
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
@@ -46,14 +44,9 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
var classes = this["class"].split(" ") || [],
isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();
if(this.selectedClass) {
if((this.set || this.setTitle) && this.setTo) {
const selectedAria = ALLOWED_SELECTED_ARIA_ATTR.includes(this.selectedAria) ? this.selectedAria : "aria-checked";
if(this.isSelected()) {
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
domNode.setAttribute(selectedAria, "true");
} else {
domNode.setAttribute(selectedAria, "false");
}
if((this.set || this.setTitle) && this.setTo && this.isSelected()) {
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
domNode.setAttribute("aria-checked", "true");
}
if(isPoppedUp) {
$tw.utils.pushTop(classes,this.selectedClass.split(" "));
@@ -228,7 +221,6 @@ ButtonWidget.prototype.execute = function() {
this.style = this.getAttribute("style");
this["class"] = this.getAttribute("class","");
this.selectedClass = this.getAttribute("selectedClass");
this.selectedAria = this.getAttribute("selectedAria");
this.defaultSetValue = this.getAttribute("default","");
this.buttonTag = this.getAttribute("tag");
this.dragTiddler = this.getAttribute("dragTiddler");

View File

@@ -9,8 +9,8 @@ Widget to display a diff between two texts
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
var Widget = require("$:/core/modules/widgets/widget.js").widget,
dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
var DiffTextWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
@@ -35,24 +35,19 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
this.computeAttributes();
this.execute();
// Create the diff object
const editCost = $tw.utils.parseNumber(this.getAttribute("editcost","4"));
const mode = this.getAttribute("mode") || "chars";
let diffs;
if(mode === "lines" || mode === "words") {
diffs = diffLineWordMode(this.getAttribute("source",""),this.getAttribute("dest",""),mode,editCost);
} else {
diffs = dmp.diffMain(this.getAttribute("source",""),this.getAttribute("dest",""),{diffEditCost: editCost});
}
var dmpObject = new dmp.diff_match_patch();
dmpObject.Diff_EditCost = $tw.utils.parseNumber(this.getAttribute("editcost","4"));
var diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
// Apply required cleanup
switch(this.getAttribute("cleanup","semantic")) {
case "none":
// No cleanup
break;
case "efficiency":
dmp.diffCleanupEfficiency(diffs, {diffEditCost: editCost});
dmpObject.diff_cleanupEfficiency(diffs);
break;
default: // case "semantic"
dmp.diffCleanupSemantic(diffs);
dmpObject.diff_cleanupSemantic(diffs);
break;
}
// Create the elements
@@ -138,7 +133,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/
DiffTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup || changedAttributes.mode || changedAttributes.editcost) {
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup || changedAttributes.editcost) {
this.refreshSelf();
return true;
} else {
@@ -146,15 +141,4 @@ DiffTextWidget.prototype.refresh = function(changedTiddlers) {
}
};
// This function is adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
function diffLineWordMode(text1,text2,mode,editCost) {
var a = $tw.utils.diffPartsToChars(text1,text2,mode);
var lineText1 = a.chars1;
var lineText2 = a.chars2;
var lineArray = a.lineArray;
var diffs = dmp.diffMain(lineText1,lineText2,{diffEditCost: editCost});
dmp.diffCharsToLines(diffs,lineArray);
return diffs;
}
exports["diff-text"] = DiffTextWidget;

View File

@@ -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] || "",

View File

@@ -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 {

View File

@@ -9,215 +9,376 @@ View widget
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var ViewWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
const Widget = require("$:/core/modules/widgets/widget.js").widget;
/*
Inherit from the base widget class
==========================================
ViewHandler Base Class
==========================================
Base class for all view format handlers.
Provides common functionality and defines the interface for subclasses.
*/
ViewWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ViewWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
if(this.text) {
var textNode = this.document.createTextNode(this.text);
parent.insertBefore(textNode,nextSibling);
this.domNodes.push(textNode);
} else {
this.makeChildWidgets();
this.renderChildren(parent,nextSibling);
class ViewHandler {
constructor(widget) {
this.widget = widget;
this.wiki = widget.wiki;
this.document = widget.document;
this.viewTitle = widget.viewTitle;
this.viewField = widget.viewField;
this.viewIndex = widget.viewIndex;
this.viewSubtiddler = widget.viewSubtiddler;
this.viewTemplate = widget.viewTemplate;
this.viewMode = widget.viewMode;
}
};
/*
Compute the internal state of the widget
*/
ViewWidget.prototype.execute = function() {
// Get parameters from our attributes
this.viewTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
this.viewSubtiddler = this.getAttribute("subtiddler");
this.viewField = this.getAttribute("field","text");
this.viewIndex = this.getAttribute("index");
this.viewFormat = this.getAttribute("format","text");
this.viewTemplate = this.getAttribute("template","");
this.viewMode = this.getAttribute("mode","block");
switch(this.viewFormat) {
case "htmlwikified":
this.text = this.getValueAsHtmlWikified(this.viewMode);
break;
case "plainwikified":
this.text = this.getValueAsPlainWikified(this.viewMode);
break;
case "htmlencodedplainwikified":
this.text = this.getValueAsHtmlEncodedPlainWikified(this.viewMode);
break;
case "htmlencoded":
this.text = this.getValueAsHtmlEncoded();
break;
case "htmltextencoded":
this.text = this.getValueAsHtmlTextEncoded();
break;
case "urlencoded":
this.text = this.getValueAsUrlEncoded();
break;
case "doubleurlencoded":
this.text = this.getValueAsDoubleUrlEncoded();
break;
case "date":
this.text = this.getValueAsDate(this.viewTemplate);
break;
case "relativedate":
this.text = this.getValueAsRelativeDate();
break;
case "stripcomments":
this.text = this.getValueAsStrippedComments();
break;
case "jsencoded":
this.text = this.getValueAsJsEncoded();
break;
default: // "text"
this.text = this.getValueAsText();
break;
render(parent, nextSibling) {
this.text = this.getValue();
this.createTextNode(parent, nextSibling);
}
};
/*
The various formatter functions are baked into this widget for the moment. Eventually they will be replaced by macro functions
*/
getValue() {
return this.widget.getValueAsText();
}
/*
Retrieve the value of the widget. Options are:
asString: Optionally return the value as a string
*/
ViewWidget.prototype.getValue = function(options) {
options = options || {};
var value = options.asString ? "" : undefined;
if(this.viewIndex) {
value = this.wiki.extractTiddlerDataItem(this.viewTitle,this.viewIndex);
} else {
var tiddler;
if(this.viewSubtiddler) {
tiddler = this.wiki.getSubTiddler(this.viewTitle,this.viewSubtiddler);
createTextNode(parent, nextSibling) {
if(this.text) {
const textNode = this.document.createTextNode(this.text);
parent.insertBefore(textNode, nextSibling);
this.widget.domNodes.push(textNode);
} else {
tiddler = this.wiki.getTiddler(this.viewTitle);
}
if(tiddler) {
if(this.viewField === "text" && !this.viewSubtiddler) {
// Calling getTiddlerText() triggers lazy loading of skinny tiddlers
value = this.wiki.getTiddlerText(this.viewTitle);
} else {
if($tw.utils.hop(tiddler.fields,this.viewField)) {
if(options.asString) {
value = tiddler.getFieldString(this.viewField);
} else {
value = tiddler.fields[this.viewField];
}
}
}
} else {
if(this.viewField === "title") {
value = this.viewTitle;
}
this.widget.makeChildWidgets();
this.widget.renderChildren(parent, nextSibling);
}
}
return value;
};
ViewWidget.prototype.getValueAsText = function() {
return this.getValue({asString: true});
};
ViewWidget.prototype.getValueAsHtmlWikified = function(mode) {
return this.wiki.renderText("text/html","text/vnd.tiddlywiki",this.getValueAsText(),{
parseAsInline: mode !== "block",
parentWidget: this
});
};
ViewWidget.prototype.getValueAsPlainWikified = function(mode) {
return this.wiki.renderText("text/plain","text/vnd.tiddlywiki",this.getValueAsText(),{
parseAsInline: mode !== "block",
parentWidget: this
});
};
ViewWidget.prototype.getValueAsHtmlEncodedPlainWikified = function(mode) {
return $tw.utils.htmlEncode(this.wiki.renderText("text/plain","text/vnd.tiddlywiki",this.getValueAsText(),{
parseAsInline: mode !== "block",
parentWidget: this
}));
};
ViewWidget.prototype.getValueAsHtmlEncoded = function() {
return $tw.utils.htmlEncode(this.getValueAsText());
};
ViewWidget.prototype.getValueAsHtmlTextEncoded = function() {
return $tw.utils.htmlTextEncode(this.getValueAsText());
};
ViewWidget.prototype.getValueAsUrlEncoded = function() {
return $tw.utils.encodeURIComponentExtended(this.getValueAsText());
};
ViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {
return $tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.getValueAsText()));
};
ViewWidget.prototype.getValueAsDate = function(format) {
format = format || "YYYY MM DD 0hh:0mm";
var value = $tw.utils.parseDate(this.getValue());
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
return $tw.utils.formatDateString(value,format);
} else {
return "";
}
};
ViewWidget.prototype.getValueAsRelativeDate = function(format) {
var value = $tw.utils.parseDate(this.getValue());
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
return $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;
} else {
return "";
}
};
ViewWidget.prototype.getValueAsStrippedComments = function() {
var lines = this.getValueAsText().split("\n"),
out = [];
for(var line=0; line<lines.length; line++) {
var text = lines[line];
if(!/^\s*\/\/#/.test(text)) {
out.push(text);
}
}
return out.join("\n");
};
ViewWidget.prototype.getValueAsJsEncoded = function() {
return $tw.utils.stringify(this.getValueAsText());
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ViewWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {
this.refreshSelf();
return true;
} else {
refresh() {
var self = this;
return false;
}
}
/*
==========================================
Wikified View Handler Base
==========================================
Base class for wikified view handlers
*/
class WikifiedViewHandler extends ViewHandler {
constructor(widget) {
super(widget);
this.fakeWidget = null;
this.fakeNode = null;
}
render(parent, nextSibling) {
this.createFakeWidget();
this.text = this.getValue();
this.createWikifiedTextNode(parent, nextSibling);
}
createFakeWidget() {
this.fakeWidget = this.wiki.makeTranscludeWidget(this.viewTitle, {
document: $tw.fakeDocument,
field: this.viewField,
index: this.viewIndex,
parseAsInline: this.viewMode !== "block",
mode: this.viewMode === "block" ? "block" : "inline",
parentWidget: this.widget,
subTiddler: this.viewSubtiddler
});
this.fakeNode = $tw.fakeDocument.createElement("div");
this.fakeWidget.makeChildWidgets();
this.fakeWidget.render(this.fakeNode, null);
}
createWikifiedTextNode(parent, nextSibling) {
const textNode = this.document.createTextNode(this.text || "");
parent.insertBefore(textNode, nextSibling);
this.widget.domNodes.push(textNode);
}
refresh(changedTiddlers) {
const refreshed = this.fakeWidget.refresh(changedTiddlers);
if(refreshed) {
const newText = this.getValue();
if(newText !== this.text) {
this.widget.domNodes[0].textContent = newText;
this.text = newText;
}
}
return refreshed;
}
}
/*
==========================================
Text View Handler
==========================================
Default handler for plain text display
*/
class TextViewHandler extends ViewHandler {}
/*
==========================================
HTML Wikified View Handler
==========================================
Handler for wikified HTML content
*/
class HTMLWikifiedViewHandler extends WikifiedViewHandler {
getValue() {
return this.fakeNode.innerHTML;
}
}
/*
==========================================
Plain Wikified View Handler
==========================================
Handler for wikified plain text content
*/
class PlainWikifiedViewHandler extends WikifiedViewHandler {
getValue() {
return this.fakeNode.textContent;
}
}
/*
==========================================
HTML Encoded Plain Wikified View Handler
==========================================
Handler for HTML-encoded wikified plain text
*/
class HTMLEncodedPlainWikifiedViewHandler extends WikifiedViewHandler {
getValue() {
return $tw.utils.htmlEncode(this.fakeNode.textContent);
}
}
/*
==========================================
HTML Encoded View Handler
==========================================
Handler for HTML-encoded text
*/
class HTMLEncodedViewHandler extends ViewHandler {
getValue() {
return $tw.utils.htmlEncode(this.widget.getValueAsText());
}
}
/*
==========================================
HTML Text Encoded View Handler
==========================================
Handler for HTML text-encoded content
*/
class HTMLTextEncodedViewHandler extends ViewHandler {
getValue() {
return $tw.utils.htmlTextEncode(this.widget.getValueAsText());
}
}
/*
==========================================
URL Encoded View Handler
==========================================
Handler for URL-encoded text
*/
class URLEncodedViewHandler extends ViewHandler {
getValue() {
return $tw.utils.encodeURIComponentExtended(this.widget.getValueAsText());
}
}
/*
==========================================
Double URL Encoded View Handler
==========================================
Handler for double URL-encoded text
*/
class DoubleURLEncodedViewHandler extends ViewHandler {
getValue() {
const text = this.widget.getValueAsText();
return $tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(text));
}
}
/*
==========================================
Date View Handler
==========================================
Handler for date formatting
*/
class DateViewHandler extends ViewHandler {
getValue() {
const format = this.viewTemplate || "YYYY MM DD 0hh:0mm";
const rawValue = this.widget.getValueAsText();
const value = $tw.utils.parseDate(rawValue);
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
return $tw.utils.formatDateString(value, format);
} else {
return "";
}
}
}
/*
==========================================
Relative Date View Handler
==========================================
Handler for relative date display
*/
class RelativeDateViewHandler extends ViewHandler {
getValue() {
const rawValue = this.widget.getValueAsText();
const value = $tw.utils.parseDate(rawValue);
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
return $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;
} else {
return "";
}
}
}
/*
==========================================
Strip Comments View Handler
==========================================
Handler for stripping comments from text
*/
class StripCommentsViewHandler extends ViewHandler {
getValue() {
const lines = this.widget.getValueAsText().split("\n");
const out = [];
for(const text of lines) {
if(!/^\s*\/\/#/.test(text)) {
out.push(text);
}
}
return out.join("\n");
}
}
/*
==========================================
JS Encoded View Handler
==========================================
Handler for JavaScript string encoding
*/
class JSEncodedViewHandler extends ViewHandler {
getValue() {
return $tw.utils.stringify(this.widget.getValueAsText());
}
}
/*
==========================================
ViewHandlerFactory
==========================================
Factory for creating appropriate view handlers based on format
*/
const ViewHandlerFactory = {
handlers: {
"text": TextViewHandler,
"htmlwikified": HTMLWikifiedViewHandler,
"plainwikified": PlainWikifiedViewHandler,
"htmlencodedplainwikified": HTMLEncodedPlainWikifiedViewHandler,
"htmlencoded": HTMLEncodedViewHandler,
"htmltextencoded": HTMLTextEncodedViewHandler,
"urlencoded": URLEncodedViewHandler,
"doubleurlencoded": DoubleURLEncodedViewHandler,
"date": DateViewHandler,
"relativedate": RelativeDateViewHandler,
"stripcomments": StripCommentsViewHandler,
"jsencoded": JSEncodedViewHandler
},
createHandler(format, widget) {
const HandlerClass = this.handlers[format] || this.handlers["text"];
return new HandlerClass(widget);
},
registerHandler(format, handlerClass) {
this.handlers[format] = handlerClass;
}
};
exports.view = ViewWidget;
/*
==========================================
ViewWidget
==========================================
Main widget class that orchestrates view handlers
*/
class ViewWidget extends Widget {
constructor(parseTreeNode, options) {
super();
this.initialise(parseTreeNode, options);
}
render(parent, nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
this.viewHandler = ViewHandlerFactory.createHandler(this.viewFormat, this);
this.viewHandler.render(parent, nextSibling);
}
execute() {
this.viewTitle = this.getAttribute("tiddler", this.getVariable("currentTiddler"));
this.viewSubtiddler = this.getAttribute("subtiddler");
this.viewField = this.getAttribute("field", "text");
this.viewIndex = this.getAttribute("index");
this.viewFormat = this.getAttribute("format", "text");
this.viewTemplate = this.getAttribute("template", "");
this.viewMode = this.getAttribute("mode", "block");
}
getValue(options = {}) {
let value = options.asString ? "" : undefined;
if(this.viewIndex) {
value = this.wiki.extractTiddlerDataItem(this.viewTitle, this.viewIndex);
} else {
let tiddler;
if(this.viewSubtiddler) {
tiddler = this.wiki.getSubTiddler(this.viewTitle, this.viewSubtiddler);
} else {
tiddler = this.wiki.getTiddler(this.viewTitle);
}
if(tiddler) {
if(this.viewField === "text" && !this.viewSubtiddler) {
value = this.wiki.getTiddlerText(this.viewTitle);
} else {
if($tw.utils.hop(tiddler.fields, this.viewField)) {
if(options.asString) {
value = tiddler.getFieldString(this.viewField);
} else {
value = tiddler.fields[this.viewField];
}
}
}
} else {
if(this.viewField === "title") {
value = this.viewTitle;
}
}
}
return value;
}
getValueAsText() {
return this.getValue({asString: true});
}
refresh(changedTiddlers) {
const changedAttributes = this.computeAttributes();
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index ||
changedAttributes.template || changedAttributes.format || changedTiddlers[this.viewTitle]) {
this.refreshSelf();
return true;
} else {
return this.viewHandler.refresh(changedTiddlers);
}
}
}
exports.view = ViewWidget;

View File

@@ -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 {

View File

@@ -369,16 +369,31 @@ Sort an array of tiddler titles by a specified field
isDescending: true if the sort should be descending
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
*/
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric,locale) {
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {
var self = this;
if(sortField === "title") {
if(!isNumeric && !isAlphaNumeric) {
const sorter = new Intl.Collator(locale, { sensitivity: isCaseSensitive ? "variant" : "accent" });
if(isDescending) {
titles.sort((a,b) => sorter.compare(b, a));
if(isCaseSensitive) {
if(isDescending) {
titles.sort(function(a,b) {
return b.localeCompare(a);
});
} else {
titles.sort(function(a,b) {
return a.localeCompare(b);
});
}
} else {
titles.sort((a,b) => sorter.compare(a, b));
}
if(isDescending) {
titles.sort(function(a,b) {
return b.toLowerCase().localeCompare(a.toLowerCase());
});
} else {
titles.sort(function(a,b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
}
}
} else {
titles.sort(function(a,b) {
var x,y;
@@ -399,8 +414,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
}
}
}
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
if(isAlphaNumeric) {
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
}
if(!isCaseSensitive) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
});
}
} else {
@@ -442,8 +463,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
}
a = String(a);
b = String(b);
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
if(isAlphaNumeric) {
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
}
if(!isCaseSensitive) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
});
}
};

View File

@@ -25,6 +25,7 @@ title: $:/core/templates/tiddlywiki5.html
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}
{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}
{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
<!--~~ Style section start ~~-->
</head>
<body class="tc-body">
<!--~~ Raw markup for the top of the body section ~~-->

View File

@@ -1,7 +1,7 @@
title: $:/core/ui/PageTemplate/alerts
tags: $:/tags/PageTemplate
<div class="tc-alerts" role="region" aria-label={{$:/language/Alerts}}>
<div class="tc-alerts" role="region" aria-label="Alerts">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Alert]!is[draft]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>

View File

@@ -0,0 +1,15 @@
title: $:/core/ui/RootStylesheet
code-body: yes
\import [subfilter{$:/core/config/GlobalImportFilter}]
\whitespace trim
<$let currentTiddler={{$:/language}} languageTitle={{!!name}}>
<style type="text/css">
<$view tiddler="$:/themes/tiddlywiki/vanilla/reset" format="text" mode="block"/>
</style>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Stylesheet]!is[draft]] -[[$:/themes/tiddlywiki/vanilla/reset]]">
<style type="text/css">
<$view format={{{ [<currentTiddler>tag[$:/tags/Stylesheet/Static]then[text]else[plainwikified]] }}} mode="block"/>
</style>
</$list>
</$let>

View File

@@ -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$

View File

@@ -2,7 +2,7 @@ title: $:/core/ui/TiddlerInfo
\whitespace trim
<div style="position:relative;">
<div class="tc-tiddler-controls tc-tiddler-info-controls">
<div class="tc-tiddler-controls" style="position:absolute;right:0;">
<$reveal state="$:/config/TiddlerInfo/Mode" type="match" text="sticky">
<$button set=<<tiddlerInfoState>> setTo="" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class="tc-btn-invisible">
{{$:/core/images/close-button}}

View File

@@ -11,13 +11,9 @@ tags: $:/tags/ViewTemplate
storyview="pop"
variable="listItem"
>
<$let condition={{{ [<listItem>get[condition]] }}}>
<%if [<condition>!is[blank]] :and[<currentTiddler>subfilter<condition>limit[1]] :else[<condition>is[blank]then[true]] %>
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
<$transclude tiddler=<<listItem>>/>
</$set>
<%endif%>
</$let>
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
<$transclude tiddler=<<listItem>>/>
</$set>
</$list>
</span>
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>

View File

@@ -41,8 +41,6 @@ Drag this link to copy this tool to another wiki
</$wikify>
\end capture-item-wikified
\function get.shadow.source() [shadowsource[]]
\procedure capture-wiki-info(tempWikiInfo)
<$transclude $variable="capture-item-wikified" label="TiddlyWiki Version" value="<<version>>"/>
<$transclude $variable="capture-item" label="Current palette" value={{$:/palette}}/>
@@ -66,7 +64,6 @@ Drag this link to copy this tool to another wiki
<$transclude $variable="capture-item" label="Keyboard shortcuts that have been customised" value={{{ [all[tiddlers]prefix[$:/config/shortcuts]] +[join[,]] }}}/>
<$transclude $variable="capture-item" label="Disabled plugins" value={{{ [all[tiddlers]prefix[$:/config/Plugins/Disabled/]] :filter[{!!text}match[yes]] :map[<currentTiddler>removeprefix[$:/config/Plugins/Disabled/]] +[join[,]] }}}/>
<$transclude $variable="capture-item" label="Plugins" value={{{ [has[plugin-type]sort[]] :filter[<currentTiddler>addprefix[$:/config/Plugins/Disabled/]get[text]else[no]!match[yes]] :map[{!!version}addprefix[ - ]addprefix<currentTiddler>] +[addprefix[ ]addprefix<crlf>join[]] }}}/>
<$transclude $variable="capture-item" label="Stylesheets" value={{{ [all[shadows+tiddlers]tag[$:/tags/Stylesheet]!is[draft]] :map[is[shadow]addsuffix[ ∈ ]addsuffix<get.shadow.source>else<currentTiddler>] +[addprefix[ ]addprefix<crlf>join[]] }}}/>
\end capture-wiki-info
\procedure template-header()

View File

@@ -1,39 +0,0 @@
title: $:/core/macros/CSS/property
<!-- CSS property macros -->
<!-- TODO: Deprecate the following CSS macros once 2020 baseline is supported -->
\procedure margin-start(size)
-webkit-margin-start: <<size>>;
margin-inline-start: <<size>>;
\end
\procedure margin-end(size)
-webkit-margin-end: <<size>>;
margin-inline-end: <<size>>;
\end
\procedure padding-start(size)
-webkit-padding-start: <<size>>;
padding-inline-start: <<size>>;
\end
\procedure padding-end(size)
-webkit-padding-end: <<size>>;
padding-inline-end: <<size>>;
\end
\procedure margin-inline(start,end)
-webkit-margin-start: <<start>>;
margin-inline-start: <<start>>;
-webkit-margin-end: <<end>>;
margin-inline-end: <<end>>;
\end
\procedure padding-inline(start,end)
-webkit-padding-start: <<start>>;
padding-inline-start: <<start>>;
-webkit-padding-end: <<end>>;
padding-inline-end: <<end>>;
\end

View File

@@ -22,7 +22,7 @@ tags: $:/tags/Macro
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
\end
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate, displayField:"caption")
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate)
\whitespace trim
<$set name="_tiddler" value="""$tiddler$""" emptyValue=<<currentTiddler>> >
<$let field-reference={{{ [<_tiddler>] "!!" [[$field$]] +[join[]] }}}
@@ -42,7 +42,7 @@ tags: $:/tags/Macro
<$transclude tiddler="""$itemTemplate$""">
<$link to={{!!title}}>
<$let tv-wikilinks="no">
<$transclude field=<<__displayField__>>>
<$transclude field="caption">
<$view field="title"/>
</$transclude>
</$let>
@@ -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:"")
\whitespace trim
<span class="tc-tagged-draggable-list">
<$set name="tag" value=<<__tag__>>>
@@ -110,11 +110,7 @@ tags: $:/tags/Macro
<$genesis $type=<<__elementTag__>>>
<$transclude tiddler="""$itemTemplate$""">
<$link to={{!!title}}>
<$let tv-wikilinks="no">
<$transclude field=<<__displayField__>>>
<$view field="title"/>
</$transclude>
</$let>
<$view field="title"/>
</$link>
</$transclude>
</$genesis>

View File

@@ -9,9 +9,8 @@ code-body: yes
setTo=<<currentTab>>
default=<<__default__>>
selectedClass="tc-tab-selected"
selectedAria="aria-selected"
tooltip={{!!tooltip}}
role="tab"
role="switch"
data-tab-title=<<currentTab>>
>
<$tiddler tiddler=<<save-currentTiddler>>>
@@ -58,12 +57,12 @@ code-body: yes
\whitespace trim
<$qualify title=<<__state__>> name="qualifiedState">
<$let tabsState={{{ [<__explicitState__>minlength[1]] ~[<qualifiedState>] }}}>
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}} role="tablist">
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}}>
<div class={{{ [[tc-tab-buttons]addsuffix[ ]addsuffix<__class__>] }}}>
<<tabs-tab-list>>
</div>
<div class={{{ [[tc-tab-divider]addsuffix[ ]addsuffix<__class__>] }}}/>
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}} role="tabpanel">
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}}>
<<tabs-tab-body>>
</div>
</div>

View File

@@ -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}}

View File

@@ -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"""/}
)

View File

@@ -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}}/>

View File

@@ -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<<:>>

View File

@@ -0,0 +1,17 @@
caption: savetiddlers
color: #4DB6AC
community-author: Buggyj
created: 20171109171935039
delivery: Browser Extension
description: Extension pour les navigateurs Chrome et Firefox
fr-title:
method: save
modified: 20220402105820520
tags: Chrome Firefox Saving [[Other Resources]] plugins
title: "savetiddlers" Extension for Chrome and Firefox by buggyj
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Une extension pour Google Chrome et Mozilla Firefox qui fluidifie l'utilisation de [[l'enregistreur HTML5 par défaut|Saving with the HTML5 fallback saver]] de <<tw>>, et le rend presque aussi convivial que ~TiddlyFox une fois configurée.
https://github.com/buggyj/savetiddlers

View File

@@ -1,17 +0,0 @@
caption: savetiddlers
color: #4DB6AC
community-author: buggyj
created: 20171109171935039
delivery: Browser Extension
description: Extension pour les navigateur Firefox
fr-title:
method: save
modified: 20250809092435788
tags: Firefox Saving [[Other Resources]] plugins
title: savetiddlers: Extension for Firefox by buggyj
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Une extension Mozilla Firefox qui fluidifie l'utilisation de [[l'enregistreur HTML5 par défaut|Saving with the HTML5 fallback saver]] de <<tw>>, et le rend presque aussi convivial que [[TiddlyFox]] une fois configurée.
{{!!url}}

View File

@@ -0,0 +1,18 @@
caption: savetiddlers
color: #4DB6AC
community-author: Buggyj
created: 20171109171935039
delivery: Browser Extension
description: ChromeとFirefoxのブラウザ拡張機能
method: save
modified: 20241014110546647
original-modified: 20210106151027189
tags: Chrome Firefox Saving [[Other Resources]] plugins
title: "savetiddlers" Extension for Chrome and Firefox by buggyj
ja-title: buggyjによるChromeとFirefoxの"savetiddlers"拡張機能
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Google ChromeとMozilla Firefoxの拡張機能で、TiddlyWikiの組み込み[[HTML5セーバー|Saving with the HTML5 saver]]による使いにくさの一部を解消し、正しく設定すればTiddlyFoxとほぼ同じくらい簡単に使用できるようになります。
https://github.com/buggyj/savetiddlers

View File

@@ -1,18 +0,0 @@
caption: savetiddlers
color: #4DB6AC
community-author: buggyj
created: 20171109171935039
delivery: Browser Extension
description: Firefoxのブラウザ拡張機能
method: save
modified: 20250809092435788
original-modified: 20250809092435788
tags: Firefox Saving [[Other Resources]] plugins
title: savetiddlers: Extension for Firefox by buggyj
ja-title: buggyjによるFirefoxの"savetiddlers"拡張機能
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Mozilla Firefoxの拡張機能で、TiddlyWikiの組み込み[[HTML5セーバー|Saving with the HTML5 saver]]による使いにくさの一部を解消し、正しく設定すれば[[TiddlyFox]]とほぼ同じくらい簡単に使用できるようになります。
{{!!url}}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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)$`>>

View File

@@ -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">>/>

View File

@@ -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}}>>/>

View File

@@ -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>>

View File

@@ -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">>.

View File

@@ -2,4 +2,4 @@ title: expected-test-tabs-horizontal-a
type: text/html
description: Horizontal tabs test - This is the expected HTML output from a test in test-wikitext-tabs-macro.js
<p><div class="tc-tab-set " role="tablist"><div class="tc-tab-buttons "><button aria-selected="false" class="" data-tab-title="TabOne" role="tab">t 1</button><button aria-selected="true" class=" tc-tab-selected" data-tab-title="TabTwo" role="tab">t 2</button><button aria-selected="false" class="" data-tab-title="TabThree" role="tab">t 3</button><button aria-selected="false" class="" data-tab-title="TabFour" role="tab">TabFour</button></div><div class="tc-tab-divider "></div><div class="tc-tab-content " role="tabpanel"><div class="tc-reveal" hidden="true"></div><div class="tc-reveal"><p>Text tab 2</p></div><div class="tc-reveal" hidden="true"></div><div class="tc-reveal" hidden="true"></div></div></div></p>
<p><div class="tc-tab-set "><div class="tc-tab-buttons "><button class="" data-tab-title="TabOne" role="switch">t 1</button><button aria-checked="true" class=" tc-tab-selected" data-tab-title="TabTwo" role="switch">t 2</button><button class="" data-tab-title="TabThree" role="switch">t 3</button><button class="" data-tab-title="TabFour" role="switch">TabFour</button></div><div class="tc-tab-divider "></div><div class="tc-tab-content "><div class="tc-reveal" hidden="true"></div><div class="tc-reveal"><p>Text tab 2</p></div><div class="tc-reveal" hidden="true"></div><div class="tc-reveal" hidden="true"></div></div></div></p>

View File

@@ -2,4 +2,4 @@ title: expected-test-tabs-horizontal-all
type: text/html
description: Horizontal tabs with all parameters active. This is the expected HTML output from a test in test-wikitext-tabs-macro.js
<p><div class="tc-tab-set " role="tablist"><div class="tc-tab-buttons "><button aria-selected="false" class="" data-tab-title="TabOne" role="tab">t 1</button><button aria-selected="true" class=" tc-tab-selected" data-tab-title="TabTwo" role="tab">t 2</button><button aria-selected="false" class="" data-tab-title="TabThree" role="tab">desc</button><button aria-selected="false" class="" data-tab-title="TabFour" role="tab">TabFour</button></div><div class="tc-tab-divider "></div><div class="tc-tab-content " role="tabpanel"><div class="tc-reveal" hidden="true"></div><div class="tc-reveal"><h2 class="">TabTwo</h2><p><p>Text tab 2</p></p></div><div class="tc-reveal" hidden="true"></div><div class="tc-reveal" hidden="true"></div></div></div></p>
<p><div class="tc-tab-set "><div class="tc-tab-buttons "><button class="" data-tab-title="TabOne" role="switch">t 1</button><button aria-checked="true" class=" tc-tab-selected" data-tab-title="TabTwo" role="switch">t 2</button><button class="" data-tab-title="TabThree" role="switch">desc</button><button class="" data-tab-title="TabFour" role="switch">TabFour</button></div><div class="tc-tab-divider "></div><div class="tc-tab-content "><div class="tc-reveal" hidden="true"></div><div class="tc-reveal"><h2 class="">TabTwo</h2><p><p>Text tab 2</p></p></div><div class="tc-reveal" hidden="true"></div><div class="tc-reveal" hidden="true"></div></div></div></p>

View File

@@ -2,4 +2,4 @@ title: expected-test-tabs-vertical
type: text/html
description: Vertical tabs test -- This is the expected HTML output from the test in test-wikitext-tabs-macro.js
<p><div class="tc-tab-set tc-vertical" role="tablist"><div class="tc-tab-buttons tc-vertical"><button aria-selected="false" class="" data-tab-title="TabOne" role="tab">t 1</button><button aria-selected="true" class=" tc-tab-selected" data-tab-title="TabTwo" role="tab">t 2</button><button aria-selected="false" class="" data-tab-title="TabThree" role="tab">t 3</button><button aria-selected="false" class="" data-tab-title="TabFour" role="tab">TabFour</button></div><div class="tc-tab-divider tc-vertical"></div><div class="tc-tab-content tc-vertical" role="tabpanel"><div class="tc-reveal" hidden="true"></div><div class="tc-reveal"><p>Text tab 2</p></div><div class="tc-reveal" hidden="true"></div><div class="tc-reveal" hidden="true"></div></div></div></p>
<p><div class="tc-tab-set tc-vertical"><div class="tc-tab-buttons tc-vertical"><button class="" data-tab-title="TabOne" role="switch">t 1</button><button aria-checked="true" class=" tc-tab-selected" data-tab-title="TabTwo" role="switch">t 2</button><button class="" data-tab-title="TabThree" role="switch">t 3</button><button class="" data-tab-title="TabFour" role="switch">TabFour</button></div><div class="tc-tab-divider tc-vertical"></div><div class="tc-tab-content tc-vertical"><div class="tc-reveal" hidden="true"></div><div class="tc-reveal"><p>Text tab 2</p></div><div class="tc-reveal" hidden="true"></div><div class="tc-reveal" hidden="true"></div></div></div></p>

View File

@@ -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 }
);
});

View File

@@ -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"}]
);

View File

@@ -1,6 +0,0 @@
created: 20251001034405510
list: A a Ä ä Z z O o Õ õ Ö ö Ü ü Y y
modified: 20251218023544134
tags:
title: Locale Example
type: text/vnd.tiddlywiki

View File

@@ -26,6 +26,7 @@ For the convenience of existing users, we also continue to operate the original
* [[TiddlyWiki Subreddit|https://www.reddit.com/r/TiddlyWiki5/]]
* Chat on Discord at https://discord.gg/HFFZVQ8
* [[TiddlyWiki Subreddit|https://www.reddit.com/r/TiddlyWiki5/]]
!! Developers

View File

@@ -0,0 +1,16 @@
caption: savetiddlers
color: #4DB6AC
community-author: Buggyj
created: 20171109171935039
delivery: Browser Extension
description: Browser extension for Chrome and Firefox
method: save
modified: 20210106151027189
tags: Chrome Firefox Saving [[Other Resources]] plugins
title: "savetiddlers" Extension for Chrome and Firefox by buggyj
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
An extension for Google Chrome and Mozilla Firefox that smoothes out some of the friction from TiddlyWiki's built-in [[HTML5 saver|Saving with the HTML5 saver]], making it almost as easy to use as TiddlyFox once it is set up correctly.
https://github.com/buggyj/savetiddlers

View File

@@ -1,16 +0,0 @@
caption: savetiddlers
color: #4DB6AC
community-author: buggyj
created: 20171109171935039
delivery: Browser Extension
description: Browser extension for Firefox
method: save
modified: 20250809092435788
tags: Firefox Saving [[Other Resources]] plugins
title: savetiddlers: Extension for Firefox by buggyj
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
An extension for Mozilla Firefox that smoothes out some of the friction from TiddlyWiki's built-in [[HTML5 saver|Saving with the HTML5 saver]], making it almost as easy to use as [[TiddlyFox]] once it is set up correctly.
{{!!url}}

View File

@@ -1,5 +1,5 @@
created: 20150117190213631
modified: 20251225215015507
modified: 20230226144641763
tags: Concepts
title: Date Fields
type: text/vnd.tiddlywiki
@@ -28,5 +28,4 @@ As an example, the <<.field created>> field of this tiddler has the value <<.val
Dates can be [[converted to other formats|DateFormat]] for display:
<$macrocall $name="wikitext-example-without-html"
src="""<$view field="created" format="date" template="DDD DDth MMM YYYY"/>"""/>
src="""<$view field="created" format="date" template="DDD DDth MMM YYYY"/>""">

View File

@@ -25,4 +25,4 @@ A filter output can change as tiddlers are added and deleted in the wiki. ~Tiddl
* <$linkcatcher message="tm-navigate" actions=<<openAdvancedSearch>> >[[Advanced Search|$:/AdvancedSearch]]</$linkcatcher> -- has a <<.advancedsearch-tab Filter>> tab that makes it easy to experiment with filters.
* [[Filtered Transclusions|Transclusion in WikiText]] -- if you want to use filter results in your text
* [[Filter Syntax History]] -- if you are curious why the filter syntax is the way it is
* [[TiddlyWiki Syntax History]] -- if you are curious why the filter syntax is the way it is

View File

@@ -0,0 +1,9 @@
created: 20131211220000000
modified: 20131211224200000
tags: Definitions
title: TiddlyIE
type: text/vnd.tiddlywiki
TiddlyIE is an extension for Internet Explorer that allows standalone TiddlyWiki files to save their changes directly to the file system. TiddlyIE works with the desktop version of Internet Explorer.
See [[Saving with TiddlyIE]].

View File

@@ -1,9 +1,7 @@
created: 20211117003509226
modified: 20260102135713260
modified: 20251119135921343
tags: sampletag1 sampletag2 [[Widget Examples]]
title: SampleTiddlerFirst
type: text/vnd.tiddlywiki
This is a test tiddler called SampleTidlerFirst.
It is used in [[DiffTextWidget]].
You can modify its content.
This is a test tiddler called SampleTidlerFirst.

View File

@@ -1,8 +1,6 @@
created: 20211117003511221
modified: 20260102135739735
modified: 20211117003724108
tags: sampletag1 sampletag2 [[Widget Examples]]
title: SampleTiddlerSecond
This test tiddler is called SampleTiddlerSecond.
It is used in [[DiffTextWidget]].
You can edit its content.
This test tiddler is called SampleTiddlerSecond.

View File

@@ -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>
"""/>

View File

@@ -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>
"""/>

View File

@@ -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.

View File

@@ -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>
"""/>

View File

@@ -1,5 +1,5 @@
created: 20150124112340000
modified: 20251218023608468
modified: 20150124113250000
tags: [[sort Operator]] [[Operator Examples]]
title: sort Operator (Examples)
type: text/vnd.tiddlywiki
@@ -11,10 +11,3 @@ type: text/vnd.tiddlywiki
<<.operator-example 3 "one two Three four +[sort[]]">>
<<.operator-example 4 "[prefix[Tiddl]sort[text]]">>
<<.operator-example 5 "[has[created]sort[created]limit[10]]" "the oldest 10 tiddlers in the wiki">>
! Using a custom locale
The following examples shows the differences when using the sort operator with default, Swedish and Estonian locale.
<<.operator-example 6 "[list[Locale Example]sort[]]">>
<<.operator-example 7 "[list[Locale Example]sort[],[sv]]">>
<<.operator-example 8 "[list[Locale Example]sort[],[et]]">>

View File

@@ -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.

View File

@@ -1,15 +1,15 @@
caption: nsort
created: 20140410103123179
modified: 20251227084602319
op-input: a [[selection of titles|Title Selection]]
op-neg-output: the input, likewise sorted into descending order
op-output: the input, sorted into ascending order by field <<.field F>>, treating field values as numbers
op-parameter: accept same parameters as the [[sort Operator]]
op-parameter-name: F
op-purpose: sort the input by number field
modified: 20150203190051000
tags: [[Filter Operators]] [[Field Operators]] [[Order Operators]] [[Negatable Operators]]
title: nsort Operator
type: text/vnd.tiddlywiki
caption: nsort
op-purpose: sort the input by number field
op-input: a [[selection of titles|Title Selection]]
op-parameter: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
op-parameter-name: F
op-output: the input, sorted into ascending order by field <<.field F>>, treating field values as numbers
op-neg-output: the input, likewise sorted into descending order
Non-numeric values are treated as having a higher value than any number, and the difference between capital and lowercase letters is ignored. Compare <<.olink nsortcs>>.

View File

@@ -1,10 +1,10 @@
caption: nsortcs
created: 20140410103123179
modified: 20251227084615705
modified: 20150417125717078
op-input: a [[selection of titles|Title Selection]]
op-neg-output: the input, likewise sorted into descending order
op-output: the input, sorted into ascending order by field <<.place F>>, treating field values as numbers
op-parameter: accept same parameters as the [[sort Operator]]
op-parameter: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
op-parameter-name: F
op-purpose: sort the input titles by number field, treating upper and lower case as different
tags: [[Filter Operators]] [[Field Operators]] [[Order Operators]] [[Negatable Operators]]

View File

@@ -1,22 +1,16 @@
caption: sort
created: 20140410103123179
modified: 20251227084644651
op-input: a [[selection of titles|Title Selection]]
op-neg-output: the input, likewise sorted into descending order
op-output: the input, sorted into ascending order by field <<.field F>>, treating field values as text
op-parameter: the <<.op sort>> operator accepts 1 or 2 parameters, see below for details
op-parameter-name: F
op-purpose: sort the input by text field
modified: 20150203191228000
tags: [[Filter Operators]] [[Common Operators]] [[Field Operators]] [[Order Operators]] [[Negatable Operators]]
title: sort Operator
type: text/vnd.tiddlywiki
caption: sort
op-purpose: sort the input by text field
op-input: a [[selection of titles|Title Selection]]
op-parameter: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
op-parameter-name: F
op-output: the input, sorted into ascending order by field <<.field F>>, treating field values as text
op-neg-output: the input, likewise sorted into descending order
The difference between capital and lowercase letters is ignored. Compare <<.olink sortcs>>.
```
[sort[<field>],[<locale>]]
```
* ''field'' : the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
* ''locale'': (optional). A string with a [[BCP 47 language tag|https://developer.mozilla.org/en-US/docs/Glossary/BCP_47_language_tag]]
<<.operator-examples "sort">>

View File

@@ -1,10 +1,10 @@
caption: sortan
created: 20180222071605739
modified: 20251227084439804
modified: 20180223012553446
op-input: a [[selection of titles|Title Selection]]
op-neg-output: the input, likewise sorted into descending order
op-output: the input, sorted into ascending order by field <<.field F>>, treating field values as alphanumerics
op-parameter: accept same parameters as the [[sort Operator]]
op-parameter: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
op-parameter-name: F
op-purpose: sort the input by text field considering them as alphanumerics
tags: [[Filter Operators]] [[Common Operators]] [[Field Operators]] [[Order Operators]] [[Negatable Operators]]

View File

@@ -1,10 +1,10 @@
caption: sortcs
created: 20140410103123179
modified: 20251227084416522
modified: 20150417125704503
op-input: a [[selection of titles|Title Selection]]
op-neg-output: the input, likewise sorted into descending order
op-output: the input, sorted into ascending order by field <<.field F>>, treating field values as text
op-parameter: accept same parameters as the [[sort Operator]]
op-parameter: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
op-parameter-name: F
op-purpose: sort the input by text field, treating upper and lower case as different
tags: [[Filter Operators]] [[Field Operators]] [[Order Operators]] [[Negatable Operators]]

View File

@@ -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

View File

@@ -0,0 +1,10 @@
caption: Internet Explorer
created: 20140811172058274
modified: 20211114031651879
tags: GettingStarted $:/deprecated
title: GettingStarted - Internet Explorer
type: text/vnd.tiddlywiki
{{Saving with TiddlyIE}}
The [[Windows HTA Hack]] describes an alternative method of using TiddlyWiki with Internet Explorer.

View File

@@ -1,5 +1,5 @@
created: 20150414070451144
list: [[HelloThumbnail - Newsletter]] [[HelloThumbnail - Community Survey 2025]] [[HelloThumbnail - Introduction Video]] [[HelloThumbnail - Grok TiddlyWiki]] [[HelloThumbnail - Latest Version]] [[HelloThumbnail - MultiWikiServer]] [[HelloThumbnail - Twenty Years of TiddlyWiki]] [[HelloThumbnail - Funding]] [[HelloThumbnail - TiddlyWiki Privacy]] [[HelloThumbnail - Marketplace]] [[HelloThumbnail - Intertwingled Innovations]] [[HelloThumbnail - TiddlyWikiLinks]]
list: [[HelloThumbnail - Community Survey 2025]] [[HelloThumbnail - Twenty Years of TiddlyWiki]] [[HelloThumbnail - Introduction Video]] [[HelloThumbnail - TiddlyWiki Privacy]] [[HelloThumbnail - Latest Version]] [[HelloThumbnail - Newsletter]] [[HelloThumbnail - Grok TiddlyWiki]] [[HelloThumbnail - TiddlyWikiLinks]] [[HelloThumbnail - MultiWikiServer]] [[HelloThumbnail - Funding]] [[HelloThumbnail - Marketplace]] [[HelloThumbnail - Intertwingled Innovations]]
modified: 20150414070948246
title: HelloThumbnail
type: text/vnd.tiddlywiki

View File

@@ -5,6 +5,5 @@ link: TiddlyWiki Newsletter
image: TiddlyWiki Newsletter Badge
color: #fff
type: text/vnd.tiddlywiki
ribbon-text: NEW
Subscribe to the ~TiddlyWiki Newsletter, a summary of the most interesting and relevant news from the ~TiddlyWiki community

View File

@@ -0,0 +1,17 @@
caption: HTA Hack
color: #F06292
created: 20131212223146250
delivery: DIY
description: Manual method to let Internet Explorer save changes directly
method: save
modified: 20200507110355115
tags: Saving Windows $:/deprecated
title: Windows HTA Hack
type: text/vnd.tiddlywiki
<<.deprecated-since "5.3.6">>
Under Windows it is possible to convert TiddlyWiki into a true local application by renaming the HTML file to have the extension `*.hta`. The ''fsosaver'' module can then use the ~ActiveX ~FileSystemObject to save changes.
Note that one disadvantage of this approach is that the TiddlyWiki file is saved in UTF-16 format, making it up to twice as large as it would be with the usual UTF-8 encoding. However, opening and saving the file via another saving method will re-encode the file to UTF-8.
See Wikipedia for more details: https://en.wikipedia.org/wiki/HTML_Application

View File

@@ -31,10 +31,6 @@ The <<.def list-links-draggable>> [[macro|Macros]] renders the ListField of a ti
; itemTemplate
: Optional title of a tiddler to use as the template for rendering list items
;displayField
: Optional name of the field to display when the list is rendered. Defaults to the "caption" field; if "caption" is not present, the "title" field is used instead
If the `itemTemplate` parameter is not provided then the list items are rendered as simple links. Within the `itemTemplate`, the [[currentTiddler Variable]] refers to the current list item.
<<.macro-examples "list-links-draggable">>

View File

@@ -17,9 +17,6 @@ The <<.def list-tagged-draggable>> [[macro|Macros]] renders the tiddlers with a
: Optional title of a tiddler to use as the template for rendering list items
;emptyMessage
: Optional wikitext to display if there are no tiddlers with the specified tag
Heres a corrected and polished version of your sentence in clear, standard English:
;displayField
: Optional name of the field to display when the list is rendered. Defaults to `title` field.
Note that the [[ordering|Order of Tagged Tiddlers]] is accomplished by assigning a new list to the `list` field of the tag tiddler. Any `list-before` or `list-after` fields on any of the other tiddlers carrying the tag are also removed to ensure the `list` field is respected.

View File

@@ -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.

View File

@@ -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}}/>

View File

@@ -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:

View File

@@ -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"""/}
)

View File

@@ -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}}/>

View File

@@ -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

View File

@@ -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.">>

View File

@@ -1,6 +1,6 @@
caption: tag-pill
created: 20161128190930538
modified: 20260114112210310
modified: 20161128191220364
tags: Macros [[Core Macros]]
title: tag-pill Macro
type: text/vnd.tiddlywiki
@@ -9,18 +9,13 @@ The <<.def tag-pill>> [[macro|Macros]] generates a static tag pill showing a spe
!! Parameters
; tag
;tag
: The title of the tag
; element-tag
: The element name to be used for the pill (defaults to HTML element SPAN).
: If an ''actions'' parameter is used the element-tag needs to be set to `$button`
; element-attributes
: Additional attributes for the element specified in ''element-tag''
; actions
: If an actions parameter should be activated, the ''element-tag'' parameter needs to be set to `$button`.
: Action widgets to be triggered when the pill is clicked. Within the text, the macro parameter ''tag'' contains the title of the selected tag
;element-tag
: The element name to be used for the pill (defaults to "span")
;element-attributes
: Additional attributes for the pill element
;actions
: Action widgets to be triggered when the pill is clicked. Within the text, the macro parameter ''tag'' contains the title of the selected tag.
<<.macro-examples "tag-pill">>

View File

@@ -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>
```

View File

@@ -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

View File

@@ -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>
```

View File

@@ -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.

View File

@@ -0,0 +1,17 @@
title: $:/changenotes/5.4.0/#8130
created: 20251212171804335
modified: 20251212171804335
tags: $:/tags/ChangeNote
change-type: performance
change-category: internal
description: Different Stylesheets are now included as single `<style>` tags in the Header
release: 5.4.0
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8130
github-contributors: BurningTreeC
type: text/vnd.tiddlywiki
Previously, all stylesheets were combined in a single `<style>` tag in the `<head>`.
Now, a separate `<style>` tag is created in the `<head>` for each stylesheet.
As part of these changes, the 'view widget' has also been updated. It can now respond dynamically to changes in the 'wikified' formats as well.

Some files were not shown because too many files have changed in this diff Show More