mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-09-15 14:21:23 +00:00
Compare commits
203
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
714ad2296b | ||
|
|
8c599e64c0 | ||
|
|
2b60da0dcf | ||
|
|
5d3f2685a3 | ||
|
|
685a80dfc6 | ||
|
|
3aec096a07 | ||
|
|
ddc59ee77b | ||
|
|
e0e6ab69b1 | ||
|
|
e4ce6b3433 | ||
|
|
47806feb85 | ||
|
|
5577a3d07b | ||
|
|
d62b75cceb | ||
|
|
30a51be168 | ||
|
|
38fa4486e4 | ||
|
|
d0a0198f49 | ||
|
|
52c60be3a0 | ||
|
|
b3279e348d | ||
|
|
516135e1b2 | ||
|
|
6845f1c47e | ||
|
|
6680967875 | ||
|
|
f9d5ee0ad7 | ||
|
|
68630c939d | ||
|
|
5e5937838b | ||
|
|
6c8ac9b6a7 | ||
|
|
0c60e1fa7a | ||
|
|
b40b6de3ae | ||
|
|
aac08a6252 | ||
|
|
40b353bd0e | ||
|
|
7efbd01801 | ||
|
|
5143138c16 | ||
|
|
8e65fdc06a | ||
|
|
ceb0817176 | ||
|
|
2f578589a0 | ||
|
|
916df90cc9 | ||
|
|
ea18c85a4c | ||
|
|
abf134afe4 | ||
|
|
45d2ca948a | ||
|
|
94b046b8cb | ||
|
|
c710a56b21 | ||
|
|
e681096127 | ||
|
|
24b433211d | ||
|
|
abf8ffdbca | ||
|
|
97e27d0dad | ||
|
|
855dc2fbb9 | ||
|
|
e1e34f4907 | ||
|
|
7196b9ee9b | ||
|
|
c0b3403f87 | ||
|
|
ed71c8262a | ||
|
|
2ececf21c7 | ||
|
|
7516d96eed | ||
|
|
4bf7e9d192 | ||
|
|
04cd3081e4 | ||
|
|
d27716c1e0 | ||
|
|
7f7f36d986 | ||
|
|
86a4e18134 | ||
|
|
304858c7c5 | ||
|
|
7ececf9e0f | ||
|
|
521e530e11 | ||
|
|
4c29dae4af | ||
|
|
f5317dc225 | ||
|
|
c952450c2e | ||
|
|
1eb7ec4402 | ||
|
|
9a0bbf831b | ||
|
|
a30854a4c7 | ||
|
|
869557f7d1 | ||
|
|
856057be81 | ||
|
|
c9f1154643 | ||
|
|
748f04c9e3 | ||
|
|
d391595836 | ||
|
|
967140a148 | ||
|
|
95e68b0437 | ||
|
|
8ddede1611 | ||
|
|
ceb200b08c | ||
|
|
00e5f48a59 | ||
|
|
ea0e9105bc | ||
|
|
51459815ba | ||
|
|
8c62935a01 | ||
|
|
839fa2417d | ||
|
|
1b8610e4d8 | ||
|
|
ca063cbe90 | ||
|
|
7d4328b2fb | ||
|
|
1ae224ab74 | ||
|
|
c308fc44c4 | ||
|
|
aa3fb85919 | ||
|
|
bd052a33f8 | ||
|
|
bb766c36c3 | ||
|
|
566a341328 | ||
|
|
9316234001 | ||
|
|
c1cb93c9df | ||
|
|
e46361fbc0 | ||
|
|
e730836d6f | ||
|
|
d050dd30cc | ||
|
|
635f6b5e76 | ||
|
|
40d0d542f7 | ||
|
|
a66d9a596c | ||
|
|
23063ea9c8 | ||
|
|
9c1f69e9c1 | ||
|
|
6abfcb631d | ||
|
|
14b11575d0 | ||
|
|
c9b1fbbb76 | ||
|
|
27c568e53e | ||
|
|
0023d3f6fa | ||
|
|
76ebe9d8e9 | ||
|
|
40444eade5 | ||
|
|
fe8723be49 | ||
|
|
56ea0789e1 | ||
|
|
fff648b959 | ||
|
|
e1cff6068c | ||
|
|
6721164f15 | ||
|
|
3c37aa267d | ||
|
|
a603146b3c | ||
|
|
f992f4ffab | ||
|
|
dfedd8594f | ||
|
|
ea84baa5a3 | ||
|
|
a4e4d36bf6 | ||
|
|
3ed481b2e2 | ||
|
|
27c60ff58d | ||
|
|
748ef8aa8d | ||
|
|
9cfa5a29fb | ||
|
|
5ea43ce212 | ||
|
|
df6bbbdedf | ||
|
|
37a461323e | ||
|
|
b29da7baac | ||
|
|
75b54457ed | ||
|
|
51f322c3c6 | ||
|
|
853af2d848 | ||
|
|
2c1cb33081 | ||
|
|
2f63abc12a | ||
|
|
5f80256576 | ||
|
|
aa837300d0 | ||
|
|
7f2baa17a9 | ||
|
|
39c6d8fb53 | ||
|
|
9afe5226f1 | ||
|
|
94aa37fe7e | ||
|
|
1e9c1ef82a | ||
|
|
6cde5e94ff | ||
|
|
fd0d3ccc27 | ||
|
|
1ad2e66cbc | ||
|
|
4699db9f89 | ||
|
|
d977b0ac5c | ||
|
|
7298684951 | ||
|
|
f78d8252af | ||
|
|
54260b5be8 | ||
|
|
95f12eb857 | ||
|
|
207a68cc59 | ||
|
|
b434b9d7ea | ||
|
|
b0013333de | ||
|
|
bcc30e305a | ||
|
|
34f4dfb903 | ||
|
|
32a3a3e478 | ||
|
|
c6520c4429 | ||
|
|
83d242fb2c | ||
|
|
ecafb7a4c0 | ||
|
|
0640e0abe2 | ||
|
|
a71ac56cc9 | ||
|
|
f518bdf27c | ||
|
|
0387b1100b | ||
|
|
c3a73fccd1 | ||
|
|
c25659d87c | ||
|
|
0c26a75472 | ||
|
|
a24dc0e9e8 | ||
|
|
a499ed0906 | ||
|
|
3cfb6b1202 | ||
|
|
ac769e5dcd | ||
|
|
ed01af8e47 | ||
|
|
92caa7312e | ||
|
|
478dce7009 | ||
|
|
f3c9cb2310 | ||
|
|
85fb634cae | ||
|
|
280701fbde | ||
|
|
01d3cde964 | ||
|
|
2ea3663ea7 | ||
|
|
78b6f6f442 | ||
|
|
3a4a8a206f | ||
|
|
aff5be7195 | ||
|
|
c4991a54a0 | ||
|
|
1d915389d9 | ||
|
|
f5b4b1781e | ||
|
|
65fcded29f | ||
|
|
962692c90c | ||
|
|
533414b1df | ||
|
|
ec27a4bf20 | ||
|
|
e1cf523e2c | ||
|
|
1ece822d7a | ||
|
|
b7a3418823 | ||
|
|
bb6d88f144 | ||
|
|
57c72756ef | ||
|
|
dda4c7fb10 | ||
|
|
fd3b96e2dd | ||
|
|
c07396c453 | ||
|
|
7fc255f90c | ||
|
|
4cd84a6ba1 | ||
|
|
fdfcd66c9b | ||
|
|
3983086b96 | ||
|
|
a61331e6ed | ||
|
|
8773a0433c | ||
|
|
846deb3039 | ||
|
|
111a168b0c | ||
|
|
02b4c04a56 | ||
|
|
9d5b5111d0 | ||
|
|
48cff401b2 | ||
|
|
7a866b93e3 | ||
|
|
a3acbaa2f1 |
@@ -5,17 +5,17 @@ on:
|
||||
- master
|
||||
- tiddlywiki-com
|
||||
env:
|
||||
NODE_VERSION: "22"
|
||||
NODE_VERSION: "22.22"
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
- run: "./bin/ci-test.sh"
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
@@ -30,8 +30,8 @@ jobs:
|
||||
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
|
||||
TW5_BUILD_OUTPUT: "./output/prerelease"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
- run: "./bin/ci-pre-build.sh"
|
||||
@@ -62,8 +62,8 @@ jobs:
|
||||
TW5_BUILD_OUTPUT: "./output"
|
||||
TW5_BUILD_ARCHIVE: "./output"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
- run: "./bin/ci-pre-build.sh"
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
steps:
|
||||
- name: build-size-check
|
||||
id: get_sizes
|
||||
uses: TiddlyWiki/cerebrus@v7
|
||||
uses: TiddlyWiki/cerebrus@v8.1
|
||||
with:
|
||||
pr_number: ${{ github.event.pull_request.number }}
|
||||
repo: ${{ github.repository }}
|
||||
@@ -52,4 +52,4 @@ jobs:
|
||||
pr_size: '${{ needs.calculate-build-size.outputs.pr_size }}',
|
||||
base_size: '${{ needs.calculate-build-size.outputs.base_size }}'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Build and check size
|
||||
uses: TiddlyWiki/cerebrus@v7
|
||||
uses: TiddlyWiki/cerebrus@v8.1
|
||||
with:
|
||||
pr_number: ${{ inputs.pr_number }}
|
||||
repo: ${{ github.repository }}
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
# Step 1: Validate PR paths
|
||||
- name: Validate PR Paths
|
||||
uses: TiddlyWiki/cerebrus@v6
|
||||
uses: TiddlyWiki/cerebrus@v8.1
|
||||
with:
|
||||
pr_number: ${{ github.event.pull_request.number }}
|
||||
repo: ${{ github.repository }}
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
# Step 2: Validate change notes
|
||||
- name: Validate Change Notes
|
||||
uses: TiddlyWiki/cerebrus@v7
|
||||
uses: TiddlyWiki/cerebrus@v8.1
|
||||
with:
|
||||
pr_number: ${{ github.event.pull_request.number }}
|
||||
repo: ${{ github.repository }}
|
||||
|
||||
+11
-1
@@ -2,10 +2,20 @@
|
||||
.c9/
|
||||
.vs/
|
||||
.vscode/
|
||||
.claude/
|
||||
# TiddlyWiki
|
||||
tmp/
|
||||
output/
|
||||
node_modules/
|
||||
$__StoryList.tid
|
||||
# Playwright
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
$__StoryList.tid
|
||||
/playwright/.auth/
|
||||
test-screenshots/
|
||||
test-output.txt
|
||||
.playwright-mcp
|
||||
# TiddlyWiki MPC
|
||||
.tw-mcp
|
||||
@@ -3,3 +3,4 @@
|
||||
tmp/
|
||||
output/
|
||||
node_modules/
|
||||
.claude/
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
# Default to the current version number for building the plugin library
|
||||
|
||||
if [ -z "$TW5_BUILD_VERSION" ]; then
|
||||
TW5_BUILD_VERSION=v5.4.0
|
||||
TW5_BUILD_VERSION=v5.5.0.
|
||||
fi
|
||||
|
||||
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ git clone --depth=1 --branch=main "https://github.com/TiddlyWiki/tiddlywiki.org-
|
||||
|
||||
# Make the CNAME file that GitHub Pages requires
|
||||
|
||||
echo "tiddlywiki.org" > $TWORG_BUILD_OUTPUT/CNAME
|
||||
# echo "tiddlywiki.org" > $TWORG_BUILD_OUTPUT/CNAME
|
||||
|
||||
# Delete any existing static content
|
||||
|
||||
|
||||
+7
-5
@@ -47,6 +47,13 @@ $tw.utils.hop = function(object,property) {
|
||||
/** @deprecated Use Array.isArray instead */
|
||||
$tw.utils.isArray = (value) => Array.isArray(value);
|
||||
|
||||
/*
|
||||
Determine if a value is a date, even across VM boundaries
|
||||
*/
|
||||
$tw.utils.isDate = function(value) {
|
||||
return Object.prototype.toString.call(value) === "[object Date]";
|
||||
};
|
||||
|
||||
/*
|
||||
Check if an array is equal by value and by reference.
|
||||
*/
|
||||
@@ -124,9 +131,6 @@ $tw.utils.pushTop = function(array,value) {
|
||||
return array;
|
||||
};
|
||||
|
||||
/** @deprecated Use instanceof Date instead */
|
||||
$tw.utils.isDate = (value) => value instanceof Date;
|
||||
|
||||
/** @deprecated Use array iterative methods instead */
|
||||
$tw.utils.each = function(object,callback) {
|
||||
if(object) {
|
||||
@@ -1577,8 +1581,6 @@ $tw.Wiki.prototype.processSafeMode = function() {
|
||||
this.addTiddler(new $tw.Tiddler({title: titleReportTiddler, text: report.join("\n\n")}));
|
||||
// Set $:/DefaultTiddlers to point to our report
|
||||
this.addTiddler(new $tw.Tiddler({title: "$:/DefaultTiddlers", text: "[[" + titleReportTiddler + "]]"}));
|
||||
// Switch to the safe mode layout
|
||||
this.addTiddler({title: "$:/layout", text: "$:/core/ui/SafeLayout"});
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
created: 20250909171928024
|
||||
modified: 20251110133437795
|
||||
tags: Community/Team
|
||||
leader: @kjharcombe
|
||||
team: @MotovunJack
|
||||
title: Infrastructure Team
|
||||
|
||||
@@ -12,4 +13,4 @@ The infrastructure includes:
|
||||
* github.com/TiddlyWiki
|
||||
* tiddlywiki.com DNS
|
||||
* Netlify account for PR previews
|
||||
* edit.tiddlywiki.com
|
||||
* edit.tiddlywiki.com
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
title: TiddlyWiki Team
|
||||
tags: Community/Team
|
||||
modified: 20260708095630754
|
||||
created: 20260708095630754
|
||||
leader: @BurningTreeC
|
||||
team:
|
||||
|
||||
The TiddlyDesktop development repository is at https://github.com/TiddlyWiki/TiddlyDesktop
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -217,6 +217,11 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
|
||||
fileInfo.isEditableFile = true;
|
||||
fileInfo.originalpath = options.fileInfo.originalpath;
|
||||
}
|
||||
// Propagate the pinFilepath flag (so generateTiddlerFilepath can short-circuit
|
||||
// FileSystemPaths and write back to the original location)
|
||||
if(options.fileInfo && !!options.fileInfo.pinFilepath) {
|
||||
fileInfo.pinFilepath = true;
|
||||
}
|
||||
// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace
|
||||
var hasUnsafeFields = false;
|
||||
$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {
|
||||
@@ -319,9 +324,16 @@ exports.generateTiddlerFilepath = function(title,options) {
|
||||
extension = options.extension || "",
|
||||
originalpath = (options.fileInfo && options.fileInfo.originalpath) ? options.fileInfo.originalpath : "",
|
||||
overwrite = options.fileInfo && options.fileInfo.overwrite || false,
|
||||
pinFilepath = !!(options.fileInfo && options.fileInfo.pinFilepath),
|
||||
filepath;
|
||||
// If the tiddler's filepath is pinned via tiddlywiki.files, the originalpath
|
||||
// wins and the path filters are skipped entirely.
|
||||
if(pinFilepath && originalpath) {
|
||||
var pinnedExt = path.extname(originalpath);
|
||||
filepath = originalpath.substring(0,originalpath.length - pinnedExt.length);
|
||||
}
|
||||
// Check if any of the pathFilters applies
|
||||
if(options.pathFilters && options.wiki) {
|
||||
if(!filepath && options.pathFilters && options.wiki) {
|
||||
$tw.utils.each(options.pathFilters,function(filter) {
|
||||
if(!filepath) {
|
||||
var source = options.wiki.makeTiddlerIterator([title]),
|
||||
@@ -336,13 +348,14 @@ exports.generateTiddlerFilepath = function(title,options) {
|
||||
//Use the originalpath without the extension
|
||||
var ext = path.extname(originalpath);
|
||||
filepath = originalpath.substring(0,originalpath.length - ext.length);
|
||||
// normalise "\" to "/" so the sanitiser keeps subdirectories
|
||||
// (it strips "\", not "/") instead of flattening them.
|
||||
filepath = filepath.split(path.sep).join("/");
|
||||
} else if(!filepath) {
|
||||
filepath = title;
|
||||
// Remove any forward or backward slashes so we don't create directories
|
||||
filepath = filepath.replace(/\/|\\/g,"_");
|
||||
}
|
||||
// Replace any Windows control codes
|
||||
filepath = filepath.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
|
||||
// Replace any leading spaces with the same number of underscores
|
||||
filepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, "_");});
|
||||
//If the path does not start with "." or ".." && a path seperator, then
|
||||
@@ -352,8 +365,23 @@ exports.generateTiddlerFilepath = function(title,options) {
|
||||
}
|
||||
// Replace any Unicode control codes
|
||||
filepath = filepath.replace(/[\x00-\x1f\x80-\x9f]/g,"_");
|
||||
// Replace any characters that can't be used in cross-platform filenames
|
||||
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_"));
|
||||
// Replace any characters that can't be used in cross-platform filenames.
|
||||
if(!pinFilepath) {
|
||||
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^|\\/g,"_"));
|
||||
}
|
||||
// Per segment (catches "sub/CON"), MUST be after transliterate which can create a
|
||||
// reserved name. Reserved names are wrapped on every path incl pinned;
|
||||
// trailing dots/spaces (Windows strips) fixed for generated names, not pinned.
|
||||
filepath = filepath.split("/").map(function(segment) {
|
||||
if(segment === "" || segment === "." || segment === "..") {
|
||||
return segment;
|
||||
}
|
||||
segment = segment.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
|
||||
if(!pinFilepath) {
|
||||
segment = segment.replace(/[. ]+$/,function(u) { return u.replace(/[. ]/g,"_"); });
|
||||
}
|
||||
return segment;
|
||||
}).join("/");
|
||||
// Replace any dots or spaces at the end of the extension with the same number of underscores
|
||||
extension = extension.replace(/[\. ]+$/, function (u) { return u.replace(/[\. ]/g, "_");});
|
||||
// Truncate the extension if it is too long
|
||||
|
||||
@@ -9,15 +9,14 @@ Serve tiddlers over http
|
||||
|
||||
"use strict";
|
||||
|
||||
let fs, url, path, querystring, crypto, zlib;
|
||||
let fs, path, crypto, zlib, URL;
|
||||
|
||||
if($tw.node) {
|
||||
fs = require("fs"),
|
||||
url = require("url"),
|
||||
path = require("path"),
|
||||
querystring = require("querystring"),
|
||||
crypto = require("crypto"),
|
||||
zlib = require("zlib");
|
||||
URL = require("url").URL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -260,8 +259,8 @@ Server.prototype.requestHandler = function(request,response,options) {
|
||||
state.wiki = options.wiki || self.wiki;
|
||||
state.boot = options.boot || self.boot;
|
||||
state.server = self;
|
||||
state.urlInfo = url.parse(request.url);
|
||||
state.queryParameters = querystring.parse(state.urlInfo.query);
|
||||
state.urlInfo = new URL(request.url, "http://localhost");
|
||||
state.queryParameters = Object.fromEntries(state.urlInfo.searchParams);
|
||||
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
|
||||
// Enable CORS
|
||||
if(this.corsEnable) {
|
||||
|
||||
@@ -255,4 +255,5 @@ ViewTemplateTags/Caption: View Template Tags
|
||||
ViewTemplateTags/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the tags area of a tiddler.
|
||||
WikiInformation/Caption: Wiki Information
|
||||
WikiInformation/Hint: This page summarises high level information about the configuration of this ~TiddlyWiki. It is designed to enable users to quickly share relevant aspects of the configuration of their ~TiddlyWiki with others, for example when seeking help in one of the forums. No private or personal information is included, and nothing is shared without being explicitly copied and pasted elsewhere
|
||||
WikiInformation/Drag/Caption: Drag this link to copy this tool to another wiki
|
||||
WikiInformation/Drag/Caption: Drag this link to copy this tool to another wiki
|
||||
WikiInformation/Generate/Caption: Click to generate wiki information report
|
||||
@@ -59,7 +59,6 @@ Manager/Controls/Show/Option/Tiddlers: tiddlers
|
||||
Manager/Controls/Show/Prompt: Show:
|
||||
Manager/Controls/Sort/Prompt: Sort by:
|
||||
Manager/Item/Colour: Colour
|
||||
Manager/Item/Editor: Editor
|
||||
Manager/Item/Fields: Fields
|
||||
Manager/Item/Icon/None: (none)
|
||||
Manager/Item/Icon: Icon
|
||||
|
||||
@@ -10,7 +10,7 @@ Advanced/ShadowInfo/Shadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text te
|
||||
Advanced/ShadowInfo/Shadow/Source: It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>
|
||||
Advanced/ShadowInfo/OverriddenShadow/Hint: It is overridden by an ordinary tiddler
|
||||
Advanced/CascadeInfo/Heading: Cascade Details
|
||||
Advanced/CascadeInfo/Hint: These are the view template segments (tagged <<tag "$:/tags/ViewTemplate">>) using a cascade filter and their resulting template for the current tiddler.
|
||||
Advanced/CascadeInfo/Hint: These are the view template segments that are resolved for each of the system view template cascades
|
||||
Advanced/CascadeInfo/Detail/View: View
|
||||
Advanced/CascadeInfo/Detail/ActiveCascadeFilter: Active cascade filter
|
||||
Advanced/CascadeInfo/Detail/Template: Template
|
||||
|
||||
@@ -78,7 +78,6 @@ class BackgroundActionTracker {
|
||||
fnProcess: (changes) => {
|
||||
if(this.hasChanged) {
|
||||
this.hasChanged = false;
|
||||
console.log("Processing background action", this.title);
|
||||
const tiddler = this.wiki.getTiddler(this.title);
|
||||
let doActions = true;
|
||||
if(tiddler && tiddler.fields.platforms) {
|
||||
@@ -89,6 +88,7 @@ class BackgroundActionTracker {
|
||||
}
|
||||
}
|
||||
if(doActions) {
|
||||
console.log("Processing background action", this.title);
|
||||
this.wiki.invokeActionString(
|
||||
this.actions,
|
||||
null,
|
||||
|
||||
@@ -156,14 +156,13 @@ Fix the height of textarea to fit content
|
||||
FramedEngine.prototype.fixHeight = function() {
|
||||
// Make sure styles are updated
|
||||
this.copyStyles();
|
||||
// If .editRows is initialised, it takes precedence
|
||||
if(this.widget.editTag === "textarea" && !this.widget.editRows) {
|
||||
if(this.widget.editTag === "textarea") {
|
||||
if(this.widget.editAutoHeight) {
|
||||
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
||||
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
||||
this.iframeNode.style.height = newHeight + "px";
|
||||
}
|
||||
} else {
|
||||
} else if(!this.widget.editRows) {
|
||||
var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10);
|
||||
fixedHeight = Math.max(fixedHeight,20);
|
||||
this.domNode.style.height = fixedHeight + "px";
|
||||
|
||||
@@ -100,13 +100,12 @@ SimpleEngine.prototype.getText = function() {
|
||||
Fix the height of textarea to fit content
|
||||
*/
|
||||
SimpleEngine.prototype.fixHeight = function() {
|
||||
// If .editRows is initialised, it takes precedence
|
||||
if((this.widget.editTag === "textarea") && !this.widget.editRows) {
|
||||
if(this.widget.editTag === "textarea") {
|
||||
if(this.widget.editAutoHeight) {
|
||||
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
||||
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
||||
}
|
||||
} else {
|
||||
} else if(!this.widget.editRows) {
|
||||
var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10);
|
||||
fixedHeight = Math.max(fixedHeight,20);
|
||||
this.domNode.style.height = fixedHeight + "px";
|
||||
|
||||
@@ -210,6 +210,29 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
this.editShowToolbar = this.wiki.getTiddlerText(ENABLE_TOOLBAR_TITLE,"yes");
|
||||
this.editShowToolbar = (this.editShowToolbar === "yes") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom);
|
||||
};
|
||||
|
||||
EditTextWidget.prototype.updateDomNodeClasses = function() {
|
||||
var domNodeClasses = this.engine.domNode.className.split(/\s+/).filter(Boolean),
|
||||
oldClasses = this.editClass.split(/\s+/).filter(Boolean),
|
||||
newClasses;
|
||||
|
||||
this.editClass = this.getAttribute("class","");
|
||||
newClasses = this.editClass.split(/\s+/).filter(Boolean);
|
||||
|
||||
// Remove classes assigned from the old value of the class attribute
|
||||
domNodeClasses = domNodeClasses.filter(function(className) {
|
||||
return !oldClasses.includes(className);
|
||||
});
|
||||
|
||||
// Add new classes from the updated class attribute
|
||||
domNodeClasses = domNodeClasses.concat(
|
||||
newClasses.filter(function(className) {
|
||||
return !domNodeClasses.includes(className);
|
||||
})
|
||||
);
|
||||
|
||||
this.engine.domNode.className = domNodeClasses.join(" ");
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
@@ -217,7 +240,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
EditTextWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
// Completely rerender if any of our attributes have changed
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else if(changedTiddlers[this.editRefreshTitle]) {
|
||||
@@ -226,6 +249,9 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
var editInfo = this.getEditInfo();
|
||||
this.updateEditor(editInfo.value,editInfo.type);
|
||||
}
|
||||
if(changedAttributes["class"]) {
|
||||
this.updateDomNodeClasses();
|
||||
}
|
||||
this.engine.fixHeight();
|
||||
if(this.editShowToolbar) {
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
|
||||
@@ -13,14 +13,15 @@ Export our filter prefix function
|
||||
exports.intersection = function(operationSubFunction) {
|
||||
return function(results,source,widget) {
|
||||
if(results.length !== 0) {
|
||||
var secondRunResults = operationSubFunction(source,widget);
|
||||
var firstRunResults = results.toArray();
|
||||
const secondRunResults = operationSubFunction(source,widget),
|
||||
secondRunSet = new Set(secondRunResults),
|
||||
firstRunResults = results.toArray();
|
||||
results.clear();
|
||||
$tw.utils.each(firstRunResults,function(title) {
|
||||
if(secondRunResults.indexOf(title) !== -1) {
|
||||
firstRunResults.forEach((title) => {
|
||||
if(secondRunSet.has(title)) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -13,33 +13,28 @@ Export our filter prefix function
|
||||
exports.sort = function(operationSubFunction,options) {
|
||||
return function(results,source,widget) {
|
||||
if(results.length > 0) {
|
||||
var suffixes = options.suffixes,
|
||||
const suffixes = options.suffixes,
|
||||
sortType = (suffixes[0] && suffixes[0][0]) ? suffixes[0][0] : "string",
|
||||
invert = suffixes[1] ? (suffixes[1].indexOf("reverse") !== -1) : false,
|
||||
isCaseSensitive = suffixes[1] ? (suffixes[1].indexOf("casesensitive") !== -1) : false,
|
||||
invert = suffixes[1] ? suffixes[1].includes("reverse") : false,
|
||||
isCaseSensitive = suffixes[1] ? suffixes[1].includes("casesensitive") : false,
|
||||
inputTitles = results.toArray(),
|
||||
sortKeys = [],
|
||||
indexes = new Array(inputTitles.length),
|
||||
compareFn;
|
||||
results.each(function(title) {
|
||||
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
|
||||
"currentTiddler": "" + title,
|
||||
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
|
||||
}));
|
||||
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
|
||||
results.each((title) => {
|
||||
const key = operationSubFunction(
|
||||
options.wiki.makeTiddlerIterator([title]),
|
||||
widget.makeFakeWidgetWithVariables({
|
||||
"currentTiddler": "" + title,
|
||||
"..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
|
||||
})
|
||||
);
|
||||
sortKeys.push(key[0] || "");
|
||||
});
|
||||
results.clear();
|
||||
// Prepare an array of indexes to sort
|
||||
for(var t=0; t<inputTitles.length; t++) {
|
||||
indexes[t] = t;
|
||||
}
|
||||
// Sort the indexes
|
||||
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
|
||||
indexes = indexes.sort(function(a,b) {
|
||||
return compareFn(sortKeys[a],sortKeys[b]);
|
||||
});
|
||||
// Add to results in correct order
|
||||
$tw.utils.each(indexes,function(index) {
|
||||
let indexes = Array.from(inputTitles.keys());
|
||||
indexes.sort((a,b) => compareFn(sortKeys[a],sortKeys[b]));
|
||||
indexes.forEach((index) => {
|
||||
results.push(inputTitles[index]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ exports.compileFilter = function(filterString) {
|
||||
var varTree = $tw.utils.parseFilterVariable(operand.text);
|
||||
var resultList = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source});
|
||||
if((resultList.length > 0 && resultList[0] !== undefined) || resultList.length === 0) {
|
||||
operand.multiValue = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source}) || [];
|
||||
operand.multiValue = resultList || [];
|
||||
operand.value = operand.multiValue[0] || "";
|
||||
} else {
|
||||
operand.value = "";
|
||||
|
||||
@@ -9,69 +9,56 @@ Filter operators for manipulating the current selection list
|
||||
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Fetch titles from the current list
|
||||
*/
|
||||
const prepare_results = (source) => {
|
||||
const results = [];
|
||||
source((tiddler,title) => results.push(title));
|
||||
return results;
|
||||
};
|
||||
|
||||
/*
|
||||
Order a list
|
||||
*/
|
||||
exports.order = function(source,operator,options) {
|
||||
var results = [];
|
||||
if(operator.operand.toLowerCase() === "reverse") {
|
||||
source(function(tiddler,title) {
|
||||
results.unshift(title);
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
}
|
||||
return results;
|
||||
const results = prepare_results(source);
|
||||
return operator.operand.toLowerCase() === "reverse" ?
|
||||
results.reverse() :
|
||||
results;
|
||||
};
|
||||
|
||||
/*
|
||||
Reverse list
|
||||
*/
|
||||
exports.reverse = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.unshift(title);
|
||||
});
|
||||
return results;
|
||||
return prepare_results(source).reverse();
|
||||
};
|
||||
|
||||
/*
|
||||
First entry/entries in list
|
||||
*/
|
||||
exports.first = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,1),
|
||||
results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
return results.slice(0,count);
|
||||
const count = $tw.utils.getInt(operator.operand,1);
|
||||
return prepare_results(source).slice(0,count);
|
||||
};
|
||||
|
||||
/*
|
||||
Last entry/entries in list
|
||||
*/
|
||||
exports.last = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,1),
|
||||
results = [];
|
||||
if(count === 0) return results;
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
return results.slice(-count);
|
||||
const count = $tw.utils.getInt(operator.operand,1);
|
||||
return count === 0 ?
|
||||
[] :
|
||||
prepare_results(source).slice(-count);
|
||||
};
|
||||
|
||||
/*
|
||||
All but the first entry/entries of the list
|
||||
*/
|
||||
exports.rest = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,1),
|
||||
results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
return results.slice(count);
|
||||
const count = $tw.utils.getInt(operator.operand,1);
|
||||
return prepare_results(source).slice(count);
|
||||
};
|
||||
exports.butfirst = exports.rest;
|
||||
exports.bf = exports.rest;
|
||||
@@ -80,12 +67,9 @@ exports.bf = exports.rest;
|
||||
All but the last entry/entries of the list
|
||||
*/
|
||||
exports.butlast = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,1),
|
||||
results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
var index = count === 0 ? results.length : -count;
|
||||
const count = $tw.utils.getInt(operator.operand,1),
|
||||
results = prepare_results(source),
|
||||
index = count === 0 ? results.length : -count;
|
||||
return results.slice(0,index);
|
||||
};
|
||||
exports.bl = exports.butlast;
|
||||
@@ -94,22 +78,14 @@ exports.bl = exports.butlast;
|
||||
The nth member of the list
|
||||
*/
|
||||
exports.nth = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,1),
|
||||
results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
return results.slice(count - 1,count);
|
||||
const count = $tw.utils.getInt(operator.operand,1);
|
||||
return prepare_results(source).slice(count - 1,count);
|
||||
};
|
||||
|
||||
/*
|
||||
The zero based nth member of the list
|
||||
*/
|
||||
exports.zth = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,0),
|
||||
results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
return results.slice(count,count + 1);
|
||||
};
|
||||
const count = $tw.utils.getInt(operator.operand,0);
|
||||
return prepare_results(source).slice(count,count + 1);
|
||||
};
|
||||
@@ -13,37 +13,22 @@ Filter operator for checking if a title starts with a prefix
|
||||
Export our filter function
|
||||
*/
|
||||
exports.prefix = function(source,operator,options) {
|
||||
var results = [],
|
||||
suffixes = (operator.suffixes || [])[0] || [];
|
||||
if(suffixes.indexOf("caseinsensitive") !== -1) {
|
||||
var operand = operator.operand.toLowerCase();
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title.toLowerCase().substr(0,operand.length) !== operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(title.toLowerCase().substr(0,operand.length) === operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
const results = [],
|
||||
suffixes = (operator.suffixes || [])[0] || [],
|
||||
caseInsensitive = suffixes.includes("caseinsensitive"),
|
||||
negate = operator.prefix === "!";
|
||||
|
||||
const operand = caseInsensitive ?
|
||||
operator.operand.toLowerCase() :
|
||||
operator.operand;
|
||||
|
||||
source((tiddler,title) => {
|
||||
const value = caseInsensitive ? title.toLowerCase() : title,
|
||||
matches = value.startsWith(operand);
|
||||
if(negate ? !matches : matches) {
|
||||
results.push(title);
|
||||
}
|
||||
} else {
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title.substr(0,operator.operand.length) !== operator.operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(title.substr(0,operator.operand.length) === operator.operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
};
|
||||
};
|
||||
@@ -14,31 +14,31 @@ Export our filter function
|
||||
*/
|
||||
exports.sort = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,false,undefined,operator.operands[1]);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,false);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.nsort = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,true,undefined,operator.operands[1]);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,true);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.sortan = function(source, operator, options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results, operator.operands[0] || "title", operator.prefix === "!",false,false,true,operator.operands[1]);
|
||||
options.wiki.sortTiddlers(results, operator.operand || "title", operator.prefix === "!",false,false,true);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.sortcs = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,false,undefined,operator.operands[1]);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,false);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.nsortcs = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,true,undefined,operator.operands[1]);
|
||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,true);
|
||||
return results;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@ Export our filter function
|
||||
*/
|
||||
exports.sortsub = function(source,operator,options) {
|
||||
// Compile the subfilter
|
||||
var filterFn = options.wiki.compileFilter(operator.operand);
|
||||
let filterFn = options.wiki.compileFilter(operator.operand);
|
||||
// Collect the input titles and the corresponding sort keys
|
||||
var inputTitles = [],
|
||||
let inputTitles = [],
|
||||
sortKeys = [];
|
||||
source(function(tiddler,title) {
|
||||
inputTitles.push(title);
|
||||
var r = filterFn.call(options.wiki,function(iterator) {
|
||||
let r = filterFn.call(options.wiki,function(iterator) {
|
||||
iterator(options.wiki.getTiddler(title),title);
|
||||
},options.widget.makeFakeWidgetWithVariables({
|
||||
"currentTiddler": "" + title,
|
||||
@@ -29,17 +29,12 @@ exports.sortsub = function(source,operator,options) {
|
||||
sortKeys.push(r[0] || "");
|
||||
});
|
||||
// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays
|
||||
var indexes = new Array(inputTitles.length);
|
||||
for(var t=0; t<inputTitles.length; t++) {
|
||||
indexes[t] = t;
|
||||
}
|
||||
let indexes = Array.from(inputTitles.keys());
|
||||
// Sort the indexes
|
||||
var compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
|
||||
indexes = indexes.sort(function(a,b) {
|
||||
return compareFn(sortKeys[a],sortKeys[b]);
|
||||
});
|
||||
let compareFn = $tw.utils.makeCompareFunction(operator.suffix,{defaultType: "string",invert: operator.prefix === "!"});
|
||||
indexes = indexes.sort((a,b) => compareFn(sortKeys[a],sortKeys[b]));
|
||||
// Make the results array in order
|
||||
var results = [];
|
||||
let results = [];
|
||||
$tw.utils.each(indexes,function(index) {
|
||||
results.push(inputTitles[index]);
|
||||
});
|
||||
|
||||
@@ -91,22 +91,35 @@ function diffLineWordMode(text1,text2,mode) {
|
||||
return diffs;
|
||||
}
|
||||
|
||||
exports.makepatches = function(source,operator,options) {
|
||||
var suffix = operator.suffix || "",
|
||||
result = [];
|
||||
|
||||
source(function(tiddler,title) {
|
||||
let diffs, patches;
|
||||
if(suffix === "lines" || suffix === "words") {
|
||||
diffs = diffLineWordMode(title,operator.operand,suffix);
|
||||
patches = dmp.patchMake(title,diffs);
|
||||
exports.makepatches = function(source, operator, options) {
|
||||
const suffixes = operator.suffixes || [],
|
||||
[modeArg = [], formatArg = []] = suffixes,
|
||||
modeSuffix = modeArg[0] || operator.suffix || "",
|
||||
mode = ["lines", "words"].includes(modeSuffix) ? modeSuffix : "",
|
||||
isJson = formatArg[0] === "json",
|
||||
results = [];
|
||||
|
||||
source((tiddler, title) => {
|
||||
if (isJson) {
|
||||
const diffs = (mode === "lines" || mode === "words")
|
||||
? diffLineWordMode(title, operator.operand, mode)
|
||||
: dmp.diffMain(title, operator.operand);
|
||||
|
||||
const jsonOutput = diffs.map(([typeCode, text]) => ({
|
||||
type: typeCode === 1 ? "insert" : (typeCode === -1 ? "delete" : "equal"),
|
||||
text
|
||||
}));
|
||||
results.push(JSON.stringify(jsonOutput));
|
||||
} else {
|
||||
patches = dmp.patchMake(title,operator.operand);
|
||||
const patches = (mode === "lines" || mode === "words")
|
||||
? dmp.patchMake(title, diffLineWordMode(title, operator.operand, mode))
|
||||
: dmp.patchMake(title, operator.operand);
|
||||
|
||||
results.push(dmp.patchToText(patches));
|
||||
}
|
||||
Array.prototype.push.apply(result,[dmp.patchToText(patches)]);
|
||||
});
|
||||
|
||||
return result;
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.applypatches = makeStringBinaryOperator(
|
||||
@@ -235,4 +248,4 @@ exports.charcode = function(source,operator,options) {
|
||||
}
|
||||
});
|
||||
return [chars.join("")];
|
||||
};
|
||||
};
|
||||
@@ -13,11 +13,12 @@ Filter operator returning its operand evaluated as a filter
|
||||
Export our filter function
|
||||
*/
|
||||
exports.subfilter = function(source,operator,options) {
|
||||
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
|
||||
const list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
|
||||
if(operator.prefix === "!") {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
if(list.indexOf(title) === -1) {
|
||||
const results = [],
|
||||
listSet = new Set(list);
|
||||
source((tiddler,title) => {
|
||||
if(!listSet.has(title)) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,41 +13,27 @@ Filter operator for checking if a title ends with a suffix
|
||||
Export our filter function
|
||||
*/
|
||||
exports.suffix = function(source,operator,options) {
|
||||
var results = [],
|
||||
const results = [],
|
||||
suffixes = (operator.suffixes || [])[0] || [];
|
||||
|
||||
if(!operator.operand) {
|
||||
source(function(tiddler,title) {
|
||||
source((tiddler,title) => {
|
||||
results.push(title);
|
||||
});
|
||||
} else if(suffixes.indexOf("caseinsensitive") !== -1) {
|
||||
var operand = operator.operand.toLowerCase();
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title.toLowerCase().substr(-operand.length) !== operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(title.toLowerCase().substr(-operand.length) === operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title.substr(-operator.operand.length) !== operator.operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(title.substr(-operator.operand.length) === operator.operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
const caseInsensitive = suffixes.indexOf("caseinsensitive") !== -1,
|
||||
negate = operator.prefix === "!",
|
||||
operand = caseInsensitive ? operator.operand.toLowerCase() : operator.operand;
|
||||
|
||||
source((tiddler,title) => {
|
||||
const value = caseInsensitive ? title.toLowerCase() : title,
|
||||
matches = value.endsWith(operand);
|
||||
if(negate ? !matches : matches) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
@@ -22,12 +22,11 @@ exports.tag = function(source,operator,options) {
|
||||
});
|
||||
} else {
|
||||
// Old semantics:
|
||||
var tiddlers;
|
||||
if(operator.prefix === "!") {
|
||||
// Returns a copy of the input if operator.operand is missing
|
||||
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
|
||||
const excludeTagSet = new Set(options.wiki.getTiddlersWithTag(operator.operand));
|
||||
source(function(tiddler,title) {
|
||||
if(tiddlers.indexOf(title) === -1) {
|
||||
if(!excludeTagSet.has(title)) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
@@ -39,9 +38,9 @@ exports.tag = function(source,operator,options) {
|
||||
return indexedResults;
|
||||
}
|
||||
} else {
|
||||
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
|
||||
const includeTagSet = new Set(options.wiki.getTiddlersWithTag(operator.operand));
|
||||
source(function(tiddler,title) {
|
||||
if(tiddlers.indexOf(title) !== -1) {
|
||||
if(includeTagSet.has(title)) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,20 +11,18 @@ Extended filter operators to manipulate the current list.
|
||||
|
||||
/*
|
||||
Fetch titles from the current list
|
||||
*/
|
||||
var prepare_results = function (source) {
|
||||
var results = [];
|
||||
source(function (tiddler, title) {
|
||||
results.push(title);
|
||||
});
|
||||
*/
|
||||
const prepare_results = (source) => {
|
||||
const results = [];
|
||||
source((tiddler,title) => results.push(title));
|
||||
return results;
|
||||
};
|
||||
|
||||
/*
|
||||
Moves a number of items from the tail of the current list before the item named in the operand
|
||||
*/
|
||||
exports.putbefore = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.putbefore = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand),
|
||||
count = $tw.utils.getInt(operator.suffix,1);
|
||||
return (index === -1) ?
|
||||
@@ -34,9 +32,9 @@ exports.putbefore = function (source, operator) {
|
||||
|
||||
/*
|
||||
Moves a number of items from the tail of the current list after the item named in the operand
|
||||
*/
|
||||
exports.putafter = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.putafter = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand),
|
||||
count = $tw.utils.getInt(operator.suffix,1);
|
||||
return (index === -1) ?
|
||||
@@ -46,9 +44,9 @@ exports.putafter = function (source, operator) {
|
||||
|
||||
/*
|
||||
Replaces the item named in the operand with a number of items from the tail of the current list
|
||||
*/
|
||||
exports.replace = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.replace = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand),
|
||||
count = $tw.utils.getInt(operator.suffix,1);
|
||||
return (index === -1) ?
|
||||
@@ -58,39 +56,39 @@ exports.replace = function (source, operator) {
|
||||
|
||||
/*
|
||||
Moves a number of items from the tail of the current list to the head of the list
|
||||
*/
|
||||
exports.putfirst = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.putfirst = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
count = $tw.utils.getInt(operator.suffix,1);
|
||||
return results.slice(-count).concat(results.slice(0, -count));
|
||||
return [...results.slice(-count), ...results.slice(0, -count)];
|
||||
};
|
||||
|
||||
/*
|
||||
Moves a number of items from the head of the current list to the tail of the list
|
||||
*/
|
||||
exports.putlast = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.putlast = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
count = $tw.utils.getInt(operator.suffix,1);
|
||||
return results.slice(count).concat(results.slice(0, count));
|
||||
return [...results.slice(count), ...results.slice(0, count)];
|
||||
};
|
||||
|
||||
/*
|
||||
Moves the item named in the operand a number of places forward or backward in the list
|
||||
*/
|
||||
exports.move = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.move = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand),
|
||||
count = $tw.utils.getInt(operator.suffix,1),
|
||||
marker = results.splice(index, 1),
|
||||
offset = (index + count) > 0 ? index + count : 0;
|
||||
offset = (index + count) > 0 ? index + count : 0;
|
||||
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
|
||||
};
|
||||
|
||||
/*
|
||||
Returns the items from the current list that are after the item named in the operand
|
||||
*/
|
||||
exports.allafter = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.allafter = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand);
|
||||
return (index === -1) ? [] :
|
||||
(operator.suffix) ? results.slice(index) :
|
||||
@@ -99,9 +97,9 @@ exports.allafter = function (source, operator) {
|
||||
|
||||
/*
|
||||
Returns the items from the current list that are before the item named in the operand
|
||||
*/
|
||||
exports.allbefore = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
*/
|
||||
exports.allbefore = function(source,operator) {
|
||||
const results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand);
|
||||
return (index === -1) ? [] :
|
||||
(operator.suffix) ? results.slice(0, index + 1) :
|
||||
@@ -110,9 +108,9 @@ exports.allbefore = function (source, operator) {
|
||||
|
||||
/*
|
||||
Appends the items listed in the operand array to the tail of the current list
|
||||
*/
|
||||
exports.append = function (source, operator) {
|
||||
var append = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||
*/
|
||||
exports.append = function(source,operator) {
|
||||
const append = $tw.utils.parseStringArray(operator.operand,"true"),
|
||||
results = prepare_results(source),
|
||||
count = parseInt(operator.suffix) || append.length;
|
||||
return (append.length === 0) ? results :
|
||||
@@ -122,9 +120,9 @@ exports.append = function (source, operator) {
|
||||
|
||||
/*
|
||||
Prepends the items listed in the operand array to the head of the current list
|
||||
*/
|
||||
exports.prepend = function (source, operator) {
|
||||
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||
*/
|
||||
exports.prepend = function(source,operator) {
|
||||
const prepend = $tw.utils.parseStringArray(operator.operand,"true"),
|
||||
results = prepare_results(source),
|
||||
count = $tw.utils.getInt(operator.suffix,prepend.length);
|
||||
return (prepend.length === 0) ? results :
|
||||
@@ -134,21 +132,19 @@ exports.prepend = function (source, operator) {
|
||||
|
||||
/*
|
||||
Returns all items from the current list except the items listed in the operand array
|
||||
*/
|
||||
exports.remove = function (source, operator) {
|
||||
var array = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||
results = prepare_results(source),
|
||||
count = parseInt(operator.suffix) || array.length,
|
||||
p,
|
||||
len,
|
||||
index;
|
||||
len = array.length - 1;
|
||||
for(p = 0; p < count; ++p) {
|
||||
if(operator.prefix) {
|
||||
index = results.indexOf(array[len - p]);
|
||||
} else {
|
||||
index = results.indexOf(array[p]);
|
||||
}
|
||||
*/
|
||||
exports.remove = function(source, operator) {
|
||||
const array = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||
results = prepare_results(source);
|
||||
|
||||
if(array.length === 0) {
|
||||
return results;
|
||||
}
|
||||
const count = parseInt(operator.suffix, 10) || array.length,
|
||||
targetItems = operator.prefix ? array.slice(-count).reverse() : array.slice(0, count);
|
||||
|
||||
for(const item of targetItems) {
|
||||
const index = results.indexOf(item);
|
||||
if(index !== -1) {
|
||||
results.splice(index, 1);
|
||||
}
|
||||
@@ -158,40 +154,38 @@ exports.remove = function (source, operator) {
|
||||
|
||||
/*
|
||||
Returns all items from the current list sorted in the order of the items in the operand array
|
||||
*/
|
||||
exports.sortby = function (source, operator) {
|
||||
var results = prepare_results(source);
|
||||
*/
|
||||
exports.sortby = function(source,operator) {
|
||||
const results = prepare_results(source);
|
||||
if(!results || results.length < 2) {
|
||||
return results;
|
||||
}
|
||||
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
|
||||
results.sort(function (a, b) {
|
||||
return lookup.indexOf(a) - lookup.indexOf(b);
|
||||
});
|
||||
return results;
|
||||
const lookup = $tw.utils.parseStringArray(operator.operand,"true"),
|
||||
// The "end" suffix places unlisted titles last, the default is first
|
||||
unlisted = operator.suffix === "end" ? lookup.length : -1,
|
||||
position = (title) => {
|
||||
const index = lookup.indexOf(title);
|
||||
return index === -1 ? unlisted : index;
|
||||
};
|
||||
return results.sort((a,b) => position(a) - position(b));
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Removes all duplicate items from the current list
|
||||
*/
|
||||
exports.unique = function (source, operator) {
|
||||
var results = prepare_results(source);
|
||||
var set = results.reduce(function (a, b) {
|
||||
if(a.indexOf(b) < 0) {
|
||||
a.push(b);
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
return set;
|
||||
*/
|
||||
exports.unique = function(source, operator) {
|
||||
return Array.from(new Set(prepare_results(source)));
|
||||
};
|
||||
|
||||
var cycleValueInArray = function(results,operands,stepSize) {
|
||||
var resultsIndex,
|
||||
const cycleValueInArray = function(results,operands,stepSize) {
|
||||
let resultsIndex,
|
||||
step = stepSize || 1,
|
||||
i = 0,
|
||||
opLength = operands.length,
|
||||
nextOperandIndex;
|
||||
for(i; i < opLength; i++) {
|
||||
const opLength = operands.length;
|
||||
|
||||
for(; i < opLength; i++) {
|
||||
resultsIndex = results.indexOf(operands[i]);
|
||||
if(resultsIndex !== -1) {
|
||||
break;
|
||||
@@ -213,18 +207,19 @@ var cycleValueInArray = function(results,operands,stepSize) {
|
||||
|
||||
/*
|
||||
Toggles an item in the current list.
|
||||
*/
|
||||
*/
|
||||
exports.toggle = function(source,operator) {
|
||||
return cycleValueInArray(prepare_results(source),operator.operands);
|
||||
};
|
||||
|
||||
exports.cycle = function(source,operator) {
|
||||
var results = prepare_results(source),
|
||||
operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]),
|
||||
step = $tw.utils.getInt(operator.operands[1]||"",1);
|
||||
const results = prepare_results(source),
|
||||
operands = operator.operand.length ? $tw.utils.parseStringArray(operator.operand,"true") : [""];
|
||||
let step = $tw.utils.getInt(operator.operands[1] || "",1);
|
||||
|
||||
if(step < 0) {
|
||||
operands.reverse();
|
||||
step = Math.abs(step);
|
||||
}
|
||||
return cycleValueInArray(results,operands,step);
|
||||
};
|
||||
};
|
||||
@@ -88,10 +88,11 @@ BackSubIndexer.prototype.update = function(updateDescriptor) {
|
||||
var newTargets = [],
|
||||
oldTargets = [],
|
||||
self = this;
|
||||
if(updateDescriptor.old.exists) {
|
||||
// System tiddlers are never indexed as sources, matching the _init() scan
|
||||
if(updateDescriptor.old.exists && !this.wiki.isSystemTiddler(updateDescriptor.old.tiddler.fields.title)) {
|
||||
oldTargets = this._getTarget(updateDescriptor.old.tiddler);
|
||||
}
|
||||
if(updateDescriptor.new.exists) {
|
||||
if(updateDescriptor.new.exists && !this.wiki.isSystemTiddler(updateDescriptor.new.tiddler.fields.title)) {
|
||||
newTargets = this._getTarget(updateDescriptor.new.tiddler);
|
||||
}
|
||||
|
||||
|
||||
+151
-114
@@ -107,7 +107,7 @@ exports.parseStringLiteral = function(source,pos) {
|
||||
type: "string",
|
||||
start: pos
|
||||
};
|
||||
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')|\[\[((?:[^\]]|\](?!\]))*)\]\]/g;
|
||||
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')|\[\[((?:[^\]]|\](?!\]))*)\]\]/y;
|
||||
reString.lastIndex = pos;
|
||||
var match = reString.exec(source);
|
||||
if(match && match.index === pos) {
|
||||
@@ -221,7 +221,7 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) {
|
||||
orderedAttributes: []
|
||||
};
|
||||
// Define our regexps
|
||||
var reVarName = /([^\s>"'=:]+)/g;
|
||||
var reVarName = /([^\s>"'=]+)/y;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double opening angle bracket
|
||||
@@ -237,9 +237,11 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) {
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(node,"$variable",token.match[1]);
|
||||
pos = token.end;
|
||||
// Check that the tag is terminated by a space or >>
|
||||
if(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === ">" && source.charAt(pos + 1) === ">") ) {
|
||||
return null;
|
||||
// Check that the tag is terminated by a space or >>, and that there is a closing >> somewhere ahead
|
||||
if(!(source.charAt(pos) === ">" && source.charAt(pos + 1) === ">") ) {
|
||||
if(source.indexOf(">>",pos) === -1) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Process attributes
|
||||
pos = $tw.utils.parseMacroParametersAsAttributes(node,source,pos);
|
||||
@@ -267,7 +269,7 @@ exports.parseMVVReferenceAsTransclusion = function(source,pos) {
|
||||
orderedAttributes: []
|
||||
};
|
||||
// Define our regexps
|
||||
var reVarName = /([^\s>"'=:)]+)/g;
|
||||
var reVarName = /([^\s>"'=)]+)/y;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double opening parenthesis
|
||||
@@ -323,18 +325,24 @@ exports.parseMacroParameterAsAttribute = function(source,pos) {
|
||||
start: pos
|
||||
};
|
||||
// Define our regexps
|
||||
var reAttributeName = /([^\/\s>"'`=:]+)/g,
|
||||
reUnquotedAttribute = /((?:(?:>(?!>))|[^\s>"'])+)/g,
|
||||
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g,
|
||||
reIndirectValue = /\{\{([^\}]+)\}\}/g,
|
||||
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g;
|
||||
var reAttributeName = /([^\/\s>"'`=:]+)/y,
|
||||
reStrictIdentifier = /^[A-Za-z0-9\-_]+$/,
|
||||
reUnquotedAttribute = /(?!<<)((?:(?:>(?!>))|[^\s>"'])+)/y,
|
||||
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/y,
|
||||
reIndirectValue = /\{\{([^\}]+)\}\}/y,
|
||||
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/y;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Get the attribute name and the separator token
|
||||
var nameToken = $tw.utils.parseTokenRegExp(source,pos,reAttributeName),
|
||||
namePos = nameToken && $tw.utils.skipWhiteSpace(source,nameToken.end),
|
||||
separatorToken = nameToken && $tw.utils.parseTokenRegExp(source,namePos,/=|:/g),
|
||||
separatorToken = nameToken && $tw.utils.parseTokenRegExp(source,namePos,/=|:/y),
|
||||
isNewStyleSeparator = false; // If there is no separator then we don't allow new style values
|
||||
// Colon separator requires a strict identifier name to avoid mis-parsing values like $:/foo
|
||||
if(nameToken && separatorToken && separatorToken.match[0] === ":" && !reStrictIdentifier.test(nameToken.match[1])) {
|
||||
nameToken = null;
|
||||
separatorToken = null;
|
||||
}
|
||||
// If we have a name and a separator then we have a named attribute
|
||||
if(nameToken && separatorToken) {
|
||||
node.name = nameToken.match[1];
|
||||
@@ -345,64 +353,78 @@ exports.parseMacroParameterAsAttribute = function(source,pos) {
|
||||
}
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a string literal
|
||||
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
|
||||
if(stringLiteral) {
|
||||
pos = stringLiteral.end;
|
||||
node.type = "string";
|
||||
node.value = stringLiteral.value;
|
||||
// Mark the value as having been quoted in the source
|
||||
node.quoted = true;
|
||||
} else {
|
||||
// Look for a filtered value
|
||||
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
|
||||
if(filteredValue && isNewStyleSeparator) {
|
||||
pos = filteredValue.end;
|
||||
node.type = "filtered";
|
||||
node.filter = filteredValue.match[1];
|
||||
} else {
|
||||
|
||||
do {
|
||||
// Look for a string literal
|
||||
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
|
||||
if(stringLiteral) {
|
||||
pos = stringLiteral.end;
|
||||
node.type = "string";
|
||||
node.value = stringLiteral.value;
|
||||
// Mark the value as having been quoted in the source
|
||||
node.quoted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(isNewStyleSeparator) {
|
||||
// Look for a filtered value
|
||||
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
|
||||
if(filteredValue) {
|
||||
pos = filteredValue.end;
|
||||
node.type = "filtered";
|
||||
node.filter = filteredValue.match[1];
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for an indirect value
|
||||
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
|
||||
if(indirectValue && isNewStyleSeparator) {
|
||||
if(indirectValue) {
|
||||
pos = indirectValue.end;
|
||||
node.type = "indirect";
|
||||
node.textReference = indirectValue.match[1];
|
||||
} else {
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation && isNewStyleSeparator) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
} else {
|
||||
// Look for an MVV reference value
|
||||
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
|
||||
if(mvvReference && isNewStyleSeparator) {
|
||||
pos = mvvReference.end;
|
||||
node.type = "macro";
|
||||
node.value = mvvReference;
|
||||
node.isMVV = true;
|
||||
} else {
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue && isNewStyleSeparator) {
|
||||
pos = substitutedValue.end;
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
} else {
|
||||
// Look for a unquoted value
|
||||
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
|
||||
if(unquotedValue) {
|
||||
pos = unquotedValue.end;
|
||||
node.type = "string";
|
||||
node.value = unquotedValue.match[1];
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for an MVV reference value
|
||||
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
|
||||
if(mvvReference) {
|
||||
pos = mvvReference.end;
|
||||
node.type = "macro";
|
||||
node.value = mvvReference;
|
||||
node.isMVV = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for a substituted value
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue) {
|
||||
pos = substitutedValue.end;
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a unquoted value
|
||||
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
|
||||
if(unquotedValue) {
|
||||
pos = unquotedValue.end;
|
||||
node.type = "string";
|
||||
node.value = unquotedValue.match[1];
|
||||
break; // redundant, but leaving for consistency
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
// Bail if we don't have a value
|
||||
if(!node.type) {
|
||||
return null;
|
||||
@@ -506,64 +528,79 @@ exports.parseAttribute = function(source,pos) {
|
||||
pos = token.end;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a string literal
|
||||
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
|
||||
if(stringLiteral) {
|
||||
pos = stringLiteral.end;
|
||||
node.type = "string";
|
||||
node.value = stringLiteral.value;
|
||||
} else {
|
||||
do {
|
||||
// Look for a string literal
|
||||
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
|
||||
if(stringLiteral) {
|
||||
pos = stringLiteral.end;
|
||||
node.type = "string";
|
||||
node.value = stringLiteral.value;
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for a filtered value
|
||||
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
|
||||
if(filteredValue) {
|
||||
pos = filteredValue.end;
|
||||
node.type = "filtered";
|
||||
node.filter = filteredValue.match[1];
|
||||
} else {
|
||||
// Look for an indirect value
|
||||
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
|
||||
if(indirectValue) {
|
||||
pos = indirectValue.end;
|
||||
node.type = "indirect";
|
||||
node.textReference = indirectValue.match[1];
|
||||
} else {
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
} else {
|
||||
// Look for an MVV reference value
|
||||
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
|
||||
if(mvvReference) {
|
||||
pos = mvvReference.end;
|
||||
node.type = "macro";
|
||||
node.value = mvvReference;
|
||||
node.isMVV = true;
|
||||
} else {
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue) {
|
||||
pos = substitutedValue.end;
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
} else {
|
||||
// Look for a unquoted value
|
||||
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
|
||||
if(unquotedValue) {
|
||||
pos = unquotedValue.end;
|
||||
node.type = "string";
|
||||
node.value = unquotedValue.match[1];
|
||||
} else {
|
||||
node.type = "string";
|
||||
node.value = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for an indirect value
|
||||
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
|
||||
if(indirectValue) {
|
||||
pos = indirectValue.end;
|
||||
node.type = "indirect";
|
||||
node.textReference = indirectValue.match[1];
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for a macro invocation value
|
||||
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
|
||||
if(macroInvocation) {
|
||||
pos = macroInvocation.end;
|
||||
node.type = "macro";
|
||||
node.value = macroInvocation;
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for an MVV reference value
|
||||
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
|
||||
if(mvvReference) {
|
||||
pos = mvvReference.end;
|
||||
node.type = "macro";
|
||||
node.value = mvvReference;
|
||||
node.isMVV = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for a substituted value
|
||||
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
|
||||
if(substitutedValue) {
|
||||
pos = substitutedValue.end;
|
||||
node.type = "substituted";
|
||||
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for a unquoted value
|
||||
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
|
||||
if(unquotedValue) {
|
||||
pos = unquotedValue.end;
|
||||
node.type = "string";
|
||||
node.value = unquotedValue.match[1];
|
||||
break;
|
||||
}
|
||||
|
||||
if(source.charAt(pos) === "<" && source.charAt(pos + 1) === "<" && source.indexOf(">>",pos) !== -1) {
|
||||
// Value looks like a macro invocation (starts with << with a closing >> ahead) but does not parse as one. Return null so the enclosing tag fails to parse rather than silently binding the attribute to "true" and treating the remainder as further attributes (restores v5.3.8 behaviour)
|
||||
return null;
|
||||
}
|
||||
|
||||
node.type = "string";
|
||||
node.value = "true";
|
||||
} while(false);
|
||||
} else {
|
||||
// If there is no equals sign or colon, then this is an attribute with no value, defaulting to "true"
|
||||
node.type = "string";
|
||||
|
||||
@@ -25,7 +25,7 @@ exports.init = function(parser) {
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
var reEnd = /(\r?\n```$)/mg;
|
||||
var reEnd = /(^|\r?\n)```$/mg;
|
||||
var languageStart = this.parser.pos + 3,
|
||||
languageEnd = languageStart + this.match[1].length;
|
||||
// Move past the match
|
||||
|
||||
@@ -31,13 +31,16 @@ exports.parse = function() {
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source),
|
||||
text,
|
||||
start = this.parser.pos;
|
||||
start = this.parser.pos,
|
||||
textEnd;
|
||||
// Process the text
|
||||
if(match) {
|
||||
text = this.parser.source.substring(this.parser.pos,match.index);
|
||||
textEnd = match.index;
|
||||
this.parser.pos = match.index + match[0].length;
|
||||
} else {
|
||||
text = this.parser.source.substr(this.parser.pos);
|
||||
textEnd = this.parser.sourceLength;
|
||||
this.parser.pos = this.parser.sourceLength;
|
||||
}
|
||||
return [{
|
||||
@@ -47,7 +50,7 @@ exports.parse = function() {
|
||||
type: "text",
|
||||
text: text,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
end: textEnd
|
||||
}]
|
||||
}];
|
||||
};
|
||||
|
||||
@@ -32,7 +32,8 @@ exports.parse = function() {
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Create the link unless it is suppressed
|
||||
if(this.match[0].substr(0,1) === "~") {
|
||||
return [{type: "text", text: this.match[0].substr(1), start: start, end: this.parser.pos}];
|
||||
// Start after the suppressing "~" so the span matches the plain text
|
||||
return [{type: "text", text: this.match[0].substr(1), start: start + 1, end: this.parser.pos}];
|
||||
} else {
|
||||
return [{
|
||||
type: "element",
|
||||
|
||||
@@ -34,7 +34,7 @@ exports.parse = function() {
|
||||
// Parse the filter terminated by a line break
|
||||
var reMatch = /(.*)(?:$|\r?\n)/mg;
|
||||
reMatch.lastIndex = this.parser.pos;
|
||||
var filterStart = this.parser.source;
|
||||
var filterStart = this.parser.pos;
|
||||
var match = reMatch.exec(this.parser.source);
|
||||
this.parser.pos = reMatch.lastIndex;
|
||||
// Parse tree nodes to return
|
||||
|
||||
@@ -27,9 +27,11 @@ Parse the most recent match
|
||||
*/
|
||||
exports.parse = function() {
|
||||
// Get the details of the match
|
||||
var linkText = this.match[0];
|
||||
var linkText = this.match[0],
|
||||
// Start after the suppressing "~" so the span matches the plain text
|
||||
start = this.parser.pos + 1;
|
||||
// Move past the wikilink
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Return the link without unwikilink character as plain text
|
||||
return [{type: "text", text: linkText.substr(1)}];
|
||||
return [{type: "text", text: linkText.substr(1), start: start, end: this.parser.pos}];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*\
|
||||
title: $:/core/modules/relinkers/tiddlers.js
|
||||
type: application/javascript
|
||||
module-type: relinker
|
||||
|
||||
Relinks the tags and list fields of tiddlers.
|
||||
|
||||
Calls a tw-relinking-tiddler hook for every altered tiddler.
|
||||
|
||||
\*/
|
||||
|
||||
exports.name = "tiddlers";
|
||||
|
||||
exports.relink = function(wiki,fromTitle,toTitle,options) {
|
||||
wiki.each(function(tiddler,title) {
|
||||
var type = tiddler.fields.type || "";
|
||||
// Don't touch plugins or JavaScript modules
|
||||
if(!tiddler.fields["plugin-type"] && type !== "application/javascript") {
|
||||
var tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,
|
||||
list = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,
|
||||
isModified = false,
|
||||
processList = function(listField) {
|
||||
if(listField && listField.indexOf(fromTitle) !== -1) {
|
||||
// Remove any existing instances of the toTitle
|
||||
var p = listField.indexOf(toTitle);
|
||||
while(p !== -1) {
|
||||
listField.splice(p,1);
|
||||
p = listField.indexOf(toTitle);
|
||||
}
|
||||
// Replace the fromTitle with toTitle
|
||||
$tw.utils.each(listField,function (title,index) {
|
||||
if(title === fromTitle) {
|
||||
listField[index] = toTitle;
|
||||
isModified = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if(!options.dontRenameInTags) {
|
||||
// Rename tags
|
||||
processList(tags);
|
||||
}
|
||||
if(!options.dontRenameInLists) {
|
||||
// Rename lists
|
||||
processList(list);
|
||||
}
|
||||
if(isModified) {
|
||||
var newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},wiki.getModificationFields());
|
||||
newTiddler = $tw.hooks.invokeHook("th-relinking-tiddler",newTiddler,tiddler);
|
||||
wiki.addTiddler(newTiddler);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -4,7 +4,6 @@ type: application/javascript
|
||||
module-type: startup
|
||||
|
||||
Browser message handling
|
||||
|
||||
\*/
|
||||
|
||||
"use strict";
|
||||
@@ -18,6 +17,20 @@ exports.synchronous = true;
|
||||
/*
|
||||
Load a specified url as an iframe and call the callback when it is loaded. If the url is already loaded then the existing iframe instance is used
|
||||
*/
|
||||
|
||||
// Ensure the callback fires once, whether by PLUGIN-LIBRARY-READY or onload (legacy)
|
||||
|
||||
function flushCallbacks(iframeInfo, err) {
|
||||
if(iframeInfo.status !== "loaded") {
|
||||
iframeInfo.status = err ? "error" : "loaded";
|
||||
saveIFrameInfoTiddler(iframeInfo);
|
||||
var cb;
|
||||
while((cb = iframeInfo.callbacks.shift())) {
|
||||
cb(err, iframeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadIFrame(url,callback) {
|
||||
// Check if iframe already exists
|
||||
var iframeInfo = $tw.browserMessaging.iframeInfoMap[url];
|
||||
@@ -30,7 +43,8 @@ function loadIFrame(url,callback) {
|
||||
iframeInfo = {
|
||||
url: url,
|
||||
status: "loading",
|
||||
domNode: iframe
|
||||
domNode: iframe,
|
||||
callbacks: [callback]
|
||||
};
|
||||
$tw.browserMessaging.iframeInfoMap[url] = iframeInfo;
|
||||
saveIFrameInfoTiddler(iframeInfo);
|
||||
@@ -38,19 +52,18 @@ function loadIFrame(url,callback) {
|
||||
iframe.style.display = "none";
|
||||
iframe.setAttribute("library","true");
|
||||
document.body.appendChild(iframe);
|
||||
// Set up onload
|
||||
|
||||
// Set up onload. Legacy fallback: if PLUGIN-LIBRARY-READY never arrives, onload triggers the flush later
|
||||
iframe.onload = function() {
|
||||
iframeInfo.status = "loaded";
|
||||
saveIFrameInfoTiddler(iframeInfo);
|
||||
callback(null,iframeInfo);
|
||||
flushCallbacks(iframeInfo);
|
||||
};
|
||||
iframe.onerror = function() {
|
||||
callback("Cannot load iframe");
|
||||
flushCallbacks(iframeInfo, "Cannot load iframe");
|
||||
};
|
||||
try {
|
||||
iframe.src = url;
|
||||
} catch(ex) {
|
||||
callback(ex);
|
||||
flushCallbacks(iframeInfo, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,7 +73,7 @@ Unload library iframe for given url
|
||||
*/
|
||||
function unloadIFrame(url){
|
||||
var iframes = document.getElementsByTagName("iframe");
|
||||
for(var t=iframes.length-1; t--; t>=0) {
|
||||
for(var t = iframes.length - 1; t >= 0; t--) {
|
||||
var iframe = iframes[t];
|
||||
if(iframe.getAttribute("library") === "true" &&
|
||||
iframe.getAttribute("src") === url) {
|
||||
@@ -147,6 +160,13 @@ exports.startup = function() {
|
||||
// console.log("browser-messaging: Received message from",event.origin);
|
||||
// console.log("browser-messaging: Message content",event.data);
|
||||
switch(event.data.verb) {
|
||||
case "PLUGIN-LIBRARY-READY":
|
||||
$tw.utils.each($tw.browserMessaging.iframeInfoMap, function(info) {
|
||||
if(info && info.domNode && info.domNode.contentWindow === event.source) {
|
||||
flushCallbacks(info);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "GET-RESPONSE":
|
||||
if(event.data.status.charAt(0) === "2") {
|
||||
if(event.data.cookies) {
|
||||
|
||||
@@ -40,6 +40,8 @@ exports.startup = function() {
|
||||
// The rest of the startup process here is not strictly to do with loading modules, but are needed before other startup
|
||||
// modules are executed. It is easier to put them here than to introduce a new startup module
|
||||
// --------------------------
|
||||
// Set up the performance framework
|
||||
$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,"no") === "yes");
|
||||
// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers
|
||||
$tw.rootWidget = new widget.widget({
|
||||
type: "widget",
|
||||
@@ -48,8 +50,6 @@ exports.startup = function() {
|
||||
wiki: $tw.wiki,
|
||||
document: $tw.browser ? document : $tw.fakeDocument
|
||||
});
|
||||
// Set up the performance framework
|
||||
$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,"no") === "yes");
|
||||
// Kick off the filter tracker
|
||||
$tw.filterTracker = new $tw.FilterTracker($tw.wiki);
|
||||
$tw.wiki.addEventListener("change",function(changes) {
|
||||
|
||||
@@ -221,7 +221,7 @@ function updateLocationHash(options) {
|
||||
$tw.utils.copyToClipboard(url,{successNotification: options.successNotification, failureNotification: options.failureNotification});
|
||||
}
|
||||
// Only change the location hash if we must, thus avoiding unnecessary onhashchange events
|
||||
if($tw.utils.getLocationHash() !== $tw.locationHash && !$tw.safeMode) {
|
||||
if($tw.utils.getLocationHash() !== $tw.locationHash) {
|
||||
if(options.updateHistory === "yes") {
|
||||
// Assign the location hash so that history is updated
|
||||
window.location.hash = $tw.locationHash;
|
||||
|
||||
@@ -15,7 +15,8 @@ var getCellInfo = function(text, start, length, SEPARATOR) {
|
||||
var isCellQuoted = text.charAt(start) === QUOTE;
|
||||
var cellStart = isCellQuoted ? start + 1 : start;
|
||||
|
||||
if(text.charAt(i) === SEPARATOR) {
|
||||
// A quote licenses a separator inside the cell, so only an unquoted cell reads an immediate separator as empty
|
||||
if(!isCellQuoted && text.charAt(cellStart) === SEPARATOR) {
|
||||
return [cellStart, cellStart, false];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,43 @@ title: $:/core/modules/utils/deprecated.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Deprecated util functions
|
||||
Deprecated util functions. These preserve the pre-5.4.0 signatures and
|
||||
behaviour for backwards compatibility with plugins and external scripts.
|
||||
Prefer modern alternatives in new code (Array.prototype methods, classList,
|
||||
Math.sign, String.prototype.repeat, etc.).
|
||||
|
||||
\*/
|
||||
|
||||
exports.logTable = (data) => console.table(data);
|
||||
|
||||
exports.repeat = (str,count) => str.repeat(count);
|
||||
/*
|
||||
Repeats a string
|
||||
*/
|
||||
exports.repeat = function(str,count) {
|
||||
var result = "";
|
||||
for(var t=0;t<count;t++) {
|
||||
result += str;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.startsWith = (str,search) => str.startsWith(search);
|
||||
/*
|
||||
Check if a string starts with another string
|
||||
*/
|
||||
exports.startsWith = function(str,search) {
|
||||
return str.substring(0, search.length) === search;
|
||||
};
|
||||
|
||||
exports.endsWith = (str,search) => str.endsWith(search);
|
||||
/*
|
||||
Check if a string ends with another string
|
||||
*/
|
||||
exports.endsWith = function(str,search) {
|
||||
return str.substring(str.length - search.length) === search;
|
||||
};
|
||||
|
||||
/*
|
||||
Trim whitespace from the start and end of a string
|
||||
*/
|
||||
exports.trim = function(str) {
|
||||
if(typeof str === "string") {
|
||||
return str.trim();
|
||||
@@ -29,30 +54,54 @@ exports.sign = Math.sign;
|
||||
|
||||
exports.strEndsWith = (str,ending,position) => str.endsWith(ending,position);
|
||||
|
||||
exports.stringifyNumber = (num) => num.toString();
|
||||
exports.stringifyNumber = function(num) {
|
||||
return num + "";
|
||||
};
|
||||
|
||||
// Returns the fully escaped CSS selector for a tag, e.g.
|
||||
// "$:/tags/Stylesheet" -> "tc-tagged-\%24\%3A\%2Ftags\%2FStylesheet"
|
||||
exports.tagToCssSelector = function(tagName) {
|
||||
return "tc-tagged-" + encodeURIComponent(tagName).replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{\|}~,]/mg,function(c) {
|
||||
return "\\" + c;
|
||||
});
|
||||
};
|
||||
|
||||
exports.domContains = (a,b) => a.compareDocumentPosition(b) & 16;
|
||||
/*
|
||||
Determines whether element 'a' contains element 'b'.
|
||||
Returns false when a === b (matches the original John Resig semantics).
|
||||
*/
|
||||
exports.domContains = function(a,b) {
|
||||
return a !== b && a.contains(b);
|
||||
};
|
||||
|
||||
exports.domMatchesSelector = (node,selector) => node.matches(selector);
|
||||
|
||||
exports.hasClass = (el,className) => el.classList && el.classList.contains(className);
|
||||
exports.hasClass = function(el,className) {
|
||||
return !!(el && el.classList && el.classList.contains(className));
|
||||
};
|
||||
|
||||
// addClass/removeClass/toggleClass split on whitespace to preserve the
|
||||
// original setAttribute("class", ...) acceptance of "foo bar" as two
|
||||
// classes. Regressed in #9251.
|
||||
function splitClasses(className) {
|
||||
return (typeof className === "string" && className.match(/\S+/g)) || [];
|
||||
}
|
||||
|
||||
exports.addClass = function(el,className) {
|
||||
el.classList && className && el.classList.add(className);
|
||||
if(!el.classList) return;
|
||||
splitClasses(className).forEach(function(c) { el.classList.add(c); });
|
||||
};
|
||||
|
||||
exports.removeClass = function(el,className) {
|
||||
el.classList && className && el.classList.remove(className);
|
||||
if(!el.classList) return;
|
||||
splitClasses(className).forEach(function(c) { el.classList.remove(c); });
|
||||
};
|
||||
|
||||
exports.toggleClass = function(el,className,status) {
|
||||
el.classList && className && el.classList.toggle(className, status);
|
||||
if(!el.classList) return;
|
||||
splitClasses(className).forEach(function(c) { el.classList.toggle(c,status); });
|
||||
};
|
||||
|
||||
exports.getLocationPath = () => window.location.origin + window.location.pathname;
|
||||
exports.getLocationPath = function() {
|
||||
return window.location.toString().split("#")[0];
|
||||
};
|
||||
|
||||
@@ -77,10 +77,23 @@ exports.resizeTextAreaToFit = function(domNode,minHeight) {
|
||||
// Measure the specified minimum height
|
||||
domNode.style.height = minHeight;
|
||||
var measuredHeight = domNode.offsetHeight || parseInt(minHeight,10);
|
||||
// Temporarily force rows=1 during auto-measurement so the intrinsic floor
|
||||
// is one row rather than the HTML default of two; restore afterwards
|
||||
var hadRowsAttr = domNode.hasAttribute("rows"),
|
||||
savedRows = hadRowsAttr ? domNode.getAttribute("rows") : null;
|
||||
if(!hadRowsAttr) {
|
||||
domNode.setAttribute("rows","1");
|
||||
}
|
||||
// Set its height to auto so that it snaps to the correct height
|
||||
domNode.style.height = "auto";
|
||||
// Calculate the revised height
|
||||
var newHeight = Math.max(domNode.scrollHeight + domNode.offsetHeight - domNode.clientHeight,measuredHeight);
|
||||
// Restore the original rows attribute state
|
||||
if(!hadRowsAttr) {
|
||||
domNode.removeAttribute("rows");
|
||||
} else {
|
||||
domNode.setAttribute("rows",savedRows);
|
||||
}
|
||||
// Only try to change the height if it has changed
|
||||
if(newHeight !== domNode.offsetHeight) {
|
||||
domNode.style.height = newHeight + "px";
|
||||
@@ -151,15 +164,16 @@ exports.forceLayout = function(element) {
|
||||
Pulse an element for debugging purposes
|
||||
*/
|
||||
exports.pulseElement = function(element) {
|
||||
var eventName = $tw.utils.convertEventName("animationEnd");
|
||||
// Event handler to remove the class at the end
|
||||
element.addEventListener($tw.browser.animationEnd,function handler(event) {
|
||||
element.removeEventListener($tw.browser.animationEnd,handler,false);
|
||||
$tw.utils.removeClass(element,"pulse");
|
||||
element.addEventListener(eventName,function handler(event) {
|
||||
element.removeEventListener(eventName,handler,false);
|
||||
$tw.utils.removeClass(element,"tc-pulse");
|
||||
},false);
|
||||
// Apply the pulse class
|
||||
$tw.utils.removeClass(element,"pulse");
|
||||
$tw.utils.removeClass(element,"tc-pulse");
|
||||
$tw.utils.forceLayout(element);
|
||||
$tw.utils.addClass(element,"pulse");
|
||||
$tw.utils.addClass(element,"tc-pulse");
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -82,6 +82,11 @@ var TW_Style = function(el) {
|
||||
// Return a Proxy to handle direct access to individual style properties
|
||||
return new Proxy(styleObject, {
|
||||
get: function(target, property) {
|
||||
// Real CSSStyleDeclaration returns undefined for non-string keys.
|
||||
// Guards against crashes when consumers probe Symbol.toPrimitive etc.
|
||||
if(typeof property !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
// If the property exists on styleObject, return it (get, set, setProperty methods)
|
||||
if(property in target) {
|
||||
return target[property];
|
||||
@@ -90,6 +95,10 @@ var TW_Style = function(el) {
|
||||
return el._style[$tw.utils.convertStyleNameToPropertyName(property)] || "";
|
||||
},
|
||||
set: function(target, property, value) {
|
||||
// Mirror the get trap: ignore non-string keys instead of crashing.
|
||||
if(typeof property !== "string") {
|
||||
return true;
|
||||
}
|
||||
// Set the property in _style
|
||||
el._style[$tw.utils.convertStyleNameToPropertyName(property)] = value;
|
||||
return true;
|
||||
@@ -106,7 +115,9 @@ var TW_Element = function(tag, namespace) {
|
||||
this.children = [];
|
||||
this._style = {}; // Internal style object
|
||||
this.style = new TW_Style(this); // Proxy for style management
|
||||
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
|
||||
// createElementNS with empty-string or null normalises to null (no namespace) per spec.
|
||||
// https://dom.spec.whatwg.org/#dom-document-createelementns
|
||||
this.namespaceURI = namespace !== undefined ? (namespace || null) : "http://www.w3.org/1999/xhtml";
|
||||
};
|
||||
|
||||
|
||||
@@ -197,7 +208,16 @@ TW_Element.prototype.addEventListener = function(type,listener,useCapture) {
|
||||
|
||||
Object.defineProperty(TW_Element.prototype, "tagName", {
|
||||
get: function() {
|
||||
return this.tag || "";
|
||||
if(!this.tag) {
|
||||
return "";
|
||||
}
|
||||
// HTML elements report uppercase tagName per DOM spec. Other namespaces
|
||||
// preserve case. Fakedom only models HTML documents.
|
||||
// https://dom.spec.whatwg.org/#dom-element-tagname
|
||||
if(this.namespaceURI === "http://www.w3.org/1999/xhtml") {
|
||||
return this.tag.toUpperCase();
|
||||
}
|
||||
return this.tag;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -243,8 +243,28 @@ exports.slowInSlowOut = function(t) {
|
||||
};
|
||||
|
||||
exports.copyObjectPropertiesSafe = function(object) {
|
||||
const seen = new Set(),
|
||||
isDOMElement = (value) => value instanceof Node || value instanceof Window;
|
||||
const seen = new Set();
|
||||
|
||||
function isDOMElement(value) {
|
||||
if(!value || typeof value !== "object") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cross-realm DOM nodes
|
||||
if(typeof value.nodeType === "number" &&
|
||||
typeof value.nodeName === "string") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cross-realm Window objects
|
||||
if(value.window === value &&
|
||||
value.document &&
|
||||
value.location) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function safeCopy(obj) {
|
||||
// skip circular references
|
||||
@@ -255,10 +275,6 @@ exports.copyObjectPropertiesSafe = function(object) {
|
||||
if(typeof obj !== "object" || obj === null) {
|
||||
return obj;
|
||||
}
|
||||
// skip DOM elements
|
||||
if(isDOMElement(obj)) {
|
||||
return undefined;
|
||||
}
|
||||
// copy arrays, preserving positions
|
||||
if(Array.isArray(obj)) {
|
||||
return obj.map((item) => {
|
||||
@@ -266,7 +282,11 @@ exports.copyObjectPropertiesSafe = function(object) {
|
||||
return value === undefined ? null : value;
|
||||
});
|
||||
}
|
||||
|
||||
// skip DOM elements
|
||||
if(isDOMElement(obj)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
seen.add(obj);
|
||||
const copy = {};
|
||||
let key,
|
||||
|
||||
@@ -61,7 +61,7 @@ LogWidget.prototype.log = function() {
|
||||
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
|
||||
if(name.substring(0,2) !== "$$") {
|
||||
var resultList = self.computeAttribute(attribute,{asList: true});
|
||||
if(resultList.length <= 1) {
|
||||
if(resultList && resultList.length <= 1) {
|
||||
data[name] = resultList[0] || "";
|
||||
} else {
|
||||
data[name] = resultList;
|
||||
@@ -75,7 +75,7 @@ LogWidget.prototype.log = function() {
|
||||
allVars[v] = variable.value;
|
||||
} else {
|
||||
var variableInfo = this.getVariableInfo(v);
|
||||
allVars[v] = variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
|
||||
allVars[v] = variableInfo && variableInfo.resultList && variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
|
||||
}
|
||||
}
|
||||
if(this.filter) {
|
||||
|
||||
@@ -151,10 +151,24 @@ ButtonWidget.prototype.getBoundingClientRect = function() {
|
||||
};
|
||||
|
||||
ButtonWidget.prototype.isSelected = function() {
|
||||
return this.setTitle ? (this.setField ? this.wiki.getTiddler(this.setTitle).getFieldString(this.setField) === this.setTo :
|
||||
(this.setIndex ? this.wiki.extractTiddlerDataItem(this.setTitle,this.setIndex) === this.setTo :
|
||||
this.wiki.getTiddlerText(this.setTitle))) || this.defaultSetValue || this.getVariable("currentTiddler") :
|
||||
this.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable("currentTiddler")) === this.setTo;
|
||||
var currentValue;
|
||||
if(this.setTitle) {
|
||||
if(this.setField) {
|
||||
// The state tiddler usually does not exist until the button is first clicked
|
||||
var tiddler = this.wiki.getTiddler(this.setTitle);
|
||||
currentValue = tiddler ? tiddler.getFieldString(this.setField) : undefined;
|
||||
} else if(this.setIndex) {
|
||||
currentValue = this.wiki.extractTiddlerDataItem(this.setTitle,this.setIndex);
|
||||
} else {
|
||||
currentValue = this.wiki.getTiddlerText(this.setTitle);
|
||||
}
|
||||
if(!currentValue) {
|
||||
currentValue = this.defaultSetValue || this.getVariable("currentTiddler");
|
||||
}
|
||||
} else {
|
||||
currentValue = this.wiki.getTextReference(this.set,this.defaultSetValue,this.getVariable("currentTiddler"));
|
||||
}
|
||||
return currentValue === this.setTo;
|
||||
};
|
||||
|
||||
ButtonWidget.prototype.isPoppedUp = function() {
|
||||
@@ -267,7 +281,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
*/
|
||||
ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.tooltip || changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
if(changedAttributes.tooltip || changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.setTitle && changedTiddlers[this.setTitle]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,7 @@ Inherit from the base widget class
|
||||
DiffTextWidget.prototype = new Widget();
|
||||
|
||||
DiffTextWidget.prototype.invisibleCharacters = {
|
||||
"\n": "↩︎\n",
|
||||
"\n": "↲\n",
|
||||
"\r": "⇠",
|
||||
"\t": "⇥\t"
|
||||
};
|
||||
|
||||
@@ -99,7 +99,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
||||
wikiLinkText = this.wiki.filterTiddlers(wikilinkTransformFilter,this,function(iterator) {
|
||||
iterator(self.wiki.getTiddler(self.to),self.to);
|
||||
})[0];
|
||||
} else {
|
||||
}
|
||||
if(!wikiLinkText) {
|
||||
// Expand the tv-wikilink-template variable to construct the href
|
||||
var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"),
|
||||
wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$";
|
||||
|
||||
@@ -125,13 +125,12 @@ SelectWidget.prototype.setSelectValue = function() {
|
||||
values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);
|
||||
for(var i=0; i < select.children.length; i++){
|
||||
child=select.children[i];
|
||||
if(child.children.length === 0){
|
||||
child.selected = values.indexOf(child.value) !== -1;
|
||||
} else {
|
||||
// grouped options
|
||||
if(child.tagName && child.tagName.toUpperCase() === "OPTGROUP"){
|
||||
for(var y=0; y < child.children.length; y++){
|
||||
child.children[y].selected = values.indexOf(child.children[y].value) !== -1;
|
||||
}
|
||||
} else {
|
||||
child.selected = values.indexOf(child.value) !== -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -189,7 +189,7 @@ Widget.prototype.getVariableInfo = function(name,options) {
|
||||
}
|
||||
return {
|
||||
text: text,
|
||||
resultList: [text]
|
||||
resultList: text === undefined ? text : [text]
|
||||
};
|
||||
};
|
||||
|
||||
@@ -338,7 +338,7 @@ Widget.prototype.makeFakeWidgetWithVariables = function(vars = {}) {
|
||||
const value = vars[name];
|
||||
return Array.isArray(value)
|
||||
? { text: value[0], resultList: value }
|
||||
: { text: value, resultList: [value] };
|
||||
: { text: value, resultList: value === undefined ? value : [value] };
|
||||
}
|
||||
opts = opts || {};
|
||||
opts.variables = Object.assign({}, vars, opts.variables || {});
|
||||
|
||||
@@ -9,6 +9,7 @@ Bulk tiddler operations such as rename.
|
||||
|
||||
"use strict";
|
||||
|
||||
var relinkers = $tw.modules.getModulesByTypeAsHashmap("relinker");
|
||||
/*
|
||||
Rename a tiddler, and relink any tags or lists that reference it.
|
||||
*/
|
||||
@@ -32,50 +33,13 @@ function renameTiddler(fromTitle,toTitle,options) {
|
||||
Relink any tags or lists that reference a given tiddler
|
||||
*/
|
||||
function relinkTiddler(fromTitle,toTitle,options) {
|
||||
var self = this;
|
||||
fromTitle = (fromTitle || "").trim();
|
||||
toTitle = (toTitle || "").trim();
|
||||
options = options || {};
|
||||
if(fromTitle && toTitle && fromTitle !== toTitle) {
|
||||
this.each(function(tiddler,title) {
|
||||
var type = tiddler.fields.type || "";
|
||||
// Don't touch plugins or JavaScript modules
|
||||
if(!tiddler.fields["plugin-type"] && type !== "application/javascript") {
|
||||
var tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,
|
||||
list = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,
|
||||
isModified = false,
|
||||
processList = function(listField) {
|
||||
if(listField && listField.indexOf(fromTitle) !== -1) {
|
||||
// Remove any existing instances of the toTitle
|
||||
var p = listField.indexOf(toTitle);
|
||||
while(p !== -1) {
|
||||
listField.splice(p,1);
|
||||
p = listField.indexOf(toTitle);
|
||||
}
|
||||
// Replace the fromTitle with toTitle
|
||||
$tw.utils.each(listField,function (title,index) {
|
||||
if(title === fromTitle) {
|
||||
listField[index] = toTitle;
|
||||
isModified = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if(!options.dontRenameInTags) {
|
||||
// Rename tags
|
||||
processList(tags);
|
||||
}
|
||||
if(!options.dontRenameInLists) {
|
||||
// Rename lists
|
||||
processList(list);
|
||||
}
|
||||
if(isModified) {
|
||||
var newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},self.getModificationFields());
|
||||
newTiddler = $tw.hooks.invokeHook("th-relinking-tiddler",newTiddler,tiddler);
|
||||
self.addTiddler(newTiddler);
|
||||
}
|
||||
}
|
||||
});
|
||||
for(var name in relinkers) {
|
||||
relinkers[name].relink(this,fromTitle,toTitle,options);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+37
-10
@@ -369,16 +369,31 @@ Sort an array of tiddler titles by a specified field
|
||||
isDescending: true if the sort should be descending
|
||||
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
|
||||
*/
|
||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric,locale) {
|
||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {
|
||||
var self = this;
|
||||
if(sortField === "title") {
|
||||
if(!isNumeric && !isAlphaNumeric) {
|
||||
const sorter = new Intl.Collator(locale, { sensitivity: isCaseSensitive ? "variant" : "accent" });
|
||||
if(isDescending) {
|
||||
titles.sort((a,b) => sorter.compare(b, a));
|
||||
if(isCaseSensitive) {
|
||||
if(isDescending) {
|
||||
titles.sort(function(a,b) {
|
||||
return b.localeCompare(a);
|
||||
});
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
titles.sort((a,b) => sorter.compare(a, b));
|
||||
}
|
||||
if(isDescending) {
|
||||
titles.sort(function(a,b) {
|
||||
return b.toLowerCase().localeCompare(a.toLowerCase());
|
||||
});
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
var x,y;
|
||||
@@ -399,8 +414,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
|
||||
}
|
||||
}
|
||||
}
|
||||
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
|
||||
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
|
||||
if(isAlphaNumeric) {
|
||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
||||
}
|
||||
if(!isCaseSensitive) {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
}
|
||||
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -442,8 +463,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
|
||||
}
|
||||
a = String(a);
|
||||
b = String(b);
|
||||
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
|
||||
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
|
||||
if(isAlphaNumeric) {
|
||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
||||
}
|
||||
if(!isCaseSensitive) {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
}
|
||||
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/core/stylesheets/custom-properties
|
||||
|
||||
\rules only transcludeinline macrocallinline html transcludeblock
|
||||
\rules only transcludeinline macrocallinline html transcludeblock filteredtranscludeinline
|
||||
|
||||
/* Tiddlywiki's CSS properties */
|
||||
|
||||
@@ -21,10 +21,10 @@ title: $:/core/stylesheets/custom-properties
|
||||
--tp-story-left: {{$:/themes/tiddlywiki/vanilla/metrics/storyleft}};
|
||||
--tp-story-top: {{$:/themes/tiddlywiki/vanilla/metrics/storytop}};
|
||||
--tp-story-right: {{$:/themes/tiddlywiki/vanilla/metrics/storyright}};
|
||||
--tp-story-width: {{$:/themes/tiddlywiki/vanilla/metrics/storyrwidth}};
|
||||
--tp-story-width: {{$:/themes/tiddlywiki/vanilla/metrics/storywidth}};
|
||||
--tp-tiddler-width: {{$:/themes/tiddlywiki/vanilla/metrics/tiddlerwidth}};
|
||||
--tp-sidebar-breakpoint: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}};
|
||||
--tp-sidebar-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}};
|
||||
|
||||
--tp-animation-duration: {{{ [{$:/config/AnimationDuration}addsuffix[ms]] }}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
title: $:/core/templates/plain-text
|
||||
|
||||
<$text text=<<text>>/>
|
||||
@@ -0,0 +1,3 @@
|
||||
title: $:/core/templates/rendered-text
|
||||
|
||||
<<text>>
|
||||
@@ -4,13 +4,15 @@ description: create a new journal tiddler
|
||||
|
||||
\whitespace trim
|
||||
\function get-tags() [<textFieldTags>] [<tagsFieldTags>] +[join[ ]]
|
||||
<$let journalTitleTemplate={{$:/config/NewJournal/Title}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}} journalText={{$:/config/NewJournal/Text}}>
|
||||
<$wikify name="journalTitle" text="<$transclude $variable='now' format=<<journalTitleTemplate>>/>">
|
||||
<$let journalTitle=<<now format={{$:/config/NewJournal/Title}}>>
|
||||
textFieldTags={{$:/config/NewJournal/Tags}}
|
||||
tagsFieldTags={{$:/config/NewJournal/Tags!!tags}}
|
||||
journalText={{$:/config/NewJournal/Text}}
|
||||
>
|
||||
<$reveal type="nomatch" state=<<journalTitle>> text="">
|
||||
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<get-tags>> text={{{ [<journalTitle>get[]] }}}/>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<journalTitle>> text="">
|
||||
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<get-tags>> text=<<journalText>>/>
|
||||
</$reveal>
|
||||
</$wikify>
|
||||
</$let>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
title: $:/core/ui/EditTemplate/body/toolbar/button
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\define toolbar-button-icon()
|
||||
<$list
|
||||
|
||||
|
||||
@@ -108,10 +108,10 @@ tags: $:/tags/EditTemplate
|
||||
storeTitle=<<newFieldNameInputTiddler>>
|
||||
searchListState=<<newFieldNameSelectionTiddler>>
|
||||
>
|
||||
<div class="tc-edit-field-add-name-wrapper">
|
||||
<div class=`tc-edit-field-add-name-wrapper ${ [<newFieldNameTiddler>get[text]] :intersection[<storyTiddler>fields[]] :then[[tc-edit-field-exists]] }$`>
|
||||
<$transclude $variable="keyboard-driven-input"
|
||||
cancelPopups="yes"
|
||||
class=`tc-edit-texteditor tc-popup-handle ${ [<newFieldNameTiddler>get[text]] :intersection[<storyTiddler>fields[]] :then[[tc-edit-field-exists]] }$`
|
||||
class="tc-edit-texteditor tc-popup-handle"
|
||||
configTiddlerFilter="[[$:/config/EditMode/fieldname-filter]]"
|
||||
default=""
|
||||
focus={{{ [{!!draft.of}is[tiddler]then{$:/config/AutoFocusEdit}match[fields]then[true]] :else[{$:/config/AutoFocus}match[fields]then[true]] :else[[false]] }}}
|
||||
@@ -178,4 +178,4 @@ tags: $:/tags/EditTemplate
|
||||
</$let>
|
||||
</$let>
|
||||
</div>
|
||||
</$let>
|
||||
</$let>
|
||||
|
||||
@@ -6,28 +6,25 @@ tags: $:/tags/EditTemplate
|
||||
\procedure lingo-base() $:/language/EditTemplate/
|
||||
|
||||
\procedure tag-body-inner(colour,fallbackTarget,colourA,colourB,icon,tagField:"tags")
|
||||
<$wikify name="foregroundColor"
|
||||
text="""<$macrocall $name="contrastcolour"
|
||||
target=<<colour>>
|
||||
fallbackTarget=<<fallbackTarget>>
|
||||
colourA=<<colourA>>
|
||||
colourB=<<colourB>>/>
|
||||
"""
|
||||
>
|
||||
<$let backgroundColor=<<colour>> >
|
||||
<span class="tc-tag-label tc-tag-list-item tc-small-gap-right"
|
||||
data-tag-title=<<currentTiddler>>
|
||||
style=`color:$(foregroundColor)$; background-color:$(backgroundColor)$; --tp-remove-tag-button-color:$(foregroundColor)$`
|
||||
<$let foregroundColor=<<contrastcolour target=<<colour>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>> >>
|
||||
backgroundColor=<<colour>>
|
||||
>
|
||||
<span class="tc-tag-label tc-tag-list-item tc-small-gap-right"
|
||||
data-tag-title=<<currentTiddler>>
|
||||
style=`color:$(foregroundColor)$; fill:$(foregroundColor)$; background-color:$(backgroundColor)$;`
|
||||
>
|
||||
<$transclude tiddler=<<icon>>/>
|
||||
<$view field="title" format="text"/>
|
||||
<$button class="tc-btn-invisible tc-remove-tag-button"
|
||||
style.fill=<<foregroundColor>>
|
||||
>
|
||||
<$transclude tiddler=<<icon>>/>
|
||||
<$view field="title" format="text"/>
|
||||
<$button class="tc-btn-invisible tc-remove-tag-button">
|
||||
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="-[{!!title}]"/>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
</span>
|
||||
</$let>
|
||||
</$wikify>
|
||||
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="-[{!!title}]"/>
|
||||
<!-- Touch a temp tiddler so that the tag remove animation fires instantly. Otherwise it's delayed by the typing timeout duration -->
|
||||
<$action-setfield $tiddler="$:/temp/tags-edit-refresh" text=<<currentTiddler>>/>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
</span>
|
||||
</$let>
|
||||
\end
|
||||
|
||||
\procedure tag-body(colour,palette,icon,tagField:"tags")
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
title: $:/Manager/ItemMain/Editor
|
||||
tags: $:/tags/Manager/ItemMain
|
||||
caption: {{$:/language/Manager/Item/Editor}}
|
||||
|
||||
<$edit-text tag="textarea" class="tc-edit-texteditor tc-edit-texteditor-body tc-max-width"/>
|
||||
@@ -13,8 +13,3 @@ caption: {{$:/language/Manager/Item/Tools}}
|
||||
{{$:/core/images/edit-button}} edit
|
||||
</$button>
|
||||
</p>
|
||||
<p>
|
||||
<$button message="tm-delete-tiddler" param=<<currentTiddler>>>
|
||||
{{$:/core/images/delete-button}} delete
|
||||
</$button>
|
||||
</p>
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
title: $:/core/ui/SafeLayout
|
||||
tags: $:/tags/Layout
|
||||
name: Safe Mode Layout
|
||||
description: Safe Mode Layout
|
||||
icon: $:/core/images/list
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
|
||||
|
||||
\define tv-config-toolbar-class() tc-btn-invisible
|
||||
\define tv-config-toolbar-icons() yes
|
||||
\define tv-config-toolbar-text() no
|
||||
|
||||
<div style="margin: 1em;">
|
||||
|
||||
<$navigator story="$:/StoryList" history="$:/HistoryList">
|
||||
|
||||
<h2>Layout</h2>
|
||||
|
||||
{{$:/snippets/LayoutSwitcher}}
|
||||
|
||||
<h2>Controls</h2>
|
||||
|
||||
<div class="tc-page-controls">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]">
|
||||
<$transclude mode="inline"/>
|
||||
</$list>
|
||||
</div>
|
||||
|
||||
<h2>Tiddlers</h2>
|
||||
|
||||
<$transclude tiddler="$:/Manager" mode="block"/>
|
||||
|
||||
</$navigator>
|
||||
|
||||
</div>
|
||||
@@ -16,15 +16,13 @@ title: $:/core/ui/TagPickerTagTemplate
|
||||
<$set name="backgroundColor"
|
||||
value={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
|
||||
>
|
||||
<$wikify name="foregroundColor"
|
||||
text="""<$macrocall $name="contrastcolour" target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>"""
|
||||
>
|
||||
<$let foregroundColor=<<contrastcolour target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>> >> >
|
||||
<span class="tc-tag-label tc-btn-invisible"
|
||||
style=<<tag-pill-styles>>
|
||||
data-tag-title=<<currentTiddler>>
|
||||
>
|
||||
{{||$:/core/ui/TiddlerIcon}}<$view field="title" format="text"/>
|
||||
</span>
|
||||
</$wikify>
|
||||
</$let>
|
||||
</$set>
|
||||
</$button>
|
||||
|
||||
@@ -2,7 +2,7 @@ title: $:/core/ui/ViewTemplate/title
|
||||
tags: $:/tags/ViewTemplate
|
||||
|
||||
\whitespace trim
|
||||
\define title-styles() color:$(foregroundColor)$;
|
||||
\define title-styles() fill:$(foregroundColor)$;
|
||||
|
||||
<div class="tc-tiddler-title tc-clearfix">
|
||||
<div class="tc-titlebar">
|
||||
|
||||
@@ -6,7 +6,6 @@ description: {{$:/language/Buttons/NewJournalHere/Hint}}
|
||||
\whitespace trim
|
||||
\procedure journalButton()
|
||||
<$button tooltip={{$:/language/Buttons/NewJournalHere/Hint}} aria-label={{$:/language/Buttons/NewJournalHere/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$wikify name="journalTitle" text="""<$transclude $variable="now" format=<<journalTitleTemplate>>/>""">
|
||||
<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=`[[$(currentTiddlerTag)$]] $(journalTags)$`/>
|
||||
<%if [<tv-config-toolbar-icons>match[yes]] %>
|
||||
{{$:/core/images/new-journal-button}}
|
||||
@@ -16,9 +15,11 @@ description: {{$:/language/Buttons/NewJournalHere/Hint}}
|
||||
<$text text={{$:/language/Buttons/NewJournalHere/Caption}}/>
|
||||
</span>
|
||||
<%endif%>
|
||||
</$wikify>
|
||||
</$button>
|
||||
\end
|
||||
<$let journalTitleTemplate={{$:/config/NewJournal/Title}} journalTags={{$:/config/NewJournal/Tags}} currentTiddlerTag=<<currentTiddler>>>
|
||||
<$let journalTitle=<<now format={{$:/config/NewJournal/Title}}>>
|
||||
journalTags={{$:/config/NewJournal/Tags}}
|
||||
currentTiddlerTag=<<currentTiddler>>
|
||||
>
|
||||
<<journalButton>>
|
||||
</$let>
|
||||
|
||||
@@ -17,6 +17,10 @@ This page summarises high level information about the configuration of this ~Tid
|
||||
Drag this link to copy this tool to another wiki
|
||||
\end intrinsic-lingo-Drag/Caption
|
||||
|
||||
\procedure intrinsic-lingo-Generate/Caption()
|
||||
Click to generate wiki information report
|
||||
\end intrinsic-lingo-Generate/Caption
|
||||
|
||||
\procedure lingo(title,mode:"inline")
|
||||
<%if [<title>addprefix<lingo-base>is[shadow]] %>
|
||||
<$transclude $tiddler={{{ [<title>addprefix<lingo-base>] }}} $mode=<<mode>>/>
|
||||
@@ -105,7 +109,7 @@ Drag this link to copy this tool to another wiki
|
||||
|
||||
<$button>
|
||||
<<display-wiki-info-modal>>
|
||||
Click to generate wiki information report
|
||||
<<lingo title:"Generate/Caption">>
|
||||
</$button>
|
||||
|
||||
<$link to="$:/core/ui/ControlPanel/WikiInformation">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
title: $:/state/popup/manager/item/$:/Manager/
|
||||
|
||||
ItemMain/RawText: hide
|
||||
ItemMain/Editor: hide
|
||||
ItemMain/RawText: hide
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/library/v5.4.0/index.html
|
||||
url: https://tiddlywiki.com/library/v5.5.0/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}}
|
||||
|
||||
{{$:/language/OfficialPluginLibrary/Hint}}
|
||||
|
||||
@@ -3,6 +3,7 @@ tags: $:/tags/Macro
|
||||
|
||||
\define tag-pill-styles()
|
||||
background-color:$(backgroundColor)$;
|
||||
fill:$(foregroundColor)$;
|
||||
color:$(foregroundColor)$;
|
||||
\end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ tags: $:/tags/Macro
|
||||
style="width:$width$px;height:$height$px;background-color:$background-color$;"
|
||||
></$reveal></div><div
|
||||
class="tc-thumbnail-icon"
|
||||
style="color:$color$;"
|
||||
style="fill:$color$;color:$color$;"
|
||||
>$icon$</div><div class="tc-thumbnail-caption">$caption$</div></div></$link>
|
||||
\end
|
||||
|
||||
|
||||
@@ -8,9 +8,8 @@ type: text/vnd.tiddlywiki
|
||||
# Ensure the new release banner image is up to date
|
||||
# Update ''master'' with changes from ''tiddlywiki-com''
|
||||
# Verify the version numbers in [[$:/config/OfficialPluginLibrary]] in `core/wiki/config/OfficialPluginLibrary.tid`
|
||||
# Move the latest release note from the prerelease edition into the tw5.com edition
|
||||
# Adjust the release date and the ''released'' field of the latest release tiddler (eg, [[Release 5.1.3]])
|
||||
# Also adjust the github.com comparison link to point to the tag for the new release
|
||||
# Adjust the release date and the ''released'' field of the release tiddler (eg, [[Release 5.1.3]])
|
||||
# Update the ''release-introduction'' definition with the new release text, and if necessary the ''description'' field of the release tiddler
|
||||
# Adjust the tiddler [[TiddlyWiki Archive]] to include the new version number
|
||||
# Ensure [[TiddlyWiki Releases]] has the new version as the default tab
|
||||
# Adjust the modified time of HelloThere
|
||||
@@ -19,10 +18,10 @@ type: text/vnd.tiddlywiki
|
||||
!! Update Readmes and release note
|
||||
|
||||
# Edit `package.json` to the new version number
|
||||
# Run `npm install` to update the `package-lock.json` file
|
||||
# Run `./bin/readme-bld.sh` to build the readme files
|
||||
# Commit the new readme files to ''master''
|
||||
# Restore `package.json` to the previous version number
|
||||
# Adjust the link for "GitHub for detailed change history of this release" in the release note
|
||||
# Add the credits for the new release banner to the release note, including a link to the GitHub instance of the image from the commit history
|
||||
|
||||
!! Make New Release
|
||||
|
||||
@@ -6,4 +6,4 @@ title: Data Management during Runtime
|
||||
During the runtime the data of Tiddlywiki is stored in javascript objects. These objects are synchronized with the DOM-Representation of Tiddlywiki. This means every change of the original data of a Tiddler, fires an event which changes all DOM-Representations of the Tiddler and the javascript object. The bare-bones Wiki store is created during the boot process and is kept in a object called \$tw.Wiki. This object contains amongst others a hashmap of the different Tiddlers of Tiddlywiki. The Hashmap is used to store the javascript object representation of the different Tiddlers. Furthermore this object is used to manage the tiddlers during runtime, it provides methods for adding tiddlers, search tiddlers by name and delete tiddlers.
|
||||
As shown in the picture below, every change at the DOM triggers an event which changes the corresponding widget which again changes the store of the tiddlers. The whole image shows how WikiText is parsed by a set of rules into the parse tree and this parse tree is rendered as a tree of widgets. This Rendertree is synchronised to the DOM. Every modification on the Rendertree provokes a start of the rendering-pipeline. As well as every change on the wikiText triggers an event at the RenderTree. This Process uses a selective updating so that only the changed parts are updated. This means only widgets which have to change the DOM in consequence of a changed tiddler are refreshed.
|
||||
|
||||
{{TiddlyWikiArchitecture.svg}}
|
||||
{{TiddlyWiki Architecture.svg}}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
title: $:/editions/dev/github-fork-ribbon
|
||||
tags: $:/tags/PageTemplate
|
||||
caption: ~GitHub ribbon
|
||||
description: ~GitHub ribbon for tw5.com/dev
|
||||
|
||||
<div class="github-fork-ribbon-wrapper right" style><div class="github-fork-ribbon" style="background-color:#DF4848;"><a href="https://github.com/TiddlyWiki/TiddlyWiki5" target="_blank" rel="noopener noreferrer">Find me on ~GitHub</a></div></div>
|
||||
@@ -2,7 +2,6 @@
|
||||
"description": "Developer documentation from https://tiddlywiki.com/dev/",
|
||||
"plugins": [
|
||||
"tiddlywiki/highlight",
|
||||
"tiddlywiki/nodewebkitsaver",
|
||||
"tiddlywiki/github-fork-ribbon",
|
||||
"tiddlywiki/menubar",
|
||||
"tiddlywiki/internals",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"description": "A step by step introduction to TiddlyWiki",
|
||||
"plugins": [
|
||||
"tiddlywiki/cecily",
|
||||
"tiddlywiki/codemirror",
|
||||
"tiddlywiki/highlight",
|
||||
"tiddlywiki/katex"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
created: 20251021142729667
|
||||
modified: 20260327113434425
|
||||
original-modified: 20251021142729667
|
||||
tags:
|
||||
title: Concatenating a text reference to create a URL
|
||||
ja-title: テキスト参照を連結してURL作成
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! 変数とテキスト参照を連結してURLを作成する
|
||||
|
||||
<$macrocall $name=wikitext-example src="""<$let hash={{{ [<currentTiddler>encodeuricomponent[]] }}}>
|
||||
<a href=`${ [{!!base-url}] }$#$(hash)$`>これはtiddlywiki.comのTiddlerです</a>
|
||||
</$let>"""/>
|
||||
|
||||
参照: [[置換属性値|Substituted Attribute Values]]
|
||||
@@ -0,0 +1,15 @@
|
||||
created: 20251021142733998
|
||||
modified: 20260327113417322
|
||||
original-modified: 20251021142733998
|
||||
tags:
|
||||
title: Concatenating variables to create a URL
|
||||
ja-title: 変数を連結してURL作成
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! 文字列と変数を連結してURLを作成する
|
||||
|
||||
<$macrocall $name=wikitext-example src="""<$let hash={{{ [<currentTiddler>encodeuricomponent[]] }}}>
|
||||
<a href=`http://tiddlywiki.com/#$(hash)$`>これはtiddlywiki.comのTiddlerです</a>
|
||||
</$let>"""/>
|
||||
|
||||
参照: [[置換属性値|Substituted Attribute Values]]
|
||||
@@ -0,0 +1,91 @@
|
||||
code-body: yes
|
||||
created: 20150117184156000
|
||||
modified: 20260217110459190
|
||||
original-modified: 20240716181836632
|
||||
tags: $:/tags/Macro
|
||||
title: $:/editions/tw5.com/wikitext-macros
|
||||
ja-title: $:/editions/tw5.com/wikitext-macros
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\procedure activatePluginTab()
|
||||
<$action-setfield $tiddler="$:/state/tab-1749438307" text="$:/core/ui/ControlPanel/Plugins"/>
|
||||
<$action-navigate $to="$:/ControlPanel"/>
|
||||
\end
|
||||
|
||||
\procedure activateTiddlerWindow()
|
||||
<$action-sendmessage $message="tm-open-window" $param=<<currentTiddler>> windowTitle="Side by Side View" width="800" height="600" />
|
||||
\end
|
||||
|
||||
\procedure controlPanel-plugin-link()
|
||||
<$button actions=<<activatePluginTab>> class="tc-btn-invisible tc-tiddlylink">
|
||||
{{$:/core/images/options-button}} ~ControlPanel
|
||||
</$button>
|
||||
\end
|
||||
|
||||
\procedure open-tiddler-in-window()
|
||||
\whitespace notrim
|
||||
<$button actions=<<activateTiddlerWindow>> class="tc-btn-invisible tc-tiddlylink">
|
||||
''この''Tiddlerを新しいウィンドウで開く
|
||||
</$button>
|
||||
\end
|
||||
|
||||
\procedure activateEditionWindow(url)
|
||||
<$action-sendmessage $message="tm-open-external-window" $param=<<url>> windowName="_edition" windowFeatures="width=800 height=600" />
|
||||
\end
|
||||
|
||||
\procedure open-external-window(url)
|
||||
\whitespace notrim
|
||||
<$button actions=<<activateEditionWindow <<url>> class="tc-btn-invisible tc-tiddlylink">
|
||||
''サンプル''を新しいウィンドウで開く
|
||||
</$button>
|
||||
\end
|
||||
|
||||
|
||||
\procedure wikitext-example(src)
|
||||
<div class="doc-example">
|
||||
<$macrocall $name="copy-to-clipboard-above-right" src=<<src>>/>
|
||||
<$codeblock code=<<src>>/>
|
||||
<p>
|
||||
次のように表示されます:
|
||||
</p>
|
||||
<$transclude $variable="src" $mode="block"/>
|
||||
<p>
|
||||
... そして、土台となるHTMLは次のようになります:
|
||||
</p>
|
||||
<$wikify name="html" text=<<src>> output="html">
|
||||
<$codeblock code=<<html>>/>
|
||||
</$wikify>
|
||||
</div>
|
||||
\end
|
||||
|
||||
\procedure wikitext-example-without-html(src)
|
||||
<div class="doc-example">
|
||||
<$macrocall $name="copy-to-clipboard-above-right" src=<<src>>/>
|
||||
<$codeblock code=<<src>>/>
|
||||
<p>
|
||||
次のように表示されます:
|
||||
</p>
|
||||
<$transclude $variable="src" $mode="block"/>
|
||||
</div>
|
||||
\end
|
||||
|
||||
\procedure wikitext-example-table-header() <thead><tr><th/><th>wiki text</th><th>renders as</th></tr></thead>
|
||||
|
||||
\procedure wikitext-example-table-row(id, code)
|
||||
<tr>
|
||||
<th><<id>></th>
|
||||
<td><$codeblock code=<<code>>/></td>
|
||||
<td><$transclude $variable="code" $mode="block"/></td>
|
||||
</tr>
|
||||
\end
|
||||
|
||||
\procedure tw-code(tiddler)
|
||||
<$codeblock language={{{ [<tiddler>get[type]] }}} code={{{ [<tiddler>get[text]] }}}/>
|
||||
\end
|
||||
|
||||
\procedure tw-code-link(tiddler)
|
||||
<$link to=<<tiddler>>/>:
|
||||
<$transclude $variable=tw-code tiddler=<<tiddler>> />
|
||||
\end
|
||||
@@ -11,6 +11,7 @@ ja-title: TiddlyWikiアーカイブ
|
||||
5.1.20 5.1.21 5.1.22 5.1.23
|
||||
5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7
|
||||
5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.3.8
|
||||
5.4.0
|
||||
\end
|
||||
|
||||
TiddlyWikiの古いバージョンは[[アーカイブ|https://github.com/TiddlyWiki/tiddlywiki.com-gh-pages/tree/master/archive]]で入手できます:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
title: Donations
|
||||
ja-title: 寄付
|
||||
tags: About HelloThere
|
||||
modified: 20260406043554401
|
||||
original-modified: 20260403103452943
|
||||
created: 20260403103452943
|
||||
|
||||
<a href="https://opencollective.com/tiddlywiki" class="tc-btn-invisible" target="_blank">
|
||||
{{TiddlyWiki Donation Graphic}}
|
||||
</a>
|
||||
|
||||
TiddlyWikiは無料のオープンソースプロジェクトであり、ホスティング費用を賄い、プロジェクトの継続的な成長を支えるために、皆様からの寛大なご寄付に頼っています。
|
||||
こちらから寄付できます:
|
||||
|
||||
https://opencollective.com/tiddlywiki
|
||||
|
||||
TiddlyWikiの資金調達に関する詳細情報や、プロジェクトを支援する方法については、[[TiddlyWikiへの資金提供|Funding TiddlyWiki]]をご覧ください。
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20140721121924384
|
||||
modified: 20241002115027813
|
||||
modified: 20260406052319609
|
||||
original-modified: 20240925113748341
|
||||
tags: Community
|
||||
title: Forums
|
||||
@@ -7,19 +7,17 @@ ja-title: フォーラム
|
||||
caption: フォーラム
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!!! ユーザー
|
||||
! ユーザーフォーラム
|
||||
|
||||
TiddlyWiki公式フォーラムは、~TiddlyWikiについて話し合う場です。ヘルプのリクエスト、新しいリリースやプラグインの[[アナウンス|https://talk.tiddlywiki.org/c/announcements/20]]、新機能の議論、または単にエクスペリエンスを共有するなどできます。関連するWebサイトから参加することも、電子メールで購読することもできます。
|
||||
!! Talk ~TiddlyWiki
|
||||
|
||||
公式~TiddlyWikiフォーラムとして、Talk ~TiddlyWikiは、~TiddlyWikiについて話し合う場です: ヘルプのリクエスト、新しいリリースやプラグインの[[アナウンス|https://talk.tiddlywiki.org/c/announcements/20]]、新機能の議論、または単にエクスペリエンスを共有するなどできます。関連するWebサイトから参加することも、電子メールで購読することもできます。
|
||||
|
||||
https://talk.tiddlywiki.org/
|
||||
|
||||
その他のフォーラム:
|
||||
!! Googleグループ
|
||||
|
||||
!!! Googleグループ
|
||||
|
||||
<<<
|
||||
既存ユーザーの便宜を図るため、オリジナルの~TiddlyWikiグループ(2005年からGoogleグループでホストされている)も引き続き運営しています。: https://groups.google.com/group/TiddlyWiki
|
||||
<<<
|
||||
既存ユーザーの便宜を図るため、オリジナルの~TiddlyWikiグループ(2005年からGoogleグループでホストされている)も引き続き運営しています: https://groups.google.com/group/TiddlyWiki
|
||||
|
||||
! 開発者フォーラム
|
||||
|
||||
@@ -27,9 +25,5 @@ https://talk.tiddlywiki.org/
|
||||
|
||||
! その他のフォーラム
|
||||
|
||||
* [[TiddlyWikiサブレディット|https://www.reddit.com/r/TiddlyWiki5/]]
|
||||
* https://discord.gg/HFFZVQ8 でDiscordでチャット
|
||||
|
||||
!! 開発者
|
||||
|
||||
{{Developers}}
|
||||
* TiddlyWikiサブレディット: [[/r/TiddlyWiki5|https://www.reddit.com/r/TiddlyWiki5/]]
|
||||
* https://discord.gg/HFFZVQ8 でDiscordでチャット
|
||||
@@ -0,0 +1,20 @@
|
||||
created: 20140107114355828
|
||||
modified: 20260406000640400
|
||||
original-modified: 20150220160920000
|
||||
tags: Concepts
|
||||
title: TemplateTiddlers
|
||||
ja-title: テンプレートTiddler
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
テンプレートTiddlerは、実際にはTiddlerの一種ではなく、Tiddlerが使用される役割の一つです。
|
||||
|
||||
テンプレートは、[[Wikiテキスト|WikiText]]の断片を再利用する方法です。
|
||||
|
||||
テンプレートを介したトランスクルージョンは、2つのTiddlerを組み合わせることで、[[トランスクルージョン|Transclusion]]の基本機能を拡張します:
|
||||
|
||||
* 表示する[[Wikiテキスト|WikiText]]を含むテンプレートTiddler。[[現在のTiddler|Current Tiddler]]内のフィールドを参照するトランスクルージョンを含めることができます。
|
||||
* フィールドへの参照を解決する際に、現在のTiddlerとして扱われるターゲットTiddler
|
||||
|
||||
テンプレートの最も優れた例は、TiddlyWikiのメインストーリーリバーです。ストーリーリバー内の各Tiddlerは、各フィールドのレンダリング方法を指定するViewTemplateを介してレンダリングされます。
|
||||
|
||||
詳細については、[[テンプレートを使用したトランスクルージョン|Transclusion with Templates]]を参照してください。
|
||||
@@ -0,0 +1,36 @@
|
||||
created: 20130827075900000
|
||||
modified: 20260406013639263
|
||||
original-modified: 20230321130421587
|
||||
tags: Concepts
|
||||
title: TextReference
|
||||
ja-title: テキスト参照
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
[[テキスト参照|TextReference]]は、テキストの断片をTiddlerのフィールドや[[データTiddler|DataTiddlers]]内のインデックスとして記述するための汎用的な方法です。
|
||||
|
||||
状況に応じて、テキスト参照を使用して値を取得したり、変更すべき値を指定したりすることができます。
|
||||
|
||||
[[テキスト参照|TextReference]]はいくつかのパーツから構成されます:
|
||||
|
||||
* 対象Tiddlerのタイトル。省略した場合、デフォルトで[[現在のTiddler|Current Tiddler]]が使用されます
|
||||
* 以下のいずれか:
|
||||
** フィールド名(`!!`でマークされます)
|
||||
** [[データTiddler|DataTiddlers]]内のインデックス名(`##`でマークされます)
|
||||
* フィールドとインデックスの両方が省略された場合、textフィールドがデフォルトとして使用されます
|
||||
|
||||
テキスト参照のほとんどのパーツは省略可能です:
|
||||
|
||||
* `tiddlerTitle` - 指定したTiddlerのtitle[[フィールド|TiddlerFields]]
|
||||
* `tiddlerTitle!!field` - [[Tiddlerのフィールド|TiddlerFields]] (例: `modified`、`modifier`、`type` など)
|
||||
* `!!field` - 現在のTiddlerの[[フィールド|TiddlerFields]]
|
||||
* `tiddlerTitle##propertyIndex` - DataTiddlersから名前付きプロパティを抽出
|
||||
|
||||
テキスト参照は、以下の場所で使用できます:
|
||||
|
||||
* [[フィルタ|Filters]]内の[[間接パラメータ|Filter Parameter]]として (例: `<$list filter="[tag{MyTag!!name}]"/>`)
|
||||
* 要素やウィジェットの[[間接属性|HTML in WikiText]]として (例: `<$widget attrib={{Title!!description}}/>`)
|
||||
* トランスクルージョンショートカットのパラメータとして (例: `{{MyTiddler!!title}}`)
|
||||
* [[Revealウィジェット|RevealWidget]]と[[LinkCatcherウィジェット|LinkCatcherWidget]]の`state`属性として
|
||||
|
||||
<$macrocall $name=".tip" _="""`foo!!bar`のようなテキスト参照と`{{foo!!bar}}`のようなテキスト参照のトランスクルージョンの違いに注意してください"""/>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
created: 20141129194651420
|
||||
modified: 20260406001216888
|
||||
original-modified: 20240621074019077
|
||||
tags: Concepts Definitions
|
||||
title: Transclusion
|
||||
ja-title: トランスクルージョン
|
||||
|
||||
! 定義
|
||||
|
||||
<<< Wikipedia: [[トランスクルージョン|https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%82%AF%E3%83%AB%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3]]
|
||||
コンピュータ科学において、トランスクルージョンとは、ハイパーテキストを介した参照によって、電子文書の一部または全部を他の1つまたは複数の文書に組み込むことを指します。
|
||||
<<<
|
||||
|
||||
~TiddlyWikiでは、''トランスクルージョン''とは、あるTiddler "A"を別のTiddler "B"から参照するプロセスであり、"A"の内容が"B"の一部であるかのように見せかけるものです。
|
||||
|
||||
コンテンツをコピー&ペーストすると、同じコンテンツが複数の場所に複製されてしまいます。一方、トランスクルージョンでは、単一のコピーと、Tiddler "A"からコンテンツを挿入する位置を示す特別な指示が"B"に記述されるだけで済みます。
|
||||
|
||||
"A"の内容が変更されると、"B"にも自動的に変更内容が反映されることに注意してください。これにより、コンテンツを1か所に記述し、複数の場所から閲覧できるため、繰り返し使用するコンテンツの管理が容易になります。
|
||||
|
||||
トランスクルージョンの概念は、小さなコンテンツを組み合わせる主要な方法であるため、[[Tiddlerの哲学|Philosophy of Tiddlers]]において重要な役割を果たしています。
|
||||
|
||||
詳細はこちらをご覧ください:
|
||||
|
||||
* [[Wikiテキストでのトランスクルージョン|Transclusion in WikiText]]
|
||||
* [[トランスクルージョンの基本的な使用法|Transclusion Basic Usage]]
|
||||
* [[テンプレートを使用したトランスクルージョン|Transclusion with Templates]]
|
||||
* [[トランスクルージョンと置換|Transclusion and Substitution]]
|
||||
* [[テキスト参照|TextReference]]
|
||||
* [[テンプレートTiddler|TemplateTiddlers]]
|
||||
* [[Transcludeウィジェット|TranscludeWidget]]
|
||||
* [[ハードトランスクルージョンとソフトトランスクルージョン|Hard and Soft Transclusions]]
|
||||
@@ -0,0 +1,17 @@
|
||||
created: 20131205155227468
|
||||
modified: 20260216114242627
|
||||
original-modified: 20230303214711802
|
||||
tags: Concepts Reference
|
||||
title: WikiText
|
||||
ja-title: Wikiテキスト
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
WikiTextは、広範囲のテキストフォーマット、ハイパーテキスト、インタラクティブ機能を入力するための簡潔で表現力豊かな方法です。複雑なユーザーインターフェイスに邪魔されることなく、執筆に集中できます。[[マークダウン|Markdown]]のユーザーにとって使いやすいように設計されていますが、リンクとインタラクティブ機能に重点が置かれています
|
||||
|
||||
[[エディターツールバー|Editor toolbar]]ボタンを使用して、Wikiテキストをテキストフィールドに挿入することもできます
|
||||
|
||||
Wikiテキストの概要については、[[Wikiテキストのフォーマット|Formatting in WikiText]]と[[TiddlyWikiのテキストフォーマット|Formatting text in TiddlyWiki]]を参照してください
|
||||
|
||||
次の要素のWikiテキスト構文がコアに組み込まれています:
|
||||
|
||||
<<list-links filter:"[tag[WikiText]]" class:"multi-columns">>
|
||||
@@ -0,0 +1,9 @@
|
||||
created: 20150221180826000
|
||||
modified: 20260406063958939
|
||||
original-modified: 20150221181700000
|
||||
tags: Definitions
|
||||
title: Base64
|
||||
ja-title: Base64
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.dlink-ex Base64 "https://en.wikipedia.org/wiki/Base64">>は、画像などのバイナリデータをテキスト文字列として表現する方法です
|
||||
@@ -0,0 +1,9 @@
|
||||
created: 20150221120651000
|
||||
modified: 20260406064757649
|
||||
original-modified: 20150221181705000
|
||||
tags: Definitions
|
||||
title: Cascading Style Sheets
|
||||
ja-title: カスケーディングスタイルシート(CSS)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.dlink-ex CSS "https://en.wikipedia.org/wiki/Cascading_Style_Sheets">>は、Webページ上のさまざまな要素の表示スタイルを定義するために使用される標準プレーンテキスト形式です
|
||||
@@ -0,0 +1,12 @@
|
||||
color: #7bb95d
|
||||
created: 20130825145100000
|
||||
modified: 20260406064409034
|
||||
original-modified: 20250104111522881
|
||||
title: Definitions
|
||||
ja-title: 定義
|
||||
tags: Reference
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
これらは、このドキュメントで使用される技術的なワードやフレーズの定義です(TiddlyWiki自体を構成する[[コンセプト|Concepts]]とは異なります)
|
||||
|
||||
<<list-links "[tag[Definitions]]" class:"multi-columns">>
|
||||
@@ -0,0 +1,13 @@
|
||||
created: 20230410105035569
|
||||
modified: 20260406065237731
|
||||
original-modified: 20230410105035569
|
||||
tags: Definitions
|
||||
title: Tiddlyhost
|
||||
ja-title: Tiddlyhost
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<span style="float:right;">[img width=140 [Tiddlyhost Logo]]</span>
|
||||
|
||||
[[Tiddlyhost.com|https://tiddlyhost.com/]]は、Simon Bairdによって作成されたTiddlyWikiのホスティングサービスです。サインアップして電子メールを確認すると、オンライン保存をサポートする"サイト"(つまり、~TiddlyWiki)を作成できます。サイトはプライベートやパブリックにすることができ、オプションでタグ付け可能で検索可能な[[Tiddlyhostハブ|https://tiddlyhost.com/hub]]にサイトをリストし、他のユーザーが見付けられるようにすることもできます。
|
||||
|
||||
[[TiddlySpot|Saving on TiddlySpot]]とは異なり、[[Tiddlyhost|https://tiddlyhost.com]]は安全でオープンソースであり、TiddlyWiki5を適切にサポートしています。また、既存の~TiddlyWikiファイルをアップロードしたり、TiddlyWikiClassicをサポートしたり、~TiddlySpotサイトの所有権を主張したりすることもできます。詳細については、[[FAQ|https://github.com/simonbaird/tiddlyhost/wiki/FAQ]]と[[About|https://tiddlyhost.com/about]]ページをご覧ください。
|
||||
@@ -21,3 +21,5 @@ type: text/vnd.tiddlywiki
|
||||
<<.tip """上に示したように、図に開始線と終了線が1つある場合は、リンクされた上位レベルにさらに情報があることを意味します。パンくずリストはナビゲーションに使用できます""">>
|
||||
|
||||
<<.tip """下位レベルで使用されているように、図に開始点と終了点がない場合は、読みやすさと単純さを高めるために、上位レベルのシンタックス要素が削除されていることを意味します。パンくずリストはナビゲーションに使用できます""">>
|
||||
|
||||
<<.note """フィルタ式の再帰深度は最大300です。この制限を超えて自身を再帰的に呼び出すフィルタ(例えば、<<.olink subfilter>>や<<.olink filter>>演算子を使ったもの)は、エラーメッセージ`/**-- Excessive filter recursion --**/`を返します。これは無限ループを防ぐためです。""">>
|
||||
|
||||
@@ -14,6 +14,8 @@ type: text/vnd.tiddlywiki
|
||||
"{" [: <-"間接"-> /"}以外"/] "}"
|
||||
|
|
||||
"<" [: <-"変数"-> /">以外"/] ">"
|
||||
|
|
||||
"(" [: <-"複数値変数"-> /")以外"/ ] ")" /"v5.4.0"/
|
||||
)
|
||||
"""/>
|
||||
|
||||
@@ -22,6 +24,7 @@ type: text/vnd.tiddlywiki
|
||||
;<<.def ハード>>
|
||||
: `[パラメータ例]`
|
||||
: パラメータは、角括弧内のテキストそのものです。
|
||||
|
||||
;<<.def ソフト>>
|
||||
: <<.def 間接>>
|
||||
:: `{パラメータ例}`
|
||||
@@ -30,6 +33,9 @@ type: text/vnd.tiddlywiki
|
||||
:: `<パラメータ例>`
|
||||
:: パラメータは、山括弧内の[[変数|Variables]]の現在値です。マクロパラメータは、v5.2.0まではサポートされて<<.em いません>>。
|
||||
::<<.from-version "5.2.0">> リテラルマクロパラメータがサポートされています。例: `[<now [UTC]YYYY0MM0DD0hh0mm0ssXXX>]`。
|
||||
: <<.def "複数値変数">>
|
||||
:: `(パラメータ例)`
|
||||
:: <<.from-version "5.4.0">> このパラメータは、丸括弧で囲まれた名前の[[複数値変数|Multi-Valued Variables]]に格納されている値のリスト全体に展開されます。このようにアクセスすると、フィルタ演算子は最初の値だけでなく、すべての値を受け取ります。詳細については、[[複数値変数|Multi-Valued Variables]]を参照してください。
|
||||
|
||||
<<.note """すべての[[フィルタオペレータ|filter Operator]]の後にはパラメータ式が続く必要があります。[[パラメータの無いオペレータ|Operators without parameters]]の場合、その式は空になります(`[<currentTiddler>links[]]`のフィルタオペレータ<<.olink links>>と同様)。""">>
|
||||
|
||||
@@ -37,4 +43,8 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.1.23">> [[フィルタステップ|Filter Step]]では、`,`文字で区切られた複数のパラメータがサポートされます。
|
||||
|
||||
例えば: `[param1],[param2]`や`<param1>,{param2}`
|
||||
例えば: `[param1],[param2]`や`<param1>,{param2}`、 `[param1],(param2)`
|
||||
|
||||
---
|
||||
|
||||
<<.warning """`/regexp/(flags)`オペランド構文は非推奨であり、ブラウザのコンソールに警告が表示されます。代わりに<<.olink regexp>>演算子を使用してください。""">>
|
||||
@@ -6,7 +6,6 @@ title: Filter Run Prefix
|
||||
ja-title: フィルタランプレフィックス
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
There are 2 types of filter run prefixes that are interchangeable; [[named prefixes|Named Filter Run Prefix]] and [[shortcut prefixes|Shortcut Filter Run Prefix]].
|
||||
交換可能なフィルタランプレフィックスには、[[名前付きプレフィックス|Named Filter Run Prefix]]と[[ショートカットプレフィックス|Shortcut Filter Run Prefix]]の2種類があります。
|
||||
|
||||
<$railroad text="""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user