mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-24 20:04:40 +00:00
Compare commits
231 Commits
wikitext-v
...
v5.1.20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f49c55fe3c | ||
|
|
ad175e222b | ||
|
|
2a3ea14437 | ||
|
|
762810361f | ||
|
|
9244a2f4fd | ||
|
|
067e8a9f94 | ||
|
|
a91ae1a877 | ||
|
|
2be09f23eb | ||
|
|
59264bbf2a | ||
|
|
803c2c749f | ||
|
|
c3df892321 | ||
|
|
68e6298e7d | ||
|
|
9df64c1ecf | ||
|
|
b8ac2d7a06 | ||
|
|
41d30bebc8 | ||
|
|
6df7b617fb | ||
|
|
31e7dbf020 | ||
|
|
f49ab78ebd | ||
|
|
41d3e80397 | ||
|
|
e1bb532d98 | ||
|
|
8159c4a865 | ||
|
|
0903fd2fec | ||
|
|
62a7fa4203 | ||
|
|
776ce0f65f | ||
|
|
4952be6518 | ||
|
|
427fbfd623 | ||
|
|
17711657b6 | ||
|
|
394725f00c | ||
|
|
9a2de11db1 | ||
|
|
fab67a463b | ||
|
|
64fe260f4d | ||
|
|
8db893b9c9 | ||
|
|
2d4831f920 | ||
|
|
0a6870656f | ||
|
|
b5653babdf | ||
|
|
3afaa9de9a | ||
|
|
dbaccf792d | ||
|
|
5faae2547d | ||
|
|
7f78065992 | ||
|
|
cb1d35e230 | ||
|
|
0a2d532a7b | ||
|
|
e669ec098f | ||
|
|
269fa5313f | ||
|
|
b30746813b | ||
|
|
32c5490a20 | ||
|
|
e86d4d29d5 | ||
|
|
cbd07465f3 | ||
|
|
27b75f3922 | ||
|
|
8a53cca00d | ||
|
|
5d36b484c6 | ||
|
|
e2bad34e89 | ||
|
|
b67e088e55 | ||
|
|
cb77f3f503 | ||
|
|
8226efa154 | ||
|
|
ac49b4d20c | ||
|
|
78cc80db13 | ||
|
|
2bcb36f151 | ||
|
|
8e7c0907f8 | ||
|
|
66dc7df745 | ||
|
|
fd88be4173 | ||
|
|
880a2aa153 | ||
|
|
173e9c6c3a | ||
|
|
a87a299aa9 | ||
|
|
f5b2599432 | ||
|
|
ba2f4822dd | ||
|
|
a3a25f2453 | ||
|
|
ecbbe87a0d | ||
|
|
217670cdf3 | ||
|
|
345a6a0f90 | ||
|
|
c647b42574 | ||
|
|
7811614d53 | ||
|
|
8aa6427d67 | ||
|
|
86286c6fce | ||
|
|
f7da4bafae | ||
|
|
08c900786e | ||
|
|
efa593bb50 | ||
|
|
19f2280803 | ||
|
|
6721d70de5 | ||
|
|
7b3d190974 | ||
|
|
3997600137 | ||
|
|
9f31867731 | ||
|
|
a06acc4eb8 | ||
|
|
6f3db0118e | ||
|
|
f5acf3adaa | ||
|
|
5ac2064d18 | ||
|
|
2a4c60b23d | ||
|
|
3edaa652ee | ||
|
|
77fedf9582 | ||
|
|
cf4c4532c3 | ||
|
|
ea0e1357bf | ||
|
|
ef7210adf4 | ||
|
|
e91fb29253 | ||
|
|
f978355ea4 | ||
|
|
1e1b2e28b6 | ||
|
|
d489f61f2a | ||
|
|
727d660715 | ||
|
|
6e5566b907 | ||
|
|
958b3e7b7c | ||
|
|
c578566dea | ||
|
|
8a0aef4dcb | ||
|
|
35a71ad577 | ||
|
|
c202ef4201 | ||
|
|
f42351e235 | ||
|
|
da61917797 | ||
|
|
16a53ae394 | ||
|
|
d1948621d3 | ||
|
|
de04755a0a | ||
|
|
02b141f97f | ||
|
|
15b576618f | ||
|
|
91db09bd1e | ||
|
|
d2f1debf92 | ||
|
|
f6c9150d32 | ||
|
|
2f723dd85a | ||
|
|
42bde75de2 | ||
|
|
112443c054 | ||
|
|
7781cb1f8b | ||
|
|
bf51ae0019 | ||
|
|
ed67f4a88b | ||
|
|
274dffe750 | ||
|
|
14003b0e88 | ||
|
|
36c7e82cc0 | ||
|
|
31b141097d | ||
|
|
448d108d69 | ||
|
|
69d3a47073 | ||
|
|
e313b0b7ca | ||
|
|
dc9f4e2de7 | ||
|
|
cb2bf25563 | ||
|
|
e09ac2ab37 | ||
|
|
b580baf5ee | ||
|
|
a6500ba711 | ||
|
|
fd8ede07bf | ||
|
|
c8d6f3b681 | ||
|
|
6582b106ee | ||
|
|
90684f9f52 | ||
|
|
ceb2d9f119 | ||
|
|
9b27f82a80 | ||
|
|
d8b79723cd | ||
|
|
2e2ed7902c | ||
|
|
6fd70f9c11 | ||
|
|
6099ec576c | ||
|
|
47dc59cd54 | ||
|
|
c963680f9c | ||
|
|
e6ac709840 | ||
|
|
32a2bea7f5 | ||
|
|
62829dc9d3 | ||
|
|
58cb300a0a | ||
|
|
a4dcc20797 | ||
|
|
2002ff72b7 | ||
|
|
250a1e5356 | ||
|
|
630a0ecf9e | ||
|
|
fef2ea97a1 | ||
|
|
73eb7fbd4e | ||
|
|
fc09f8e331 | ||
|
|
1a08430a0c | ||
|
|
23dd8da22c | ||
|
|
e5e5b1d739 | ||
|
|
7fcdc83bae | ||
|
|
86387a9185 | ||
|
|
dd7837d164 | ||
|
|
4a66ecbf6f | ||
|
|
f02352f6a1 | ||
|
|
cd412d8ccb | ||
|
|
18fe112da7 | ||
|
|
37bb75f0cf | ||
|
|
ac1d5b828d | ||
|
|
55bc6e086f | ||
|
|
6fdc5c8cb2 | ||
|
|
7590977dd5 | ||
|
|
1e8a56768f | ||
|
|
8012a3508f | ||
|
|
abb3c01505 | ||
|
|
28c732d2be | ||
|
|
72c64013c7 | ||
|
|
9c2726c530 | ||
|
|
427b56039b | ||
|
|
736ac9052d | ||
|
|
6c08fec2ee | ||
|
|
147d758931 | ||
|
|
5f6abad3c5 | ||
|
|
5b09881679 | ||
|
|
496610aa49 | ||
|
|
c80fcf19c0 | ||
|
|
698733a4ad | ||
|
|
a8f70b08a8 | ||
|
|
b992b79adb | ||
|
|
feab75a6d1 | ||
|
|
2f8053265e | ||
|
|
409a297a63 | ||
|
|
ba0da99b17 | ||
|
|
634ac92ba2 | ||
|
|
184fd9dda8 | ||
|
|
94d18a2f18 | ||
|
|
ff85fcfe93 | ||
|
|
e8d1fbba6c | ||
|
|
7869546fef | ||
|
|
dddfb7ce67 | ||
|
|
5ae14a16ec | ||
|
|
fddc5d4ee6 | ||
|
|
091864ddaf | ||
|
|
07198b9cda | ||
|
|
4401e71498 | ||
|
|
df416814b1 | ||
|
|
b7e0930122 | ||
|
|
0a5c826816 | ||
|
|
25c0ebb523 | ||
|
|
b32a5aa9af | ||
|
|
232eba2f7d | ||
|
|
04a4a0f92e | ||
|
|
0513837228 | ||
|
|
58cdbbf865 | ||
|
|
373afd72c8 | ||
|
|
7fcd2f132e | ||
|
|
edd3156430 | ||
|
|
8c72a28f0c | ||
|
|
61db047870 | ||
|
|
9b72eabd1a | ||
|
|
12b08b7abf | ||
|
|
53124e1d82 | ||
|
|
4ecc99c9d5 | ||
|
|
61d87875ff | ||
|
|
73703da2e7 | ||
|
|
aa5eaa98fc | ||
|
|
662ae91067 | ||
|
|
d5fa68b46a | ||
|
|
6e81122fa3 | ||
|
|
6575db07c7 | ||
|
|
f4d8c90191 | ||
|
|
37ea659bf0 | ||
|
|
754c1251a9 | ||
|
|
d51a89135d | ||
|
|
05243a6c48 |
@@ -34,6 +34,12 @@ fi
|
||||
|
||||
echo "Using TW5_BUILD_DETAILS as [$TW5_BUILD_DETAILS]"
|
||||
|
||||
if [ -z "$TW5_BUILD_COMMIT" ]; then
|
||||
TW5_BUILD_COMMIT="$(git rev-parse HEAD)"
|
||||
fi
|
||||
|
||||
echo "Using TW5_BUILD_COMMIT as [$TW5_BUILD_COMMIT]"
|
||||
|
||||
# Set up the build output directory
|
||||
|
||||
if [ -z "$TW5_BUILD_OUTPUT" ]; then
|
||||
@@ -74,7 +80,7 @@ echo "<a href='./plugins/tiddlywiki/tahoelafs/index.html'>Moved to http://tiddly
|
||||
|
||||
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
|
||||
|
||||
echo -e -n "title: $:/build\n\n$TW5_BUILD_DETAILS\n" > $TW5_BUILD_OUTPUT/build.tid
|
||||
echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n" > $TW5_BUILD_OUTPUT/build.tid
|
||||
|
||||
######################################################
|
||||
#
|
||||
|
||||
7
bin/npm-publish.sh
Executable file
7
bin/npm-publish.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# publish to npm
|
||||
|
||||
./bin/clean.sh
|
||||
|
||||
npm publish || exit 1
|
||||
8
bin/quick-bld.sh
Executable file
8
bin/quick-bld.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Abbreviated build script for building prerelease
|
||||
|
||||
tiddlywiki editions/prerelease \
|
||||
--verbose \
|
||||
--build favicon index \
|
||||
|| exit 1
|
||||
17
bin/readme-bld.sh
Executable file
17
bin/readme-bld.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build readmes from corresponding tiddlers
|
||||
|
||||
# Default to the version of TiddlyWiki installed in this repo
|
||||
|
||||
if [ -z "$TW5_BUILD_TIDDLYWIKI" ]; then
|
||||
TW5_BUILD_TIDDLYWIKI=./tiddlywiki.js
|
||||
fi
|
||||
|
||||
# tw5.com readmes
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
editions/tw5.com \
|
||||
--verbose \
|
||||
--output . \
|
||||
--build readmes \
|
||||
|| exit 1
|
||||
@@ -1,3 +1,4 @@
|
||||
<h1 class="">Script Files</h1><p>The <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> repository contains several scripts in the <code>bin</code> folder that you can use to automate common tasks, or as a useful starting point for your own scripts. See <a class="tc-tiddlylink tc-tiddlylink-missing" href="https://tiddlywiki.com/static/Scripts%2520for%2520building%2520tiddlywiki.com.html">Scripts for building tiddlywiki.com</a> for details of the scripts used to build and release <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/</a>.</p><p>All the scripts expect to be run from the root folder of the repository.</p><h2 class=""><code>serve</code>: serves tw5.com</h2><pre><code>./bin/serve.sh -h
|
||||
./bin/serve.sh [edition dir] [username] [password] [host] [port]</code></pre><p>Or:</p><pre><code>./bin/serve.cmd -h
|
||||
./bin/serve.cmd [edition dir] [username] [password] [host] [port]</code></pre><p>This script starts <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> running as an HTTP server, defaulting to the content from the <code>tw5.com-server</code> edition. By default, the Node.js serves on port 8080. If the optional <code>username</code> parameter is provided, it is used for signing edits. If the <code>password</code> is provided then HTTP basic authentication is used. Run the script with the <code>-h</code> parameter to see online help.</p><p>To experiment with this configuration, run the script and then visit <code>http://127.0.0.1:8080</code> in a browser.</p><p>Changes made in the browser propagate to the server over HTTP (use the browser developer console to see these requests). The server then syncs changes to the file system (and logs each change to the screen).</p><h2 class=""><code>test</code>: build and run tests</h2><p>This script runs the <code>test</code> edition of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on the server to perform the server-side tests and to build <code>test.html</code> for running the tests in the browser.</p><h2 class=""><code>lazy</code>: serves tw5.com with lazily loaded images</h2><pre><code>./bin/lazy.sh <username> [<password>]</code></pre><p>Or:</p><pre><code>./bin/lazy.cmd <username> [<password>]</code></pre><p>This script serves the <code>tw5.com-server</code> edition content with <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/LazyLoading.html">LazyLoading</a> applied to images.</p><h2 class=""><code>2bld</code>: builds <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> 2.6.5</h2><p>This script builds <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> 2.6.5 from the original source and then displays the differences between them (<code>diff</code> is used for *nix, <code>fc</code> for Windows).</p>
|
||||
./bin/serve.cmd [edition dir] [username] [password] [host] [port]</code></pre><p>This script starts <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> running as an HTTP server, defaulting to the content from the <code>tw5.com-server</code> edition. By default, the Node.js serves on port 8080. If the optional <code>username</code> parameter is provided, it is used for signing edits. If the <code>password</code> is provided then HTTP basic authentication is used. Run the script with the <code>-h</code> parameter to see online help.</p><p>To experiment with this configuration, run the script and then visit <code>http://127.0.0.1:8080</code> in a browser.</p><p>Changes made in the browser propagate to the server over HTTP (use the browser developer console to see these requests). The server then syncs changes to the file system (and logs each change to the screen).</p><h2 class=""><code>test</code>: build and run tests</h2><p>This script runs the <code>test</code> edition of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on the server to perform the server-side tests and to build <code>test.html</code> for running the tests in the browser.</p><h2 class=""><code>lazy</code>: serves tw5.com with lazily loaded images</h2><pre><code>./bin/lazy.sh <username> [<password>]</code></pre><p>Or:</p><pre><code>./bin/lazy.cmd <username> [<password>]</code></pre><p>This script serves the <code>tw5.com-server</code> edition content with <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/LazyLoading.html">LazyLoading</a> applied to images.
|
||||
</p>
|
||||
17
bin/verbump.sh
Executable file
17
bin/verbump.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bump to a new version number
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Missing version (eg '5.1.38-prerelease')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set the new version number (will also commit and tag the release)
|
||||
|
||||
npm version $1 -m "Version number update for $1" || exit 1
|
||||
|
||||
# Make sure our tags are pushed to the origin server
|
||||
|
||||
git push origin --tags || exit 1
|
||||
139
boot/boot.js
139
boot/boot.js
@@ -1013,7 +1013,7 @@ $tw.modules.define("$:/boot/tiddlerfields/list","tiddlerfield",{
|
||||
/*
|
||||
Wiki constructor. State is stored in private members that only a small number of privileged accessor methods have direct access. Methods added via the prototype have to use these accessors and cannot access the state data directly.
|
||||
options include:
|
||||
shadowTiddlers: Array of shadow tiddlers to be added
|
||||
enableIndexers - Array of indexer names to enable, or null to use all available indexers
|
||||
*/
|
||||
$tw.Wiki = function(options) {
|
||||
options = options || {};
|
||||
@@ -1028,14 +1028,31 @@ $tw.Wiki = function(options) {
|
||||
},
|
||||
pluginTiddlers = [], // Array of tiddlers containing registered plugins, ordered by priority
|
||||
pluginInfo = Object.create(null), // Hashmap of parsed plugin content
|
||||
shadowTiddlers = options.shadowTiddlers || Object.create(null), // Hashmap by title of {source:, tiddler:}
|
||||
shadowTiddlers = Object.create(null), // Hashmap by title of {source:, tiddler:}
|
||||
shadowTiddlerTitles = null,
|
||||
getShadowTiddlerTitles = function() {
|
||||
if(!shadowTiddlerTitles) {
|
||||
shadowTiddlerTitles = Object.keys(shadowTiddlers);
|
||||
}
|
||||
return shadowTiddlerTitles;
|
||||
};
|
||||
},
|
||||
enableIndexers = options.enableIndexers || null,
|
||||
indexers = [],
|
||||
indexersByName = Object.create(null);
|
||||
|
||||
this.addIndexer = function(indexer,name) {
|
||||
// Bail if this indexer is not enabled
|
||||
if(enableIndexers && enableIndexers.indexOf(name) === -1) {
|
||||
return;
|
||||
}
|
||||
indexers.push(indexer);
|
||||
indexersByName[name] = indexer;
|
||||
indexer.init();
|
||||
};
|
||||
|
||||
this.getIndexer = function(name) {
|
||||
return indexersByName[name] || null;
|
||||
};
|
||||
|
||||
// Add a tiddler to the store
|
||||
this.addTiddler = function(tiddler) {
|
||||
@@ -1048,12 +1065,33 @@ $tw.Wiki = function(options) {
|
||||
if(title) {
|
||||
// Uncomment the following line for detailed logs of all tiddler writes
|
||||
// console.log("Adding",title,tiddler)
|
||||
// Record the old tiddler state
|
||||
var updateDescriptor = {
|
||||
old: {
|
||||
tiddler: this.getTiddler(title),
|
||||
shadow: this.isShadowTiddler(title),
|
||||
exists: this.tiddlerExists(title)
|
||||
}
|
||||
}
|
||||
// Save the new tiddler
|
||||
tiddlers[title] = tiddler;
|
||||
// Check we've got it's title
|
||||
if(tiddlerTitles && tiddlerTitles.indexOf(title) === -1) {
|
||||
tiddlerTitles.push(title);
|
||||
}
|
||||
// Record the new tiddler state
|
||||
updateDescriptor["new"] = {
|
||||
tiddler: tiddler,
|
||||
shadow: this.isShadowTiddler(title),
|
||||
exists: this.tiddlerExists(title)
|
||||
}
|
||||
// Update indexes
|
||||
this.clearCache(title);
|
||||
this.clearGlobalCache();
|
||||
$tw.utils.each(indexers,function(indexer) {
|
||||
indexer.update(updateDescriptor);
|
||||
});
|
||||
// Queue a change event
|
||||
this.enqueueTiddlerEvent(title);
|
||||
}
|
||||
}
|
||||
@@ -1064,15 +1102,36 @@ $tw.Wiki = function(options) {
|
||||
// Uncomment the following line for detailed logs of all tiddler deletions
|
||||
// console.log("Deleting",title)
|
||||
if($tw.utils.hop(tiddlers,title)) {
|
||||
// Record the old tiddler state
|
||||
var updateDescriptor = {
|
||||
old: {
|
||||
tiddler: this.getTiddler(title),
|
||||
shadow: this.isShadowTiddler(title),
|
||||
exists: this.tiddlerExists(title)
|
||||
}
|
||||
}
|
||||
// Delete the tiddler
|
||||
delete tiddlers[title];
|
||||
// Delete it from the list of titles
|
||||
if(tiddlerTitles) {
|
||||
var index = tiddlerTitles.indexOf(title);
|
||||
if(index !== -1) {
|
||||
tiddlerTitles.splice(index,1);
|
||||
}
|
||||
}
|
||||
// Record the new tiddler state
|
||||
updateDescriptor["new"] = {
|
||||
tiddler: this.getTiddler(title),
|
||||
shadow: this.isShadowTiddler(title),
|
||||
exists: this.tiddlerExists(title)
|
||||
}
|
||||
// Update indexes
|
||||
this.clearCache(title);
|
||||
this.clearGlobalCache();
|
||||
$tw.utils.each(indexers,function(indexer) {
|
||||
indexer.update(updateDescriptor);
|
||||
});
|
||||
// Queue a change event
|
||||
this.enqueueTiddlerEvent(title,true);
|
||||
}
|
||||
};
|
||||
@@ -1159,7 +1218,6 @@ $tw.Wiki = function(options) {
|
||||
callback(tiddlers[title],title);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Test for the existence of a tiddler (excludes shadow tiddlers)
|
||||
@@ -1273,8 +1331,14 @@ $tw.Wiki = function(options) {
|
||||
shadowTiddlerTitles = null;
|
||||
this.clearCache(null);
|
||||
this.clearGlobalCache();
|
||||
$tw.utils.each(indexers,function(indexer) {
|
||||
indexer.rebuild();
|
||||
});
|
||||
};
|
||||
|
||||
if(this.addIndexersToWiki) {
|
||||
this.addIndexersToWiki();
|
||||
}
|
||||
};
|
||||
|
||||
// Dummy methods that will be filled in after boot
|
||||
@@ -1469,8 +1533,40 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/html","tiddlerdeserializer",{
|
||||
});
|
||||
$tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
|
||||
"application/json": function(text,fields) {
|
||||
var data = JSON.parse(text);
|
||||
return $tw.utils.isArray(data) ? data : [data];
|
||||
var isTiddlerValid = function(data) {
|
||||
// Not valid if it's not an object with a title property
|
||||
if(typeof(data) !== "object" || !$tw.utils.hop(data,"title")) {
|
||||
return false;
|
||||
}
|
||||
for(var f in data) {
|
||||
if($tw.utils.hop(data,f)) {
|
||||
// Check field name doesn't contain whitespace or control characters
|
||||
if(typeof(data[f]) !== "string" || /[\x00-\x1F\s]/.test(f)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
isTiddlerArrayValid = function(data) {
|
||||
for(var t=0; t<data.length; t++) {
|
||||
if(!isTiddlerValid(data[t])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
data = JSON.parse(text);
|
||||
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
|
||||
return data;
|
||||
} else if(isTiddlerValid(data)) {
|
||||
return [data];
|
||||
} else {
|
||||
// Plain JSON file
|
||||
fields.text = text;
|
||||
fields.type = "application/json";
|
||||
return [fields];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1623,9 +1719,11 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
|
||||
typeInfo = type ? $tw.config.contentTypeInfo[type] : null,
|
||||
data = fs.readFileSync(filepath,typeInfo ? typeInfo.encoding : "utf8"),
|
||||
tiddlers = $tw.wiki.deserializeTiddlers(ext,data,fields),
|
||||
metadata;
|
||||
if(ext !== ".json" && tiddlers.length === 1) {
|
||||
metadata = $tw.loadMetadataForFile(filepath);
|
||||
if(metadata) {
|
||||
if(type === "application/json") {
|
||||
tiddlers = [{text: data, type: "application/json"}];
|
||||
}
|
||||
tiddlers = [$tw.utils.extend({},tiddlers[0],metadata)];
|
||||
}
|
||||
return {filepath: filepath, type: type, tiddlers: tiddlers, hasMetaFile: !!metadata};
|
||||
@@ -1855,8 +1953,10 @@ $tw.loadPlugin = function(name,paths) {
|
||||
var pluginFields = $tw.loadPluginFolder(pluginPath);
|
||||
if(pluginFields) {
|
||||
$tw.wiki.addTiddler(pluginFields);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("Warning: Cannot find plugin '" + name + "'");
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1870,7 +1970,7 @@ $tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
|
||||
if(env) {
|
||||
env.split(path.delimiter).map(function(item) {
|
||||
if(item) {
|
||||
pluginPaths.push(item)
|
||||
pluginPaths.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2006,6 +2106,21 @@ $tw.loadTiddlersNode = function() {
|
||||
});
|
||||
// Load the core tiddlers
|
||||
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
|
||||
// Load any extra plugins
|
||||
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
||||
if(name.charAt(0) === "+") { // Relative path to plugin
|
||||
var pluginFields = $tw.loadPluginFolder(name.substring(1));;
|
||||
if(pluginFields) {
|
||||
$tw.wiki.addTiddler(pluginFields);
|
||||
}
|
||||
} else {
|
||||
var parts = name.split("/"),
|
||||
type = parts[0];
|
||||
if(parts.length === 3 && ["plugins","themes","languages"].indexOf(type) !== -1) {
|
||||
$tw.loadPlugins([parts[1] + "/" + parts[2]],$tw.config[type + "Path"],$tw.config[type + "EnvVar"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Load the tiddlers from the wiki directory
|
||||
if($tw.boot.wikiPath) {
|
||||
$tw.boot.wikiInfo = $tw.loadWikiTiddlers($tw.boot.wikiPath);
|
||||
@@ -2069,6 +2184,12 @@ $tw.boot.startup = function(options) {
|
||||
if($tw.boot.argv.length === 0) {
|
||||
$tw.boot.argv = ["--help"];
|
||||
}
|
||||
// Parse any extra plugin references
|
||||
$tw.boot.extraPlugins = $tw.boot.extraPlugins || [];
|
||||
while($tw.boot.argv[0] && $tw.boot.argv[0].indexOf("+") === 0) {
|
||||
$tw.boot.extraPlugins.push($tw.boot.argv[0].substring(1));
|
||||
$tw.boot.argv.splice(0,1);
|
||||
}
|
||||
// If the first command line argument doesn't start with `--` then we
|
||||
// interpret it as the path to the wiki folder, which will otherwise default
|
||||
// to the current folder
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<h1 class="">Contributing to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a></h1><p>We welcome contributions to the code and documentation of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> in several ways:</p><ul><li><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/ReportingBugs.html">ReportingBugs</a></li><li>Helping to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Improving%2520TiddlyWiki%2520Documentation.html">improve our documentation</a></li><li>Contributing to the code via <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5" rel="noopener noreferrer" target="_blank">GitHub</a><ul><li>See <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/dev" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/dev</a> for more details</li></ul></li></ul><p>There are other ways to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/HelpingTiddlyWiki.html">help TiddlyWiki</a> too.</p><h1 class="">Contributor License Agreement</h1><p>Like other <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/OpenSource.html">OpenSource</a> projects, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> needs a signed contributor license agreement from individual contributors. This is a legal agreement that allows contributors to assert that they own the copyright of their contribution, and that they agree to license it to the <a class="tc-tiddlylink tc-tiddlylink-missing" href="https://tiddlywiki.com/static/UnaMesa.html">UnaMesa</a> Association (the legal entity that owns <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on behalf of the community).</p><ul><li>For individuals use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a></li><li>For entities use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a></li></ul><h1 class="">How to sign the CLA</h1><p>Create a <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/GitHub.html">GitHub</a> pull request to add your name to <code>cla-individual.md</code> or <code>cla-entity.md</code>, with the date in the format (YYYY/MM/DD).</p><p><strong>step by step</strong></p><ol><li>Navigate to <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a> or <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a> according to whether you are signing as an individual or representative of an organisation</li><li>Click the "edit" button at the top-right corner (clicking this button will fork the project so you can edit the file)</li><li>Add your name at the bottom<ul><li>eg: <code>Jeremy Ruston, @Jermolene, 2011/11/22</code></li></ul></li><li>Below the edit box for the CLA text you should see a box labelled <strong>Propose file change</strong></li><li>Enter a brief title to explain the change (eg, "Signing the CLA")</li><li>Click the green button labelled <strong>Propose file change</strong></li><li>On the following screen, click the green button labelled <strong>Create pull request</strong></li></ol><hr><p><em>The CLA documents used for this project were created using <a class="tc-tiddlylink-external" href="http://www.harmonyagreements.org" rel="noopener noreferrer" target="_blank">Harmony Project Templates</a>. "HA-CLA-I-LIST Version 1.0" for "CLA-individual" and "HA-CLA-E-LIST Version 1.0" for "CLA-entity".</em></p><p>Remarks
|
||||
----—</p><ul><li><ul><li>When not owning the copyright in the entire work of authorship**</li></ul></li></ul><p>In this case, please clearly state so, since otherwise we assume that you are the legal copyright holder of the contributed work! Please provide links and additional information that clarify under which license the rest of the code is distributed.
|
||||
<h1 class="">Contributing to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a></h1><p>We welcome contributions to the code and documentation of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> in several ways:</p><ul><li><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/ReportingBugs.html">ReportingBugs</a></li><li>Helping to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Improving%2520TiddlyWiki%2520Documentation.html">improve our documentation</a></li><li>Contributing to the code via <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5" rel="noopener noreferrer" target="_blank">GitHub</a><ul><li>See <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/dev" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/dev</a> for more details</li></ul></li></ul><p>There are other ways to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/HelpingTiddlyWiki.html">help TiddlyWiki</a> too.</p><h1 class="">Contributor License Agreement</h1><p>Like other <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/OpenSource.html">OpenSource</a> projects, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> needs a signed contributor license agreement from individual contributors. This is a legal agreement that allows contributors to assert that they own the copyright of their contribution, and that they agree to license it to the <a class="tc-tiddlylink tc-tiddlylink-missing" href="https://tiddlywiki.com/static/UnaMesa.html">UnaMesa</a> Association (the legal entity that owns <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on behalf of the community).</p><ul><li>For individuals use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a></li><li>For entities use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a></li></ul><h1 class="">How to sign the CLA</h1><p>Create a <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/GitHub.html">GitHub</a> pull request to add your name to <code>cla-individual.md</code> or <code>cla-entity.md</code>, with the date in the format (YYYY/MM/DD).</p><p><strong>step by step</strong></p><ol><li>Navigate to <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a> or <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a> according to whether you are signing as an individual or representative of an organisation</li><li>Ensure that the "branch" dropdown at the top left is set to <code>tiddlywiki-com</code></li><li>Click the "edit" button at the top-right corner (clicking this button will fork the project so you can edit the file)</li><li>Add your name at the bottom<ul><li>eg: <code>Jeremy Ruston, @Jermolene, 2011/11/22</code></li></ul></li><li>Below the edit box for the CLA text you should see a box labelled <strong>Propose file change</strong></li><li>Enter a brief title to explain the change (eg, "Signing the CLA")</li><li>Click the green button labelled <strong>Propose file change</strong></li><li>On the following screen, click the green button labelled <strong>Create pull request</strong></li></ol><hr><p><em>The CLA documents used for this project were created using <a class="tc-tiddlylink-external" href="http://www.harmonyagreements.org" rel="noopener noreferrer" target="_blank">Harmony Project Templates</a>. "HA-CLA-I-LIST Version 1.0" for "CLA-individual" and "HA-CLA-E-LIST Version 1.0" for "CLA-entity".</em></p><h2 class="">Remarks</h2><p><strong>If you do not own the copyright in the entire work of authorship</strong>:</p><p>In this case, please clearly state so and provide links and any additional information that clarify under which license the rest of the code is distributed.
|
||||
</p><p><em>This file was automatically generated by <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a></em>
|
||||
</p>
|
||||
@@ -32,6 +32,7 @@ ExportTiddler/Caption: export tiddler
|
||||
ExportTiddler/Hint: Export tiddler
|
||||
ExportTiddlers/Caption: export tiddlers
|
||||
ExportTiddlers/Hint: Export tiddlers
|
||||
SidebarSearch/Hint: Select the sidebar search field
|
||||
Fold/Caption: fold tiddler
|
||||
Fold/Hint: Fold the body of this tiddler
|
||||
Fold/FoldBar/Caption: fold-bar
|
||||
@@ -181,6 +182,7 @@ Subscript/Caption: subscript
|
||||
Subscript/Hint: Apply subscript formatting to selection
|
||||
Superscript/Caption: superscript
|
||||
Superscript/Hint: Apply superscript formatting to selection
|
||||
ToggleSidebar/Hint: Toggle the sidebar visibility
|
||||
Transcludify/Caption: transclusion
|
||||
Transcludify/Hint: Wrap selection in curly brackets
|
||||
Underline/Caption: underline
|
||||
|
||||
@@ -47,6 +47,8 @@ LoadedModules/Hint: These are the currently loaded tiddler modules linked to the
|
||||
Palette/Caption: Palette
|
||||
Palette/Editor/Clone/Caption: clone
|
||||
Palette/Editor/Clone/Prompt: It is recommended that you clone this shadow palette before editing it
|
||||
Palette/Editor/Delete/Hint: delete this entry from the current palette
|
||||
Palette/Editor/Names/External/Show: Show color names that are not part of the current palette
|
||||
Palette/Editor/Prompt/Modified: This shadow palette has been modified
|
||||
Palette/Editor/Prompt: Editing
|
||||
Palette/Editor/Reset/Caption: reset
|
||||
@@ -89,6 +91,18 @@ Saving/DownloadSaver/Hint: These settings apply to the HTML5-compatible download
|
||||
Saving/General/Caption: General
|
||||
Saving/General/Hint: These settings apply to all the loaded savers
|
||||
Saving/Hint: Settings used for saving the entire TiddlyWiki as a single file via a saver module
|
||||
Saving/GitService/Branch: Target branch for saving
|
||||
Saving/GitService/CommitMessage: Saved by TiddlyWiki
|
||||
Saving/GitService/Description: These settings are only used when saving to <<service-name>>
|
||||
Saving/GitService/Filename: Filename of target file (e.g. `index.html`)
|
||||
Saving/GitService/Path: Path to target file (e.g. `/wiki/`)
|
||||
Saving/GitService/Repo: Target repository (e.g. `Jermolene/TiddlyWiki5`)
|
||||
Saving/GitService/ServerURL: Server API URL
|
||||
Saving/GitService/UserName: Username
|
||||
Saving/GitService/GitHub/Caption: ~GitHub Saver
|
||||
Saving/GitService/GitHub/Password: Password, OAUTH token, or personal access token (see [[GitHub help page|https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line]] for details)
|
||||
Saving/GitService/GitLab/Caption: ~GitLab Saver
|
||||
Saving/GitService/GitLab/Password: Personal access token for API (see [[GitLab help page|https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html]] for details)
|
||||
Saving/TiddlySpot/Advanced/Heading: Advanced Settings
|
||||
Saving/TiddlySpot/BackupDir: Backup Directory
|
||||
Saving/TiddlySpot/Backups: Backups
|
||||
|
||||
8
core/language/en-GB/Help/deletetiddlers.tid
Normal file
8
core/language/en-GB/Help/deletetiddlers.tid
Normal file
@@ -0,0 +1,8 @@
|
||||
title: $:/language/Help/deletetiddlers
|
||||
description: Deletes a group of tiddlers
|
||||
|
||||
<<.from-version "5.1.20">> Deletes a group of tiddlers identified by a filter.
|
||||
|
||||
```
|
||||
--deletetiddlers <filter>
|
||||
```
|
||||
19
core/language/en-GB/Help/savewikifolder.tid
Normal file
19
core/language/en-GB/Help/savewikifolder.tid
Normal file
@@ -0,0 +1,19 @@
|
||||
title: $:/language/Help/savewikifolder
|
||||
description: Saves a wiki to a new wiki folder
|
||||
|
||||
<<.from-version "5.1.20">> Saves the current wiki as a wiki folder, including tiddlers, plugins and configuration:
|
||||
|
||||
```
|
||||
--savewikifolder <wikifolderpath> [<filter>]
|
||||
```
|
||||
|
||||
* The target wiki folder must be empty or non-existent
|
||||
* The filter specifies which tiddlers should be included. It is optional, defaulting to `[all[tiddlers]]`
|
||||
* Plugins from the official plugin library are replaced with references to those plugins in the `tiddlywiki.info` file
|
||||
* Custom plugins are unpacked into their own folder
|
||||
|
||||
A common usage is to convert a TiddlyWiki HTML file into a wiki folder:
|
||||
|
||||
```
|
||||
tiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder
|
||||
```
|
||||
42
core/modules/commands/deletetiddlers.js
Normal file
42
core/modules/commands/deletetiddlers.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/deletetiddlers.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to delete tiddlers
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "deletetiddlers",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
if(this.params.length < 1) {
|
||||
return "Missing filter";
|
||||
}
|
||||
var self = this,
|
||||
wiki = this.commander.wiki,
|
||||
filter = this.params[0],
|
||||
tiddlers = wiki.filterTiddlers(filter);
|
||||
$tw.utils.each(tiddlers,function(title) {
|
||||
wiki.deleteTiddler(title);
|
||||
});
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
184
core/modules/commands/savewikifolder.js
Normal file
184
core/modules/commands/savewikifolder.js
Normal file
@@ -0,0 +1,184 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/savewikifolder.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to save the current wiki as a wiki folder
|
||||
|
||||
--savewikifolder <wikifolderpath> [<filter>]
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "savewikifolder",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var fs,path;
|
||||
if($tw.node) {
|
||||
fs = require("fs");
|
||||
path = require("path");
|
||||
}
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
if(this.params.length < 1) {
|
||||
return "Missing wiki folder path";
|
||||
}
|
||||
var wikifoldermaker = new WikiFolderMaker(this.params[0],this.params[1],this.commander);
|
||||
return wikifoldermaker.save();
|
||||
};
|
||||
|
||||
function WikiFolderMaker(wikiFolderPath,wikiFilter,commander) {
|
||||
this.wikiFolderPath = wikiFolderPath;
|
||||
this.wikiFilter = wikiFilter || "[all[tiddlers]]";
|
||||
this.commander = commander;
|
||||
this.wiki = commander.wiki;
|
||||
this.savedPaths = []; // So that we can detect filename clashes
|
||||
}
|
||||
|
||||
WikiFolderMaker.prototype.log = function(str) {
|
||||
if(this.commander.verbose) {
|
||||
console.log(str);
|
||||
}
|
||||
};
|
||||
|
||||
WikiFolderMaker.prototype.tiddlersToIgnore = [
|
||||
"$:/boot/boot.css",
|
||||
"$:/boot/boot.js",
|
||||
"$:/boot/bootprefix.js",
|
||||
"$:/core",
|
||||
"$:/library/sjcl.js",
|
||||
"$:/temp/info-plugin"
|
||||
];
|
||||
|
||||
/*
|
||||
Returns null if successful, or an error string if there was an error
|
||||
*/
|
||||
WikiFolderMaker.prototype.save = function() {
|
||||
var self = this;
|
||||
// Check that the output directory doesn't exist
|
||||
if(fs.existsSync(this.wikiFolderPath) && !$tw.utils.isDirectoryEmpty(this.wikiFolderPath)) {
|
||||
return "The unpackwiki command requires that the output wiki folder be empty";
|
||||
}
|
||||
// Get the tiddlers from the source wiki
|
||||
var tiddlerTitles = this.wiki.filterTiddlers(this.wikiFilter);
|
||||
// Initialise a new tiddlwiki.info file
|
||||
var newWikiInfo = {};
|
||||
// Process each incoming tiddler in turn
|
||||
$tw.utils.each(tiddlerTitles,function(title) {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
if(self.tiddlersToIgnore.indexOf(title) !== -1) {
|
||||
// Ignore the core plugin and the ephemeral info plugin
|
||||
self.log("Ignoring tiddler: " + title);
|
||||
} else {
|
||||
var type = tiddler.fields.type,
|
||||
pluginType = tiddler.fields["plugin-type"];
|
||||
if(type === "application/json" && pluginType) {
|
||||
// Plugin tiddler
|
||||
var libraryDetails = self.findPluginInLibrary(title);
|
||||
if(libraryDetails) {
|
||||
// A plugin from the core library
|
||||
self.log("Adding built-in plugin: " + libraryDetails.name);
|
||||
newWikiInfo[libraryDetails.type] = newWikiInfo[libraryDetails.type] || [];
|
||||
$tw.utils.pushTop(newWikiInfo[libraryDetails.type],libraryDetails.name);
|
||||
} else {
|
||||
// A custom plugin
|
||||
self.log("Processing custom plugin: " + title);
|
||||
self.saveCustomPlugin(tiddler);
|
||||
}
|
||||
} else {
|
||||
// Ordinary tiddler
|
||||
self.saveTiddler("tiddlers",tiddler);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Save the tiddlywiki.info file
|
||||
this.saveJSONFile("tiddlywiki.info",newWikiInfo);
|
||||
self.log("Writing tiddlywiki.info: " + JSON.stringify(newWikiInfo,null,$tw.config.preferences.jsonSpaces));
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
Test whether the specified tiddler is a plugin in the plugin library
|
||||
*/
|
||||
WikiFolderMaker.prototype.findPluginInLibrary = function(title) {
|
||||
var parts = title.split("/"),
|
||||
pluginPath, type, name;
|
||||
if(parts[0] === "$:") {
|
||||
if(parts[1] === "languages" && parts.length === 3) {
|
||||
pluginPath = "languages" + path.sep + parts[2];
|
||||
type = parts[1];
|
||||
name = parts[2];
|
||||
} else if(parts[1] === "plugins" || parts[1] === "themes" && parts.length === 4) {
|
||||
pluginPath = parts[1] + path.sep + parts[2] + path.sep + parts[3];
|
||||
type = parts[1];
|
||||
name = parts[2] + "/" + parts[3];
|
||||
}
|
||||
}
|
||||
if(pluginPath && type && name) {
|
||||
pluginPath = path.resolve($tw.boot.bootPath,"..",pluginPath);
|
||||
if(fs.existsSync(pluginPath)) {
|
||||
return {
|
||||
pluginPath: pluginPath,
|
||||
type: type,
|
||||
name: name
|
||||
};
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
|
||||
var self = this,
|
||||
pluginTitle = pluginTiddler.fields.title,
|
||||
titleParts = pluginTitle.split("/"),
|
||||
directory = $tw.utils.generateTiddlerFilepath(titleParts[titleParts.length - 1],{
|
||||
directory: path.resolve(this.wikiFolderPath,pluginTiddler.fields["plugin-type"] + "s")
|
||||
}),
|
||||
pluginInfo = pluginTiddler.getFieldStrings({exclude: ["text","type"]});
|
||||
this.saveJSONFile(directory + path.sep + "plugin.info",pluginInfo);
|
||||
self.log("Writing " + directory + path.sep + "plugin.info: " + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));
|
||||
var pluginTiddlers = JSON.parse(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
|
||||
$tw.utils.each(pluginTiddlers,function(tiddler) {
|
||||
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
|
||||
});
|
||||
};
|
||||
|
||||
WikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {
|
||||
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
|
||||
directory: path.resolve(this.wikiFolderPath,directory),
|
||||
wiki: this.wiki
|
||||
});
|
||||
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
|
||||
};
|
||||
|
||||
WikiFolderMaker.prototype.saveJSONFile = function(filename,json) {
|
||||
this.saveTextFile(filename,JSON.stringify(json,null,$tw.config.preferences.jsonSpaces));
|
||||
};
|
||||
|
||||
WikiFolderMaker.prototype.saveTextFile = function(filename,data) {
|
||||
this.saveFile(filename,"utf8",data);
|
||||
};
|
||||
|
||||
WikiFolderMaker.prototype.saveFile = function(filename,encoding,data) {
|
||||
var filepath = path.resolve(this.wikiFolderPath,filename);
|
||||
$tw.utils.createFileDirectories(filepath);
|
||||
fs.writeFileSync(filepath,data,encoding);
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -42,6 +42,7 @@ function FramedEngine(options) {
|
||||
this.iframeNode.style.border = "none";
|
||||
this.iframeNode.style.padding = "0";
|
||||
this.iframeNode.style.resize = "none";
|
||||
this.iframeNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
|
||||
this.iframeDoc.body.style.margin = "0";
|
||||
this.iframeDoc.body.style.padding = "0";
|
||||
this.widget.domNodes.push(this.iframeNode);
|
||||
@@ -78,6 +79,7 @@ function FramedEngine(options) {
|
||||
// Add event listeners
|
||||
$tw.utils.addEventListeners(this.domNode,[
|
||||
{name: "click",handlerObject: this,handlerMethod: "handleClickEvent"},
|
||||
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"},
|
||||
{name: "input",handlerObject: this,handlerMethod: "handleInputEvent"},
|
||||
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"}
|
||||
]);
|
||||
@@ -95,6 +97,7 @@ FramedEngine.prototype.copyStyles = function() {
|
||||
this.domNode.style.display = "block";
|
||||
this.domNode.style.width = "100%";
|
||||
this.domNode.style.margin = "0";
|
||||
this.domNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
|
||||
// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour
|
||||
this.domNode.style["-webkit-text-fill-color"] = "currentcolor";
|
||||
};
|
||||
@@ -150,6 +153,14 @@ FramedEngine.prototype.focus = function() {
|
||||
this.domNode.select();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Handle the focus event
|
||||
*/
|
||||
FramedEngine.prototype.handleFocusEvent = function(event) {
|
||||
this.widget.cancelPopups();
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Handle a click
|
||||
|
||||
@@ -122,6 +122,7 @@ SimpleEngine.prototype.handleInputEvent = function(event) {
|
||||
Handle a dom "focus" event
|
||||
*/
|
||||
SimpleEngine.prototype.handleFocusEvent = function(event) {
|
||||
this.widget.cancelPopups();
|
||||
if(this.widget.editFocusPopup) {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: this.domNode,
|
||||
|
||||
@@ -193,7 +193,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
type = type || "text";
|
||||
}
|
||||
// Get the rest of our parameters
|
||||
this.editTag = this.getAttribute("tag",tag);
|
||||
this.editTag = this.getAttribute("tag",tag) || "input";
|
||||
this.editType = this.getAttribute("type",type);
|
||||
// Make the child widgets
|
||||
this.makeChildWidgets();
|
||||
@@ -248,6 +248,13 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Cancel Popups
|
||||
*/
|
||||
EditTextWidget.prototype.cancelPopups = function() {
|
||||
$tw.popup.cancel(0,this.engine.domNode);
|
||||
};
|
||||
|
||||
/*
|
||||
Handle a dom "keydown" event, which we'll bubble up to our container for the keyboard widgets benefit
|
||||
*/
|
||||
|
||||
@@ -119,7 +119,7 @@ exports.parseFilter = function(filterString) {
|
||||
p = 0, // Current position in the filter string
|
||||
match;
|
||||
var whitespaceRegExp = /(\s+)/mg,
|
||||
operandRegExp = /((?:\+|\-|~)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
||||
operandRegExp = /((?:\+|\-|~|=)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
||||
while(p < filterString.length) {
|
||||
// Skip any whitespace
|
||||
whitespaceRegExp.lastIndex = p;
|
||||
@@ -248,6 +248,10 @@ exports.compileFilter = function(filterString) {
|
||||
return function(results,source,widget) {
|
||||
$tw.utils.pushTop(results,operationSubFunction(source,widget));
|
||||
};
|
||||
case "=": // The results of the operation are pushed into the result without deduplication
|
||||
return function(results,source,widget) {
|
||||
Array.prototype.push.apply(results,operationSubFunction(source,widget));
|
||||
};
|
||||
case "-": // The results of this operation are removed from the main result
|
||||
return function(results,source,widget) {
|
||||
$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));
|
||||
@@ -270,7 +274,7 @@ exports.compileFilter = function(filterString) {
|
||||
})());
|
||||
});
|
||||
// Return a function that applies the operations to a source iterator of tiddler titles
|
||||
return $tw.perf.measure("filter",function filterFunction(source,widget) {
|
||||
return $tw.perf.measure("filter: " + filterString,function filterFunction(source,widget) {
|
||||
if(!source) {
|
||||
source = self.each;
|
||||
} else if(typeof source === "object") { // Array or hashmap
|
||||
|
||||
30
core/modules/filters/else.js
Normal file
30
core/modules/filters/else.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/else.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for replacing an empty input list with a constant, passing a non-empty input list straight through
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.else = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
if(results.length === 0) {
|
||||
return [operator.operand];
|
||||
} else {
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -98,4 +98,13 @@ exports.escaperegexp = function(source,operator,options) {
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.escapecss = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
// escape any character with a special meaning in CSS using CSS.escape()
|
||||
results.push(CSS.escape(title));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -16,7 +16,16 @@ Filter operator returning its operand parsed as a list
|
||||
Export our filter function
|
||||
*/
|
||||
exports.enlist = function(source,operator,options) {
|
||||
var list = $tw.utils.parseStringArray(operator.operand);
|
||||
var allowDuplicates = false;
|
||||
switch(operator.suffix) {
|
||||
case "raw":
|
||||
allowDuplicates = true;
|
||||
break;
|
||||
case "dedupe":
|
||||
allowDuplicates = false;
|
||||
break;
|
||||
}
|
||||
var list = $tw.utils.parseStringArray(operator.operand,allowDuplicates);
|
||||
if(operator.prefix === "!") {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
|
||||
@@ -16,7 +16,7 @@ Filter operator for comparing fields for equality
|
||||
Export our filter function
|
||||
*/
|
||||
exports.field = function(source,operator,options) {
|
||||
var results = [],
|
||||
var results = [],indexedResults,
|
||||
fieldname = (operator.suffix || operator.operator || "title").toLowerCase();
|
||||
if(operator.prefix === "!") {
|
||||
if(operator.regexp) {
|
||||
@@ -53,6 +53,12 @@ exports.field = function(source,operator,options) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if(source.byField) {
|
||||
indexedResults = source.byField(fieldname,operator.operand);
|
||||
if(indexedResults) {
|
||||
return indexedResults
|
||||
}
|
||||
}
|
||||
source(function(tiddler,title) {
|
||||
if(tiddler) {
|
||||
var text = tiddler.getFieldString(fieldname);
|
||||
|
||||
26
core/modules/filters/getvariable.js
Normal file
26
core/modules/filters/getvariable.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/getvariable.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for replacing input values by the value of the variable with the same name, or blank if the variable is missing
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.getvariable = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(options.widget.getVariable(title) || "");
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -45,7 +45,7 @@ exports.has = function(source,operator,options) {
|
||||
if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && !(tiddler.fields[operator.operand] === "" || tiddler.fields[operator.operand].length === 0)) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
||||
36
core/modules/filters/is/blank.js
Normal file
36
core/modules/filters/is/blank.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/is/blank.js
|
||||
type: application/javascript
|
||||
module-type: isfilteroperator
|
||||
|
||||
Filter function for [is[blank]]
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.blank = function(source,prefix,options) {
|
||||
var results = [];
|
||||
if(prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(!title) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
53
core/modules/filters/match.js
Normal file
53
core/modules/filters/match.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/match.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for checking if a title matches a string
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.match = function(source,operator,options) {
|
||||
var results = [],
|
||||
suffixes = (operator.suffixes || [])[0] || [];
|
||||
if(suffixes.indexOf("caseinsensitive") !== -1) {
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title.toLowerCase() !== (operator.operand || "").toLowerCase()) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(title.toLowerCase() === (operator.operand || "").toLowerCase()) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(title !== operator.operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(title === operator.operand) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -43,6 +43,10 @@ exports.trunc = makeNumericBinaryOperator(
|
||||
function(a) {return Math.trunc(a)}
|
||||
);
|
||||
|
||||
exports.untrunc = makeNumericBinaryOperator(
|
||||
function(a) {return Math.ceil(Math.abs(a)) * Math.sign(a)}
|
||||
);
|
||||
|
||||
exports.sign = makeNumericBinaryOperator(
|
||||
function(a) {return Math.sign(a)}
|
||||
);
|
||||
@@ -76,33 +80,33 @@ exports.min = makeNumericBinaryOperator(
|
||||
);
|
||||
|
||||
exports.fixed = makeNumericBinaryOperator(
|
||||
function(a,b) {return Number.prototype.toFixed.call(a,b);}
|
||||
function(a,b) {return Number.prototype.toFixed.call(a,Math.min(Math.max(b,0),100));}
|
||||
);
|
||||
|
||||
exports.precision = makeNumericBinaryOperator(
|
||||
function(a,b) {return Number.prototype.toPrecision.call(a,b);}
|
||||
function(a,b) {return Number.prototype.toPrecision.call(a,Math.min(Math.max(b,1),100));}
|
||||
);
|
||||
|
||||
exports.exponential = makeNumericBinaryOperator(
|
||||
function(a,b) {return Number.prototype.toExponential.call(a,b);}
|
||||
function(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}
|
||||
);
|
||||
|
||||
exports.sum = makeNumericArrayOperator(
|
||||
exports.sum = makeNumericReducingOperator(
|
||||
function(accumulator,value) {return accumulator + value},
|
||||
0 // Initial value
|
||||
);
|
||||
|
||||
exports.product = makeNumericArrayOperator(
|
||||
exports.product = makeNumericReducingOperator(
|
||||
function(accumulator,value) {return accumulator * value},
|
||||
1 // Initial value
|
||||
);
|
||||
|
||||
exports.maxall = makeNumericArrayOperator(
|
||||
exports.maxall = makeNumericReducingOperator(
|
||||
function(accumulator,value) {return Math.max(accumulator,value)},
|
||||
-Infinity // Initial value
|
||||
);
|
||||
|
||||
exports.minall = makeNumericArrayOperator(
|
||||
exports.minall = makeNumericReducingOperator(
|
||||
function(accumulator,value) {return Math.min(accumulator,value)},
|
||||
Infinity // Initial value
|
||||
);
|
||||
@@ -118,7 +122,7 @@ function makeNumericBinaryOperator(fnCalc) {
|
||||
};
|
||||
}
|
||||
|
||||
function makeNumericArrayOperator(fnCalc,initialValue) {
|
||||
function makeNumericReducingOperator(fnCalc,initialValue) {
|
||||
initialValue = initialValue || 0;
|
||||
return function(source,operator,options) {
|
||||
var result = [];
|
||||
|
||||
@@ -43,6 +43,7 @@ exports.search = function(source,operator,options) {
|
||||
caseSensitive: hasFlag("casesensitive"),
|
||||
literal: hasFlag("literal"),
|
||||
whitespace: hasFlag("whitespace"),
|
||||
anchored: hasFlag("anchored"),
|
||||
regexp: hasFlag("regexp"),
|
||||
words: hasFlag("words")
|
||||
});
|
||||
|
||||
@@ -26,22 +26,30 @@ exports.lowercase = makeStringBinaryOperator(
|
||||
function(a) {return [("" + a).toLowerCase()];}
|
||||
);
|
||||
|
||||
exports.sentencecase = makeStringBinaryOperator(
|
||||
function(a) {return [$tw.utils.toSentenceCase(a)];}
|
||||
);
|
||||
|
||||
exports.titlecase = makeStringBinaryOperator(
|
||||
function(a) {return [$tw.utils.toTitleCase(a)];}
|
||||
);
|
||||
|
||||
exports.trim = makeStringBinaryOperator(
|
||||
function(a) {return [$tw.utils.trim(a)];}
|
||||
);
|
||||
|
||||
exports.concat = makeStringBinaryOperator(
|
||||
function(a,b) {return ["" + a + b];}
|
||||
);
|
||||
|
||||
exports.split = makeStringBinaryOperator(
|
||||
function(a,b) {return ("" + a).split(b).filter(function(str) {return !!str;});}
|
||||
function(a,b) {return ("" + a).split(b);}
|
||||
);
|
||||
|
||||
exports.join = makeStringArrayOperator(
|
||||
exports.join = makeStringReducingOperator(
|
||||
function(accumulator,value,operand) {
|
||||
return "" + (accumulator ? accumulator + (operand || "") + value : value);
|
||||
}
|
||||
if(accumulator === null) {
|
||||
return value;
|
||||
} else {
|
||||
return accumulator + operand + value;
|
||||
}
|
||||
},null
|
||||
);
|
||||
|
||||
function makeStringBinaryOperator(fnCalc) {
|
||||
@@ -54,8 +62,7 @@ function makeStringBinaryOperator(fnCalc) {
|
||||
};
|
||||
}
|
||||
|
||||
function makeStringArrayOperator(fnCalc,initialValue) {
|
||||
initialValue = initialValue || "";
|
||||
function makeStringReducingOperator(fnCalc,initialValue) {
|
||||
return function(source,operator,options) {
|
||||
var result = [];
|
||||
source(function(tiddler,title) {
|
||||
@@ -67,4 +74,20 @@ function makeStringArrayOperator(fnCalc,initialValue) {
|
||||
};
|
||||
}
|
||||
|
||||
exports.splitregexp = function(source,operator,options) {
|
||||
var result = [],
|
||||
suffix = operator.suffix || "",
|
||||
flags = (suffix.indexOf("m") !== -1 ? "m" : "") + (suffix.indexOf("i") !== -1 ? "i" : ""),
|
||||
regExp;
|
||||
try {
|
||||
regExp = new RegExp(operator.operand || "",flags);
|
||||
} catch(ex) {
|
||||
return ["RegExp error: " + ex];
|
||||
}
|
||||
source(function(tiddler,title) {
|
||||
Array.prototype.push.apply(result,title.split(regExp));
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -16,7 +16,7 @@ Filter operator for checking for the presence of a tag
|
||||
Export our filter function
|
||||
*/
|
||||
exports.tag = function(source,operator,options) {
|
||||
var results = [];
|
||||
var results = [],indexedResults;
|
||||
if((operator.suffix || "").toLowerCase() === "strict" && !operator.operand) {
|
||||
// New semantics:
|
||||
// Always return copy of input if operator.operand is missing
|
||||
@@ -25,9 +25,10 @@ exports.tag = function(source,operator,options) {
|
||||
});
|
||||
} else {
|
||||
// Old semantics:
|
||||
var tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
|
||||
var tiddlers;
|
||||
if(operator.prefix === "!") {
|
||||
// Returns a copy of the input if operator.operand is missing
|
||||
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
|
||||
source(function(tiddler,title) {
|
||||
if(tiddlers.indexOf(title) === -1) {
|
||||
results.push(title);
|
||||
@@ -35,12 +36,20 @@ exports.tag = function(source,operator,options) {
|
||||
});
|
||||
} else {
|
||||
// Returns empty results if operator.operand is missing
|
||||
source(function(tiddler,title) {
|
||||
if(tiddlers.indexOf(title) !== -1) {
|
||||
results.push(title);
|
||||
if(source.byTag) {
|
||||
indexedResults = source.byTag(operator.operand);
|
||||
if(indexedResults) {
|
||||
return indexedResults;
|
||||
}
|
||||
});
|
||||
results = options.wiki.sortByList(results,operator.operand);
|
||||
} else {
|
||||
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
|
||||
source(function(tiddler,title) {
|
||||
if(tiddlers.indexOf(title) !== -1) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
results = options.wiki.sortByList(results,operator.operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
||||
26
core/modules/filters/then.js
Normal file
26
core/modules/filters/then.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/then.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for replacing any titles with a constant
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.then = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(operator.operand);
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
26
core/modules/filters/variables.js
Normal file
26
core/modules/filters/variables.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/variables.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for returning the names of the active variables
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.variables = function(source,operator,options) {
|
||||
var names = [];
|
||||
for(var variable in options.widget.variables) {
|
||||
names.push(variable);
|
||||
}
|
||||
return names.sort();
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -95,7 +95,7 @@ Extended filter operators to manipulate the current list.
|
||||
exports.allafter = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand);
|
||||
return (index === -1 || index > (results.length - 2)) ? [] :
|
||||
return (index === -1) ? [] :
|
||||
(operator.suffix) ? results.slice(index) :
|
||||
results.slice(index + 1);
|
||||
};
|
||||
@@ -106,7 +106,7 @@ Extended filter operators to manipulate the current list.
|
||||
exports.allbefore = function (source, operator) {
|
||||
var results = prepare_results(source),
|
||||
index = results.indexOf(operator.operand);
|
||||
return (index < 0) ? [] :
|
||||
return (index === -1) ? [] :
|
||||
(operator.suffix) ? results.slice(0, index + 1) :
|
||||
results.slice(0, index);
|
||||
};
|
||||
|
||||
143
core/modules/indexers/field-indexer.js
Normal file
143
core/modules/indexers/field-indexer.js
Normal file
@@ -0,0 +1,143 @@
|
||||
/*\
|
||||
title: $:/core/modules/indexers/field-indexer.js
|
||||
type: application/javascript
|
||||
module-type: indexer
|
||||
|
||||
Indexes the tiddlers with each field value
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global modules: false */
|
||||
"use strict";
|
||||
|
||||
var DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH = 128;
|
||||
|
||||
function FieldIndexer(wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
|
||||
FieldIndexer.prototype.init = function() {
|
||||
this.index = null;
|
||||
this.maxIndexedValueLength = DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH;
|
||||
this.addIndexMethods();
|
||||
}
|
||||
|
||||
// Provided for testing
|
||||
FieldIndexer.prototype.setMaxIndexedValueLength = function(length) {
|
||||
this.index = null;
|
||||
this.maxIndexedValueLength = length;
|
||||
};
|
||||
|
||||
FieldIndexer.prototype.addIndexMethods = function() {
|
||||
var self = this;
|
||||
this.wiki.each.byField = function(name,value) {
|
||||
var titles = self.wiki.allTitles(),
|
||||
lookup = self.lookup(name,value);
|
||||
return lookup && lookup.filter(function(title) {
|
||||
return titles.indexOf(title) !== -1;
|
||||
});
|
||||
};
|
||||
this.wiki.eachShadow.byField = function(name,value) {
|
||||
var titles = self.wiki.allShadowTitles(),
|
||||
lookup = self.lookup(name,value);
|
||||
return lookup && lookup.filter(function(title) {
|
||||
return titles.indexOf(title) !== -1;
|
||||
});
|
||||
};
|
||||
this.wiki.eachTiddlerPlusShadows.byField = function(name,value) {
|
||||
var lookup = self.lookup(name,value);
|
||||
return lookup ? lookup.slice(0) : null;
|
||||
};
|
||||
this.wiki.eachShadowPlusTiddlers.byField = function(name,value) {
|
||||
var lookup = self.lookup(name,value);
|
||||
return lookup ? lookup.slice(0) : null;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Tear down and then rebuild the index as if all tiddlers have changed
|
||||
*/
|
||||
FieldIndexer.prototype.rebuild = function() {
|
||||
// Invalidate the index so that it will be rebuilt when it is next used
|
||||
this.index = null;
|
||||
};
|
||||
|
||||
/*
|
||||
Build the index for a particular field
|
||||
*/
|
||||
FieldIndexer.prototype.buildIndexForField = function(name) {
|
||||
var self = this;
|
||||
// Hashmap by field name of hashmap by field value of array of tiddler titles
|
||||
this.index = this.index || Object.create(null);
|
||||
this.index[name] = Object.create(null);
|
||||
var baseIndex = this.index[name];
|
||||
// Update the index for each tiddler
|
||||
this.wiki.eachTiddlerPlusShadows(function(tiddler,title) {
|
||||
if(name in tiddler.fields) {
|
||||
var value = tiddler.getFieldString(name);
|
||||
// Skip any values above the maximum length
|
||||
if(value.length < self.maxIndexedValueLength) {
|
||||
baseIndex[value] = baseIndex[value] || [];
|
||||
baseIndex[value].push(title);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Update the index in the light of a tiddler value changing; note that the title must be identical. (Renames are handled as a separate delete and create)
|
||||
updateDescriptor: {old: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>},new: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>}}
|
||||
*/
|
||||
FieldIndexer.prototype.update = function(updateDescriptor) {
|
||||
var self = this;
|
||||
// Don't do anything if the index hasn't been built yet
|
||||
if(this.index === null) {
|
||||
return;
|
||||
}
|
||||
// Remove the old tiddler from the index
|
||||
if(updateDescriptor.old.tiddler) {
|
||||
$tw.utils.each(this.index,function(indexEntry,name) {
|
||||
if(name in updateDescriptor.old.tiddler.fields) {
|
||||
var value = updateDescriptor.old.tiddler.getFieldString(name),
|
||||
tiddlerList = indexEntry[value];
|
||||
if(tiddlerList) {
|
||||
var index = tiddlerList.indexOf(updateDescriptor.old.tiddler.fields.title);
|
||||
if(index !== -1) {
|
||||
tiddlerList.splice(index,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Add the new tiddler to the index
|
||||
if(updateDescriptor["new"].tiddler) {
|
||||
$tw.utils.each(this.index,function(indexEntry,name) {
|
||||
if(name in updateDescriptor["new"].tiddler.fields) {
|
||||
var value = updateDescriptor["new"].tiddler.getFieldString(name);
|
||||
if(value.length < self.maxIndexedValueLength) {
|
||||
indexEntry[value] = indexEntry[value] || [];
|
||||
indexEntry[value].push(updateDescriptor["new"].tiddler.fields.title);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Lookup the given field returning a list of tiddler titles
|
||||
FieldIndexer.prototype.lookup = function(name,value) {
|
||||
// Fail the lookup if the value is too long
|
||||
if(value.length >= this.maxIndexedValueLength) {
|
||||
return null;
|
||||
}
|
||||
// Update the index if it has yet to be built
|
||||
if(this.index === null || !this.index[name]) {
|
||||
this.buildIndexForField(name);
|
||||
}
|
||||
return this.index[name][value] || [];
|
||||
};
|
||||
|
||||
exports.FieldIndexer = FieldIndexer;
|
||||
|
||||
})();
|
||||
98
core/modules/indexers/tag-indexer.js
Normal file
98
core/modules/indexers/tag-indexer.js
Normal file
@@ -0,0 +1,98 @@
|
||||
/*\
|
||||
title: $:/core/modules/indexers/tag-indexer.js
|
||||
type: application/javascript
|
||||
module-type: indexer
|
||||
|
||||
Indexes the tiddlers with each tag
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global modules: false */
|
||||
"use strict";
|
||||
|
||||
function TagIndexer(wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
|
||||
TagIndexer.prototype.init = function() {
|
||||
this.subIndexers = [
|
||||
new TagSubIndexer(this,"each"),
|
||||
new TagSubIndexer(this,"eachShadow"),
|
||||
new TagSubIndexer(this,"eachTiddlerPlusShadows"),
|
||||
new TagSubIndexer(this,"eachShadowPlusTiddlers")
|
||||
];
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.addIndexMethod();
|
||||
});
|
||||
};
|
||||
|
||||
TagIndexer.prototype.rebuild = function() {
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.rebuild();
|
||||
});
|
||||
};
|
||||
|
||||
TagIndexer.prototype.update = function(updateDescriptor) {
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.update(updateDescriptor);
|
||||
});
|
||||
};
|
||||
|
||||
function TagSubIndexer(indexer,iteratorMethod) {
|
||||
this.indexer = indexer;
|
||||
this.iteratorMethod = iteratorMethod;
|
||||
this.index = null; // Hashmap of tag title to {isSorted: bool, titles: [array]} or null if not yet initialised
|
||||
}
|
||||
|
||||
TagSubIndexer.prototype.addIndexMethod = function() {
|
||||
var self = this;
|
||||
this.indexer.wiki[this.iteratorMethod].byTag = function(tag) {
|
||||
return self.lookup(tag).slice(0);
|
||||
};
|
||||
};
|
||||
|
||||
TagSubIndexer.prototype.rebuild = function() {
|
||||
var self = this;
|
||||
// Hashmap by tag of array of {isSorted:, titles:[]}
|
||||
this.index = Object.create(null);
|
||||
// Add all the tags
|
||||
this.indexer.wiki[this.iteratorMethod](function(tiddler,title) {
|
||||
$tw.utils.each(tiddler.fields.tags,function(tag) {
|
||||
if(!self.index[tag]) {
|
||||
self.index[tag] = {isSorted: false, titles: [title]};
|
||||
} else {
|
||||
self.index[tag].titles.push(title);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
TagSubIndexer.prototype.update = function(updateDescriptor) {
|
||||
this.index = null;
|
||||
};
|
||||
|
||||
TagSubIndexer.prototype.lookup = function(tag) {
|
||||
// Update the index if it has yet to be built
|
||||
if(this.index === null) {
|
||||
this.rebuild();
|
||||
}
|
||||
var indexRecord = this.index[tag];
|
||||
if(indexRecord) {
|
||||
if(!indexRecord.isSorted) {
|
||||
if(this.indexer.wiki.sortByList) {
|
||||
indexRecord.titles = this.indexer.wiki.sortByList(indexRecord.titles,tag);
|
||||
}
|
||||
indexRecord.isSorted = true;
|
||||
}
|
||||
return indexRecord.titles;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.TagIndexer = TagIndexer;
|
||||
|
||||
})();
|
||||
@@ -1,41 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/macros/dumpvariables.js
|
||||
type: application/javascript
|
||||
module-type: macro
|
||||
|
||||
Macro to dump all active variable values
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Information about this macro
|
||||
*/
|
||||
|
||||
exports.name = "dumpvariables";
|
||||
|
||||
exports.params = [
|
||||
];
|
||||
|
||||
/*
|
||||
Run the macro
|
||||
*/
|
||||
exports.run = function() {
|
||||
var output = ["|!Variable |!Value |"],
|
||||
variables = [], variable;
|
||||
for(variable in this.variables) {
|
||||
variables.push(variable);
|
||||
}
|
||||
variables.sort();
|
||||
for(var index=0; index<variables.length; index++) {
|
||||
var variable = variables[index];
|
||||
output.push("|" + variable + " |<input size=50 value=<<" + variable + ">>/> |")
|
||||
}
|
||||
return output.join("\n");
|
||||
};
|
||||
|
||||
})();
|
||||
118
core/modules/savers/github.js
Normal file
118
core/modules/savers/github.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/*\
|
||||
title: $:/core/modules/savers/github.js
|
||||
type: application/javascript
|
||||
module-type: saver
|
||||
|
||||
Saves wiki by pushing a commit to the GitHub v3 REST API
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Select the appropriate saver module and set it up
|
||||
*/
|
||||
var GitHubSaver = function(wiki) {
|
||||
this.wiki = wiki;
|
||||
};
|
||||
|
||||
GitHubSaver.prototype.save = function(text,method,callback) {
|
||||
var self = this,
|
||||
username = this.wiki.getTiddlerText("$:/GitHub/Username"),
|
||||
password = $tw.utils.getPassword("github"),
|
||||
repo = this.wiki.getTiddlerText("$:/GitHub/Repo"),
|
||||
path = this.wiki.getTiddlerText("$:/GitHub/Path"),
|
||||
filename = this.wiki.getTiddlerText("$:/GitHub/Filename"),
|
||||
branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "master",
|
||||
endpoint = this.wiki.getTiddlerText("$:/GitHub/ServerURL") || "https://api.github.com",
|
||||
headers = {
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"Authorization": "Basic " + window.btoa(username + ":" + password)
|
||||
};
|
||||
// Bail if we don't have everything we need
|
||||
if(!username || !password || !repo || !path || !filename) {
|
||||
return false;
|
||||
}
|
||||
// Make sure the path start and ends with a slash
|
||||
if(path.substring(0,1) !== "/") {
|
||||
path = "/" + path;
|
||||
}
|
||||
if(path.substring(path.length - 1) !== "/") {
|
||||
path = path + "/";
|
||||
}
|
||||
// Compose the base URI
|
||||
var uri = endpoint + "/repos/" + repo + "/contents" + path;
|
||||
// Perform a get request to get the details (inc shas) of files in the same path as our file
|
||||
$tw.utils.httpRequest({
|
||||
url: uri,
|
||||
type: "GET",
|
||||
headers: headers,
|
||||
data: {
|
||||
ref: branch
|
||||
},
|
||||
callback: function(err,getResponseDataJson,xhr) {
|
||||
var getResponseData,sha = "";
|
||||
if(err && xhr.status !== 404) {
|
||||
return callback(err);
|
||||
}
|
||||
if(xhr.status !== 404) {
|
||||
getResponseData = JSON.parse(getResponseDataJson);
|
||||
$tw.utils.each(getResponseData,function(details) {
|
||||
if(details.name === filename) {
|
||||
sha = details.sha;
|
||||
}
|
||||
});
|
||||
}
|
||||
var data = {
|
||||
message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
content: $tw.utils.base64Encode(text),
|
||||
branch: branch,
|
||||
sha: sha
|
||||
};
|
||||
// Perform a PUT request to save the file
|
||||
$tw.utils.httpRequest({
|
||||
url: uri + filename,
|
||||
type: "PUT",
|
||||
headers: headers,
|
||||
data: JSON.stringify(data),
|
||||
callback: function(err,putResponseDataJson,xhr) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
var putResponseData = JSON.parse(putResponseDataJson);
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Information about this saver
|
||||
*/
|
||||
GitHubSaver.prototype.info = {
|
||||
name: "github",
|
||||
priority: 2000,
|
||||
capabilities: ["save", "autosave"]
|
||||
};
|
||||
|
||||
/*
|
||||
Static method that returns true if this saver is capable of working
|
||||
*/
|
||||
exports.canSave = function(wiki) {
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Create an instance of this saver
|
||||
*/
|
||||
exports.create = function(wiki) {
|
||||
return new GitHubSaver(wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
120
core/modules/savers/gitlab.js
Normal file
120
core/modules/savers/gitlab.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/*\
|
||||
title: $:/core/modules/savers/gitlab.js
|
||||
type: application/javascript
|
||||
module-type: saver
|
||||
|
||||
Saves wiki by pushing a commit to the GitLab REST API
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: true */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Select the appropriate saver module and set it up
|
||||
*/
|
||||
var GitLabSaver = function(wiki) {
|
||||
this.wiki = wiki;
|
||||
};
|
||||
|
||||
GitLabSaver.prototype.save = function(text,method,callback) {
|
||||
/* See https://docs.gitlab.com/ee/api/repository_files.html */
|
||||
var self = this,
|
||||
username = this.wiki.getTiddlerText("$:/GitLab/Username"),
|
||||
password = $tw.utils.getPassword("gitlab"),
|
||||
repo = this.wiki.getTiddlerText("$:/GitLab/Repo"),
|
||||
path = this.wiki.getTiddlerText("$:/GitLab/Path"),
|
||||
filename = this.wiki.getTiddlerText("$:/GitLab/Filename"),
|
||||
branch = this.wiki.getTiddlerText("$:/GitLab/Branch") || "master",
|
||||
endpoint = this.wiki.getTiddlerText("$:/GitLab/ServerURL") || "https://gitlab.com/api/v4",
|
||||
headers = {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"Private-Token": password
|
||||
};
|
||||
// Bail if we don't have everything we need
|
||||
if(!username || !password || !repo || !path || !filename) {
|
||||
return false;
|
||||
}
|
||||
// Make sure the path start and ends with a slash
|
||||
if(path.substring(0,1) !== "/") {
|
||||
path = "/" + path;
|
||||
}
|
||||
if(path.substring(path.length - 1) !== "/") {
|
||||
path = path + "/";
|
||||
}
|
||||
// Compose the base URI
|
||||
var uri = endpoint + "/projects/" + encodeURIComponent(repo) + "/repository/";
|
||||
// Perform a get request to get the details (inc shas) of files in the same path as our file
|
||||
$tw.utils.httpRequest({
|
||||
url: uri + "tree/" + encodeURIComponent(path.replace(/^\/+|\/$/g, '')),
|
||||
type: "GET",
|
||||
headers: headers,
|
||||
data: {
|
||||
ref: branch
|
||||
},
|
||||
callback: function(err,getResponseDataJson,xhr) {
|
||||
var getResponseData,sha = "";
|
||||
if(err && xhr.status !== 404) {
|
||||
return callback(err);
|
||||
}
|
||||
var requestType = "POST";
|
||||
if(xhr.status !== 404) {
|
||||
getResponseData = JSON.parse(getResponseDataJson);
|
||||
$tw.utils.each(getResponseData,function(details) {
|
||||
if(details.name === filename) {
|
||||
requestType = "PUT";
|
||||
sha = details.sha;
|
||||
}
|
||||
});
|
||||
}
|
||||
var data = {
|
||||
commit_message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
content: $tw.utils.base64Encode(text),
|
||||
branch: branch,
|
||||
sha: sha
|
||||
};
|
||||
// Perform a request to save the file
|
||||
$tw.utils.httpRequest({
|
||||
url: uri + "files/" + encodeURIComponent(path.replace(/^\/+/, '') + filename),
|
||||
type: requestType,
|
||||
headers: headers,
|
||||
data: JSON.stringify(data),
|
||||
callback: function(err,putResponseDataJson,xhr) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
var putResponseData = JSON.parse(putResponseDataJson);
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Information about this saver
|
||||
*/
|
||||
GitLabSaver.prototype.info = {
|
||||
name: "gitlab",
|
||||
priority: 2000,
|
||||
capabilities: ["save", "autosave"]
|
||||
};
|
||||
|
||||
/*
|
||||
Static method that returns true if this saver is capable of working
|
||||
*/
|
||||
exports.canSave = function(wiki) {
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Create an instance of this saver
|
||||
*/
|
||||
exports.create = function(wiki) {
|
||||
return new GitLabSaver(wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -41,7 +41,7 @@ BasicAuthenticator.prototype.init = function() {
|
||||
this.credentialsData = credentialsData;
|
||||
}
|
||||
} else {
|
||||
return "Error: Unable to load user credentials from '" + credentialsFilepath + "'";
|
||||
return "Error: Unable to load user credentials from '" + resolveCredentialsFilepath + "'";
|
||||
}
|
||||
}
|
||||
// Add the hardcoded username and password if specified
|
||||
|
||||
@@ -144,9 +144,9 @@ exports.startup = function() {
|
||||
});
|
||||
// Listen for window messages from other windows
|
||||
window.addEventListener("message",function listener(event){
|
||||
console.log("browser-messaging: ",document.location.toString())
|
||||
console.log("browser-messaging: Received message from",event.origin);
|
||||
console.log("browser-messaging: Message content",event.data);
|
||||
// console.log("browser-messaging: ",document.location.toString())
|
||||
// console.log("browser-messaging: Received message from",event.origin);
|
||||
// console.log("browser-messaging: Message content",event.data);
|
||||
switch(event.data.verb) {
|
||||
case "GET-RESPONSE":
|
||||
if(event.data.status.charAt(0) === "2") {
|
||||
|
||||
114
core/modules/startup/css-escape-polyfill.js
Normal file
114
core/modules/startup/css-escape-polyfill.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/*\
|
||||
title: $:/core/modules/startup/CSSescape.js
|
||||
type: application/javascript
|
||||
module-type: startup
|
||||
|
||||
Polyfill for CSS.escape()
|
||||
|
||||
\*/
|
||||
(function(root,factory){
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
// Export name and synchronous status
|
||||
exports.name = "css-escape";
|
||||
exports.platforms = ["browser"];
|
||||
exports.after = ["startup"];
|
||||
exports.synchronous = true;
|
||||
|
||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||
// https://github.com/umdjs/umd/blob/master/returnExports.js
|
||||
exports.startup = factory(root);
|
||||
}(typeof global != 'undefined' ? global : this, function(root) {
|
||||
|
||||
if (root.CSS && root.CSS.escape) {
|
||||
return;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||
var cssEscape = function(value) {
|
||||
if (arguments.length == 0) {
|
||||
throw new TypeError('`CSS.escape` requires an argument.');
|
||||
}
|
||||
var string = String(value);
|
||||
var length = string.length;
|
||||
var index = -1;
|
||||
var codeUnit;
|
||||
var result = '';
|
||||
var firstCodeUnit = string.charCodeAt(0);
|
||||
while (++index < length) {
|
||||
codeUnit = string.charCodeAt(index);
|
||||
// Note: there’s no need to special-case astral symbols, surrogate
|
||||
// pairs, or lone surrogates.
|
||||
|
||||
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
||||
// (U+FFFD).
|
||||
if (codeUnit == 0x0000) {
|
||||
result += '\uFFFD';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||
// U+007F, […]
|
||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
||||
// If the character is the first character and is in the range [0-9]
|
||||
// (U+0030 to U+0039), […]
|
||||
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||
// If the character is the second character and is in the range [0-9]
|
||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||
(
|
||||
index == 1 &&
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||
firstCodeUnit == 0x002D
|
||||
)
|
||||
) {
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
||||
result += '\\' + codeUnit.toString(16) + ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// If the character is the first character and is a `-` (U+002D), and
|
||||
// there is no second character, […]
|
||||
index == 0 &&
|
||||
length == 1 &&
|
||||
codeUnit == 0x002D
|
||||
) {
|
||||
result += '\\' + string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the character is not handled by one of the above rules and is
|
||||
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
||||
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||
if (
|
||||
codeUnit >= 0x0080 ||
|
||||
codeUnit == 0x002D ||
|
||||
codeUnit == 0x005F ||
|
||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||
) {
|
||||
// the character itself
|
||||
result += string.charAt(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, the escaped character.
|
||||
// https://drafts.csswg.org/cssom/#escape-a-character
|
||||
result += '\\' + string.charAt(index);
|
||||
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
if (!root.CSS) {
|
||||
root.CSS = {};
|
||||
}
|
||||
|
||||
root.CSS.escape = cssEscape;
|
||||
|
||||
}));
|
||||
@@ -27,6 +27,7 @@ exports.startup = function() {
|
||||
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
|
||||
$tw.modules.applyMethods("tiddlermethod",$tw.Tiddler.prototype);
|
||||
$tw.modules.applyMethods("wikimethod",$tw.Wiki.prototype);
|
||||
$tw.wiki.addIndexersToWiki();
|
||||
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
|
||||
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
|
||||
$tw.wiki.initParsers();
|
||||
|
||||
@@ -34,6 +34,19 @@ exports.startup = function() {
|
||||
$tw.rootWidget.addEventListener("tm-copy-to-clipboard",function(event) {
|
||||
$tw.utils.copyToClipboard(event.param);
|
||||
});
|
||||
// Install the tm-focus-selector message
|
||||
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
|
||||
var selector = event.param || "",
|
||||
element;
|
||||
try {
|
||||
element = document.querySelector(selector);
|
||||
} catch(e) {
|
||||
console.log("Error in selector: ",selector)
|
||||
}
|
||||
if(element && element.focus) {
|
||||
element.focus(event.paramObject);
|
||||
}
|
||||
});
|
||||
// Install the scroller
|
||||
$tw.pageScroller = new $tw.utils.PageScroller();
|
||||
$tw.rootWidget.addEventListener("tm-scroll",function(event) {
|
||||
|
||||
@@ -28,6 +28,7 @@ exports.startup = function() {
|
||||
var refreshHandler,
|
||||
title = event.param || event.tiddlerTitle,
|
||||
paramObject = event.paramObject || {},
|
||||
windowTitle = paramObject.windowTitle || title,
|
||||
template = paramObject.template || "$:/core/templates/single.tiddler.window",
|
||||
width = paramObject.width || "700",
|
||||
height = paramObject.height || "600",
|
||||
@@ -51,7 +52,7 @@ exports.startup = function() {
|
||||
// Initialise the document
|
||||
srcDocument.write("<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.close();
|
||||
srcDocument.title = title;
|
||||
srcDocument.title = windowTitle;
|
||||
srcWindow.addEventListener("beforeunload",function(event) {
|
||||
delete windows[title];
|
||||
$tw.wiki.removeEventListener("change",refreshHandler);
|
||||
|
||||
@@ -19,6 +19,7 @@ var ClassicStoryView = function(listWidget) {
|
||||
};
|
||||
|
||||
ClassicStoryView.prototype.navigateTo = function(historyInfo) {
|
||||
var duration = $tw.utils.getAnimationDuration()
|
||||
var listElementIndex = this.listWidget.findListItem(0,historyInfo.title);
|
||||
if(listElementIndex === undefined) {
|
||||
return;
|
||||
@@ -29,80 +30,90 @@ ClassicStoryView.prototype.navigateTo = function(historyInfo) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Scroll the node into view
|
||||
this.listWidget.dispatchEvent({type: "tm-scroll", target: targetElement});
|
||||
if(duration) {
|
||||
// Scroll the node into view
|
||||
this.listWidget.dispatchEvent({type: "tm-scroll", target: targetElement});
|
||||
} else {
|
||||
targetElement.scrollIntoView();
|
||||
}
|
||||
};
|
||||
|
||||
ClassicStoryView.prototype.insert = function(widget) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
duration = $tw.utils.getAnimationDuration();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Get the current height of the tiddler
|
||||
var computedStyle = window.getComputedStyle(targetElement),
|
||||
currMarginBottom = parseInt(computedStyle.marginBottom,10),
|
||||
currMarginTop = parseInt(computedStyle.marginTop,10),
|
||||
currHeight = targetElement.offsetHeight + currMarginTop;
|
||||
// Reset the margin once the transition is over
|
||||
setTimeout(function() {
|
||||
var duration = $tw.utils.getAnimationDuration();
|
||||
if(duration) {
|
||||
var targetElement = widget.findFirstDomNode();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Get the current height of the tiddler
|
||||
var computedStyle = window.getComputedStyle(targetElement),
|
||||
currMarginBottom = parseInt(computedStyle.marginBottom,10),
|
||||
currMarginTop = parseInt(computedStyle.marginTop,10),
|
||||
currHeight = targetElement.offsetHeight + currMarginTop;
|
||||
// Reset the margin once the transition is over
|
||||
setTimeout(function() {
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{marginBottom: ""}
|
||||
]);
|
||||
},duration);
|
||||
// Set up the initial position of the element
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{marginBottom: ""}
|
||||
{marginBottom: (-currHeight) + "px"},
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
},duration);
|
||||
// Set up the initial position of the element
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{marginBottom: (-currHeight) + "px"},
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
// Transition to the final position
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "opacity " + duration + "ms " + easing + ", " +
|
||||
"margin-bottom " + duration + "ms " + easing},
|
||||
{marginBottom: currMarginBottom + "px"},
|
||||
{opacity: "1.0"}
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
// Transition to the final position
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "opacity " + duration + "ms " + easing + ", " +
|
||||
"margin-bottom " + duration + "ms " + easing},
|
||||
{marginBottom: currMarginBottom + "px"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
ClassicStoryView.prototype.remove = function(widget) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
duration = $tw.utils.getAnimationDuration(),
|
||||
removeElement = function() {
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!(targetElement instanceof Element)) {
|
||||
removeElement();
|
||||
return;
|
||||
var duration = $tw.utils.getAnimationDuration();
|
||||
if(duration) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
removeElement = function() {
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!(targetElement instanceof Element)) {
|
||||
removeElement();
|
||||
return;
|
||||
}
|
||||
// Get the current height of the tiddler
|
||||
var currWidth = targetElement.offsetWidth,
|
||||
computedStyle = window.getComputedStyle(targetElement),
|
||||
currMarginBottom = parseInt(computedStyle.marginBottom,10),
|
||||
currMarginTop = parseInt(computedStyle.marginTop,10),
|
||||
currHeight = targetElement.offsetHeight + currMarginTop;
|
||||
// Remove the dom nodes of the widget at the end of the transition
|
||||
setTimeout(removeElement,duration);
|
||||
// Animate the closure
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{transform: "translateX(0px)"},
|
||||
{marginBottom: currMarginBottom + "px"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
|
||||
"opacity " + duration + "ms " + easing + ", " +
|
||||
"margin-bottom " + duration + "ms " + easing},
|
||||
{transform: "translateX(-" + currWidth + "px)"},
|
||||
{marginBottom: (-currHeight) + "px"},
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
} else {
|
||||
widget.removeChildDomNodes();
|
||||
}
|
||||
// Get the current height of the tiddler
|
||||
var currWidth = targetElement.offsetWidth,
|
||||
computedStyle = window.getComputedStyle(targetElement),
|
||||
currMarginBottom = parseInt(computedStyle.marginBottom,10),
|
||||
currMarginTop = parseInt(computedStyle.marginTop,10),
|
||||
currHeight = targetElement.offsetHeight + currMarginTop;
|
||||
// Remove the dom nodes of the widget at the end of the transition
|
||||
setTimeout(removeElement,duration);
|
||||
// Animate the closure
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
{transform: "translateX(0px)"},
|
||||
{marginBottom: currMarginBottom + "px"},
|
||||
{opacity: "1.0"}
|
||||
]);
|
||||
$tw.utils.forceLayout(targetElement);
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
|
||||
"opacity " + duration + "ms " + easing + ", " +
|
||||
"margin-bottom " + duration + "ms " + easing},
|
||||
{transform: "translateX(-" + currWidth + "px)"},
|
||||
{marginBottom: (-currHeight) + "px"},
|
||||
{opacity: "0.0"}
|
||||
]);
|
||||
};
|
||||
|
||||
exports.classic = ClassicStoryView;
|
||||
|
||||
@@ -44,7 +44,14 @@ PopStoryView.prototype.insert = function(widget) {
|
||||
{transition: "none"},
|
||||
{transform: "none"}
|
||||
]);
|
||||
$tw.utils.setStyle(widget.document.body,[
|
||||
{"overflow-x": ""}
|
||||
]);
|
||||
},duration);
|
||||
// Prevent the page from overscrolling due to the zoom factor
|
||||
$tw.utils.setStyle(widget.document.body,[
|
||||
{"overflow-x": "hidden"}
|
||||
]);
|
||||
// Set up the initial position of the element
|
||||
$tw.utils.setStyle(targetElement,[
|
||||
{transition: "none"},
|
||||
@@ -65,7 +72,7 @@ PopStoryView.prototype.remove = function(widget) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
duration = $tw.utils.getAnimationDuration(),
|
||||
removeElement = function() {
|
||||
if(targetElement.parentNode) {
|
||||
if(targetElement && targetElement.parentNode) {
|
||||
widget.removeChildDomNodes();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,16 +75,16 @@ Get all the fields as a name:value block. Options:
|
||||
*/
|
||||
exports.getFieldStringBlock = function(options) {
|
||||
options = options || {};
|
||||
var exclude = options.exclude || [];
|
||||
var fields = [];
|
||||
for(var field in this.fields) {
|
||||
if($tw.utils.hop(this.fields,field)) {
|
||||
if(exclude.indexOf(field) === -1) {
|
||||
fields.push(field + ": " + this.getFieldString(field));
|
||||
}
|
||||
var exclude = options.exclude || [],
|
||||
fields = Object.keys(this.fields).sort(),
|
||||
result = [];
|
||||
for(var t=0; t<fields.length; t++) {
|
||||
var field = fields[t];
|
||||
if(exclude.indexOf(field) === -1) {
|
||||
result.push(field + ": " + this.getFieldString(field));
|
||||
}
|
||||
}
|
||||
return fields.join("\n");
|
||||
return result.join("\n");
|
||||
};
|
||||
|
||||
exports.getFieldDay = function(field) {
|
||||
|
||||
124
core/modules/utils/base64-utf8/base64-utf8.module.js
Normal file
124
core/modules/utils/base64-utf8/base64-utf8.module.js
Normal file
@@ -0,0 +1,124 @@
|
||||
// From https://gist.github.com/Nijikokun/5192472
|
||||
//
|
||||
// UTF8 Module
|
||||
//
|
||||
// Cleaner and modularized utf-8 encoding and decoding library for javascript.
|
||||
//
|
||||
// copyright: MIT
|
||||
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
|
||||
(function (name, definition, context, dependencies) {
|
||||
if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
|
||||
else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
|
||||
else { context[name] = definition.apply(context); }
|
||||
})('utf8', function () {
|
||||
return {
|
||||
encode: function (string) {
|
||||
if (typeof string !== 'string') return string;
|
||||
else string = string.replace(/\r\n/g, "\n");
|
||||
var output = "", i = 0, charCode;
|
||||
|
||||
for (i; i < string.length; i++) {
|
||||
charCode = string.charCodeAt(i);
|
||||
|
||||
if (charCode < 128)
|
||||
output += String.fromCharCode(charCode);
|
||||
else if ((charCode > 127) && (charCode < 2048))
|
||||
output += String.fromCharCode((charCode >> 6) | 192),
|
||||
output += String.fromCharCode((charCode & 63) | 128);
|
||||
else
|
||||
output += String.fromCharCode((charCode >> 12) | 224),
|
||||
output += String.fromCharCode(((charCode >> 6) & 63) | 128),
|
||||
output += String.fromCharCode((charCode & 63) | 128);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
decode: function (string) {
|
||||
if (typeof string !== 'string') return string;
|
||||
var output = "", i = 0, charCode = 0;
|
||||
|
||||
while (i < string.length) {
|
||||
charCode = string.charCodeAt(i);
|
||||
|
||||
if (charCode < 128)
|
||||
output += String.fromCharCode(charCode),
|
||||
i++;
|
||||
else if ((charCode > 191) && (charCode < 224))
|
||||
output += String.fromCharCode(((charCode & 31) << 6) | (string.charCodeAt(i + 1) & 63)),
|
||||
i += 2;
|
||||
else
|
||||
output += String.fromCharCode(((charCode & 15) << 12) | ((string.charCodeAt(i + 1) & 63) << 6) | (string.charCodeAt(i + 2) & 63)),
|
||||
i += 3;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
}, this);
|
||||
|
||||
// Base64 Module
|
||||
//
|
||||
// Cleaner, modularized and properly scoped base64 encoding and decoding module for strings.
|
||||
//
|
||||
// copyright: MIT
|
||||
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
|
||||
(function (name, definition, context, dependencies) {
|
||||
if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
|
||||
else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
|
||||
else { context[name] = definition.apply(context); }
|
||||
})('base64', function (utf8) {
|
||||
var $this = this;
|
||||
var $utf8 = utf8 || this.utf8;
|
||||
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
return {
|
||||
encode: function (input) {
|
||||
if (typeof $utf8 === 'undefined') throw { error: "MissingMethod", message: "UTF8 Module is missing." };
|
||||
if (typeof input !== 'string') return input;
|
||||
else input = $utf8.encode(input);
|
||||
var output = "", a, b, c, d, e, f, g, i = 0;
|
||||
|
||||
while (i < input.length) {
|
||||
a = input.charCodeAt(i++);
|
||||
b = input.charCodeAt(i++);
|
||||
c = input.charCodeAt(i++);
|
||||
d = a >> 2;
|
||||
e = ((a & 3) << 4) | (b >> 4);
|
||||
f = ((b & 15) << 2) | (c >> 6);
|
||||
g = c & 63;
|
||||
|
||||
if (isNaN(b)) f = g = 64;
|
||||
else if (isNaN(c)) g = 64;
|
||||
|
||||
output += map.charAt(d) + map.charAt(e) + map.charAt(f) + map.charAt(g);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
decode: function (input) {
|
||||
if (typeof $utf8 === 'undefined') throw { error: "MissingMethod", message: "UTF8 Module is missing." };
|
||||
if (typeof input !== 'string') return input;
|
||||
else input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
var output = "", a, b, c, d, e, f, g, i = 0;
|
||||
|
||||
while (i < input.length) {
|
||||
d = map.indexOf(input.charAt(i++));
|
||||
e = map.indexOf(input.charAt(i++));
|
||||
f = map.indexOf(input.charAt(i++));
|
||||
g = map.indexOf(input.charAt(i++));
|
||||
|
||||
a = (d << 2) | (e >> 4);
|
||||
b = ((e & 15) << 4) | (f >> 2);
|
||||
c = ((f & 3) << 6) | g;
|
||||
|
||||
output += String.fromCharCode(a);
|
||||
if (f != 64) output += String.fromCharCode(b);
|
||||
if (g != 64) output += String.fromCharCode(c);
|
||||
}
|
||||
|
||||
return $utf8.decode(output);
|
||||
}
|
||||
}
|
||||
}, this, [ "utf8" ]);
|
||||
9
core/modules/utils/base64-utf8/base64-utf8.module.min.js
vendored
Normal file
9
core/modules/utils/base64-utf8/base64-utf8.module.min.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// From https://gist.github.com/Nijikokun/5192472
|
||||
//
|
||||
// UTF8 Module
|
||||
//
|
||||
// Cleaner and modularized utf-8 encoding and decoding library for javascript.
|
||||
//
|
||||
// copyright: MIT
|
||||
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
|
||||
!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&"function"===o.define&&o.define.amd?define("utf8",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if("string"!=typeof r)return r;r=r.replace(/\r\n/g,"\n");for(var e,o="",t=0;t<r.length;t++)(e=r.charCodeAt(t))<128?o+=String.fromCharCode(e):e>127&&e<2048?(o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128)):(o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128));return o},decode:function(r){if("string"!=typeof r)return r;for(var e="",o=0,t=0;o<r.length;)(t=r.charCodeAt(o))<128?(e+=String.fromCharCode(t),o++):t>191&&t<224?(e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2):(e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3);return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var n=0;n<t.length;n++)o[t[n]]=o.require(t[n]);o.module.exports=e.apply(o)}else void 0!==o.define&&"function"===o.define&&o.define.amd?define("base64",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{encode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=e.encode(r);for(var t,n,i,d,f,a,h,c="",u=0;u<r.length;)d=(t=r.charCodeAt(u++))>>2,f=(3&t)<<4|(n=r.charCodeAt(u++))>>4,a=(15&n)<<2|(i=r.charCodeAt(u++))>>6,h=63&i,isNaN(n)?a=h=64:isNaN(i)&&(h=64),c+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return c},decode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var t,n,i,d,f,a,h="",c=0;c<r.length;)t=o.indexOf(r.charAt(c++))<<2|(d=o.indexOf(r.charAt(c++)))>>4,n=(15&d)<<4|(f=o.indexOf(r.charAt(c++)))>>2,i=(3&f)<<6|(a=o.indexOf(r.charAt(c++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(n)),64!=a&&(h+=String.fromCharCode(i));return e.decode(h)}}},this,["utf8"]);
|
||||
14
core/modules/utils/base64-utf8/tiddlywiki.files
Normal file
14
core/modules/utils/base64-utf8/tiddlywiki.files
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "base64-utf8.module.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/core/modules/utils/base64-utf8/base64-utf8.module.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "(function(){",
|
||||
"suffix": "}).call(exports);"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -136,22 +136,31 @@ exports.getBoundingPageRect = function(element) {
|
||||
Saves a named password in the browser
|
||||
*/
|
||||
exports.savePassword = function(name,password) {
|
||||
var done = false;
|
||||
try {
|
||||
if(window.localStorage) {
|
||||
localStorage.setItem("tw5-password-" + name,password);
|
||||
}
|
||||
window.localStorage.setItem("tw5-password-" + name,password);
|
||||
done = true;
|
||||
} catch(e) {
|
||||
}
|
||||
if(!done) {
|
||||
$tw.savedPasswords = $tw.savedPasswords || Object.create(null);
|
||||
$tw.savedPasswords[name] = password;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Retrieve a named password from the browser
|
||||
*/
|
||||
exports.getPassword = function(name) {
|
||||
var value;
|
||||
try {
|
||||
return window.localStorage ? localStorage.getItem("tw5-password-" + name) : "";
|
||||
value = window.localStorage.getItem("tw5-password-" + name);
|
||||
} catch(e) {
|
||||
return "";
|
||||
}
|
||||
if(value !== undefined) {
|
||||
return value;
|
||||
} else {
|
||||
return ($tw.savedPasswords || Object.create(null))[name] || "";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ A quick and dirty HTTP function; to be refactored later. Options are:
|
||||
url: URL to retrieve
|
||||
headers: hashmap of headers to send
|
||||
type: GET, PUT, POST etc
|
||||
callback: function invoked with (err,data)
|
||||
callback: function invoked with (err,data,xhr)
|
||||
returnProp: string name of the property to return as first argument of callback
|
||||
*/
|
||||
exports.httpRequest = function(options) {
|
||||
@@ -48,7 +48,7 @@ exports.httpRequest = function(options) {
|
||||
return;
|
||||
}
|
||||
// Something went wrong
|
||||
options.callback($tw.language.getString("Error/XMLHttpRequest") + ": " + this.status);
|
||||
options.callback($tw.language.getString("Error/XMLHttpRequest") + ": " + this.status,null,this);
|
||||
}
|
||||
};
|
||||
// Make the request
|
||||
@@ -67,7 +67,7 @@ exports.httpRequest = function(options) {
|
||||
try {
|
||||
request.send(data);
|
||||
} catch(e) {
|
||||
options.callback(e);
|
||||
options.callback(e,null,this);
|
||||
}
|
||||
return request;
|
||||
};
|
||||
|
||||
@@ -120,7 +120,8 @@ Popup.prototype.show = function(options) {
|
||||
this.popups.push({
|
||||
title: options.title,
|
||||
wiki: options.wiki,
|
||||
domNode: options.domNode
|
||||
domNode: options.domNode,
|
||||
noStateReference: options.noStateReference
|
||||
});
|
||||
}
|
||||
// Set the state tiddler
|
||||
@@ -148,17 +149,46 @@ Popup.prototype.show = function(options) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Detect if a Popup contains an input field that has focus
|
||||
Returns true or false
|
||||
*/
|
||||
Popup.prototype.detectInputWithinPopup = function(node) {
|
||||
var withinPopup = false,
|
||||
currNode = node;
|
||||
for(var i=0; i<this.popups.length; i++) {
|
||||
var popup = (this.popups[i] && this.popups[i].domNode) ? this.popups[i].domNode : null;
|
||||
while(node && popup) {
|
||||
if(node === popup || (node.classList && (node.classList.contains("tc-popup-keep") || (node !== currNode && node.classList.contains("tc-popup-handle"))))) {
|
||||
withinPopup = true;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
}
|
||||
return withinPopup;
|
||||
};
|
||||
|
||||
/*
|
||||
Cancel all popups at or above a specified level or DOM node
|
||||
level: popup level to cancel (0 cancels all popups)
|
||||
*/
|
||||
Popup.prototype.cancel = function(level) {
|
||||
Popup.prototype.cancel = function(level,focusedInputNode) {
|
||||
var numPopups = this.popups.length;
|
||||
level = Math.max(0,Math.min(level,numPopups));
|
||||
for(var t=level; t<numPopups; t++) {
|
||||
var popup = this.popups.pop();
|
||||
if(popup.title) {
|
||||
popup.wiki.deleteTiddler(popup.title);
|
||||
var inputWithinPopup;
|
||||
if(focusedInputNode) {
|
||||
inputWithinPopup = this.detectInputWithinPopup(focusedInputNode);
|
||||
}
|
||||
if(!inputWithinPopup) {
|
||||
var popup = this.popups.pop();
|
||||
if(popup.title) {
|
||||
if(popup.noStateReference) {
|
||||
popup.wiki.deleteTiddler(popup.title);
|
||||
} else {
|
||||
popup.wiki.deleteTiddler($tw.utils.parseTextReference(popup.title).title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.popups.length === 0) {
|
||||
|
||||
@@ -181,4 +181,169 @@ exports.deleteEmptyDirs = function(dirpath,callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Create a fileInfo object for saving a tiddler:
|
||||
filepath: the absolute path to the file containing the tiddler
|
||||
type: the type of the tiddler file (NOT the type of the tiddler)
|
||||
hasMetaFile: true if the file also has a companion .meta file
|
||||
Options include:
|
||||
directory: absolute path of root directory to which we are saving
|
||||
pathFilters: optional array of filters to be used to generate the base path
|
||||
wiki: optional wiki for evaluating the pathFilters
|
||||
*/
|
||||
exports.generateTiddlerFileInfo = function(tiddler,options) {
|
||||
var fileInfo = {};
|
||||
// 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) {
|
||||
if(fieldName !== "text") {
|
||||
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
|
||||
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
|
||||
}
|
||||
});
|
||||
// Check for field values
|
||||
if(hasUnsafeFields) {
|
||||
// Save as a JSON file
|
||||
fileInfo.type = "application/json";
|
||||
fileInfo.hasMetaFile = false;
|
||||
} else {
|
||||
// Save as a .tid or a text/binary file plus a .meta file
|
||||
var tiddlerType = tiddler.fields.type || "text/vnd.tiddlywiki";
|
||||
if(tiddlerType === "text/vnd.tiddlywiki") {
|
||||
// Save as a .tid file
|
||||
fileInfo.type = "application/x-tiddler";
|
||||
fileInfo.hasMetaFile = false;
|
||||
} else {
|
||||
// Save as a text/binary file and a .meta file
|
||||
fileInfo.type = tiddlerType;
|
||||
fileInfo.hasMetaFile = true;
|
||||
}
|
||||
}
|
||||
// Take the file extension from the tiddler content type
|
||||
var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""};
|
||||
// Generate the filepath
|
||||
fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{
|
||||
extension: contentTypeInfo.extension,
|
||||
directory: options.directory,
|
||||
pathFilters: options.pathFilters,
|
||||
wiki: options.wiki
|
||||
});
|
||||
return fileInfo;
|
||||
};
|
||||
|
||||
/*
|
||||
Generate the filepath for saving a tiddler
|
||||
Options include:
|
||||
extension: file extension to be added the finished filepath
|
||||
directory: absolute path of root directory to which we are saving
|
||||
pathFilters: optional array of filters to be used to generate the base path
|
||||
wiki: optional wiki for evaluating the pathFilters
|
||||
*/
|
||||
exports.generateTiddlerFilepath = function(title,options) {
|
||||
var self = this,
|
||||
directory = options.directory || "",
|
||||
extension = options.extension || "",
|
||||
filepath;
|
||||
// Check if any of the pathFilters applies
|
||||
if(options.pathFilters && options.wiki) {
|
||||
$tw.utils.each(options.pathFilters,function(filter) {
|
||||
if(!filepath) {
|
||||
var source = options.wiki.makeTiddlerIterator([title]),
|
||||
result = options.wiki.filterTiddlers(filter,null,source);
|
||||
if(result.length > 0) {
|
||||
filepath = result[0];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// If not, generate a base pathname
|
||||
if(!filepath) {
|
||||
filepath = title;
|
||||
// If the filepath already ends in the extension then remove it
|
||||
if(filepath.substring(filepath.length - extension.length) === extension) {
|
||||
filepath = filepath.substring(0,filepath.length - extension.length);
|
||||
}
|
||||
// Remove any forward or backward slashes so we don't create directories
|
||||
filepath = filepath.replace(/\/|\\/g,"_");
|
||||
}
|
||||
// Don't let the filename start with a dot because such files are invisible on *nix
|
||||
filepath = filepath.replace(/^\./g,"_");
|
||||
// Remove any characters that can't be used in cross-platform filenames
|
||||
filepath = $tw.utils.transliterate(filepath.replace(/<|>|\:|\"|\||\?|\*|\^/g,"_"));
|
||||
// Truncate the filename if it is too long
|
||||
if(filepath.length > 200) {
|
||||
filepath = filepath.substr(0,200);
|
||||
}
|
||||
// If the resulting filename is blank (eg because the title is just punctuation characters)
|
||||
if(!filepath) {
|
||||
// ...then just use the character codes of the title
|
||||
filepath = "";
|
||||
$tw.utils.each(title.split(""),function(char) {
|
||||
if(filepath) {
|
||||
filepath += "-";
|
||||
}
|
||||
filepath += char.charCodeAt(0).toString();
|
||||
});
|
||||
}
|
||||
// Add a uniquifier if the file already exists
|
||||
var fullPath,
|
||||
count = 0;
|
||||
do {
|
||||
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
||||
count++;
|
||||
} while(fs.existsSync(fullPath));
|
||||
// Return the full path to the file
|
||||
return fullPath;
|
||||
};
|
||||
|
||||
/*
|
||||
Save a tiddler to a file described by the fileInfo:
|
||||
filepath: the absolute path to the file containing the tiddler
|
||||
type: the type of the tiddler file (NOT the type of the tiddler)
|
||||
hasMetaFile: true if the file also has a companion .meta file
|
||||
*/
|
||||
exports.saveTiddlerToFile = function(tiddler,fileInfo,callback) {
|
||||
$tw.utils.createDirectory(path.dirname(fileInfo.filepath));
|
||||
if(fileInfo.hasMetaFile) {
|
||||
// Save the tiddler as a separate body and meta file
|
||||
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
|
||||
fs.writeFile(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding,function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
fs.writeFile(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8",callback);
|
||||
});
|
||||
} else {
|
||||
// Save the tiddler as a self contained templated file
|
||||
if(fileInfo.type === "application/x-tiddler") {
|
||||
fs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8",callback);
|
||||
} else {
|
||||
fs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8",callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Save a tiddler to a file described by the fileInfo:
|
||||
filepath: the absolute path to the file containing the tiddler
|
||||
type: the type of the tiddler file (NOT the type of the tiddler)
|
||||
hasMetaFile: true if the file also has a companion .meta file
|
||||
*/
|
||||
exports.saveTiddlerToFileSync = function(tiddler,fileInfo) {
|
||||
$tw.utils.createDirectory(path.dirname(fileInfo.filepath));
|
||||
if(fileInfo.hasMetaFile) {
|
||||
// Save the tiddler as a separate body and meta file
|
||||
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
|
||||
fs.writeFileSync(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding);
|
||||
fs.writeFileSync(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8");
|
||||
} else {
|
||||
// Save the tiddler as a self contained templated file
|
||||
if(fileInfo.type === "application/x-tiddler") {
|
||||
fs.writeFileSync(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8");
|
||||
} else {
|
||||
fs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -33,6 +33,13 @@ Logger.prototype.log = function(/* args */) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Log a structure as a table
|
||||
*/
|
||||
Logger.prototype.table = function(value) {
|
||||
(console.table || console.log)(value);
|
||||
};
|
||||
|
||||
/*
|
||||
Alert a message
|
||||
*/
|
||||
|
||||
@@ -14,10 +14,17 @@ Performance measurement.
|
||||
|
||||
function Performance(enabled) {
|
||||
this.enabled = !!enabled;
|
||||
this.measures = {}; // Hashmap of current values of measurements
|
||||
this.measures = {}; // Hashmap by measurement name of {time:, invocations:}
|
||||
this.logger = new $tw.utils.Logger("performance");
|
||||
this.showGreeting();
|
||||
}
|
||||
|
||||
Performance.prototype.showGreeting = function() {
|
||||
if($tw.browser) {
|
||||
this.logger.log("Execute $tw.perf.log(); to see filter execution timings");
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Wrap performance reporting around a top level function
|
||||
*/
|
||||
@@ -25,13 +32,9 @@ Performance.prototype.report = function(name,fn) {
|
||||
var self = this;
|
||||
if(this.enabled) {
|
||||
return function() {
|
||||
self.measures = {};
|
||||
var startTime = $tw.utils.timer(),
|
||||
result = fn.apply(this,arguments);
|
||||
self.logger.log(name + ": " + $tw.utils.timer(startTime).toFixed(2) + "ms");
|
||||
for(var m in self.measures) {
|
||||
self.logger.log("+" + m + ": " + self.measures[m].toFixed(2) + "ms");
|
||||
}
|
||||
return result;
|
||||
};
|
||||
} else {
|
||||
@@ -39,6 +42,29 @@ Performance.prototype.report = function(name,fn) {
|
||||
}
|
||||
};
|
||||
|
||||
Performance.prototype.log = function() {
|
||||
var self = this,
|
||||
totalTime = 0,
|
||||
orderedMeasures = Object.keys(this.measures).sort(function(a,b) {
|
||||
if(self.measures[a].time > self.measures[b].time) {
|
||||
return -1;
|
||||
} else if (self.measures[a].time < self.measures[b].time) {
|
||||
return + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
$tw.utils.each(orderedMeasures,function(name) {
|
||||
totalTime += self.measures[name].time;
|
||||
});
|
||||
var results = []
|
||||
$tw.utils.each(orderedMeasures,function(name) {
|
||||
var measure = self.measures[name];
|
||||
results.push({name: name,invocations: measure.invocations, avgTime: measure.time / measure.invocations, totalTime: measure.time, percentTime: (measure.time / totalTime) * 100})
|
||||
});
|
||||
self.logger.table(results);
|
||||
};
|
||||
|
||||
/*
|
||||
Wrap performance measurements around a subfunction
|
||||
*/
|
||||
@@ -47,9 +73,12 @@ Performance.prototype.measure = function(name,fn) {
|
||||
if(this.enabled) {
|
||||
return function() {
|
||||
var startTime = $tw.utils.timer(),
|
||||
result = fn.apply(this,arguments),
|
||||
value = self.measures[name] || 0;
|
||||
self.measures[name] = value + $tw.utils.timer(startTime);
|
||||
result = fn.apply(this,arguments);
|
||||
if(!(name in self.measures)) {
|
||||
self.measures[name] = {time: 0, invocations: 0};
|
||||
}
|
||||
self.measures[name].time += $tw.utils.timer(startTime);
|
||||
self.measures[name].invocations++;
|
||||
return result;
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -12,6 +12,8 @@ Various static utility functions.
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var base64utf8 = require("$:/core/modules/utils/base64-utf8/base64-utf8.module.js");
|
||||
|
||||
/*
|
||||
Display a message, in colour if we're on a terminal
|
||||
*/
|
||||
@@ -92,6 +94,20 @@ exports.trim = function(str) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Convert a string to sentence case (ie capitalise first letter)
|
||||
*/
|
||||
exports.toSentenceCase = function(str) {
|
||||
return (str || "").replace(/^\S/, function(c) {return c.toUpperCase();});
|
||||
}
|
||||
|
||||
/*
|
||||
Convert a string to title case (ie capitalise each initial letter)
|
||||
*/
|
||||
exports.toTitleCase = function(str) {
|
||||
return (str || "").replace(/(^|\s)\S/g, function(c) {return c.toUpperCase();});
|
||||
}
|
||||
|
||||
/*
|
||||
Find the line break preceding a given position in a string
|
||||
Returns position immediately after that line break, or the start of the string
|
||||
@@ -669,12 +685,14 @@ exports.hashString = function(str) {
|
||||
Decode a base64 string
|
||||
*/
|
||||
exports.base64Decode = function(string64) {
|
||||
if($tw.browser) {
|
||||
// TODO
|
||||
throw "$tw.utils.base64Decode() doesn't work in the browser";
|
||||
} else {
|
||||
return Buffer.from(string64,"base64").toString();
|
||||
}
|
||||
return base64utf8.base64.decode.call(base64utf8,string64);
|
||||
};
|
||||
|
||||
/*
|
||||
Encode a string to base64
|
||||
*/
|
||||
exports.base64Encode = function(string64) {
|
||||
return base64utf8.base64.encode.call(base64utf8,string64);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -37,6 +37,7 @@ Compute the internal state of the widget
|
||||
CreateTiddlerWidget.prototype.execute = function() {
|
||||
this.actionBaseTitle = this.getAttribute("$basetitle");
|
||||
this.actionSaveTitle = this.getAttribute("$savetitle");
|
||||
this.actionSaveDraftTitle = this.getAttribute("$savedrafttitle");
|
||||
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
|
||||
};
|
||||
|
||||
@@ -73,6 +74,9 @@ CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
if(this.actionSaveTitle) {
|
||||
this.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable("currentTiddler"));
|
||||
}
|
||||
if(this.actionSaveDraftTitle) {
|
||||
this.wiki.setTextReference(this.actionSaveDraftTitle,this.wiki.generateDraftTitle(title),this.getVariable("currentTiddler"));
|
||||
}
|
||||
return true; // Action was invoked
|
||||
};
|
||||
|
||||
|
||||
@@ -156,6 +156,9 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
|
||||
if(this.checkboxActions) {
|
||||
this.invokeActionString(this.checkboxActions,this,event);
|
||||
}
|
||||
if(this.checkboxCheckActions && checked) {
|
||||
this.invokeActionString(this.checkboxCheckActions,this,event);
|
||||
}
|
||||
if(this.checkboxUncheckActions && !checked) {
|
||||
this.invokeActionString(this.checkboxUncheckActions,this,event);
|
||||
}
|
||||
@@ -167,6 +170,7 @@ Compute the internal state of the widget
|
||||
CheckboxWidget.prototype.execute = function() {
|
||||
// Get the parameters from the attributes
|
||||
this.checkboxActions = this.getAttribute("actions");
|
||||
this.checkboxCheckActions = this.getAttribute("checkactions");
|
||||
this.checkboxUncheckActions = this.getAttribute("uncheckactions");
|
||||
this.checkboxTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
||||
this.checkboxTag = this.getAttribute("tag");
|
||||
|
||||
@@ -14,7 +14,8 @@ Edit-bitmap widget
|
||||
|
||||
// Default image sizes
|
||||
var DEFAULT_IMAGE_WIDTH = 600,
|
||||
DEFAULT_IMAGE_HEIGHT = 370;
|
||||
DEFAULT_IMAGE_HEIGHT = 370,
|
||||
DEFAULT_IMAGE_TYPE = "image/png";
|
||||
|
||||
// Configuration tiddlers
|
||||
var LINE_WIDTH_TITLE = "$:/config/BitmapEditor/LineWidth",
|
||||
@@ -154,7 +155,13 @@ EditBitmapWidget.prototype.loadCanvas = function() {
|
||||
self.refreshToolbar();
|
||||
};
|
||||
// Get the current bitmap into an image object
|
||||
currImage.src = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
|
||||
if(tiddler && tiddler.fields.type && tiddler.fields.text) {
|
||||
currImage.src = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
|
||||
} else {
|
||||
currImage.width = DEFAULT_IMAGE_WIDTH;
|
||||
currImage.height = DEFAULT_IMAGE_HEIGHT;
|
||||
currImage.onerror();
|
||||
}
|
||||
};
|
||||
|
||||
EditBitmapWidget.prototype.initCanvas = function(canvas,width,height,image) {
|
||||
@@ -319,18 +326,16 @@ EditBitmapWidget.prototype.strokeEnd = function() {
|
||||
};
|
||||
|
||||
EditBitmapWidget.prototype.saveChanges = function() {
|
||||
var tiddler = this.wiki.getTiddler(this.editTitle);
|
||||
if(tiddler) {
|
||||
// data URIs look like "data:<type>;base64,<text>"
|
||||
var dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),
|
||||
posColon = dataURL.indexOf(":"),
|
||||
posSemiColon = dataURL.indexOf(";"),
|
||||
posComma = dataURL.indexOf(","),
|
||||
type = dataURL.substring(posColon+1,posSemiColon),
|
||||
text = dataURL.substring(posComma+1);
|
||||
var update = {type: type, text: text};
|
||||
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));
|
||||
}
|
||||
var tiddler = this.wiki.getTiddler(this.editTitle) || new $tw.Tiddler({title: this.editTitle,type: DEFAULT_IMAGE_TYPE});
|
||||
// data URIs look like "data:<type>;base64,<text>"
|
||||
var dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),
|
||||
posColon = dataURL.indexOf(":"),
|
||||
posSemiColon = dataURL.indexOf(";"),
|
||||
posComma = dataURL.indexOf(","),
|
||||
type = dataURL.substring(posColon+1,posSemiColon),
|
||||
text = dataURL.substring(posComma+1);
|
||||
var update = {type: type, text: text};
|
||||
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));
|
||||
};
|
||||
|
||||
exports["edit-bitmap"] = EditBitmapWidget;
|
||||
|
||||
@@ -73,13 +73,13 @@ Compute the internal state of the widget
|
||||
KeyboardWidget.prototype.execute = function() {
|
||||
var self = this;
|
||||
// Get attributes
|
||||
this.actions = this.getAttribute("actions");
|
||||
this.message = this.getAttribute("message");
|
||||
this.param = this.getAttribute("param");
|
||||
this.key = this.getAttribute("key");
|
||||
this.tag = this.getAttribute("tag");
|
||||
this.actions = this.getAttribute("actions","");
|
||||
this.message = this.getAttribute("message","");
|
||||
this.param = this.getAttribute("param","");
|
||||
this.key = this.getAttribute("key","");
|
||||
this.tag = this.getAttribute("tag","");
|
||||
this.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);
|
||||
this["class"] = this.getAttribute("class");
|
||||
this["class"] = this.getAttribute("class","");
|
||||
if(this.key.substr(0,2) === "((" && this.key.substr(-2,2) === "))") {
|
||||
this.shortcutTiddlers = [];
|
||||
var name = this.key.substring(2,this.key.length -2);
|
||||
|
||||
@@ -183,7 +183,14 @@ LinkWidget.prototype.execute = function() {
|
||||
this.isShadow = this.wiki.isShadowTiddler(this.to);
|
||||
this.hideMissingLinks = (this.getVariable("tv-show-missing-links") || "yes") === "no";
|
||||
// Make the child widgets
|
||||
this.makeChildWidgets();
|
||||
var templateTree;
|
||||
if(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {
|
||||
templateTree = this.parseTreeNode.children;
|
||||
} else {
|
||||
// Default template is a link to the title
|
||||
templateTree = [{type: "text", text: this.to}];
|
||||
}
|
||||
this.makeChildWidgets(templateTree);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -84,39 +84,50 @@ NavigatorWidget.prototype.getStoryList = function() {
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.saveStoryList = function(storyList) {
|
||||
var storyTiddler = this.wiki.getTiddler(this.storyTitle);
|
||||
this.wiki.addTiddler(new $tw.Tiddler(
|
||||
{title: this.storyTitle},
|
||||
storyTiddler,
|
||||
{list: storyList}
|
||||
));
|
||||
if(this.storyTitle) {
|
||||
var storyTiddler = this.wiki.getTiddler(this.storyTitle);
|
||||
this.wiki.addTiddler(new $tw.Tiddler(
|
||||
{title: this.storyTitle},
|
||||
storyTiddler,
|
||||
{list: storyList}
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {
|
||||
var p = storyList.indexOf(title);
|
||||
while(p !== -1) {
|
||||
storyList.splice(p,1);
|
||||
p = storyList.indexOf(title);
|
||||
if(storyList) {
|
||||
var p = storyList.indexOf(title);
|
||||
while(p !== -1) {
|
||||
storyList.splice(p,1);
|
||||
p = storyList.indexOf(title);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle,newTitle) {
|
||||
var pos = storyList.indexOf(oldTitle);
|
||||
if(pos !== -1) {
|
||||
storyList[pos] = newTitle;
|
||||
do {
|
||||
pos = storyList.indexOf(oldTitle,pos + 1);
|
||||
if(pos !== -1) {
|
||||
storyList.splice(pos,1);
|
||||
}
|
||||
} while(pos !== -1);
|
||||
} else {
|
||||
storyList.splice(0,0,newTitle);
|
||||
if(storyList) {
|
||||
var pos = storyList.indexOf(oldTitle);
|
||||
if(pos !== -1) {
|
||||
storyList[pos] = newTitle;
|
||||
do {
|
||||
pos = storyList.indexOf(oldTitle,pos + 1);
|
||||
if(pos !== -1) {
|
||||
storyList.splice(pos,1);
|
||||
}
|
||||
} while(pos !== -1);
|
||||
} else {
|
||||
storyList.splice(0,0,newTitle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.addToStory = function(title,fromTitle) {
|
||||
this.wiki.addToStory(title,fromTitle,this.storyTitle,{openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"),openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top")});
|
||||
if(this.storyTitle) {
|
||||
this.wiki.addToStory(title,fromTitle,this.storyTitle,{
|
||||
openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"),
|
||||
openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top")
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -279,15 +290,7 @@ NavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {
|
||||
Generate a title for the draft of a given tiddler
|
||||
*/
|
||||
NavigatorWidget.prototype.generateDraftTitle = function(title) {
|
||||
var c = 0,
|
||||
draftTitle,
|
||||
username = this.wiki.getTiddlerText("$:/status/UserName"),
|
||||
attribution = username ? " by " + username : "";
|
||||
do {
|
||||
draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'" + attribution;
|
||||
c++;
|
||||
} while(this.wiki.tiddlerExists(draftTitle));
|
||||
return draftTitle;
|
||||
return this.wiki.generateDraftTitle(title);
|
||||
};
|
||||
|
||||
// Take a tiddler out of edit mode, saving the changes
|
||||
@@ -466,14 +469,14 @@ NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
|
||||
},this.wiki.getModificationFields());
|
||||
this.wiki.addTiddler(draftTiddler);
|
||||
// Update the story to insert the new draft at the top and remove any existing tiddler
|
||||
if(storyList.indexOf(draftTitle) === -1) {
|
||||
if(storyList && storyList.indexOf(draftTitle) === -1) {
|
||||
var slot = storyList.indexOf(event.navigateFromTitle);
|
||||
if(slot === -1) {
|
||||
slot = this.getAttribute("openLinkFromOutsideRiver","top") === "bottom" ? storyList.length - 1 : slot;
|
||||
}
|
||||
storyList.splice(slot + 1,0,draftTitle);
|
||||
}
|
||||
if(storyList.indexOf(title) !== -1) {
|
||||
if(storyList && storyList.indexOf(title) !== -1) {
|
||||
storyList.splice(storyList.indexOf(title),1);
|
||||
}
|
||||
this.saveStoryList(storyList);
|
||||
@@ -529,7 +532,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
|
||||
var storyList = this.getStoryList(),
|
||||
history = [];
|
||||
// Add it to the story
|
||||
if(storyList.indexOf(IMPORT_TITLE) === -1) {
|
||||
if(storyList && storyList.indexOf(IMPORT_TITLE) === -1) {
|
||||
storyList.unshift(IMPORT_TITLE);
|
||||
}
|
||||
// And to history
|
||||
@@ -606,7 +609,6 @@ NavigatorWidget.prototype.handleUnfoldAllTiddlersEvent = function(event) {
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.handleRenameTiddlerEvent = function(event) {
|
||||
event = $tw.hooks.invokeHook("th-renaming-tiddler", event);
|
||||
var paramObject = event.paramObject || {},
|
||||
from = paramObject.from || event.tiddlerTitle,
|
||||
to = paramObject.to;
|
||||
|
||||
@@ -56,32 +56,39 @@ RevealWidget.prototype.render = function(parent,nextSibling) {
|
||||
RevealWidget.prototype.positionPopup = function(domNode) {
|
||||
domNode.style.position = "absolute";
|
||||
domNode.style.zIndex = "1000";
|
||||
var left,top;
|
||||
switch(this.position) {
|
||||
case "left":
|
||||
domNode.style.left = Math.max(0, this.popup.left - domNode.offsetWidth) + "px";
|
||||
domNode.style.top = this.popup.top + "px";
|
||||
left = this.popup.left - domNode.offsetWidth;
|
||||
top = this.popup.top;
|
||||
break;
|
||||
case "above":
|
||||
domNode.style.left = this.popup.left + "px";
|
||||
domNode.style.top = Math.max(0, this.popup.top - domNode.offsetHeight) + "px";
|
||||
left = this.popup.left;
|
||||
top = this.popup.top - domNode.offsetHeight;
|
||||
break;
|
||||
case "aboveright":
|
||||
domNode.style.left = (this.popup.left + this.popup.width) + "px";
|
||||
domNode.style.top = Math.max(0, this.popup.top + this.popup.height - domNode.offsetHeight) + "px";
|
||||
left = this.popup.left + this.popup.width;
|
||||
top = this.popup.top + this.popup.height - domNode.offsetHeight;
|
||||
break;
|
||||
case "right":
|
||||
domNode.style.left = (this.popup.left + this.popup.width) + "px";
|
||||
domNode.style.top = this.popup.top + "px";
|
||||
left = this.popup.left + this.popup.width;
|
||||
top = this.popup.top;
|
||||
break;
|
||||
case "belowleft":
|
||||
domNode.style.left = Math.max(0, this.popup.left + this.popup.width - domNode.offsetWidth) + "px";
|
||||
domNode.style.top = (this.popup.top + this.popup.height) + "px";
|
||||
left = this.popup.left + this.popup.width - domNode.offsetWidth;
|
||||
top = this.popup.top + this.popup.height;
|
||||
break;
|
||||
default: // Below
|
||||
domNode.style.left = this.popup.left + "px";
|
||||
domNode.style.top = (this.popup.top + this.popup.height) + "px";
|
||||
left = this.popup.left;
|
||||
top = this.popup.top + this.popup.height;
|
||||
break;
|
||||
}
|
||||
if(!this.positionAllowNegative) {
|
||||
left = Math.max(0,left);
|
||||
top = Math.max(0,top);
|
||||
}
|
||||
domNode.style.left = left + "px";
|
||||
domNode.style.top = top + "px";
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -94,6 +101,7 @@ RevealWidget.prototype.execute = function() {
|
||||
this.type = this.getAttribute("type");
|
||||
this.text = this.getAttribute("text");
|
||||
this.position = this.getAttribute("position");
|
||||
this.positionAllowNegative = this.getAttribute("positionAllowNegative") === "yes";
|
||||
this["class"] = this.getAttribute("class","");
|
||||
this.style = this.getAttribute("style","");
|
||||
this["default"] = this.getAttribute("default","");
|
||||
@@ -142,10 +150,10 @@ RevealWidget.prototype.readState = function() {
|
||||
this.readPopupState(state);
|
||||
break;
|
||||
case "match":
|
||||
this.isOpen = !!(this.compareStateText(state) == 0);
|
||||
this.isOpen = this.text === state;
|
||||
break;
|
||||
case "nomatch":
|
||||
this.isOpen = !(this.compareStateText(state) == 0);
|
||||
this.isOpen = this.text !== state;
|
||||
break;
|
||||
case "lt":
|
||||
this.isOpen = !!(this.compareStateText(state) < 0);
|
||||
@@ -191,13 +199,13 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
*/
|
||||
RevealWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes["default"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) {
|
||||
if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes.positionAllowNegative || changedAttributes["default"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
var currentlyOpen = this.isOpen;
|
||||
this.readState();
|
||||
if(this.isOpen !== currentlyOpen || (this.stateTiddlerTitle && changedTiddlers[this.stateTiddlerTitle])) {
|
||||
if(this.isOpen !== currentlyOpen) {
|
||||
if(this.retain === "yes") {
|
||||
this.updateState();
|
||||
} else {
|
||||
|
||||
@@ -385,9 +385,10 @@ Widget.prototype.previousSibling = function() {
|
||||
Render the children of this widget into the DOM
|
||||
*/
|
||||
Widget.prototype.renderChildren = function(parent,nextSibling) {
|
||||
$tw.utils.each(this.children,function(childWidget) {
|
||||
childWidget.render(parent,nextSibling);
|
||||
});
|
||||
var children = this.children;
|
||||
for(var i = 0; i < children.length; i++) {
|
||||
children[i].render(parent,nextSibling);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -455,11 +456,11 @@ Widget.prototype.refreshSelf = function() {
|
||||
Refresh all the children of a widget
|
||||
*/
|
||||
Widget.prototype.refreshChildren = function(changedTiddlers) {
|
||||
var self = this,
|
||||
var children = this.children,
|
||||
refreshed = false;
|
||||
$tw.utils.each(this.children,function(childWidget) {
|
||||
refreshed = childWidget.refresh(changedTiddlers) || refreshed;
|
||||
});
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
refreshed = children[i].refresh(changedTiddlers) || refreshed;
|
||||
}
|
||||
return refreshed;
|
||||
};
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ function relinkTiddler(fromTitle,toTitle,options) {
|
||||
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 || []).slice(0),
|
||||
list = (tiddler.fields.list || []).slice(0),
|
||||
var tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,
|
||||
list = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,
|
||||
isModified = false;
|
||||
if(!options.dontRenameInTags) {
|
||||
// Rename tags
|
||||
|
||||
@@ -27,6 +27,16 @@ var widget = require("$:/core/modules/widgets/widget.js");
|
||||
var USER_NAME_TITLE = "$:/status/UserName",
|
||||
TIMESTAMP_DISABLE_TITLE = "$:/config/TimestampDisable";
|
||||
|
||||
/*
|
||||
Add available indexers to this wiki
|
||||
*/
|
||||
exports.addIndexersToWiki = function() {
|
||||
var self = this;
|
||||
$tw.utils.each($tw.modules.applyMethods("indexer"),function(Indexer,name) {
|
||||
self.addIndexer(new Indexer(self),name);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Get the value of a text reference. Text references can have any of these forms:
|
||||
<tiddlertitle>
|
||||
@@ -478,11 +488,18 @@ exports.getOrphanTitles = function() {
|
||||
Retrieves a list of the tiddler titles that are tagged with a given tag
|
||||
*/
|
||||
exports.getTiddlersWithTag = function(tag) {
|
||||
var self = this;
|
||||
return this.getGlobalCache("taglist-" + tag,function() {
|
||||
var tagmap = self.getTagMap();
|
||||
return self.sortByList(tagmap[tag],tag);
|
||||
});
|
||||
// Try to use the indexer
|
||||
var self = this,
|
||||
tagIndexer = this.getIndexer("TagIndexer"),
|
||||
results = tagIndexer && tagIndexer.subIndexers[3].lookup(tag);
|
||||
if(!results) {
|
||||
// If not available, perform a manual scan
|
||||
results = this.getGlobalCache("taglist-" + tag,function() {
|
||||
var tagmap = self.getTagMap();
|
||||
return self.sortByList(tagmap[tag],tag);
|
||||
});
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1048,6 +1065,7 @@ Options available:
|
||||
invert: If true returns tiddlers that do not contain the specified string
|
||||
caseSensitive: If true forces a case sensitive search
|
||||
field: If specified, restricts the search to the specified field, or an array of field names
|
||||
anchored: If true, forces all but regexp searches to be anchored to the start of text
|
||||
excludeField: If true, the field options are inverted to specify the fields that are not to be searched
|
||||
The search mode is determined by the first of these boolean flags to be true
|
||||
literal: searches for literal string
|
||||
@@ -1062,12 +1080,13 @@ exports.search = function(text,options) {
|
||||
invert = !!options.invert;
|
||||
// Convert the search string into a regexp for each term
|
||||
var terms, searchTermsRegExps,
|
||||
flags = options.caseSensitive ? "" : "i";
|
||||
flags = options.caseSensitive ? "" : "i",
|
||||
anchor = options.anchored ? "^" : "";
|
||||
if(options.literal) {
|
||||
if(text.length === 0) {
|
||||
searchTermsRegExps = null;
|
||||
} else {
|
||||
searchTermsRegExps = [new RegExp("(" + $tw.utils.escapeRegExp(text) + ")",flags)];
|
||||
searchTermsRegExps = [new RegExp("(" + anchor + $tw.utils.escapeRegExp(text) + ")",flags)];
|
||||
}
|
||||
} else if(options.whitespace) {
|
||||
terms = [];
|
||||
@@ -1076,7 +1095,7 @@ exports.search = function(text,options) {
|
||||
terms.push($tw.utils.escapeRegExp(term));
|
||||
}
|
||||
});
|
||||
searchTermsRegExps = [new RegExp("(" + terms.join("\\s+") + ")",flags)];
|
||||
searchTermsRegExps = [new RegExp("(" + anchor + terms.join("\\s+") + ")",flags)];
|
||||
} else if(options.regexp) {
|
||||
try {
|
||||
searchTermsRegExps = [new RegExp("(" + text + ")",flags)];
|
||||
@@ -1091,7 +1110,7 @@ exports.search = function(text,options) {
|
||||
} else {
|
||||
searchTermsRegExps = [];
|
||||
for(t=0; t<terms.length; t++) {
|
||||
searchTermsRegExps.push(new RegExp("(" + $tw.utils.escapeRegExp(terms[t]) + ")",flags));
|
||||
searchTermsRegExps.push(new RegExp("(" + anchor + $tw.utils.escapeRegExp(terms[t]) + ")",flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1369,8 +1388,10 @@ fromPageRect: page coordinates of the origin of the navigation
|
||||
historyTitle: title of history tiddler (defaults to $:/HistoryList)
|
||||
*/
|
||||
exports.addToHistory = function(title,fromPageRect,historyTitle) {
|
||||
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
|
||||
story.addToHistory(title,fromPageRect);
|
||||
if(historyTitle) {
|
||||
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
|
||||
story.addToHistory(title,fromPageRect);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1381,8 +1402,25 @@ storyTitle: title of story tiddler (defaults to $:/StoryList)
|
||||
options: see story.js
|
||||
*/
|
||||
exports.addToStory = function(title,fromTitle,storyTitle,options) {
|
||||
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
|
||||
story.addToStory(title,fromTitle,options);
|
||||
if(storyTitle) {
|
||||
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
|
||||
story.addToStory(title,fromTitle,options);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Generate a title for the draft of a given tiddler
|
||||
*/
|
||||
exports.generateDraftTitle = function(title) {
|
||||
var c = 0,
|
||||
draftTitle,
|
||||
username = this.getTiddlerText("$:/status/UserName"),
|
||||
attribution = username ? " by " + username : "";
|
||||
do {
|
||||
draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'" + attribution;
|
||||
c++;
|
||||
} while(this.tiddlerExists(draftTitle));
|
||||
return draftTitle;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -52,7 +52,7 @@ modal-footer-background: #3b4252
|
||||
modal-footer-border: #3b4252
|
||||
modal-header-border: #3b4252
|
||||
muted-foreground: #4C566A
|
||||
notification-background: #D08770
|
||||
notification-background: <<colour primary>>
|
||||
notification-border: #EBCB8B
|
||||
page-background: #2e3440
|
||||
pre-background: #2E3440
|
||||
|
||||
@@ -119,7 +119,7 @@ caption: {{$:/language/ControlPanel/KeyboardShortcuts/Caption}}
|
||||
</td>
|
||||
</tr>
|
||||
<$set name="dropdownState" value={{$(dropdownStateTitle)$}}>
|
||||
<$list filter="[<dropdownState>prefix[open]]" variable="listItem">
|
||||
<$list filter="[<dropdownState>match[open]]" variable="listItem">
|
||||
<<shortcut-editor>>
|
||||
</$list>
|
||||
</$set>
|
||||
|
||||
@@ -15,7 +15,7 @@ caption: {{$:/language/ControlPanel/Palette/Caption}}
|
||||
<$reveal type="match" state="$:/state/ShowPaletteEditor" text="yes">
|
||||
|
||||
<$button set="$:/state/ShowPaletteEditor" setTo="no"><<lingo HideEditor/Caption>></$button>
|
||||
{{$:/snippets/paletteeditor}}
|
||||
{{$:/PaletteManager}}
|
||||
|
||||
</$reveal>
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@ title: $:/core/ui/ControlPanel/Plugins/AddPlugins
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Plugins/
|
||||
|
||||
<$button message="tm-modal" param="$:/core/ui/ControlPanel/Modals/AddPlugins" tooltip={{$:/language/ControlPanel/Plugins/Add/Hint}} class="tc-btn-big-green" style="background:blue;">
|
||||
<$button message="tm-modal" param="$:/core/ui/ControlPanel/Modals/AddPlugins" tooltip={{$:/language/ControlPanel/Plugins/Add/Hint}} class="tc-btn-big-green tc-primary-btn">
|
||||
{{$:/core/images/download-button}} <<lingo Add/Caption>>
|
||||
</$button>
|
||||
|
||||
16
core/ui/ControlPanel/Saving/GitHub.tid
Normal file
16
core/ui/ControlPanel/Saving/GitHub.tid
Normal file
@@ -0,0 +1,16 @@
|
||||
title: $:/core/ui/ControlPanel/Saving/GitHub
|
||||
tags: $:/tags/ControlPanel/Saving
|
||||
caption: {{$:/language/ControlPanel/Saving/GitService/GitHub/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Saving/GitService/
|
||||
\define service-name() ~GitHub
|
||||
|
||||
<<lingo Description>>
|
||||
|
||||
|<<lingo UserName>> |<$edit-text tiddler="$:/GitHub/Username" default="" tag="input"/> |
|
||||
|<<lingo GitHub/Password>> |<$password name="github"/> |
|
||||
|<<lingo Repo>> |<$edit-text tiddler="$:/GitHub/Repo" default="" tag="input"/> |
|
||||
|<<lingo Branch>> |<$edit-text tiddler="$:/GitHub/Branch" default="master" tag="input"/> |
|
||||
|<<lingo Path>> |<$edit-text tiddler="$:/GitHub/Path" default="" tag="input"/> |
|
||||
|<<lingo Filename>> |<$edit-text tiddler="$:/GitHub/Filename" default="" tag="input"/> |
|
||||
|<<lingo ServerURL>> |<$edit-text tiddler="$:/GitHub/ServerURL" default="https://api.github.com" tag="input"/> |
|
||||
16
core/ui/ControlPanel/Saving/GitLab.tid
Normal file
16
core/ui/ControlPanel/Saving/GitLab.tid
Normal file
@@ -0,0 +1,16 @@
|
||||
title: $:/core/ui/ControlPanel/Saving/GitLab
|
||||
tags: $:/tags/ControlPanel/Saving
|
||||
caption: {{$:/language/ControlPanel/Saving/GitService/GitLab/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Saving/GitService/
|
||||
\define service-name() ~GitLab
|
||||
|
||||
<<lingo Description>>
|
||||
|
||||
|<<lingo UserName>> |<$edit-text tiddler="$:/GitLab/Username" default="" tag="input"/> |
|
||||
|<<lingo GitLab/Password>> |<$password name="gitlab"/> |
|
||||
|<<lingo Repo>> |<$edit-text tiddler="$:/GitLab/Repo" default="" tag="input"/> |
|
||||
|<<lingo Branch>> |<$edit-text tiddler="$:/GitLab/Branch" default="master" tag="input"/> |
|
||||
|<<lingo Path>> |<$edit-text tiddler="$:/GitLab/Path" default="" tag="input"/> |
|
||||
|<<lingo Filename>> |<$edit-text tiddler="$:/GitLab/Filename" default="" tag="input"/> |
|
||||
|<<lingo ServerURL>> |<$edit-text tiddler="$:/GitLab/ServerURL" default="https://gitlab.com/api/v4" tag="input"/> |
|
||||
@@ -29,11 +29,12 @@ $value={{$:/temp/newfieldvalue}}/>
|
||||
</$reveal>
|
||||
</$vars>
|
||||
\end
|
||||
\whitespace trim
|
||||
|
||||
<div class="tc-edit-fields">
|
||||
<table class="tc-edit-fields">
|
||||
<tbody>
|
||||
<$list filter="[all[current]fields[]] +[sort[title]]" variable="currentField">
|
||||
<$list filter="[all[current]fields[]] +[sort[title]]" variable="currentField" storyview="pop">
|
||||
<$list filter=<<config-filter>> variable="temp">
|
||||
<tr class="tc-edit-field">
|
||||
<td class="tc-edit-field-name">
|
||||
|
||||
@@ -16,7 +16,7 @@ color:$(foregroundColor)$;
|
||||
<$vars foregroundColor=<<contrastcolour target:"""$colour$""" fallbackTarget:"""$fallbackTarget$""" colourA:"""$colourA$""" colourB:"""$colourB$""">> backgroundColor="""$colour$""">
|
||||
<span style=<<tag-styles>> class="tc-tag-label tc-tag-list-item">
|
||||
<$transclude tiddler="""$icon$"""/> <$view field="title" format="text" />
|
||||
<$button message="tm-remove-tag" param={{!!title}} class="tc-btn-invisible tc-remove-tag-button">×</$button>
|
||||
<$button message="tm-remove-tag" param={{!!title}} class="tc-btn-invisible tc-remove-tag-button">{{$:/core/images/close-button}}</$button>
|
||||
</span>
|
||||
</$vars>
|
||||
\end
|
||||
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/cancel-button}} {{$:/language/Buttons/Cancel/Caption}}
|
||||
description: {{$:/language/Buttons/Cancel/Hint}}
|
||||
|
||||
<$button message="tm-cancel-tiddler" tooltip={{$:/language/Buttons/Cancel/Hint}} aria-label={{$:/language/Buttons/Cancel/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/cancel-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Cancel/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/delete-button}} {{$:/language/Buttons/Delete/Caption}}
|
||||
description: {{$:/language/Buttons/Delete/Hint}}
|
||||
|
||||
<$button message="tm-delete-tiddler" tooltip={{$:/language/Buttons/Delete/Hint}} aria-label={{$:/language/Buttons/Delete/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/delete-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Delete/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -10,10 +10,10 @@ description: {{$:/language/Buttons/Save/Hint}}
|
||||
<$action-deletetiddler $tiddler="$:/temp/newfieldname"/>
|
||||
<$action-deletetiddler $tiddler="$:/temp/newfieldvalue"/>
|
||||
<$action-sendmessage $message="tm-save-tiddler"/>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/done-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Save/Caption}}/></span>
|
||||
</$list>
|
||||
</$button></$fieldmangler>
|
||||
|
||||
@@ -3,12 +3,28 @@ title: $:/core/ui/EditorToolbar/stamp-dropdown
|
||||
\define toolbar-button-stamp-inner()
|
||||
<$button tag="a">
|
||||
|
||||
<$list filter="[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]]">
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="replace-selection"
|
||||
text={{$(snippetTitle)$}}
|
||||
/>
|
||||
|
||||
</$list>
|
||||
|
||||
|
||||
<$list filter="[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]]">
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix={{{ [[$(snippetTitle)$]addsuffix[/prefix]get[text]] }}}
|
||||
suffix={{{ [[$(snippetTitle)$]addsuffix[/suffix]get[text]] }}}
|
||||
/>
|
||||
|
||||
</$list>
|
||||
|
||||
<$action-deletetiddler
|
||||
$tiddler=<<dropdown-state>>
|
||||
/>
|
||||
|
||||
8
core/ui/KeyboardShortcuts/advanced-search.tid
Normal file
8
core/ui/KeyboardShortcuts/advanced-search.tid
Normal file
@@ -0,0 +1,8 @@
|
||||
title: $:/core/ui/KeyboardShortcuts/advanced-search
|
||||
tags: $:/tags/KeyboardShortcut
|
||||
key: ((advanced-search))
|
||||
|
||||
<$navigator story="$:/StoryList" history="$:/HistoryList">
|
||||
<$action-navigate $to="$:/AdvancedSearch"/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param="""[data-tiddler-title="$:/AdvancedSearch"] .tc-search input"""/>
|
||||
</$navigator>
|
||||
5
core/ui/KeyboardShortcuts/sidebar-search.tid
Normal file
5
core/ui/KeyboardShortcuts/sidebar-search.tid
Normal file
@@ -0,0 +1,5 @@
|
||||
title: $:/core/ui/KeyboardShortcuts/sidebar-search
|
||||
tags: $:/tags/KeyboardShortcut
|
||||
key: ((sidebar-search))
|
||||
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=".tc-search input"/>
|
||||
9
core/ui/KeyboardShortcuts/toggle-sidebar.tid
Normal file
9
core/ui/KeyboardShortcuts/toggle-sidebar.tid
Normal file
@@ -0,0 +1,9 @@
|
||||
title: $:/core/ui/KeyboardShortcut/toggle-sidebar
|
||||
tags: $:/tags/KeyboardShortcut
|
||||
key: ((toggle-sidebar))
|
||||
|
||||
<$list filter="[[$:/state/sidebar]is[missing]] [{$:/state/sidebar}removeprefix[yes]]" emptyMessage="""
|
||||
<$action-setfield $tiddler="$:/state/sidebar" text="yes"/>
|
||||
""">
|
||||
<$action-setfield $tiddler="$:/state/sidebar" text="no"/>
|
||||
</$list>
|
||||
@@ -1,15 +1,17 @@
|
||||
title: $:/core/ui/PageTemplate/pagecontrols
|
||||
|
||||
\whitespace trim
|
||||
\define config-title()
|
||||
$:/config/PageControlButtons/Visibility/$(listItem)$
|
||||
\end
|
||||
<div class="tc-page-controls">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]" variable="listItem">
|
||||
<$reveal type="nomatch" state=<<config-title>> text="hide">
|
||||
<$set name="hidden" value=<<config-title>>>
|
||||
<$list filter="[<hidden>!text[hide]]" storyview="pop">
|
||||
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
|
||||
<$transclude tiddler=<<listItem>> mode="inline"/>
|
||||
</$set>
|
||||
</$reveal>
|
||||
</$list>
|
||||
</$set>
|
||||
</$list>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/AdvancedSearch/Hint}}
|
||||
|
||||
\define control-panel-button(class)
|
||||
<$button to="$:/AdvancedSearch" tooltip={{$:/language/Buttons/AdvancedSearch/Hint}} aria-label={{$:/language/Buttons/AdvancedSearch/Caption}} class="""$(tv-config-toolbar-class)$ $class$""">
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/advanced-search-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/AdvancedSearch/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/close-all-button}} {{$:/language/Buttons/CloseAll/Capt
|
||||
description: {{$:/language/Buttons/CloseAll/Hint}}
|
||||
|
||||
<$button message="tm-close-all-tiddlers" tooltip={{$:/language/Buttons/CloseAll/Hint}} aria-label={{$:/language/Buttons/CloseAll/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/close-all-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/CloseAll/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/ControlPanel/Hint}}
|
||||
|
||||
\define control-panel-button(class)
|
||||
<$button to="$:/ControlPanel" tooltip={{$:/language/Buttons/ControlPanel/Hint}} aria-label={{$:/language/Buttons/ControlPanel/Caption}} class="""$(tv-config-toolbar-class)$ $class$""">
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/options-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/ControlPanel/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -5,20 +5,20 @@ description: {{$:/language/Buttons/Encryption/Hint}}
|
||||
|
||||
<$reveal type="match" state="$:/isEncrypted" text="yes">
|
||||
<$button message="tm-clear-password" tooltip={{$:/language/Buttons/Encryption/ClearPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/ClearPassword/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/locked-padlock}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Encryption/ClearPassword/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="nomatch" state="$:/isEncrypted" text="yes">
|
||||
<$button message="tm-set-password" tooltip={{$:/language/Buttons/Encryption/SetPassword/Hint}} aria-label={{$:/language/Buttons/Encryption/SetPassword/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/unlocked-padlock}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Encryption/SetPassword/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/FoldAll/Hint}}
|
||||
|
||||
<$button tooltip={{$:/language/Buttons/FoldAll/Hint}} aria-label={{$:/language/Buttons/FoldAll/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$action-sendmessage $message="tm-fold-all-tiddlers" $param=<<currentTiddler>> foldedStatePrefix="$:/state/folded/"/>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]" variable="listItem">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]" variable="listItem">
|
||||
{{$:/core/images/fold-all-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/FoldAll/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/full-screen-button}} {{$:/language/Buttons/FullScreen/
|
||||
description: {{$:/language/Buttons/FullScreen/Hint}}
|
||||
|
||||
<$button message="tm-full-screen" tooltip={{$:/language/Buttons/FullScreen/Hint}} aria-label={{$:/language/Buttons/FullScreen/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/full-screen-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/FullScreen/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/home-button}} {{$:/language/Buttons/Home/Caption}}
|
||||
description: {{$:/language/Buttons/Home/Hint}}
|
||||
|
||||
<$button message="tm-home" tooltip={{$:/language/Buttons/Home/Hint}} aria-label={{$:/language/Buttons/Home/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/home-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Home/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/Import/Hint}}
|
||||
|
||||
<div class="tc-file-input-wrapper">
|
||||
<$button tooltip={{$:/language/Buttons/Import/Hint}} aria-label={{$:/language/Buttons/Import/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/import-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Import/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -8,14 +8,14 @@ $(languagePluginTitle)$/icon
|
||||
\end
|
||||
<span class="tc-popup-keep">
|
||||
<$button popup=<<qualify "$:/state/popup/language">> tooltip={{$:/language/Buttons/Language/Hint}} aria-label={{$:/language/Buttons/Language/Caption}} class=<<tv-config-toolbar-class>> selectedClass="tc-selected">
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
<span class="tc-image-button">
|
||||
<$set name="languagePluginTitle" value={{$:/language}}>
|
||||
<$image source=<<flag-title>>/>
|
||||
</$set>
|
||||
</span>
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Language/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/Manager/Hint}}
|
||||
|
||||
\define manager-button(class)
|
||||
<$button to="$:/Manager" tooltip={{$:/language/Buttons/Manager/Hint}} aria-label={{$:/language/Buttons/Manager/Caption}} class="""$(tv-config-toolbar-class)$ $class$""">
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/list}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Manager/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -7,10 +7,10 @@ description: {{$:/language/Buttons/More/Hint}}
|
||||
$:/config/PageControlButtons/Visibility/$(listItem)$
|
||||
\end
|
||||
<$button popup=<<qualify "$:/state/popup/more">> tooltip={{$:/language/Buttons/More/Hint}} aria-label={{$:/language/Buttons/More/Caption}} class=<<tv-config-toolbar-class>> selectedClass="tc-selected">
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/down-arrow}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/More/Caption}}/></span>
|
||||
</$list>
|
||||
</$button><$reveal state=<<qualify "$:/state/popup/more">> type="popup" position="below" animate="yes">
|
||||
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/new-image-button}} {{$:/language/Buttons/NewImage/Capt
|
||||
description: {{$:/language/Buttons/NewImage/Hint}}
|
||||
|
||||
<$button tooltip={{$:/language/Buttons/NewImage/Hint}} aria-label={{$:/language/Buttons/NewImage/Caption}} class=<<tv-config-toolbar-class>> actions={{$:/core/ui/Actions/new-image}}>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/new-image-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/NewImage/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/NewJournal/Hint}}
|
||||
|
||||
\define journalButton()
|
||||
<$button tooltip={{$:/language/Buttons/NewJournal/Hint}} aria-label={{$:/language/Buttons/NewJournal/Caption}} class=<<tv-config-toolbar-class>> actions={{$:/core/ui/Actions/new-journal}}>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/new-journal-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/NewJournal/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/new-button}} {{$:/language/Buttons/NewTiddler/Caption}
|
||||
description: {{$:/language/Buttons/NewTiddler/Hint}}
|
||||
|
||||
<$button actions={{$:/core/ui/Actions/new-tiddler}} tooltip={{$:/language/Buttons/NewTiddler/Hint}} aria-label={{$:/language/Buttons/NewTiddler/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/new-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/NewTiddler/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -5,10 +5,10 @@ description: {{$:/language/Buttons/Palette/Hint}}
|
||||
|
||||
<span class="tc-popup-keep">
|
||||
<$button popup=<<qualify "$:/state/popup/palette">> tooltip={{$:/language/Buttons/Palette/Hint}} aria-label={{$:/language/Buttons/Palette/Caption}} class=<<tv-config-toolbar-class>> selectedClass="tc-selected">
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/palette}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Palette/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/print-button}} {{$:/language/Buttons/Print/Caption}}
|
||||
description: {{$:/language/Buttons/Print/Hint}}
|
||||
|
||||
<$button message="tm-print" tooltip={{$:/language/Buttons/Print/Hint}} aria-label={{$:/language/Buttons/Print/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/print-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Print/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -4,10 +4,10 @@ caption: {{$:/core/images/refresh-button}} {{$:/language/Buttons/Refresh/Caption
|
||||
description: {{$:/language/Buttons/Refresh/Hint}}
|
||||
|
||||
<$button message="tm-browser-refresh" tooltip={{$:/language/Buttons/Refresh/Hint}} aria-label={{$:/language/Buttons/Refresh/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/refresh-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>prefix[yes]]">
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Refresh/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user