mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-26 12:53:42 +00:00
Compare commits
67 Commits
fix-browse
...
saqimtiaz-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5797855aa1 | ||
|
|
d3fded71c2 | ||
|
|
293dbca5a1 | ||
|
|
d07fe25cdb | ||
|
|
4d1645d16d | ||
|
|
b58c14b906 | ||
|
|
ad5d3c3cde | ||
|
|
f0d8852121 | ||
|
|
48c6694d30 | ||
|
|
a993cea80c | ||
|
|
a40ce29451 | ||
|
|
75647eb623 | ||
|
|
eb3a80968e | ||
|
|
62ae4b24bc | ||
|
|
ded76aa84f | ||
|
|
e42ed6808e | ||
|
|
844564180f | ||
|
|
a670de0e95 | ||
|
|
faee49ee01 | ||
|
|
dd20be49f0 | ||
|
|
a27f74bbdc | ||
|
|
ae4e99951a | ||
|
|
be84dee26b | ||
|
|
00e17874f0 | ||
|
|
9041f099a3 | ||
|
|
3ba31be2a8 | ||
|
|
99d8afd515 | ||
|
|
2ab5f26644 | ||
|
|
419fe68ee2 | ||
|
|
0e765bdbdb | ||
|
|
855d8a9638 | ||
|
|
afcf108d29 | ||
|
|
8f9acc0ca2 | ||
|
|
5e4b8fbb3c | ||
|
|
8e301178a4 | ||
|
|
a72d3a09bf | ||
|
|
56634ffe29 | ||
|
|
24c317e1ab | ||
|
|
07329c6849 | ||
|
|
47ab3476f6 | ||
|
|
f0e64660f2 | ||
|
|
9663e65f4b | ||
|
|
7cb422242a | ||
|
|
f075f24e6b | ||
|
|
5fa1098c03 | ||
|
|
92dc927c7b | ||
|
|
98a61f01bb | ||
|
|
f3fa69e229 | ||
|
|
e2fb22ade0 | ||
|
|
7fb8560908 | ||
|
|
ff7814360e | ||
|
|
2d9303c6ff | ||
|
|
6aee5eb0c7 | ||
|
|
6eb881bffe | ||
|
|
2a5ce95d99 | ||
|
|
bd4fdd8f2e | ||
|
|
09379abd5d | ||
|
|
c6906120d8 | ||
|
|
c4c60933f4 | ||
|
|
a3979cda9c | ||
|
|
3c8ee86e23 | ||
|
|
921c0174fb | ||
|
|
4196d96adc | ||
|
|
743e99d12d | ||
|
|
6beeb23d10 | ||
|
|
838fad916d | ||
|
|
935e89bd93 |
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
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
68
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,68 +0,0 @@
|
||||
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.
|
||||
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -4,18 +4,23 @@ about: Suggest an idea for TiddlyWiki 5
|
||||
title: "[IDEA]"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
type: feature
|
||||
type: idea
|
||||
|
||||
---
|
||||
|
||||
**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 [...]
|
||||
**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 [...]
|
||||
|
||||
**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.
|
||||
|
||||
@@ -42,6 +42,8 @@ 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
|
||||
@@ -261,6 +263,13 @@ 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";
|
||||
@@ -285,6 +294,12 @@ 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
|
||||
|
||||
30
core-server/utils/base64.js
Normal file
30
core-server/utils/base64.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/*\
|
||||
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));
|
||||
95
core-server/utils/escapecss.js
Normal file
95
core-server/utils/escapecss.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/*\
|
||||
title: $:/core-server/modules/utils/escapecss.js
|
||||
type: application/javascript
|
||||
module-type: utils-node
|
||||
|
||||
Provides CSS.escape() functionality.
|
||||
|
||||
\*/
|
||||
|
||||
"use strict";
|
||||
|
||||
exports.escapeCSS = (function() {
|
||||
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||
|
||||
/* eslint-disable */
|
||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||
return function(value) {
|
||||
if (arguments.length == 0) {
|
||||
throw new TypeError('`CSS.escape` requires an argument.');
|
||||
}
|
||||
var string = String(value);
|
||||
var length = string.length;
|
||||
var index = -1;
|
||||
var codeUnit;
|
||||
var result = '';
|
||||
var firstCodeUnit = string.charCodeAt(0);
|
||||
while (++index < length) {
|
||||
codeUnit = string.charCodeAt(index);
|
||||
// Note: there’s no need to special-case astral symbols, surrogate
|
||||
// pairs, or lone surrogates.
|
||||
|
||||
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
||||
// (U+FFFD).
|
||||
if (codeUnit == 0x0000) {
|
||||
result += '\uFFFD';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||
// U+007F, […]
|
||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
||||
// If the character is the first character and is in the range [0-9]
|
||||
// (U+0030 to U+0039), […]
|
||||
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||
// If the character is the second character and is in the range [0-9]
|
||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||
(
|
||||
index == 1 &&
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||
firstCodeUnit == 0x002D
|
||||
)
|
||||
) {
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
||||
result += '\\' + codeUnit.toString(16) + ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is the first character and is a `-` (U+002D), and
|
||||
// there is no second character, […]
|
||||
index == 0 &&
|
||||
length == 1 &&
|
||||
codeUnit == 0x002D
|
||||
) {
|
||||
result += '\\' + string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the character is not handled by one of the above rules and is
|
||||
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
||||
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||
if (
|
||||
codeUnit >= 0x0080 ||
|
||||
codeUnit == 0x002D ||
|
||||
codeUnit == 0x005F ||
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||
) {
|
||||
// the character itself
|
||||
result += string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, the escaped character.
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character
|
||||
result += '\\' + string.charAt(index);
|
||||
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/* eslint-enable */
|
||||
})();
|
||||
@@ -5,3 +5,4 @@ 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]]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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.
|
||||
|
||||
@@ -14,31 +14,31 @@ Export our filter function
|
||||
*/
|
||||
exports.sort = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,false);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,false,undefined,operator.operands[1]);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.nsort = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,true);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,true,undefined,operator.operands[1]);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.sortan = function(source, operator, options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results, operator.operand || "title", operator.prefix === "!",false,false,true);
|
||||
options.wiki.sortTiddlers(results, operator.operands[0] || "title", operator.prefix === "!",false,false,true,operator.operands[1]);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.sortcs = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,false);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,false,undefined,operator.operands[1]);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.nsortcs = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,true);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,true,undefined,operator.operands[1]);
|
||||
return results;
|
||||
};
|
||||
|
||||
|
||||
@@ -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,107 +71,53 @@ exports.join = makeStringReducingOperator(
|
||||
},null
|
||||
);
|
||||
|
||||
var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
||||
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
||||
|
||||
exports.levenshtein = makeStringBinaryOperator(
|
||||
function(a,b) {
|
||||
var dmpObject = new dmp.diff_match_patch(),
|
||||
diffs = dmpObject.diff_main(a,b);
|
||||
return [dmpObject.diff_levenshtein(diffs) + ""];
|
||||
const diffs = dmp.diffMain(a,b);
|
||||
return [dmp.diffLevenshtein(diffs).toString()];
|
||||
}
|
||||
);
|
||||
|
||||
// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
|
||||
// this function is adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
|
||||
function diffLineWordMode(text1,text2,mode) {
|
||||
var dmpObject = new dmp.diff_match_patch();
|
||||
var a = diffPartsToChars(text1,text2,mode);
|
||||
var a = $tw.utils.diffPartsToChars(text1,text2,mode);
|
||||
var lineText1 = a.chars1;
|
||||
var lineText2 = a.chars2;
|
||||
var lineArray = a.lineArray;
|
||||
var diffs = dmpObject.diff_main(lineText1,lineText2,false);
|
||||
dmpObject.diff_charsToLines_(diffs,lineArray);
|
||||
var diffs = dmp.diffMain(lineText1,lineText2,false);
|
||||
dmp.diffCharsToLines(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 dmpObject = new dmp.diff_match_patch(),
|
||||
suffix = operator.suffix || "",
|
||||
var suffix = operator.suffix || "",
|
||||
result = [];
|
||||
|
||||
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)]);
|
||||
});
|
||||
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)]);
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.applypatches = makeStringBinaryOperator(
|
||||
function(a,b) {
|
||||
var dmpObject = new dmp.diff_match_patch(),
|
||||
patches;
|
||||
let patches;
|
||||
try {
|
||||
patches = dmpObject.patch_fromText(b);
|
||||
patches = dmp.patchFromText(b);
|
||||
} catch(e) {
|
||||
}
|
||||
if(patches) {
|
||||
return [dmpObject.patch_apply(patches,a)[0]];
|
||||
return [dmp.patchApply(patches,a)[0]];
|
||||
} else {
|
||||
return [a];
|
||||
}
|
||||
@@ -279,7 +225,7 @@ exports.pad = function(source,operator,options) {
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
exports.charcode = function(source,operator,options) {
|
||||
var chars = [];
|
||||
|
||||
@@ -11,17 +11,16 @@ The image parser parses an image into an embeddable HTML element
|
||||
|
||||
var ImageParser = function(type,text,options) {
|
||||
var element = {
|
||||
type: "element",
|
||||
tag: "img",
|
||||
attributes: {}
|
||||
};
|
||||
type: "image",
|
||||
attributes: {}
|
||||
};
|
||||
if(options._canonical_uri) {
|
||||
element.attributes.src = {type: "string", value: options._canonical_uri};
|
||||
element.attributes.source = {type: "string", value: options._canonical_uri};
|
||||
} else if(text) {
|
||||
if(type === "image/svg+xml" || type === ".svg") {
|
||||
element.attributes.src = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
|
||||
element.attributes.source = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
|
||||
} else {
|
||||
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
|
||||
element.attributes.source = {type: "string", value: "data:" + type + ";base64," + text};
|
||||
}
|
||||
}
|
||||
this.tree = [element];
|
||||
|
||||
@@ -18,7 +18,6 @@ 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
|
||||
@@ -45,13 +44,22 @@ exports.startup = function() {
|
||||
publishTitle();
|
||||
}
|
||||
});
|
||||
|
||||
var styleParser = $tw.wiki.parseTiddler(ROOT_STYLESHEET_TITLE,{parseAsInline: true}),
|
||||
styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: document});
|
||||
styleWidgetNode.render(document.head,null);
|
||||
|
||||
// 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);
|
||||
$tw.wiki.addEventListener("change",$tw.perf.report("styleRefresh",function(changes) {
|
||||
styleWidgetNode.refresh(changes,document.head,null);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
|
||||
$tw.perf.report("mainRender",function() {
|
||||
@@ -60,7 +68,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");
|
||||
|
||||
@@ -63,16 +63,24 @@ exports.startup = function() {
|
||||
$tw.eventBus.emit("window:closed",{windowID});
|
||||
},false);
|
||||
// Set up the styles
|
||||
var styleParser = $tw.wiki.parseTiddler("$:/core/ui/RootStylesheet",{parseAsInline: true}),
|
||||
styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: srcDocument});
|
||||
styleWidgetNode.render(srcDocument.head,null);
|
||||
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);
|
||||
// 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) {
|
||||
styleWidgetNode.refresh(changes);
|
||||
if(styleWidgetNode.refresh(changes,styleContainer,null)) {
|
||||
styleElement.innerHTML = styleContainer.textContent;
|
||||
}
|
||||
widgetNode.refresh(changes);
|
||||
};
|
||||
$tw.wiki.addEventListener("change",refreshHandler);
|
||||
|
||||
31
core/modules/utils/base64.js
Normal file
31
core/modules/utils/base64.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/*\
|
||||
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));
|
||||
@@ -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 && el.classList.add(className);
|
||||
el.classList && className && el.classList.add(className);
|
||||
};
|
||||
|
||||
exports.removeClass = function(el,className) {
|
||||
el.classList && el.classList.remove(className);
|
||||
el.classList && className && el.classList.remove(className);
|
||||
};
|
||||
|
||||
exports.toggleClass = function(el,className,status) {
|
||||
el.classList && el.classList.toggle(className, status);
|
||||
el.classList && className && el.classList.toggle(className, status);
|
||||
};
|
||||
|
||||
exports.getLocationPath = () => window.location.origin + window.location.pathname;
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/escapecss.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
module-type: utils-browser
|
||||
|
||||
Provides CSS.escape() functionality.
|
||||
|
||||
@@ -9,92 +9,6 @@ Provides CSS.escape() functionality.
|
||||
|
||||
"use strict";
|
||||
|
||||
// TODO -- resolve this construction
|
||||
exports.escapeCSS = (function() {
|
||||
// use browser's native CSS.escape() function if available
|
||||
if ($tw.browser && window.CSS && window.CSS.escape) {
|
||||
return window.CSS.escape;
|
||||
}
|
||||
|
||||
// otherwise, a utility method is provided
|
||||
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||
|
||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||
return function(value) {
|
||||
if (arguments.length == 0) {
|
||||
throw new TypeError('`CSS.escape` requires an argument.');
|
||||
}
|
||||
var string = String(value);
|
||||
var length = string.length;
|
||||
var index = -1;
|
||||
var codeUnit;
|
||||
var result = '';
|
||||
var firstCodeUnit = string.charCodeAt(0);
|
||||
while (++index < length) {
|
||||
codeUnit = string.charCodeAt(index);
|
||||
// Note: there’s no need to special-case astral symbols, surrogate
|
||||
// pairs, or lone surrogates.
|
||||
|
||||
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
||||
// (U+FFFD).
|
||||
if (codeUnit == 0x0000) {
|
||||
result += '\uFFFD';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||
// U+007F, […]
|
||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
||||
// If the character is the first character and is in the range [0-9]
|
||||
// (U+0030 to U+0039), […]
|
||||
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||
// If the character is the second character and is in the range [0-9]
|
||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||
(
|
||||
index == 1 &&
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||
firstCodeUnit == 0x002D
|
||||
)
|
||||
) {
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
||||
result += '\\' + codeUnit.toString(16) + ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is the first character and is a `-` (U+002D), and
|
||||
// there is no second character, […]
|
||||
index == 0 &&
|
||||
length == 1 &&
|
||||
codeUnit == 0x002D
|
||||
) {
|
||||
result += '\\' + string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the character is not handled by one of the above rules and is
|
||||
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
||||
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||
if (
|
||||
codeUnit >= 0x0080 ||
|
||||
codeUnit == 0x002D ||
|
||||
codeUnit == 0x005F ||
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||
) {
|
||||
// the character itself
|
||||
result += string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, the escaped character.
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character
|
||||
result += '\\' + string.charAt(index);
|
||||
|
||||
}
|
||||
return result;
|
||||
};
|
||||
return window.CSS.escape;
|
||||
})();
|
||||
|
||||
@@ -37,6 +37,7 @@ 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);
|
||||
|
||||
@@ -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,60 +759,17 @@ 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 exports.atob(encoded)
|
||||
else return exports.base64DecodeUtf8(encoded);
|
||||
const encoded = urlsafe ? string64.replace(/_/g,"/").replace(/-/g,"+") : string64;
|
||||
if(binary) return $tw.utils.atob(encoded);
|
||||
else return $tw.utils.base64DecodeUtf8(encoded);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -820,10 +777,10 @@ Encode a string to base64
|
||||
*/
|
||||
exports.base64Encode = function(string64,binary,urlsafe) {
|
||||
let encoded;
|
||||
if(binary) encoded = exports.btoa(string64);
|
||||
else encoded = exports.base64EncodeUtf8(string64);
|
||||
if(binary) encoded = $tw.utils.btoa(string64);
|
||||
else encoded = $tw.utils.base64EncodeUtf8(string64);
|
||||
if(urlsafe) {
|
||||
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
|
||||
encoded = encoded.replace(/\+/g,"-").replace(/\//g,"_");
|
||||
}
|
||||
return encoded;
|
||||
};
|
||||
@@ -957,3 +914,56 @@ 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};
|
||||
};
|
||||
|
||||
@@ -9,6 +9,8 @@ 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");
|
||||
@@ -44,9 +46,14 @@ 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 && this.isSelected()) {
|
||||
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
|
||||
domNode.setAttribute("aria-checked", "true");
|
||||
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(isPoppedUp) {
|
||||
$tw.utils.pushTop(classes,this.selectedClass.split(" "));
|
||||
@@ -221,6 +228,7 @@ 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");
|
||||
|
||||
@@ -9,8 +9,8 @@ Widget to display a diff between two texts
|
||||
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget,
|
||||
dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
||||
|
||||
var DiffTextWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
@@ -35,19 +35,24 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Create the diff object
|
||||
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",""));
|
||||
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});
|
||||
}
|
||||
// Apply required cleanup
|
||||
switch(this.getAttribute("cleanup","semantic")) {
|
||||
case "none":
|
||||
// No cleanup
|
||||
break;
|
||||
case "efficiency":
|
||||
dmpObject.diff_cleanupEfficiency(diffs);
|
||||
dmp.diffCleanupEfficiency(diffs, {diffEditCost: editCost});
|
||||
break;
|
||||
default: // case "semantic"
|
||||
dmpObject.diff_cleanupSemantic(diffs);
|
||||
dmp.diffCleanupSemantic(diffs);
|
||||
break;
|
||||
}
|
||||
// Create the elements
|
||||
@@ -133,7 +138,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.editcost) {
|
||||
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup || changedAttributes.mode || changedAttributes.editcost) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
@@ -141,4 +146,15 @@ 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;
|
||||
|
||||
@@ -7,7 +7,6 @@ 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>
|
||||
@@ -56,7 +55,7 @@ LetWidget.prototype.computeAttributes = function() {
|
||||
});
|
||||
// Run through again, setting variables and looking for differences
|
||||
$tw.utils.each(this.currentValueFor,function(value,name) {
|
||||
if(!$tw.utils.isArrayEqual(self.attributes[name],value)) {
|
||||
if(self.attributes[name] === undefined || !$tw.utils.isArrayEqual(self.attributes[name],value)) {
|
||||
self.attributes[name] = value;
|
||||
self.setVariable(name,value);
|
||||
changedAttributes[name] = true;
|
||||
@@ -68,7 +67,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] || "",
|
||||
|
||||
@@ -121,9 +121,18 @@ SelectWidget.prototype.setSelectValue = function() {
|
||||
if (this.selectMultiple) {
|
||||
value = value === undefined ? "" : value;
|
||||
var select = this.getSelectDomNode();
|
||||
var values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);
|
||||
var child,
|
||||
values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);
|
||||
for(var i=0; i < select.children.length; i++){
|
||||
select.children[i].selected = values.indexOf(select.children[i].value) !== -1
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var domNode = this.getSelectDomNode();
|
||||
|
||||
@@ -9,376 +9,215 @@ View widget
|
||||
|
||||
"use strict";
|
||||
|
||||
const Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var ViewWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
==========================================
|
||||
ViewHandler Base Class
|
||||
==========================================
|
||||
Base class for all view format handlers.
|
||||
Provides common functionality and defines the interface for subclasses.
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
render(parent, nextSibling) {
|
||||
this.text = this.getValue();
|
||||
this.createTextNode(parent, nextSibling);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.widget.getValueAsText();
|
||||
}
|
||||
|
||||
createTextNode(parent, nextSibling) {
|
||||
if(this.text) {
|
||||
const textNode = this.document.createTextNode(this.text);
|
||||
parent.insertBefore(textNode, nextSibling);
|
||||
this.widget.domNodes.push(textNode);
|
||||
} else {
|
||||
this.widget.makeChildWidgets();
|
||||
this.widget.renderChildren(parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
var self = this;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ViewWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
==========================================
|
||||
Wikified View Handler Base
|
||||
==========================================
|
||||
Base class for wikified view handlers
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
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;
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
==========================================
|
||||
ViewWidget
|
||||
==========================================
|
||||
Main widget class that orchestrates view handlers
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
class ViewWidget extends Widget {
|
||||
constructor(parseTreeNode, options) {
|
||||
super();
|
||||
this.initialise(parseTreeNode, options);
|
||||
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.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.viewHandler = ViewHandlerFactory.createHandler(this.viewFormat, this);
|
||||
this.viewHandler.render(parent, nextSibling);
|
||||
}
|
||||
/*
|
||||
The various formatter functions are baked into this widget for the moment. Eventually they will be replaced by macro functions
|
||||
*/
|
||||
|
||||
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);
|
||||
/*
|
||||
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);
|
||||
} else {
|
||||
let tiddler;
|
||||
if(this.viewSubtiddler) {
|
||||
tiddler = this.wiki.getSubTiddler(this.viewTitle, this.viewSubtiddler);
|
||||
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 {
|
||||
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];
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(this.viewField === "title") {
|
||||
value = this.viewTitle;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
getValueAsText() {
|
||||
return this.getValue({asString: true});
|
||||
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 "";
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
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");
|
||||
};
|
||||
|
||||
exports.view = ViewWidget;
|
||||
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 {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
exports.view = ViewWidget;
|
||||
|
||||
@@ -160,7 +160,7 @@ Widget.prototype.getVariableInfo = function(name,options) {
|
||||
});
|
||||
// Parameters are an array of {name:, value:, multivalue:} pairs (name and multivalue are optional)
|
||||
$tw.utils.each(params,function(param) {
|
||||
if(param.multiValue) {
|
||||
if(param.multiValue && param.multiValue.length) {
|
||||
variables[param.name] = param.multiValue;
|
||||
} else {
|
||||
variables[param.name] = param.value || "";
|
||||
@@ -233,8 +233,10 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams)
|
||||
paramMultiValue = typeof param === "string" ? [param] : (param.multiValue || [paramValue]);
|
||||
}
|
||||
// If we've still not got a value, use the default, if any
|
||||
paramValue = paramValue || paramInfo["default"] || "";
|
||||
paramMultiValue = paramMultiValue || [paramValue];
|
||||
if(!paramValue) {
|
||||
paramValue = paramInfo["default"] || "";
|
||||
paramMultiValue = [paramValue];
|
||||
}
|
||||
// Store the parameter name and value
|
||||
results.push({name: paramInfo.name, value: paramValue, multiValue: paramMultiValue});
|
||||
}
|
||||
|
||||
@@ -369,31 +369,16 @@ 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) {
|
||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric,locale) {
|
||||
var self = this;
|
||||
if(sortField === "title") {
|
||||
if(!isNumeric && !isAlphaNumeric) {
|
||||
if(isCaseSensitive) {
|
||||
if(isDescending) {
|
||||
titles.sort(function(a,b) {
|
||||
return b.localeCompare(a);
|
||||
});
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
}
|
||||
const sorter = new Intl.Collator(locale, { sensitivity: isCaseSensitive ? "variant" : "accent" });
|
||||
if(isDescending) {
|
||||
titles.sort((a,b) => sorter.compare(b, a));
|
||||
} else {
|
||||
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());
|
||||
});
|
||||
}
|
||||
}
|
||||
titles.sort((a,b) => sorter.compare(a, b));
|
||||
}
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
var x,y;
|
||||
@@ -414,14 +399,8 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
|
||||
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -463,14 +442,8 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
|
||||
}
|
||||
a = String(a);
|
||||
b = String(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);
|
||||
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
|
||||
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,7 +25,6 @@ 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 ~~-->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
title: $:/core/ui/PageTemplate/alerts
|
||||
tags: $:/tags/PageTemplate
|
||||
|
||||
<div class="tc-alerts" role="region" aria-label="Alerts">
|
||||
<div class="tc-alerts" role="region" aria-label={{$:/language/Alerts}}>
|
||||
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Alert]!is[draft]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
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>
|
||||
@@ -15,7 +15,7 @@ caption: {{$:/language/SideBar/Open/Caption}}
|
||||
|
||||
\define droppable-item(button)
|
||||
\whitespace trim
|
||||
<$droppable actions=<<drop-actions>> enable=<<tv-allow-drag-and-drop>> tag="div">
|
||||
<$droppable actions=<<drop-actions>> enable=<<tv-enable-drag-and-drop>> tag="div">
|
||||
<<placeholder>>
|
||||
<div>
|
||||
$button$
|
||||
|
||||
@@ -2,7 +2,7 @@ title: $:/core/ui/TiddlerInfo
|
||||
|
||||
\whitespace trim
|
||||
<div style="position:relative;">
|
||||
<div class="tc-tiddler-controls" style="position:absolute;right:0;">
|
||||
<div class="tc-tiddler-controls tc-tiddler-info-controls">
|
||||
<$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}}
|
||||
|
||||
@@ -11,9 +11,13 @@ tags: $:/tags/ViewTemplate
|
||||
storyview="pop"
|
||||
variable="listItem"
|
||||
>
|
||||
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
|
||||
<$transclude tiddler=<<listItem>>/>
|
||||
</$set>
|
||||
<$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>
|
||||
</$list>
|
||||
</span>
|
||||
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
|
||||
|
||||
@@ -41,6 +41,8 @@ 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}}/>
|
||||
@@ -64,6 +66,7 @@ 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()
|
||||
|
||||
39
core/wiki/macros/CSS-property.tid
Normal file
39
core/wiki/macros/CSS-property.tid
Normal file
@@ -0,0 +1,39 @@
|
||||
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
|
||||
@@ -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)
|
||||
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate, displayField:"caption")
|
||||
\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="caption">
|
||||
<$transclude field=<<__displayField__>>>
|
||||
<$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:"")
|
||||
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"",displayField:"title")
|
||||
\whitespace trim
|
||||
<span class="tc-tagged-draggable-list">
|
||||
<$set name="tag" value=<<__tag__>>>
|
||||
@@ -110,7 +110,11 @@ tags: $:/tags/Macro
|
||||
<$genesis $type=<<__elementTag__>>>
|
||||
<$transclude tiddler="""$itemTemplate$""">
|
||||
<$link to={{!!title}}>
|
||||
<$view field="title"/>
|
||||
<$let tv-wikilinks="no">
|
||||
<$transclude field=<<__displayField__>>>
|
||||
<$view field="title"/>
|
||||
</$transclude>
|
||||
</$let>
|
||||
</$link>
|
||||
</$transclude>
|
||||
</$genesis>
|
||||
|
||||
@@ -9,8 +9,9 @@ code-body: yes
|
||||
setTo=<<currentTab>>
|
||||
default=<<__default__>>
|
||||
selectedClass="tc-tab-selected"
|
||||
selectedAria="aria-selected"
|
||||
tooltip={{!!tooltip}}
|
||||
role="switch"
|
||||
role="tab"
|
||||
data-tab-title=<<currentTab>>
|
||||
>
|
||||
<$tiddler tiddler=<<save-currentTiddler>>>
|
||||
@@ -57,12 +58,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__>] }}}>
|
||||
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}} role="tablist">
|
||||
<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__>] }}}>
|
||||
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}} role="tabpanel">
|
||||
<<tabs-tab-body>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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 comlex for humans)
|
||||
(future improvement because keeping track is complex for humans)
|
||||
-->
|
||||
\procedure delete-tag-state-tiddlers()
|
||||
<$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
|
||||
@@ -111,6 +111,7 @@ The second ESC tries to close the "draft tiddler"
|
||||
refreshTitle=<<refreshTitle>>
|
||||
selectionStateTitle=<<tagSelectionState>>
|
||||
inputAcceptActions=<<add-tag-actions>>
|
||||
inputAcceptVariantActions=<<save-tiddler-actions>>
|
||||
inputCancelActions=<<clear-tags-actions>>
|
||||
tag="input"
|
||||
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
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
|
||||
@@ -0,0 +1,17 @@
|
||||
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}}
|
||||
@@ -1,18 +0,0 @@
|
||||
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
|
||||
@@ -0,0 +1,18 @@
|
||||
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}}
|
||||
@@ -0,0 +1,16 @@
|
||||
title: Functions/FunctionDefaultValues
|
||||
description: Use defaults for missing parameters in functions in filters
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
\function .test(prefix:Default) [[ Content]addprefix<prefix>]
|
||||
|
||||
<$text text={{{ [.test[Special]] }}}/>,<$text text={{{ [.test[]] }}}/>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>Special Content,Default Content</p>
|
||||
@@ -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 "><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>
|
||||
<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>
|
||||
|
||||
@@ -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 "><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>
|
||||
<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>
|
||||
|
||||
@@ -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"><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>
|
||||
<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>
|
||||
|
||||
6
editions/tw5.com/tiddlers/Locale Example.tid
Normal file
6
editions/tw5.com/tiddlers/Locale Example.tid
Normal file
@@ -0,0 +1,6 @@
|
||||
created: 20251001034405510
|
||||
list: A a Ä ä Z z O o Õ õ Ö ö Ü ü Y y
|
||||
modified: 20251218023544134
|
||||
tags:
|
||||
title: Locale Example
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -26,7 +26,6 @@ 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
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
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
|
||||
@@ -0,0 +1,16 @@
|
||||
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}}
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20150117190213631
|
||||
modified: 20230226144641763
|
||||
modified: 20251225215015507
|
||||
tags: Concepts
|
||||
title: Date Fields
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -28,4 +28,5 @@ 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"/>"""/>
|
||||
|
||||
|
||||
@@ -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
|
||||
* [[TiddlyWiki Syntax History]] -- if you are curious why the filter syntax is the way it is
|
||||
* [[Filter Syntax History]] -- if you are curious why the filter syntax is the way it is
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
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]].
|
||||
@@ -1,7 +1,9 @@
|
||||
created: 20211117003509226
|
||||
modified: 20251119135921343
|
||||
modified: 20260102135713260
|
||||
tags: sampletag1 sampletag2 [[Widget Examples]]
|
||||
title: SampleTiddlerFirst
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This is a test tiddler called SampleTidlerFirst.
|
||||
This is a test tiddler called SampleTidlerFirst.
|
||||
It is used in [[DiffTextWidget]].
|
||||
You can modify its content.
|
||||
@@ -1,6 +1,8 @@
|
||||
created: 20211117003511221
|
||||
modified: 20211117003724108
|
||||
modified: 20260102135739735
|
||||
tags: sampletag1 sampletag2 [[Widget Examples]]
|
||||
title: SampleTiddlerSecond
|
||||
|
||||
This test tiddler is called SampleTiddlerSecond.
|
||||
This test tiddler is called SampleTiddlerSecond.
|
||||
It is used in [[DiffTextWidget]].
|
||||
You can edit its content.
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20150124112340000
|
||||
modified: 20150124113250000
|
||||
modified: 20251218023608468
|
||||
tags: [[sort Operator]] [[Operator Examples]]
|
||||
title: sort Operator (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -11,3 +11,10 @@ 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]]">>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
caption: nsort
|
||||
created: 20140410103123179
|
||||
modified: 20150203190051000
|
||||
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
|
||||
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>>.
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
caption: nsortcs
|
||||
created: 20140410103123179
|
||||
modified: 20150417125717078
|
||||
modified: 20251227084615705
|
||||
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: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
|
||||
op-parameter: accept same parameters as the [[sort Operator]]
|
||||
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]]
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
caption: sort
|
||||
created: 20140410103123179
|
||||
modified: 20150203191228000
|
||||
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
|
||||
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">>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
caption: sortan
|
||||
created: 20180222071605739
|
||||
modified: 20180223012553446
|
||||
modified: 20251227084439804
|
||||
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: the name of a [[field|TiddlerFields]], defaulting to <<.field title>>
|
||||
op-parameter: accept same parameters as the [[sort Operator]]
|
||||
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]]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
caption: sortcs
|
||||
created: 20140410103123179
|
||||
modified: 20150417125704503
|
||||
modified: 20251227084416522
|
||||
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 name of a [[field|TiddlerFields]], defaulting to <<.field title>>
|
||||
op-parameter: accept same parameters as the [[sort Operator]]
|
||||
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]]
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
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.
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20150414070451144
|
||||
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]]
|
||||
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]]
|
||||
modified: 20150414070948246
|
||||
title: HelloThumbnail
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -5,5 +5,6 @@ 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
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
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
|
||||
@@ -31,6 +31,10 @@ 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">>
|
||||
|
||||
@@ -17,6 +17,9 @@ 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
|
||||
Here’s 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.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: tag-pill
|
||||
created: 20161128190930538
|
||||
modified: 20161128191220364
|
||||
modified: 20260114112210310
|
||||
tags: Macros [[Core Macros]]
|
||||
title: tag-pill Macro
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -9,13 +9,18 @@ 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 "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.
|
||||
|
||||
; 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
|
||||
|
||||
<<.macro-examples "tag-pill">>
|
||||
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#8093.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#8093.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#8093
|
||||
description: Fixes SelectWidget does not work with multiple options organised into group - issue #8092
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/issues/8093 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9616
|
||||
github-contributors: buggyj saqimtiaz
|
||||
|
||||
Fixed SelectWidget does not work with multiple options organised into group.
|
||||
@@ -1,17 +0,0 @@
|
||||
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.
|
||||
@@ -4,8 +4,8 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8972
|
||||
github-contributors: Jermolene
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8972 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9614
|
||||
github-contributors: Jermolene saqimtiaz
|
||||
|
||||
This PR introduces a new filter run prefix `:let` that assigns the result of the filter run to a variable that is made available for the remaining filter runs of the filter expression. It solves the problem that previously it was impossible to compute values for filter operator parameters; parameters could only be a literal string, text reference or variable reference.
|
||||
|
||||
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9148.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9148.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9148
|
||||
description: Bidirectional improvements for core classes
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: theme
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9148
|
||||
github-contributors: Leilei332
|
||||
|
||||
Make some core classes display properly when Tiddlywiki's language uses bidrectional scripts.
|
||||
12
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9177.tid
Normal file
12
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9177.tid
Normal file
@@ -0,0 +1,12 @@
|
||||
title: $:/changenotes/5.4.0/#9177
|
||||
description: Add Display Field to list-tagged-draggable and list-links-draggable
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: usability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9177
|
||||
github-contributors: kookma
|
||||
|
||||
A new input parameter, `displayField`, has been added to the `list-links-draggable` and `list-tagged-draggable` macros,
|
||||
allowing users to specify which field (e.g., title, caption, or any custom field) should be displayed when a tiddler is
|
||||
rendered via the draggable macro.
|
||||
17
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9206.tid
Normal file
17
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9206.tid
Normal file
@@ -0,0 +1,17 @@
|
||||
change-category: nodejs
|
||||
change-type: feature
|
||||
created: 20260120154012282
|
||||
description: Allows server routes to be prioritized via ordering.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9206
|
||||
modified: 20260120160656948
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9206
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This PR adds support for an info property to server route module exports. The info object may include a priority field, which determines the route’s order of precedence.
|
||||
|
||||
Priorities are numeric and follow a descending order: routes with higher priority values are processed first, similar to how saver modules are prioritized.
|
||||
|
||||
To maintain backward compatibility with existing code, any module that omits info or info.priority is assigned a default priority of 100. Core server routes have been updated to explicitly use this default value of 100.
|
||||
13
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9207.tid
Normal file
13
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9207.tid
Normal file
@@ -0,0 +1,13 @@
|
||||
change-category: nodejs
|
||||
change-type: feature
|
||||
created: 20260120154249928
|
||||
description: Allows server routes to support multiple HTTP methods.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9207
|
||||
modified: 20260120160159661
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9207
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Allows server routes to support multiple HTTP methods by introducing an `exports.methods` array.
|
||||
13
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9259.tid
Normal file
13
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9259.tid
Normal file
@@ -0,0 +1,13 @@
|
||||
change-category: widget
|
||||
change-type: deprecation
|
||||
created: 20260120154533983
|
||||
description: The deprecated events and actions-* atrributes for the eventcatcher widget have been removed.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9259
|
||||
modified: 20260120160236297
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9259
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Deprecates and removes the `events` and `actions-*` attributes for the $eventcatcher widget.
|
||||
@@ -0,0 +1,8 @@
|
||||
changenote: $:/changenotes/5.4.0/#9259
|
||||
created: 20260120154817011
|
||||
description: Deprecated events and actons-* attributes from the eventcatcher widget
|
||||
impact-type: deprecation
|
||||
modified: 20260120154900978
|
||||
tags: $:/tags/ImpactNote
|
||||
title: $:/changenotes/5.4.0/#9259/impacts/deprecate-eventcatcher-attributes
|
||||
type: text/vnd.tiddlywiki
|
||||
29
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9260.tid
Normal file
29
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9260.tid
Normal file
@@ -0,0 +1,29 @@
|
||||
change-category: hackability
|
||||
change-type: feature
|
||||
created: 20260120154445701
|
||||
description: Adds info tiddlers for viewport dimensions that are updated on window resize.
|
||||
github-contributors: saqimtiaz
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9260
|
||||
modified: 20260120160515462
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
title: $:/changenotes/5.4.0/#9260
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Adds info tiddlers for viewport dimensions that are updated on window resize.
|
||||
|
||||
!! Example: Main and a user-created window with windowID my-window
|
||||
|
||||
|Window | Info tiddler | Meaning |h
|
||||
|system/main |`$:/info/browser/window/system/main/outer/width` | Full browser window including chrome, tabs, toolbars |
|
||||
|system/main |`$:/info/browser/window/system/main/outer/height` | Full browser window including chrome, tabs, toolbars |
|
||||
|system/main |`$:/info/browser/window/system/main/inner/width` | Viewport width including scrollbars |
|
||||
|system/main |`$:/info/browser/window/system/main/inner/height` | Viewport height including scrollbars |
|
||||
|system/main |`$:/info/browser/window/system/main/client/width` | Content width excluding scrollbars |
|
||||
|system/main |`$:/info/browser/window/system/main/client/height` | Content height excluding scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/outer/width` | Full browser window including chrome, tabs, toolbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/outer/height` | Full browser window including chrome, tabs, toolbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/inner/width` | Viewport width including scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/inner/height` | Viewport height including scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/client/width` | Content width excluding scrollbars |
|
||||
|user/my-window |`$:/info/browser/window/user/my-window/client/height` | Content height excluding scrollbars |
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9277.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9277.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9277
|
||||
description: Added an option to enable CORS
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: feature
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9277
|
||||
github-contributors: kixam
|
||||
|
||||
Added an option to the TiddlyWiki5 server to enable CORS (ie. don't check `same-origin`). It is meant for advanced users, do not use it unless you understand the full consequences.
|
||||
@@ -1,17 +1,7 @@
|
||||
title: $:/changenotes/5.4.0/#9337/compatibility-break/math-filters
|
||||
title: $:/changenotes/5.4.0/#9337/impacts/math-filters
|
||||
changenote: $:/changenotes/5.4.0/#9337
|
||||
created - 20251112152513384
|
||||
modified - 20251112152513384
|
||||
created: 20251112152513384
|
||||
modified: 20251209160312626
|
||||
tags: $:/tags/ImpactNote
|
||||
description: filter output with empty input changes for some math filter operators
|
||||
impact-type: compatibility-break
|
||||
|
||||
These math operators will now output an empty list when the input list is empty:
|
||||
|
||||
* sum[] - previously returned 0
|
||||
* product[] - previously returned 1
|
||||
* maxall[] - previously returned -Infinity
|
||||
* minall[] - previously returned Infinity
|
||||
* average[] - previously returned NaN
|
||||
* variance[] - previously returned NaN
|
||||
* standard-deviation[] - previously returned NaN
|
||||
description: filter output changes for some math filter operators when input list is empty
|
||||
impact-type: compatibility-break
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9348.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9348.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9348
|
||||
description: Improve tabs macro accessibility
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: usability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9348
|
||||
github-contributors: Leilei332
|
||||
|
||||
Adds `tablist`, `tabpanel` and `tab` roles to the tabs macro to improve its accessibility. It also adds a `selectedAria` attribute to the button widget.
|
||||
@@ -4,7 +4,8 @@ release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: translation
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9375
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9375 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9576
|
||||
github-contributors: BramChen
|
||||
|
||||
* change camel-case hint text for chinese translations
|
||||
* change camel-case hint text for chinese translations
|
||||
* add alerts ARIA message
|
||||
@@ -0,0 +1,9 @@
|
||||
title: $:/changenotes/5.4.0/#9400/impacts/collator
|
||||
changenote: $:/changenotes/5.4.0/#9400
|
||||
created: 20251114102355243
|
||||
modified: 20251114102355243
|
||||
tags: $:/tags/ImpactNote
|
||||
description: Tiddlywiki no longer works on browsers that doesn't support [[Intl.Collator|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator]]
|
||||
impact-type: compatibility-break
|
||||
|
||||
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9400.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9400.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9400
|
||||
description: Add locale support for sort operators
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: feature
|
||||
change-category: filters
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9400
|
||||
github-contributors: Leilei332
|
||||
|
||||
Add a new parameter for `sort`, `nsort`, `sortan`, `sortcs` and `nsortcs` to support sorting with a custom locale.
|
||||
15
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9466.tid
Normal file
15
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9466.tid
Normal file
@@ -0,0 +1,15 @@
|
||||
title: $:/changenotes/5.4.0/#9466
|
||||
description: ViewToolbar buttons now support condition field
|
||||
tags: $:/tags/ChangeNote
|
||||
release: 5.4.0
|
||||
change-type: feature
|
||||
change-category: hackability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9466
|
||||
github-contributors: linonetwo
|
||||
|
||||
ViewToolbar buttons can now be conditionally displayed based on the currentTiddler using a `condition` field. Similar to how `$:/tags/Exporter` and `$:/tags/EditorTools` already have. An example would be:
|
||||
|
||||
```tid
|
||||
tags: $:/tags/ViewToolbar
|
||||
condition: [<currentTiddler>type[text/x-markdown]] [<currentTiddler>type[text/markdown]]
|
||||
```
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9494.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9494.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9494
|
||||
description: Fix LetWidget to always set all staged variables on first render
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9494
|
||||
github-contributors: yaisog
|
||||
|
||||
This PR corrects a bug where the LetWidget did not set variables if their value was the empty output of a filtered transclusion.
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9538.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9538.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9538
|
||||
description: Fix browser storage plugin making wiki dirty
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: plugin
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9538
|
||||
github-contributors: Jermolene
|
||||
|
||||
Fixed issue where the browser storage plugin caused the wiki to be marked as dirty every time it starts up. The problem was due to the use of a log tiddler titled `$:/info/browser/storage/persisted`, the fix is to rename it to `$:/state/browser/storage/persisted`.
|
||||
15
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9551.tid
Normal file
15
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9551.tid
Normal file
@@ -0,0 +1,15 @@
|
||||
title: $:/changenotes/5.4.0/#9551
|
||||
description: Add words and lines modes to diff-text widget
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: widget
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9551
|
||||
github-contributors: yaisog
|
||||
|
||||
The DiffTextWidget now supports two additional diff modes via the `mode` attribute:
|
||||
|
||||
* `mode="words"` - Performs word-level diff operations, making differences more intelligible when comparing text
|
||||
* `mode="lines"` - Performs line-level diff operations, highlighting entire lines that have changed
|
||||
|
||||
The default `mode="chars"` continues to work as before, performing character-level diff operations.
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9570.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9570.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9570
|
||||
description: Fix images loaded from _canonical_uri tiddlers not having progress classes assigned
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9570
|
||||
github-contributors: jermolene
|
||||
|
||||
Fixes issue whereby transcluding a _canonical_uri tiddler with a missing image did not assign the progress classes `tc-image-loading`, `tc-image-loaded` and `tc-image-error`.
|
||||
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9600.tid
Normal file
10
editions/tw5.com/tiddlers/releasenotes/5.4.0/#9600.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9600
|
||||
description: Fix Ctrl-Enter not working in EditTemplate tag name input
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: bugfix
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9600
|
||||
github-contributors: yaisog
|
||||
|
||||
The tag name input now calls `<<save-tiddler-actions>>` from the EditTemplate when Ctrl-Enter (or whichever key is assigned to input-accept-variant) is pressed.
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9565
|
||||
description: Add stylesheet wiki information
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: feature
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9565
|
||||
github-contributors: Leilei332
|
||||
|
||||
Extend wiki information tool to display stylesheet information.
|
||||
@@ -0,0 +1,18 @@
|
||||
title: $:/changenotes/5.4.0/#9513
|
||||
description: Bump markdown-it and its plugins to newest version
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: plugin
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9513
|
||||
github-contributors: Leilei332
|
||||
|
||||
Upgrade the markdown-it libraries used by the [[Markdown Plugin]]:
|
||||
|
||||
* markdown-it: 14.1.0
|
||||
* markdown-it-deflist: 3.0.0
|
||||
* markdown-it-footnote: 4.0.0
|
||||
* markdown-it-ins: 4.0.0
|
||||
* markdown-it-mark: 4.0.0
|
||||
* markdown-it-sub: 2.0.0
|
||||
* markdown-it-sup: 2.0.0
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9475
|
||||
description: Split escapecss.js into two platforms
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: performance
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9475
|
||||
github-contributors: Leilei332
|
||||
|
||||
Split [[$:/core/modules/utils/escapecss.js]] for two platforms: one for the browser, the other for Node.js. The `CSS.escape` polyfill is moved to `core-server`.
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9248
|
||||
description: Improve alert accessibility
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: usability
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9248 https://github.com/TiddlyWiki/TiddlyWiki5/pull/9575
|
||||
github-contributors: Leilei332
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
title: $:/changenotes/5.4.0/#9511/impacts/api
|
||||
changenote: $:/changenotes/5.4.0/#9511
|
||||
created: 20251220010540143
|
||||
modified: 20251220010540143
|
||||
tags: $:/tags/ImpactNote
|
||||
description: The diff-match-patch-es library uses different APIs
|
||||
impact-type: compatibility-break
|
||||
|
||||
* Default export and the class constructor has been removed
|
||||
* Function name has been unified to camelCase
|
||||
* Previous options like Diff_Timeout and Diff_EditCost are now passed as an options object in the arguments if needed
|
||||
@@ -0,0 +1,10 @@
|
||||
title: $:/changenotes/5.4.0/#9511
|
||||
description: Migrate diff-match-patch library to diff-match-patch-es
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: developer
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9511
|
||||
github-contributors: Leilei332
|
||||
|
||||
Migrate the unmaintained [[diff-match-patch|https://github.com/google/diff-match-patch]] library to the maintained and modern fork [[diff-match-patch-es|https://github.com/antfu/diff-match-patch-es]].
|
||||
@@ -0,0 +1,14 @@
|
||||
title: $:/changenotes/5.4.0/#9488
|
||||
description: Refactor base64 utility functions
|
||||
release: 5.4.0
|
||||
tags: $:/tags/ChangeNote
|
||||
change-type: enhancement
|
||||
change-category: internal
|
||||
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9488
|
||||
github-contributors: Leilei332
|
||||
|
||||
Refactor base64 utility functions in [[$:/core/modules/utils/utils.js]] to make it easier for maintainence.
|
||||
|
||||
* Split base64 utility functions to two platforms
|
||||
* Use `TextEncoder` and `TextDecoder` api in Node.js
|
||||
* Do not export `base64ToBytes` and `bytesToBase64`
|
||||
@@ -4,7 +4,7 @@ created: 20160216191710789
|
||||
delivery: Protocol
|
||||
description: Standard web protocol available on products such as Sharepoint
|
||||
method: save
|
||||
modified: 20220615155048712
|
||||
modified: 20260102081028704
|
||||
tags: Android Chrome Firefox [[Internet Explorer]] Linux Mac Opera PHP Safari Saving Windows iOS Edge
|
||||
title: Saving via WebDAV
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -19,6 +19,9 @@ Lightweight, portable and easy to use solutions
|
||||
|
||||
* [[rclone|https://rclone.org/commands/rclone_serve_webdav/]]
|
||||
** Running it can be as simple as: <br/>`rclone serve webdav some_directory_containing_tiddlywiki_files`
|
||||
* [[copyparty|https://github.com/9001/copyparty]]
|
||||
** Copyparty comes with a ~WebDAV server. Simply run `copyparty -v .::rwd:c,daw` to serve the current folder and visit [[http://[::1]:3923/]] to use TiddlyWiki
|
||||
** Note that you need to grant read, write and delete permission and add `daw` volflag to allow copyparty to overwrite existing files.
|
||||
* [[micromata dave - the simple webdav server|https://github.com/micromata/dave]]
|
||||
* [[dav-server|https://github.com/edrex/dav-server]] is a quick way to serve up a folder of HTML ~TiddlyWikis.
|
||||
* [[hacdias webdav server|https://github.com/hacdias/webdav/]]
|
||||
@@ -44,6 +47,10 @@ Lightweight, portable and easy to use solutions
|
||||
|
||||
* RCX is an open source file manager for Android based on //rclone//. It is available on both //F-Droid// and //Google Play//. Thanks to its integrated WebDAV server, it lets you edit the wikis that you keep in your pocket. You can share them with other devices on the local network too.
|
||||
|
||||
!! iOS
|
||||
|
||||
* There are no native apps that can serve a ~WebDAV server, but you can use rclone or copyparty on [[iSH Shell|https://apps.apple.com/cn/app/ish-shell/id1436902243]] or copyparty on [[a-Shell|https://apps.apple.com/cn/app/a-shell/id1473805438]].
|
||||
|
||||
!! Servers
|
||||
|
||||
Many [[NAS|https://en.wikipedia.org/wiki/NAS]] or [[Subversion|https://en.wikipedia.org/wiki/Apache_Subversion]] servers support ~WebDAV out of the box. Setting up your own server might take some effort though:
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
caption: ~TiddlyIE
|
||||
color: #4DB6AC
|
||||
community-author: David Jade
|
||||
created: 20131211220000000
|
||||
delivery: Browser Extension
|
||||
description: Browser extension for Internet Explorer
|
||||
method: save
|
||||
modified: 20200507201415232
|
||||
tags: [[Internet Explorer]] Saving $:/deprecated
|
||||
title: Saving with TiddlyIE
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.deprecated-since "5.3.6">>
|
||||
# Install the TiddlyIE add-on from:
|
||||
#* https://github.com/davidjade/TiddlyIE/releases
|
||||
# Restart Internet Explorer. IE will prompt you to enable the TiddlyIE add-on.
|
||||
#> You may also see a prompt to enable the //Microsoft Script Runtime//
|
||||
# [[Download]] an empty TiddlyWiki by saving this link:
|
||||
#> https://tiddlywiki.com/empty.html
|
||||
# Locate the file you just downloaded
|
||||
#* You may rename it, but be sure to keep the `.html` or `.htm` extension
|
||||
# Open the file in Internet Explorer
|
||||
# Try creating a new tiddler using the ''new tiddler'' <<.icon $:/core/images/new-button>> button in the sidebar. Type some content for the tiddler, and click the <<.icon $:/core/images/done-button>> ''ok'' button
|
||||
# Save your changes by clicking the <<.icon $:/core/images/save-button-dynamic>> ''save changes'' button in the sidebar. Internet Explorer will ask for your consent to save the file locally by presenting a file ''Save As'' dialog.
|
||||
# Refresh the browser window to verify that your changes have been saved correctly
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20230803034230294
|
||||
modified: 20230803043848449
|
||||
modified: 20260114112240512
|
||||
tags: [[Macro Examples]] [[tag-pill Macro]]
|
||||
title: tag-pill Macro (Examples)
|
||||
|
||||
@@ -12,3 +12,9 @@ This example displays the [[Definitions]] tag as an unclickable, but still-style
|
||||
<$transclude $variable=".example" n="2" eg="""<<tag-pill Definitions element-tag:"big" element-attributes:"inert">>"""/>
|
||||
|
||||
|
||||
<$transclude $variable=".example" n="3" eg="""\procedure tag-actions()
|
||||
<$action-confirm $message="test"/>
|
||||
\end
|
||||
|
||||
<$transclude $variable="tag-pill" tag="asdf" element-tag="$button" actions=<<tag-actions>>/>
|
||||
""">>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user