mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-28 05:41:26 +00:00
Compare commits
98 Commits
offload-se
...
browser-me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e76db15aa | ||
|
|
5848d66e96 | ||
|
|
485051951e | ||
|
|
135e685811 | ||
|
|
99682c5731 | ||
|
|
d58eec47c0 | ||
|
|
059978ec63 | ||
|
|
b5e20a58a6 | ||
|
|
e8fe6b98bc | ||
|
|
317104774c | ||
|
|
deed8631d8 | ||
|
|
d733b77e2f | ||
|
|
46c26a64b9 | ||
|
|
ec81d6663b | ||
|
|
23f0a9bf79 | ||
|
|
bad87c405e | ||
|
|
6f23a078b7 | ||
|
|
c3706b8a79 | ||
|
|
7ca8fb29af | ||
|
|
d39bb5274e | ||
|
|
81b69783c4 | ||
|
|
40cc62f727 | ||
|
|
b349adde16 | ||
|
|
d63a1896b3 | ||
|
|
b65fa11643 | ||
|
|
4043499633 | ||
|
|
6a39a4e13b | ||
|
|
b5153c0066 | ||
|
|
b061f90f87 | ||
|
|
8be83cf01b | ||
|
|
5b5147dade | ||
|
|
ad6ac480f9 | ||
|
|
8168512e95 | ||
|
|
276fdc8634 | ||
|
|
0b38ced43a | ||
|
|
d7e48207b9 | ||
|
|
2c8fafee48 | ||
|
|
a6383aaaea | ||
|
|
61619c07c8 | ||
|
|
09a42a54c0 | ||
|
|
f4f31c37fc | ||
|
|
61e638c972 | ||
|
|
6bdd51d72a | ||
|
|
ed3405672a | ||
|
|
e3af967cbb | ||
|
|
6b0d3fab5d | ||
|
|
13f1689e7e | ||
|
|
4c09a88272 | ||
|
|
fbf110e209 | ||
|
|
3c1d658fad | ||
|
|
5d738673ac | ||
|
|
91871d2ced | ||
|
|
5143da9cce | ||
|
|
186d1b014a | ||
|
|
58e41ee0ad | ||
|
|
97824cc3a3 | ||
|
|
6e493755be | ||
|
|
64fce62075 | ||
|
|
5a4ff56477 | ||
|
|
3889a2a0d0 | ||
|
|
34737f4e28 | ||
|
|
94673a1028 | ||
|
|
b462aaa9a3 | ||
|
|
4552c117fc | ||
|
|
dc7f2a57bb | ||
|
|
7e91bac6b8 | ||
|
|
15ba415a45 | ||
|
|
2405e65308 | ||
|
|
865f36a6f5 | ||
|
|
a36356a07d | ||
|
|
ee23097816 | ||
|
|
e753851d49 | ||
|
|
cae3d0fa2c | ||
|
|
7c020d0eb6 | ||
|
|
afe2ac45d9 | ||
|
|
6791f0f130 | ||
|
|
a2e5c2cca2 | ||
|
|
87ba87bdd2 | ||
|
|
619bdfcab5 | ||
|
|
5ff4e02a61 | ||
|
|
f8170cd50a | ||
|
|
5389dc0fa7 | ||
|
|
2cc7c96eec | ||
|
|
8cd3d4e22c | ||
|
|
37e09d1c25 | ||
|
|
7a080092d0 | ||
|
|
810ac42810 | ||
|
|
88d3f69a3b | ||
|
|
e956bb32e9 | ||
|
|
dd91ac0b82 | ||
|
|
af63a3b920 | ||
|
|
e4fb47ee76 | ||
|
|
7944f42467 | ||
|
|
578c09e0ce | ||
|
|
33d4e8ea26 | ||
|
|
f980d8a7b2 | ||
|
|
e31a201269 | ||
|
|
58d291c116 |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "${{ env.NODE_VERSION }}"
|
node-version: "${{ env.NODE_VERSION }}"
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
|
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
|
||||||
TW5_BUILD_OUTPUT: "./output/prerelease"
|
TW5_BUILD_OUTPUT: "./output/prerelease"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "${{ env.NODE_VERSION }}"
|
node-version: "${{ env.NODE_VERSION }}"
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
TW5_BUILD_OUTPUT: "./output"
|
TW5_BUILD_OUTPUT: "./output"
|
||||||
TW5_BUILD_ARCHIVE: "./output"
|
TW5_BUILD_ARCHIVE: "./output"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "${{ env.NODE_VERSION }}"
|
node-version: "${{ env.NODE_VERSION }}"
|
||||||
|
|||||||
40
.github/workflows/eslint.yml
vendored
Normal file
40
.github/workflows/eslint.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: ESLint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: lint-${{ github.event.pull_request.number || github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
# Needed for GitHub Checks API
|
||||||
|
checks: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
eslint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install --include=dev
|
||||||
|
|
||||||
|
- name: Run ESLint with reviewdog (GitHub Checks)
|
||||||
|
uses: reviewdog/action-eslint@v1
|
||||||
|
with:
|
||||||
|
eslint_flags: '.'
|
||||||
|
reporter: github-pr-check
|
||||||
|
fail_level: error
|
||||||
|
level: error
|
||||||
|
tool_name: ESLint PR code
|
||||||
@@ -73,10 +73,8 @@ rm $TW5_BUILD_OUTPUT/dev/static/*
|
|||||||
|
|
||||||
echo "<a href='./plugins/tiddlywiki/tw2parser/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tw2parser/index.html</a>" > $TW5_BUILD_OUTPUT/classicparserdemo.html
|
echo "<a href='./plugins/tiddlywiki/tw2parser/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tw2parser/index.html</a>" > $TW5_BUILD_OUTPUT/classicparserdemo.html
|
||||||
echo "<a href='./plugins/tiddlywiki/codemirror/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/codemirror/index.html</a>" > $TW5_BUILD_OUTPUT/codemirrordemo.html
|
echo "<a href='./plugins/tiddlywiki/codemirror/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/codemirror/index.html</a>" > $TW5_BUILD_OUTPUT/codemirrordemo.html
|
||||||
echo "<a href='./plugins/tiddlywiki/d3/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/d3/index.html</a>" > $TW5_BUILD_OUTPUT/d3demo.html
|
|
||||||
echo "<a href='./plugins/tiddlywiki/highlight/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/highlight/index.html</a>" > $TW5_BUILD_OUTPUT/highlightdemo.html
|
echo "<a href='./plugins/tiddlywiki/highlight/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/highlight/index.html</a>" > $TW5_BUILD_OUTPUT/highlightdemo.html
|
||||||
echo "<a href='./plugins/tiddlywiki/markdown/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/markdown/index.html</a>" > $TW5_BUILD_OUTPUT/markdowndemo.html
|
echo "<a href='./plugins/tiddlywiki/markdown/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/markdown/index.html</a>" > $TW5_BUILD_OUTPUT/markdowndemo.html
|
||||||
echo "<a href='./plugins/tiddlywiki/tahoelafs/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tahoelafs/index.html</a>" > $TW5_BUILD_OUTPUT/tahoelafs.html
|
|
||||||
|
|
||||||
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
|
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
|
||||||
|
|
||||||
@@ -301,26 +299,6 @@ node $TW5_BUILD_TIDDLYWIKI \
|
|||||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/katex/empty.html text/plain \
|
--rendertiddler $:/core/save/empty plugins/tiddlywiki/katex/empty.html text/plain \
|
||||||
|| exit 1
|
|| exit 1
|
||||||
|
|
||||||
# /plugins/tiddlywiki/tahoelafs/index.html Demo wiki with Tahoe-LAFS plugin
|
|
||||||
# /plugins/tiddlywiki/tahoelafs/empty.html Empty wiki with Tahoe-LAFS plugin
|
|
||||||
node $TW5_BUILD_TIDDLYWIKI \
|
|
||||||
./editions/tahoelafs \
|
|
||||||
--load $TW5_BUILD_OUTPUT/build.tid \
|
|
||||||
--output $TW5_BUILD_OUTPUT \
|
|
||||||
--rendertiddler $:/core/save/all plugins/tiddlywiki/tahoelafs/index.html text/plain \
|
|
||||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/tahoelafs/empty.html text/plain \
|
|
||||||
|| exit 1
|
|
||||||
|
|
||||||
# /plugins/tiddlywiki/d3/index.html Demo wiki with D3 plugin
|
|
||||||
# /plugins/tiddlywiki/d3/empty.html Empty wiki with D3 plugin
|
|
||||||
node $TW5_BUILD_TIDDLYWIKI \
|
|
||||||
./editions/d3demo \
|
|
||||||
--load $TW5_BUILD_OUTPUT/build.tid \
|
|
||||||
--output $TW5_BUILD_OUTPUT \
|
|
||||||
--rendertiddler $:/core/save/all plugins/tiddlywiki/d3/index.html text/plain \
|
|
||||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/d3/empty.html text/plain \
|
|
||||||
|| exit 1
|
|
||||||
|
|
||||||
# /plugins/tiddlywiki/codemirror/index.html Demo wiki with codemirror plugin
|
# /plugins/tiddlywiki/codemirror/index.html Demo wiki with codemirror plugin
|
||||||
# /plugins/tiddlywiki/codemirror/empty.html Empty wiki with codemirror plugin
|
# /plugins/tiddlywiki/codemirror/empty.html Empty wiki with codemirror plugin
|
||||||
node $TW5_BUILD_TIDDLYWIKI \
|
node $TW5_BUILD_TIDDLYWIKI \
|
||||||
|
|||||||
69
boot/boot.js
69
boot/boot.js
@@ -641,7 +641,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
|
|||||||
// Call the function and return the exports
|
// Call the function and return the exports
|
||||||
return fn.apply(null,contextValues);
|
return fn.apply(null,contextValues);
|
||||||
};
|
};
|
||||||
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
|
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
|
||||||
/*
|
/*
|
||||||
Run code in a sandbox with only the specified context variables in scope
|
Run code in a sandbox with only the specified context variables in scope
|
||||||
*/
|
*/
|
||||||
@@ -799,12 +799,13 @@ the password, and to encrypt/decrypt a block of text
|
|||||||
$tw.utils.Crypto = function() {
|
$tw.utils.Crypto = function() {
|
||||||
var sjcl = $tw.node ? (global.sjcl || require("./sjcl.js")) : window.sjcl,
|
var sjcl = $tw.node ? (global.sjcl || require("./sjcl.js")) : window.sjcl,
|
||||||
currentPassword = null,
|
currentPassword = null,
|
||||||
callSjcl = function(method,inputText,password) {
|
callSjcl = function(method,inputText,password,options) {
|
||||||
|
options = options || {};
|
||||||
password = password || currentPassword;
|
password = password || currentPassword;
|
||||||
var outputText;
|
var outputText;
|
||||||
try {
|
try {
|
||||||
if(password) {
|
if(password) {
|
||||||
outputText = sjcl[method](password,inputText);
|
outputText = sjcl[method](password,inputText,options);
|
||||||
}
|
}
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
console.log("Crypto error:" + ex);
|
console.log("Crypto error:" + ex);
|
||||||
@@ -830,7 +831,8 @@ $tw.utils.Crypto = function() {
|
|||||||
return !!currentPassword;
|
return !!currentPassword;
|
||||||
}
|
}
|
||||||
this.encrypt = function(text,password) {
|
this.encrypt = function(text,password) {
|
||||||
return callSjcl("encrypt",text,password);
|
// set default ks:256 -- see: http://bitwiseshiftleft.github.io/sjcl/doc/convenience.js.html
|
||||||
|
return callSjcl("encrypt",text,password,{v:1,iter:10000,ks:256,ts:64,mode:"ccm",adata:"",cipher:"aes"});
|
||||||
};
|
};
|
||||||
this.decrypt = function(text,password) {
|
this.decrypt = function(text,password) {
|
||||||
return callSjcl("decrypt",text,password);
|
return callSjcl("decrypt",text,password);
|
||||||
@@ -1433,7 +1435,7 @@ $tw.Wiki = function(options) {
|
|||||||
checkTiddler = function(tiddler,title) {
|
checkTiddler = function(tiddler,title) {
|
||||||
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
|
if(tiddler && tiddler.fields.type === "application/json" && tiddler.fields["plugin-type"] && (!pluginType || tiddler.fields["plugin-type"] === pluginType)) {
|
||||||
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
|
var disablingTiddler = self.getTiddler("$:/config/Plugins/Disabled/" + title);
|
||||||
if(title === "$:/core" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
if(title === "$:/core" || title === "$:/core-server" || !disablingTiddler || (disablingTiddler.fields.text || "").trim() !== "yes") {
|
||||||
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
|
self.unregisterPluginTiddlers(null,[title]); // Unregister the plugin if it's already registered
|
||||||
pluginTiddlers.push(tiddler);
|
pluginTiddlers.push(tiddler);
|
||||||
registeredTitles.push(tiddler.fields.title);
|
registeredTitles.push(tiddler.fields.title);
|
||||||
@@ -1530,7 +1532,8 @@ Define all modules stored in ordinary tiddlers
|
|||||||
*/
|
*/
|
||||||
$tw.Wiki.prototype.defineTiddlerModules = function() {
|
$tw.Wiki.prototype.defineTiddlerModules = function() {
|
||||||
this.each(function(tiddler,title) {
|
this.each(function(tiddler,title) {
|
||||||
if(tiddler.hasField("module-type")) {
|
// Modules in draft tiddlers are disabled
|
||||||
|
if(tiddler.hasField("module-type") && (!tiddler.hasField("draft.of"))) {
|
||||||
switch(tiddler.fields.type) {
|
switch(tiddler.fields.type) {
|
||||||
case "application/javascript":
|
case "application/javascript":
|
||||||
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
|
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
|
||||||
@@ -1557,6 +1560,11 @@ $tw.Wiki.prototype.defineShadowModules = function() {
|
|||||||
this.eachShadow(function(tiddler,title) {
|
this.eachShadow(function(tiddler,title) {
|
||||||
// Don't define the module if it is overidden by an ordinary tiddler
|
// Don't define the module if it is overidden by an ordinary tiddler
|
||||||
if(!self.tiddlerExists(title) && tiddler.hasField("module-type")) {
|
if(!self.tiddlerExists(title) && tiddler.hasField("module-type")) {
|
||||||
|
if(tiddler.hasField("draft.of")) {
|
||||||
|
// Report a fundamental problem
|
||||||
|
console.warn(`TiddlyWiki: Plugins should not contain tiddlers with a 'draft.of' field: ${tiddler.fields.title}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Define the module
|
// Define the module
|
||||||
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
|
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],tiddler.fields.text);
|
||||||
}
|
}
|
||||||
@@ -1905,7 +1913,7 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
|
|||||||
fileSize = fs.statSync(filepath).size,
|
fileSize = fs.statSync(filepath).size,
|
||||||
data;
|
data;
|
||||||
if(fileSize > $tw.config.maxEditFileSize) {
|
if(fileSize > $tw.config.maxEditFileSize) {
|
||||||
data = "File " + filepath + "not loaded because it is too large";
|
data = "File " + filepath + " not loaded because it is too large";
|
||||||
console.log("Warning: " + data);
|
console.log("Warning: " + data);
|
||||||
ext = ".txt";
|
ext = ".txt";
|
||||||
} else {
|
} else {
|
||||||
@@ -1976,22 +1984,41 @@ filepath: pathname of the directory containing the specification file
|
|||||||
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||||
var tiddlers = [];
|
var tiddlers = [];
|
||||||
// Read the specification
|
// Read the specification
|
||||||
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
|
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"), function(e) {
|
||||||
|
console.log("Warning: tiddlywiki.files in " + filepath + " invalid: " + e.message);
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
// Helper to process a file
|
// Helper to process a file
|
||||||
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
|
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
|
||||||
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
|
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
|
||||||
type = (extInfo || {}).type || fields.type || "text/plain",
|
type = (extInfo || {}).type || fields.type || "text/plain",
|
||||||
typeInfo = $tw.config.contentTypeInfo[type] || {},
|
typeInfo = $tw.config.contentTypeInfo[type] || {},
|
||||||
pathname = path.resolve(filepath,filename),
|
pathname = path.resolve(filepath,filename),
|
||||||
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8"),
|
|
||||||
metadata = $tw.loadMetadataForFile(pathname) || {},
|
metadata = $tw.loadMetadataForFile(pathname) || {},
|
||||||
fileTiddlers;
|
fileTooLarge = false,
|
||||||
|
text, fileTiddlers;
|
||||||
|
|
||||||
|
if("_canonical_uri" in fields) {
|
||||||
|
text = "";
|
||||||
|
} else if(fs.statSync(pathname).size > $tw.config.maxEditFileSize) {
|
||||||
|
var msg = "File " + pathname + " not loaded because it is too large";
|
||||||
|
console.log("Warning: " + msg);
|
||||||
|
fileTooLarge = true;
|
||||||
|
text = isTiddlerFile ? msg : "";
|
||||||
|
} else {
|
||||||
|
text = fs.readFileSync(pathname,typeInfo.encoding || "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
if(isTiddlerFile) {
|
if(isTiddlerFile) {
|
||||||
fileTiddlers = $tw.wiki.deserializeTiddlers(path.extname(pathname),text,metadata) || [];
|
fileTiddlers = $tw.wiki.deserializeTiddlers(fileTooLarge ? ".txt" : path.extname(pathname),text,metadata) || [];
|
||||||
} else {
|
} else {
|
||||||
fileTiddlers = [$tw.utils.extend({text: text},metadata)];
|
fileTiddlers = [$tw.utils.extend({text: text},metadata)];
|
||||||
}
|
}
|
||||||
var combinedFields = $tw.utils.extend({},fields,metadata);
|
var combinedFields = $tw.utils.extend({},fields,metadata);
|
||||||
|
if(fileTooLarge && isTiddlerFile) {
|
||||||
|
delete combinedFields.type; // type altered
|
||||||
|
}
|
||||||
$tw.utils.each(fileTiddlers,function(tiddler) {
|
$tw.utils.each(fileTiddlers,function(tiddler) {
|
||||||
$tw.utils.each(combinedFields,function(fieldInfo,name) {
|
$tw.utils.each(combinedFields,function(fieldInfo,name) {
|
||||||
if(typeof fieldInfo === "string" || $tw.utils.isArray(fieldInfo)) {
|
if(typeof fieldInfo === "string" || $tw.utils.isArray(fieldInfo)) {
|
||||||
@@ -2066,6 +2093,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
|||||||
} else if(tidInfo.suffix) {
|
} else if(tidInfo.suffix) {
|
||||||
tidInfo.fields.text = {suffix: tidInfo.suffix};
|
tidInfo.fields.text = {suffix: tidInfo.suffix};
|
||||||
}
|
}
|
||||||
|
tidInfo.fields = tidInfo.fields || {};
|
||||||
processFile(tidInfo.file,tidInfo.isTiddlerFile,tidInfo.fields);
|
processFile(tidInfo.file,tidInfo.isTiddlerFile,tidInfo.fields);
|
||||||
});
|
});
|
||||||
// Process any listed directories
|
// Process any listed directories
|
||||||
@@ -2087,6 +2115,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
|||||||
var thisPath = path.relative(filepath, files[t]),
|
var thisPath = path.relative(filepath, files[t]),
|
||||||
filename = path.basename(thisPath);
|
filename = path.basename(thisPath);
|
||||||
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
|
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
|
||||||
|
dirSpec.fields = dirSpec.fields || {};
|
||||||
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
|
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2350,6 +2379,7 @@ $tw.loadTiddlersNode = function() {
|
|||||||
});
|
});
|
||||||
// Load the core tiddlers
|
// Load the core tiddlers
|
||||||
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
|
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
|
||||||
|
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.coreServerPath));
|
||||||
// Load any extra plugins
|
// Load any extra plugins
|
||||||
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
||||||
if(name.charAt(0) === "+") { // Relative path to plugin
|
if(name.charAt(0) === "+") { // Relative path to plugin
|
||||||
@@ -2423,6 +2453,7 @@ $tw.boot.initStartup = function(options) {
|
|||||||
// System paths and filenames
|
// System paths and filenames
|
||||||
$tw.boot.bootPath = options.bootPath || path.dirname(module.filename);
|
$tw.boot.bootPath = options.bootPath || path.dirname(module.filename);
|
||||||
$tw.boot.corePath = path.resolve($tw.boot.bootPath,"../core");
|
$tw.boot.corePath = path.resolve($tw.boot.bootPath,"../core");
|
||||||
|
$tw.boot.coreServerPath = path.resolve($tw.boot.bootPath,"../core-server");
|
||||||
// If there's no arguments then default to `--help`
|
// If there's no arguments then default to `--help`
|
||||||
if($tw.boot.argv.length === 0) {
|
if($tw.boot.argv.length === 0) {
|
||||||
$tw.boot.argv = ["--help"];
|
$tw.boot.argv = ["--help"];
|
||||||
@@ -2547,10 +2578,10 @@ $tw.boot.execStartup = function(options){
|
|||||||
if($tw.safeMode) {
|
if($tw.safeMode) {
|
||||||
$tw.wiki.processSafeMode();
|
$tw.wiki.processSafeMode();
|
||||||
}
|
}
|
||||||
// Register typed modules from the tiddlers we've just loaded
|
// Register typed modules from the tiddlers we've just loaded and any modules within plugins
|
||||||
$tw.wiki.defineTiddlerModules();
|
// Tiddlers should appear last so that they may overwrite shadows during module registration
|
||||||
// And any modules within plugins
|
|
||||||
$tw.wiki.defineShadowModules();
|
$tw.wiki.defineShadowModules();
|
||||||
|
$tw.wiki.defineTiddlerModules();
|
||||||
// Make sure the crypto state tiddler is up to date
|
// Make sure the crypto state tiddler is up to date
|
||||||
if($tw.crypto) {
|
if($tw.crypto) {
|
||||||
$tw.crypto.updateCryptoStateTiddler();
|
$tw.crypto.updateCryptoStateTiddler();
|
||||||
@@ -2619,11 +2650,13 @@ $tw.boot.executeNextStartupTask = function(callback) {
|
|||||||
$tw.boot.log(s.join(" "));
|
$tw.boot.log(s.join(" "));
|
||||||
// Execute task
|
// Execute task
|
||||||
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
|
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
|
||||||
task.startup();
|
const thenable = task.startup();
|
||||||
if(task.name) {
|
if(thenable && typeof thenable.then === "function"){
|
||||||
$tw.boot.executedStartupModules[task.name] = true;
|
thenable.then(asyncTaskCallback);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return asyncTaskCallback();
|
||||||
}
|
}
|
||||||
return $tw.boot.executeNextStartupTask(callback);
|
|
||||||
} else {
|
} else {
|
||||||
task.startup(asyncTaskCallback);
|
task.startup(asyncTaskCallback);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ talk.tiddlywiki.org: jeremyruston
|
|||||||
github: Jermolene
|
github: Jermolene
|
||||||
linkedin: www.linkedin.com/in/jermy
|
linkedin: www.linkedin.com/in/jermy
|
||||||
flickr: www.flickr.com/photos/jermy/
|
flickr: www.flickr.com/photos/jermy/
|
||||||
|
bluesky: https://bsky.app/profile/jermolene.bsky.social
|
||||||
homepage: jermolene.com
|
homepage: jermolene.com
|
||||||
email: jeremy@jermolene.com
|
email: jeremy@jermolene.com
|
||||||
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAtAAEBAAMAAAAAAAAAAAAAAAAHBgIEBQEBAQEBAAAAAAAAAAAAAAAAAgQBBf/aAAwDAQACEAMQAAAANF4uTuPRhD2nBLnUiJvKM0DtMKy//8QAKxAAAgIBAwMDAQkAAAAAAAAAAQIDBBEABRITITEiMkFxFEJRUmFicoGR/9oACAEBAAE/AInTA6gUGP4ZOQbW1bPsmyUq1q+gmvFPUzZPDkPamtwqU75ks04JakroVcg5RwRjg66NUx25KbzqJYyMngfqSuq0M3NZYIebJIvZozIvI/iNPcp/aalSdJXsS4VcKeIzlvU3jVTcYLNiaGISrjkhWQYDfQ63pYAzCDBsOiu7Dsx4EHH6r2w2ttimjd2IsNErhhJHKI04/uzqxuCxpBYVVWKSHqwMyMSQ33SB7dUJFmlkMYRgnqZgCMf7rf8AeEt3A9YOhjXAb2k8u7dtT1RZeOtXmYxiOPj4ZWY/lb51skqUNnNW/wBNzC7IpB6gQeeB/jq/fqGOaLbowuYn5MAQOw8LjW5Vmeo0qIsqYLLKjHIZmwv9fB1//8QAHxEAAQMEAwEAAAAAAAAAAAAAEQABAgMSIWExMkFR/9oACAECAQE/AD9iTy2lJmHUB8BVKM4SNSOj46a29saX/8QAHREAAgICAwEAAAAAAAAAAAAAAQIAAwQRITGBkf/aAAgBAwEBPwDHpFpJZtamVSiBWT2Yt7hmCDsb+TKtsKqpGg3M/9k=
|
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAtAAEBAAMAAAAAAAAAAAAAAAAHBgIEBQEBAQEBAAAAAAAAAAAAAAAAAgQBBf/aAAwDAQACEAMQAAAANF4uTuPRhD2nBLnUiJvKM0DtMKy//8QAKxAAAgIBAwMDAQkAAAAAAAAAAQIDBBEABRITITEiMkFxFEJRUmFicoGR/9oACAEBAAE/AInTA6gUGP4ZOQbW1bPsmyUq1q+gmvFPUzZPDkPamtwqU75ks04JakroVcg5RwRjg66NUx25KbzqJYyMngfqSuq0M3NZYIebJIvZozIvI/iNPcp/aalSdJXsS4VcKeIzlvU3jVTcYLNiaGISrjkhWQYDfQ63pYAzCDBsOiu7Dsx4EHH6r2w2ttimjd2IsNErhhJHKI04/uzqxuCxpBYVVWKSHqwMyMSQ33SB7dUJFmlkMYRgnqZgCMf7rf8AeEt3A9YOhjXAb2k8u7dtT1RZeOtXmYxiOPj4ZWY/lb51skqUNnNW/wBNzC7IpB6gQeeB/jq/fqGOaLbowuYn5MAQOw8LjW5Vmeo0qIsqYLLKjHIZmwv9fB1//8QAHxEAAQMEAwEAAAAAAAAAAAAAEQABAgMSIWExMkFR/9oACAECAQE/AD9iTy2lJmHUB8BVKM4SNSOj46a29saX/8QAHREAAgICAwEAAAAAAAAAAAAAAQIAAwQRITGBkf/aAAgBAwEBPwDHpFpJZtamVSiBWT2Yt7hmCDsb+TKtsKqpGg3M/9k=
|
||||||
|
|||||||
@@ -99,16 +99,18 @@ Commander.prototype.executeNextCommand = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(command.info.synchronous) {
|
if(command.info.synchronous) {
|
||||||
// Synchronous command
|
// Synchronous command (await thenables)
|
||||||
c = new command.Command(params,this);
|
c = new command.Command(params,this);
|
||||||
err = c.execute();
|
err = c.execute();
|
||||||
if(err) {
|
if(err && typeof err.then === "function") {
|
||||||
|
err.then(e => { e ? this.callback(e) : this.executeNextCommand(); });
|
||||||
|
} else if(err) {
|
||||||
this.callback(err);
|
this.callback(err);
|
||||||
} else {
|
} else {
|
||||||
this.executeNextCommand();
|
this.executeNextCommand();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Asynchronous command
|
// Asynchronous command (await thenables)
|
||||||
c = new command.Command(params,this,function(err) {
|
c = new command.Command(params,this,function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
self.callback(err);
|
self.callback(err);
|
||||||
@@ -117,7 +119,9 @@ Commander.prototype.executeNextCommand = function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
err = c.execute();
|
err = c.execute();
|
||||||
if(err) {
|
if(err && typeof err.then === "function") {
|
||||||
|
err.then(e => { if(e) this.callback(e); });
|
||||||
|
} else if(err) {
|
||||||
this.callback(err);
|
this.callback(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,6 +76,7 @@ WikiFolderMaker.prototype.tiddlersToIgnore = [
|
|||||||
"$:/boot/boot.js",
|
"$:/boot/boot.js",
|
||||||
"$:/boot/bootprefix.js",
|
"$:/boot/bootprefix.js",
|
||||||
"$:/core",
|
"$:/core",
|
||||||
|
"$:/core-server",
|
||||||
"$:/library/sjcl.js",
|
"$:/library/sjcl.js",
|
||||||
"$:/temp/info-plugin"
|
"$:/temp/info-plugin"
|
||||||
];
|
];
|
||||||
11
core-server/plugin.info
Normal file
11
core-server/plugin.info
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"title": "$:/core-server",
|
||||||
|
"name": "Core Server Components",
|
||||||
|
"description": "TiddlyWiki5 core server components",
|
||||||
|
"author": "JeremyRuston",
|
||||||
|
"core-version": ">=5.0.0",
|
||||||
|
"platform": "server",
|
||||||
|
"plugin-priority": "0",
|
||||||
|
"list": "readme",
|
||||||
|
"stability": "STABILITY_2_STABLE"
|
||||||
|
}
|
||||||
7
core-server/readme.tid
Normal file
7
core-server/readme.tid
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
title: $:/core-server/readme
|
||||||
|
|
||||||
|
This plugin contains TiddlyWiki's core components that are only needed on the server, comprising:
|
||||||
|
|
||||||
|
* Commands
|
||||||
|
* HTTP server code
|
||||||
|
* Utility functions for server
|
||||||
@@ -8,10 +8,14 @@ DELETE /recipes/default/tiddlers/:title
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "DELETE";
|
exports.methods = ["DELETE"];
|
||||||
|
|
||||||
exports.path = /^\/bags\/default\/tiddlers\/(.+)$/;
|
exports.path = /^\/bags\/default\/tiddlers\/(.+)$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]);
|
var title = $tw.utils.decodeURIComponentSafe(state.params[0]);
|
||||||
state.wiki.deleteTiddler(title);
|
state.wiki.deleteTiddler(title);
|
||||||
@@ -8,10 +8,14 @@ GET /favicon.ico
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/favicon.ico$/;
|
exports.path = /^\/favicon.ico$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var buffer = state.wiki.getTiddlerText("$:/favicon.ico","");
|
var buffer = state.wiki.getTiddlerText("$:/favicon.ico","");
|
||||||
state.sendResponse(200,{"Content-Type": "image/x-icon"},buffer,"base64");
|
state.sendResponse(200,{"Content-Type": "image/x-icon"},buffer,"base64");
|
||||||
73
core-server/server/routes/get-file.js
Normal file
73
core-server/server/routes/get-file.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/server/routes/get-file.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: route
|
||||||
|
|
||||||
|
GET /files/:filepath
|
||||||
|
|
||||||
|
\*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
|
exports.path = /^\/files\/(.+)$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.handler = function(request,response,state) {
|
||||||
|
var path = require("path"),
|
||||||
|
fs = require("fs"),
|
||||||
|
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
|
baseFilename = path.resolve(state.boot.wikiPath,"files"),
|
||||||
|
filename = path.resolve(baseFilename,suppliedFilename),
|
||||||
|
extension = path.extname(filename);
|
||||||
|
// Check that the filename is inside the wiki files folder
|
||||||
|
if(path.relative(baseFilename,filename).indexOf("..") === 0) {
|
||||||
|
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
|
||||||
|
}
|
||||||
|
fs.stat(filename, function(err, stats) {
|
||||||
|
if(err) {
|
||||||
|
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
|
||||||
|
} else {
|
||||||
|
var type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream"),
|
||||||
|
responseHeaders = {
|
||||||
|
"Content-Type": type,
|
||||||
|
"Accept-Ranges": "bytes"
|
||||||
|
};
|
||||||
|
var rangeHeader = request.headers.range,
|
||||||
|
stream;
|
||||||
|
if(rangeHeader) {
|
||||||
|
// Handle range requests
|
||||||
|
var parts = rangeHeader.replace(/bytes=/, "").split("-"),
|
||||||
|
start = parseInt(parts[0], 10),
|
||||||
|
end = parts[1] ? parseInt(parts[1], 10) : stats.size - 1;
|
||||||
|
// Validate start and end
|
||||||
|
if(isNaN(start) || isNaN(end) || start < 0 || end < start || end >= stats.size) {
|
||||||
|
responseHeaders["Content-Range"] = "bytes */" + stats.size;
|
||||||
|
return response.writeHead(416, responseHeaders).end();
|
||||||
|
}
|
||||||
|
var chunksize = (end - start) + 1;
|
||||||
|
responseHeaders["Content-Range"] = "bytes " + start + "-" + end + "/" + stats.size;
|
||||||
|
responseHeaders["Content-Length"] = chunksize;
|
||||||
|
response.writeHead(206, responseHeaders);
|
||||||
|
stream = fs.createReadStream(filename, {start: start, end: end});
|
||||||
|
} else {
|
||||||
|
responseHeaders["Content-Length"] = stats.size;
|
||||||
|
response.writeHead(200, responseHeaders);
|
||||||
|
stream = fs.createReadStream(filename);
|
||||||
|
}
|
||||||
|
// Common stream error handling
|
||||||
|
stream.on("error", function(err) {
|
||||||
|
if(!response.headersSent) {
|
||||||
|
response.writeHead(500, {"Content-Type": "text/plain"});
|
||||||
|
response.end("Read error");
|
||||||
|
} else {
|
||||||
|
response.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stream.pipe(response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -8,10 +8,14 @@ GET /
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/$/;
|
exports.path = /^\/$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler")),
|
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler")),
|
||||||
responseHeaders = {
|
responseHeaders = {
|
||||||
@@ -8,10 +8,14 @@ GET /login-basic -- force a Basic Authentication challenge
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/login-basic$/;
|
exports.path = /^\/login-basic$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
if(!state.authenticatedUsername) {
|
if(!state.authenticatedUsername) {
|
||||||
// Challenge if there's no username
|
// Challenge if there's no username
|
||||||
@@ -8,10 +8,14 @@ GET /status
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/status$/;
|
exports.path = /^\/status$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var text = JSON.stringify({
|
var text = JSON.stringify({
|
||||||
username: state.authenticatedUsername || state.server.get("anon-username") || "",
|
username: state.authenticatedUsername || state.server.get("anon-username") || "",
|
||||||
@@ -8,10 +8,14 @@ GET /:title
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/([^\/]+)$/;
|
exports.path = /^\/([^\/]+)$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
tiddler = state.wiki.getTiddler(title);
|
tiddler = state.wiki.getTiddler(title);
|
||||||
@@ -8,10 +8,14 @@ GET /recipes/default/tiddlers/:title
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
tiddler = state.wiki.getTiddler(title),
|
tiddler = state.wiki.getTiddler(title),
|
||||||
@@ -10,10 +10,14 @@ GET /recipes/default/tiddlers.json?filter=<filter>
|
|||||||
|
|
||||||
var DEFAULT_FILTER = "[all[tiddlers]!is[system]sort[title]]";
|
var DEFAULT_FILTER = "[all[tiddlers]!is[system]sort[title]]";
|
||||||
|
|
||||||
exports.method = "GET";
|
exports.methods = ["GET"];
|
||||||
|
|
||||||
exports.path = /^\/recipes\/default\/tiddlers.json$/;
|
exports.path = /^\/recipes\/default\/tiddlers.json$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var filter = state.queryParameters.filter || DEFAULT_FILTER;
|
var filter = state.queryParameters.filter || DEFAULT_FILTER;
|
||||||
if(state.wiki.getTiddlerText("$:/config/Server/AllowAllExternalFilters") !== "yes") {
|
if(state.wiki.getTiddlerText("$:/config/Server/AllowAllExternalFilters") !== "yes") {
|
||||||
@@ -8,10 +8,14 @@ PUT /recipes/default/tiddlers/:title
|
|||||||
\*/
|
\*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.method = "PUT";
|
exports.methods = ["PUT"];
|
||||||
|
|
||||||
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
||||||
|
|
||||||
|
exports.info = {
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
exports.handler = function(request,response,state) {
|
||||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
fields = $tw.utils.parseJSONSafe(state.data);
|
fields = $tw.utils.parseJSONSafe(state.data);
|
||||||
@@ -74,6 +74,11 @@ function Server(options) {
|
|||||||
// console.log("Loading server route " + title);
|
// console.log("Loading server route " + title);
|
||||||
self.addRoute(routeDefinition);
|
self.addRoute(routeDefinition);
|
||||||
});
|
});
|
||||||
|
this.routes.sort((a, b) => {
|
||||||
|
const priorityA = a.info?.priority ?? 100,
|
||||||
|
priorityB = b.info?.priority ?? 100;
|
||||||
|
return priorityB - priorityA;
|
||||||
|
});
|
||||||
// Initialise the http vs https
|
// Initialise the http vs https
|
||||||
this.listenOptions = null;
|
this.listenOptions = null;
|
||||||
this.protocol = "http";
|
this.protocol = "http";
|
||||||
@@ -217,7 +222,7 @@ Server.prototype.findMatchingRoute = function(request,state) {
|
|||||||
} else {
|
} else {
|
||||||
match = potentialRoute.path.exec(pathname);
|
match = potentialRoute.path.exec(pathname);
|
||||||
}
|
}
|
||||||
if(match && request.method === potentialRoute.method) {
|
if(match && (potentialRoute.methods?.includes(request.method) || potentialRoute.method === request.method)) {
|
||||||
state.params = [];
|
state.params = [];
|
||||||
for(var p=1; p<match.length; p++) {
|
for(var p=1; p<match.length; p++) {
|
||||||
state.params.push(match[p]);
|
state.params.push(match[p]);
|
||||||
@@ -147,7 +147,7 @@ Settings/AutoSave/Disabled/Description: Do not save changes automatically
|
|||||||
Settings/AutoSave/Enabled/Description: Save changes automatically
|
Settings/AutoSave/Enabled/Description: Save changes automatically
|
||||||
Settings/AutoSave/Hint: Attempt to automatically save changes during editing when using a supporting saver
|
Settings/AutoSave/Hint: Attempt to automatically save changes during editing when using a supporting saver
|
||||||
Settings/CamelCase/Caption: Camel Case Wiki Links
|
Settings/CamelCase/Caption: Camel Case Wiki Links
|
||||||
Settings/CamelCase/Hint: You can globally disable automatic linking of ~CamelCase phrases. Requires reload to take effect
|
Settings/CamelCase/Hint: Requires reload to take effect
|
||||||
Settings/CamelCase/Description: Enable automatic ~CamelCase linking
|
Settings/CamelCase/Description: Enable automatic ~CamelCase linking
|
||||||
Settings/Caption: Settings
|
Settings/Caption: Settings
|
||||||
Settings/EditorToolbar/Caption: Editor Toolbar
|
Settings/EditorToolbar/Caption: Editor Toolbar
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ function FramedEngine(options) {
|
|||||||
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette");
|
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette");
|
||||||
var colorScheme = (this.widget.wiki.getTiddler(paletteTitle) || {fields: {}}).fields["color-scheme"] || "light";
|
var colorScheme = (this.widget.wiki.getTiddler(paletteTitle) || {fields: {}}).fields["color-scheme"] || "light";
|
||||||
this.iframeDoc.open();
|
this.iframeDoc.open();
|
||||||
this.iframeDoc.write("<meta name='color-scheme' content='" + colorScheme + "'>");
|
this.iframeDoc.write("<!DOCTYPE html><html><head><meta name='color-scheme' content='" + colorScheme + "'></head><body></body></html>");
|
||||||
this.iframeDoc.close();
|
this.iframeDoc.close();
|
||||||
// Style the iframe
|
// Style the iframe
|
||||||
this.iframeNode.className = this.dummyTextArea.className;
|
this.iframeNode.className = this.dummyTextArea.className;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
|||||||
// Fix height
|
// Fix height
|
||||||
this.engine.fixHeight();
|
this.engine.fixHeight();
|
||||||
// Focus if required
|
// Focus if required
|
||||||
if(this.editFocus === "true" || this.editFocus === "yes") {
|
if($tw.browser && (this.editFocus === "true" || this.editFocus === "yes") && !$tw.utils.hasClass(this.parentDomNode.ownerDocument.activeElement,"tc-keep-focus")) {
|
||||||
this.engine.focus();
|
this.engine.focus();
|
||||||
}
|
}
|
||||||
// Add widget message listeners
|
// Add widget message listeners
|
||||||
|
|||||||
@@ -217,6 +217,10 @@ function makeNumericReducingOperator(fnCalc,initialValue,fnFinal) {
|
|||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
result.push($tw.utils.parseNumber(title));
|
result.push($tw.utils.parseNumber(title));
|
||||||
});
|
});
|
||||||
|
// We return an empty array if there are no input titles
|
||||||
|
if(result.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
var value = result.reduce(function(accumulator,currentValue) {
|
var value = result.reduce(function(accumulator,currentValue) {
|
||||||
return fnCalc(accumulator,currentValue);
|
return fnCalc(accumulator,currentValue);
|
||||||
},initialValue);
|
},initialValue);
|
||||||
|
|||||||
86
core/modules/info/dimensions.js
Normal file
86
core/modules/info/dimensions.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/info/windowdimensions.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: info
|
||||||
|
\*/
|
||||||
|
|
||||||
|
exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
|
||||||
|
if(!$tw.browser) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class WindowDimensionsTracker {
|
||||||
|
constructor(updateCallback) {
|
||||||
|
this.updateCallback = updateCallback;
|
||||||
|
this.resizeHandlers = new Map();
|
||||||
|
this.dimensionsInfo = [
|
||||||
|
["outer/width", win => win.outerWidth],
|
||||||
|
["outer/height", win => win.outerHeight],
|
||||||
|
["inner/width", win => win.innerWidth],
|
||||||
|
["inner/height", win => win.innerHeight],
|
||||||
|
["client/width", win => win.document.documentElement.clientWidth],
|
||||||
|
["client/height", win => win.document.documentElement.clientHeight]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTiddlers(win,windowId) {
|
||||||
|
const prefix = `$:/info/browser/window/${windowId}/`;
|
||||||
|
return this.dimensionsInfo.map(([suffix, getter]) => ({
|
||||||
|
title: prefix + suffix,
|
||||||
|
text: String(getter(win))
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTiddlers(windowId) {
|
||||||
|
const prefix = `$:/info/browser/window/${windowId}/`,
|
||||||
|
deletions = this.dimensionsInfo.map(([suffix]) => prefix + suffix);
|
||||||
|
this.updateCallback([], deletions);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUpdateHandler(win,windowId) {
|
||||||
|
let scheduled = false;
|
||||||
|
return () => {
|
||||||
|
if(!scheduled) {
|
||||||
|
scheduled = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
this.updateCallback(this.buildTiddlers(win,windowId), []);
|
||||||
|
scheduled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
trackWindow(win,windowId) {
|
||||||
|
const handler = this.getUpdateHandler(win, windowId);
|
||||||
|
handler(); // initial update
|
||||||
|
win.addEventListener("resize",handler,{passive:true});
|
||||||
|
this.resizeHandlers.set(windowId,{win, handler});
|
||||||
|
}
|
||||||
|
|
||||||
|
untrackWindow(windowId) {
|
||||||
|
const entry = this.resizeHandlers.get(windowId);
|
||||||
|
if(entry) {
|
||||||
|
entry.win.removeEventListener("resize", entry.handler);
|
||||||
|
this.resizeHandlers.delete(windowId);
|
||||||
|
}
|
||||||
|
this.clearTiddlers(windowId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tracker = new WindowDimensionsTracker(updateInfoTiddlersCallback);
|
||||||
|
|
||||||
|
// Track main window
|
||||||
|
tracker.trackWindow(window,"system/main");
|
||||||
|
|
||||||
|
// Hook into event bus for user windows
|
||||||
|
if($tw.eventBus) {
|
||||||
|
$tw.eventBus.on("window:opened", ({window: win, windowID}) => {
|
||||||
|
tracker.trackWindow(win, "user/" + windowID);
|
||||||
|
});
|
||||||
|
$tw.eventBus.on("window:closed", ({windowID}) => {
|
||||||
|
tracker.untrackWindow("user/" + windowID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
@@ -7,23 +7,34 @@ The audio parser parses an audio tiddler into an embeddable HTML element
|
|||||||
|
|
||||||
\*/
|
\*/
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var AudioParser = function(type,text,options) {
|
var AudioParser = function(type,text,options) {
|
||||||
var element = {
|
var element = {
|
||||||
type: "element",
|
type: "element",
|
||||||
tag: "audio",
|
tag: "$audio", // Using $audio to enable widget interception
|
||||||
attributes: {
|
attributes: {
|
||||||
controls: {type: "string", value: "controls"},
|
controls: {type: "string", value: "controls"},
|
||||||
style: {type: "string", value: "width: 100%; object-fit: contain"}
|
style: {type: "string", value: "width: 100%; object-fit: contain"}
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
src;
|
|
||||||
|
// Pass through source information
|
||||||
if(options._canonical_uri) {
|
if(options._canonical_uri) {
|
||||||
element.attributes.src = {type: "string", value: options._canonical_uri};
|
element.attributes.src = {type: "string", value: options._canonical_uri};
|
||||||
|
element.attributes.type = {type: "string", value: type};
|
||||||
} else if(text) {
|
} else if(text) {
|
||||||
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
|
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
|
||||||
|
element.attributes.type = {type: "string", value: type};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pass through tiddler title if available
|
||||||
|
if(options.title) {
|
||||||
|
element.attributes.tiddler = {type: "string", value: options.title};
|
||||||
|
}
|
||||||
|
|
||||||
this.tree = [element];
|
this.tree = [element];
|
||||||
this.source = text;
|
this.source = text;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -33,3 +44,4 @@ exports["audio/ogg"] = AudioParser;
|
|||||||
exports["audio/mpeg"] = AudioParser;
|
exports["audio/mpeg"] = AudioParser;
|
||||||
exports["audio/mp3"] = AudioParser;
|
exports["audio/mp3"] = AudioParser;
|
||||||
exports["audio/mp4"] = AudioParser;
|
exports["audio/mp4"] = AudioParser;
|
||||||
|
|
||||||
@@ -82,6 +82,7 @@ exports.parseTokenString = function(source,pos,token) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
|
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
|
||||||
|
Use the "Y" (sticky) flag to avoid searching the entire rest of the string
|
||||||
*/
|
*/
|
||||||
exports.parseTokenRegExp = function(source,pos,reToken) {
|
exports.parseTokenRegExp = function(source,pos,reToken) {
|
||||||
var node = {
|
var node = {
|
||||||
@@ -172,7 +173,7 @@ exports.parseMacroParameter = function(source,pos) {
|
|||||||
start: pos
|
start: pos
|
||||||
};
|
};
|
||||||
// Define our regexp
|
// Define our regexp
|
||||||
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/g;
|
const reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/y;
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||||
// Look for the parameter
|
// Look for the parameter
|
||||||
@@ -240,7 +241,7 @@ exports.parseMacroInvocation = function(source,pos) {
|
|||||||
params: []
|
params: []
|
||||||
};
|
};
|
||||||
// Define our regexps
|
// Define our regexps
|
||||||
var reMacroName = /([^\s>"'=]+)/g;
|
const reMacroName = /([^\s>"'=]+)/y;
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||||
// Look for a double less than sign
|
// Look for a double less than sign
|
||||||
@@ -277,7 +278,7 @@ exports.parseFilterVariable = function(source) {
|
|||||||
params: [],
|
params: [],
|
||||||
},
|
},
|
||||||
pos = 0,
|
pos = 0,
|
||||||
reName = /([^\s"']+)/g;
|
reName = /([^\s"']+)/y;
|
||||||
// If there is no whitespace or it is an empty string then there are no macro parameters
|
// If there is no whitespace or it is an empty string then there are no macro parameters
|
||||||
if(/^\S*$/.test(source)) {
|
if(/^\S*$/.test(source)) {
|
||||||
node.name = source;
|
node.name = source;
|
||||||
@@ -302,11 +303,11 @@ exports.parseAttribute = function(source,pos) {
|
|||||||
start: pos
|
start: pos
|
||||||
};
|
};
|
||||||
// Define our regexps
|
// Define our regexps
|
||||||
var reAttributeName = /([^\/\s>"'`=]+)/g,
|
const reAttributeName = /([^\/\s>"'`=]+)/y,
|
||||||
reUnquotedAttribute = /([^\/\s<>"'`=]+)/g,
|
reUnquotedAttribute = /([^\/\s<>"'`=]+)/y,
|
||||||
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g,
|
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/y,
|
||||||
reIndirectValue = /\{\{([^\}]+)\}\}/g,
|
reIndirectValue = /\{\{([^\}]+)\}\}/y,
|
||||||
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g;
|
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/y;
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||||
// Get the attribute name
|
// Get the attribute name
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ exports.parse = function() {
|
|||||||
// Return the classed span
|
// Return the classed span
|
||||||
return [{
|
return [{
|
||||||
type: "element",
|
type: "element",
|
||||||
tag: "strike",
|
tag: "s",
|
||||||
children: tree
|
children: tree
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ exports.parse = function() {
|
|||||||
// Advance the parser position to past the tag
|
// Advance the parser position to past the tag
|
||||||
this.parser.pos = tag.end;
|
this.parser.pos = tag.end;
|
||||||
// Check for an immediately following double linebreak
|
// Check for an immediately following double linebreak
|
||||||
var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g);
|
var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/y);
|
||||||
// Set whether we're in block mode
|
// Set whether we're in block mode
|
||||||
tag.isBlock = this.is.block || hasLineBreak;
|
tag.isBlock = this.is.block || hasLineBreak;
|
||||||
// Parse the body if we need to
|
// Parse the body if we need to
|
||||||
@@ -100,7 +100,7 @@ exports.parseTag = function(source,pos,options) {
|
|||||||
orderedAttributes: []
|
orderedAttributes: []
|
||||||
};
|
};
|
||||||
// Define our regexps
|
// Define our regexps
|
||||||
var reTagName = /([a-zA-Z0-9\-\$\.]+)/g;
|
const reTagName = /([a-zA-Z0-9\-\$\.]+)/y;
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||||
// Look for a less than sign
|
// Look for a less than sign
|
||||||
@@ -148,7 +148,7 @@ exports.parseTag = function(source,pos,options) {
|
|||||||
pos = token.end;
|
pos = token.end;
|
||||||
// Check for a required line break
|
// Check for a required line break
|
||||||
if(options.requireLineBreak) {
|
if(options.requireLineBreak) {
|
||||||
token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g);
|
token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/y);
|
||||||
if(!token) {
|
if(!token) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ exports.parseImage = function(source,pos) {
|
|||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||||
// Get the source up to the terminating `]]`
|
// Get the source up to the terminating `]]`
|
||||||
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/g);
|
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/y);
|
||||||
if(!token) {
|
if(!token) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,27 @@ exports.init = function(parser) {
|
|||||||
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}(?:\r?\n|$)/mg;
|
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}(?:\r?\n|$)/mg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reject the match if we don't have a template or text reference
|
||||||
|
*/
|
||||||
|
exports.findNextMatch = function(startPos) {
|
||||||
|
this.matchRegExp.lastIndex = startPos;
|
||||||
|
this.match = this.matchRegExp.exec(this.parser.source);
|
||||||
|
if(this.match) {
|
||||||
|
var template = $tw.utils.trim(this.match[2]),
|
||||||
|
textRef = $tw.utils.trim(this.match[1]);
|
||||||
|
// Bail if we don't have a template or text reference
|
||||||
|
if(!template && !textRef) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return this.match.index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this.match ? this.match.index : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the match
|
// Move past the match
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
this.parser.pos = this.matchRegExp.lastIndex;
|
||||||
|
|||||||
@@ -23,6 +23,27 @@ exports.init = function(parser) {
|
|||||||
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}/mg;
|
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}/mg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reject the match if we don't have a template or text reference
|
||||||
|
*/
|
||||||
|
exports.findNextMatch = function(startPos) {
|
||||||
|
this.matchRegExp.lastIndex = startPos;
|
||||||
|
this.match = this.matchRegExp.exec(this.parser.source);
|
||||||
|
if(this.match) {
|
||||||
|
var template = $tw.utils.trim(this.match[2]),
|
||||||
|
textRef = $tw.utils.trim(this.match[1]);
|
||||||
|
// Bail if we don't have a template or text reference
|
||||||
|
if(!template && !textRef) {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return this.match.index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this.match ? this.match.index : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the match
|
// Move past the match
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
this.parser.pos = this.matchRegExp.lastIndex;
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ DownloadSaver.prototype.save = function(text,method,callback,options) {
|
|||||||
}
|
}
|
||||||
// Set up the link
|
// Set up the link
|
||||||
var link = document.createElement("a");
|
var link = document.createElement("a");
|
||||||
if(Blob !== undefined) {
|
// We prefer Blobs if they're available, unless we're dealing with a tiddler type declaring itself full of base64 encoded content.
|
||||||
|
// Then we use data urls, because browsers will know to decode the stream and download the actual binary file as intended.
|
||||||
|
if(Blob !== undefined && !type.includes(";base64")) {
|
||||||
var blob = new Blob([text], {type: type});
|
var blob = new Blob([text], {type: type});
|
||||||
link.setAttribute("href", URL.createObjectURL(blob));
|
link.setAttribute("href", URL.createObjectURL(blob));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
66
core/modules/savers/postmessage.js
Normal file
66
core/modules/savers/postmessage.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/savers/postmessage.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: saver
|
||||||
|
|
||||||
|
Handles saving changes via window.postMessage() to the window.parent
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Select the appropriate saver module and set it up
|
||||||
|
*/
|
||||||
|
var PostMessageSaver = function(wiki) {
|
||||||
|
this.publisher = new $tw.utils.BrowserMessagingPublisher({type: "SAVE"});
|
||||||
|
};
|
||||||
|
|
||||||
|
PostMessageSaver.prototype.save = function(text,method,callback,options) {
|
||||||
|
// Fail if the publisher hasn't been fully initialised
|
||||||
|
if(!this.publisher.canSend()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Send the save request
|
||||||
|
this.publisher.send({
|
||||||
|
verb: "SAVE",
|
||||||
|
body: text
|
||||||
|
},function(err) {
|
||||||
|
if(err) {
|
||||||
|
callback("PostMessageSaver Error: " + err);
|
||||||
|
} else {
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Indicate that we handled the save
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Information about this saver
|
||||||
|
*/
|
||||||
|
PostMessageSaver.prototype.info = {
|
||||||
|
name: "postmessage",
|
||||||
|
capabilities: ["save", "autosave"],
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Static method that returns true if this saver is capable of working
|
||||||
|
*/
|
||||||
|
exports.canSave = function(wiki) {
|
||||||
|
// Provisionally say that we can save
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create an instance of this saver
|
||||||
|
*/
|
||||||
|
exports.create = function(wiki) {
|
||||||
|
return new PostMessageSaver(wiki);
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*\
|
|
||||||
title: $:/core/modules/server/routes/get-file.js
|
|
||||||
type: application/javascript
|
|
||||||
module-type: route
|
|
||||||
|
|
||||||
GET /files/:filepath
|
|
||||||
|
|
||||||
\*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
exports.method = "GET";
|
|
||||||
|
|
||||||
exports.path = /^\/files\/(.+)$/;
|
|
||||||
|
|
||||||
exports.handler = function(request,response,state) {
|
|
||||||
var path = require("path"),
|
|
||||||
fs = require("fs"),
|
|
||||||
util = require("util"),
|
|
||||||
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
|
||||||
baseFilename = path.resolve(state.boot.wikiPath,"files"),
|
|
||||||
filename = path.resolve(baseFilename,suppliedFilename),
|
|
||||||
extension = path.extname(filename);
|
|
||||||
// Check that the filename is inside the wiki files folder
|
|
||||||
if(path.relative(baseFilename,filename).indexOf("..") !== 0) {
|
|
||||||
// Send the file
|
|
||||||
fs.readFile(filename,function(err,content) {
|
|
||||||
var status,content,type = "text/plain";
|
|
||||||
if(err) {
|
|
||||||
console.log("Error accessing file " + filename + ": " + err.toString());
|
|
||||||
status = 404;
|
|
||||||
content = "File '" + suppliedFilename + "' not found";
|
|
||||||
} else {
|
|
||||||
status = 200;
|
|
||||||
content = content;
|
|
||||||
type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream");
|
|
||||||
}
|
|
||||||
state.sendResponse(status,{"Content-Type": type},content);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
46
core/modules/startup/eventbus.js
Normal file
46
core/modules/startup/eventbus.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/startup/eventbus.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: startup
|
||||||
|
|
||||||
|
Event bus for cross module communication
|
||||||
|
\*/
|
||||||
|
|
||||||
|
exports.name = "eventbus";
|
||||||
|
exports.platforms = ["browser"];
|
||||||
|
exports.before = ["windows"];
|
||||||
|
exports.synchronous = true;
|
||||||
|
|
||||||
|
$tw.eventBus = {
|
||||||
|
listenersMap: new Map(),
|
||||||
|
|
||||||
|
on(event,handler) {
|
||||||
|
if(!this.listenersMap.has(event)) {
|
||||||
|
this.listenersMap.set(event,new Set());
|
||||||
|
}
|
||||||
|
const listeners = this.listenersMap.get(event);
|
||||||
|
listeners.add(handler);
|
||||||
|
},
|
||||||
|
|
||||||
|
off(event,handler) {
|
||||||
|
const listeners = this.listenersMap.get(event);
|
||||||
|
if(listeners) {
|
||||||
|
listeners.delete(handler);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
once(event,handler) {
|
||||||
|
const wrapper = (...args) => {
|
||||||
|
handler(...args);
|
||||||
|
this.off(event, wrapper);
|
||||||
|
};
|
||||||
|
this.on(event, wrapper);
|
||||||
|
},
|
||||||
|
|
||||||
|
emit(event,data) {
|
||||||
|
const listeners = this.listenersMap.get(event);
|
||||||
|
if(listeners) {
|
||||||
|
listeners.forEach(fn => fn(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -19,6 +19,16 @@ exports.synchronous = true;
|
|||||||
var FAVICON_TITLE = "$:/favicon.ico";
|
var FAVICON_TITLE = "$:/favicon.ico";
|
||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
|
var setFavicon = function() {
|
||||||
|
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
|
||||||
|
if(tiddler) {
|
||||||
|
var faviconLink = document.getElementById("faviconLink"),
|
||||||
|
dataURI = $tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri);
|
||||||
|
faviconLink.setAttribute("href",dataURI);
|
||||||
|
$tw.faviconPublisher.send({verb: "FAVICON",body: dataURI});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tw.faviconPublisher = new $tw.utils.BrowserMessagingPublisher({type: "FAVICON", onsubscribe: setFavicon});
|
||||||
// Set up the favicon
|
// Set up the favicon
|
||||||
setFavicon();
|
setFavicon();
|
||||||
// Reset the favicon when the tiddler changes
|
// Reset the favicon when the tiddler changes
|
||||||
@@ -28,11 +38,3 @@ exports.startup = function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function setFavicon() {
|
|
||||||
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
|
|
||||||
if(tiddler) {
|
|
||||||
var faviconLink = document.getElementById("faviconLink");
|
|
||||||
faviconLink.setAttribute("href",$tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,11 +19,17 @@ var TITLE_INFO_PLUGIN = "$:/temp/info-plugin";
|
|||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
// Function to bake the info plugin with new tiddlers
|
// Function to bake the info plugin with new tiddlers
|
||||||
var updateInfoPlugin = function(tiddlerFieldsArray) {
|
// additions: array of tiddler field objects
|
||||||
|
// removals: array of titles to remove
|
||||||
|
var updateInfoPlugin = function(additions = [], removals = []) {
|
||||||
// Get the existing tiddlers
|
// Get the existing tiddlers
|
||||||
var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});
|
var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});
|
||||||
// Add the new ones
|
$tw.utils.each(removals,function(title) {
|
||||||
$tw.utils.each(tiddlerFieldsArray,function(fields) {
|
if(json.tiddlers[title]) {
|
||||||
|
delete json.tiddlers[title];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$tw.utils.each(additions,function(fields) {
|
||||||
if(fields && fields.title) {
|
if(fields && fields.title) {
|
||||||
json.tiddlers[fields.title] = fields;
|
json.tiddlers[fields.title] = fields;
|
||||||
}
|
}
|
||||||
@@ -47,7 +53,7 @@ exports.startup = function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateInfoPlugin(tiddlerFieldsArray);
|
updateInfoPlugin(tiddlerFieldsArray);
|
||||||
var changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
$tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
||||||
$tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]);
|
$tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]);
|
||||||
$tw.wiki.unpackPluginTiddlers();
|
$tw.wiki.unpackPluginTiddlers();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,5 +31,7 @@ exports.startup = function() {
|
|||||||
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
|
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
|
||||||
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
|
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
|
||||||
$tw.wiki.initParsers();
|
$tw.wiki.initParsers();
|
||||||
$tw.Commander.initCommands();
|
if($tw.node) {
|
||||||
|
$tw.Commander.initCommands();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,10 +33,15 @@ exports.startup = function() {
|
|||||||
});
|
});
|
||||||
$tw.titleContainer = $tw.fakeDocument.createElement("div");
|
$tw.titleContainer = $tw.fakeDocument.createElement("div");
|
||||||
$tw.titleWidgetNode.render($tw.titleContainer,null);
|
$tw.titleWidgetNode.render($tw.titleContainer,null);
|
||||||
document.title = $tw.titleContainer.textContent;
|
var publishTitle = function() {
|
||||||
|
$tw.titlePublisher.send({verb: "PAGETITLE",body: document.title});
|
||||||
|
document.title = $tw.titleContainer.textContent;
|
||||||
|
};
|
||||||
|
$tw.titlePublisher = new $tw.utils.BrowserMessagingPublisher({type: "PAGETITLE", onsubscribe: publishTitle});
|
||||||
|
publishTitle();
|
||||||
$tw.wiki.addEventListener("change",function(changes) {
|
$tw.wiki.addEventListener("change",function(changes) {
|
||||||
if($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {
|
if($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {
|
||||||
document.title = $tw.titleContainer.textContent;
|
publishTitle();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Set up the styles
|
// Set up the styles
|
||||||
|
|||||||
@@ -56,9 +56,11 @@ exports.startup = function() {
|
|||||||
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||||
srcDocument.close();
|
srcDocument.close();
|
||||||
srcDocument.title = windowTitle;
|
srcDocument.title = windowTitle;
|
||||||
|
$tw.eventBus.emit("window:opened",{windowID, window: srcWindow});
|
||||||
srcWindow.addEventListener("beforeunload",function(event) {
|
srcWindow.addEventListener("beforeunload",function(event) {
|
||||||
delete $tw.windows[windowID];
|
delete $tw.windows[windowID];
|
||||||
$tw.wiki.removeEventListener("change",refreshHandler);
|
$tw.wiki.removeEventListener("change",refreshHandler);
|
||||||
|
$tw.eventBus.emit("window:closed",{windowID});
|
||||||
},false);
|
},false);
|
||||||
// Set up the styles
|
// Set up the styles
|
||||||
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
|
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
|
||||||
|
|||||||
@@ -47,16 +47,16 @@ ClassicStoryView.prototype.insert = function(widget) {
|
|||||||
// Reset the margin once the transition is over
|
// Reset the margin once the transition is over
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
{transition: "none"},
|
|
||||||
{marginBottom: ""}
|
{marginBottom: ""}
|
||||||
]);
|
]);
|
||||||
|
$tw.utils.removeStyle(targetElement, "transition");
|
||||||
},duration);
|
},duration);
|
||||||
// Set up the initial position of the element
|
// Set up the initial position of the element
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
{transition: "none"},
|
|
||||||
{marginBottom: (-currHeight) + "px"},
|
{marginBottom: (-currHeight) + "px"},
|
||||||
{opacity: "0.0"}
|
{opacity: "0.0"}
|
||||||
]);
|
]);
|
||||||
|
$tw.utils.removeStyle(targetElement, "transition");
|
||||||
$tw.utils.forceLayout(targetElement);
|
$tw.utils.forceLayout(targetElement);
|
||||||
// Transition to the final position
|
// Transition to the final position
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
@@ -64,7 +64,7 @@ ClassicStoryView.prototype.insert = function(widget) {
|
|||||||
"margin-bottom " + duration + "ms " + easing},
|
"margin-bottom " + duration + "ms " + easing},
|
||||||
{marginBottom: currMarginBottom + "px"},
|
{marginBottom: currMarginBottom + "px"},
|
||||||
{opacity: "1.0"}
|
{opacity: "1.0"}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,11 +94,9 @@ ClassicStoryView.prototype.remove = function(widget) {
|
|||||||
setTimeout(removeElement,duration);
|
setTimeout(removeElement,duration);
|
||||||
// Animate the closure
|
// Animate the closure
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
{transition: "none"},
|
|
||||||
{transform: "translateX(0px)"},
|
|
||||||
{marginBottom: currMarginBottom + "px"},
|
{marginBottom: currMarginBottom + "px"},
|
||||||
{opacity: "1.0"}
|
|
||||||
]);
|
]);
|
||||||
|
$tw.utils.removeStyles(targetElement, ["transition", "transform", "opacity"]);
|
||||||
$tw.utils.forceLayout(targetElement);
|
$tw.utils.forceLayout(targetElement);
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
|
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
|
||||||
@@ -113,4 +111,4 @@ ClassicStoryView.prototype.remove = function(widget) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.classic = ClassicStoryView;
|
exports.classic = ClassicStoryView;
|
||||||
@@ -37,10 +37,7 @@ PopStoryView.prototype.insert = function(widget) {
|
|||||||
}
|
}
|
||||||
// Reset once the transition is over
|
// Reset once the transition is over
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.removeStyles(targetElement, ["transition", "transform"]);
|
||||||
{transition: "none"},
|
|
||||||
{transform: "none"}
|
|
||||||
]);
|
|
||||||
$tw.utils.setStyle(widget.document.body,[
|
$tw.utils.setStyle(widget.document.body,[
|
||||||
{"overflow-x": ""}
|
{"overflow-x": ""}
|
||||||
]);
|
]);
|
||||||
@@ -51,10 +48,10 @@ PopStoryView.prototype.insert = function(widget) {
|
|||||||
]);
|
]);
|
||||||
// Set up the initial position of the element
|
// Set up the initial position of the element
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
{transition: "none"},
|
|
||||||
{transform: "scale(2)"},
|
{transform: "scale(2)"},
|
||||||
{opacity: "0.0"}
|
{opacity: "0.0"}
|
||||||
]);
|
]);
|
||||||
|
$tw.utils.removeStyle(targetElement, "transition");
|
||||||
$tw.utils.forceLayout(targetElement);
|
$tw.utils.forceLayout(targetElement);
|
||||||
// Transition to the final position
|
// Transition to the final position
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
@@ -63,6 +60,9 @@ PopStoryView.prototype.insert = function(widget) {
|
|||||||
{transform: "scale(1)"},
|
{transform: "scale(1)"},
|
||||||
{opacity: "1.0"}
|
{opacity: "1.0"}
|
||||||
]);
|
]);
|
||||||
|
setTimeout(function() {
|
||||||
|
$tw.utils.removeStyles(targetElement, ["transition", "transform", "opactity"]);
|
||||||
|
}, duration)
|
||||||
};
|
};
|
||||||
|
|
||||||
PopStoryView.prototype.remove = function(widget) {
|
PopStoryView.prototype.remove = function(widget) {
|
||||||
@@ -81,11 +81,7 @@ PopStoryView.prototype.remove = function(widget) {
|
|||||||
// Remove the element at the end of the transition
|
// Remove the element at the end of the transition
|
||||||
setTimeout(removeElement,duration);
|
setTimeout(removeElement,duration);
|
||||||
// Animate the closure
|
// Animate the closure
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.removeStyles(targetElement, ["transition", "transform", "opacity"]);
|
||||||
{transition: "none"},
|
|
||||||
{transform: "scale(1)"},
|
|
||||||
{opacity: "1.0"}
|
|
||||||
]);
|
|
||||||
$tw.utils.forceLayout(targetElement);
|
$tw.utils.forceLayout(targetElement);
|
||||||
$tw.utils.setStyle(targetElement,[
|
$tw.utils.setStyle(targetElement,[
|
||||||
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " +
|
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms ease-in-out, " +
|
||||||
@@ -95,4 +91,4 @@ PopStoryView.prototype.remove = function(widget) {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.pop = PopStoryView;
|
exports.pop = PopStoryView;
|
||||||
@@ -96,6 +96,9 @@ ZoominListView.prototype.navigateTo = function(historyInfo) {
|
|||||||
{transform: "translateX(0px) translateY(0px) scale(1)"},
|
{transform: "translateX(0px) translateY(0px) scale(1)"},
|
||||||
{zIndex: "500"},
|
{zIndex: "500"},
|
||||||
]);
|
]);
|
||||||
|
setTimeout(function() {
|
||||||
|
$tw.utils.removeStyles(targetElement, ["transition", "opacity", "transform", "zIndex"]);
|
||||||
|
}, duration);
|
||||||
// Transform the previous tiddler out of the way and then hide it
|
// Transform the previous tiddler out of the way and then hide it
|
||||||
if(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {
|
if(prevCurrentTiddler && prevCurrentTiddler !== targetElement) {
|
||||||
scale = zoomBounds.width / sourceBounds.width;
|
scale = zoomBounds.width / sourceBounds.width;
|
||||||
@@ -207,6 +210,9 @@ ZoominListView.prototype.remove = function(widget) {
|
|||||||
{opacity: "0"},
|
{opacity: "0"},
|
||||||
{zIndex: "0"}
|
{zIndex: "0"}
|
||||||
]);
|
]);
|
||||||
|
setTimeout(function() {
|
||||||
|
$tw.utils.removeStyles(toWidgetDomNode, ["transformOrigin", "transform", "transition", "opacity", "zIndex"]);
|
||||||
|
}, duration);
|
||||||
setTimeout(removeElement,duration);
|
setTimeout(removeElement,duration);
|
||||||
// Now the tiddler we're going back to
|
// Now the tiddler we're going back to
|
||||||
if(toWidgetDomNode) {
|
if(toWidgetDomNode) {
|
||||||
@@ -222,4 +228,4 @@ ZoominListView.prototype.logTextNodeRoot = function(node) {
|
|||||||
this.textNodeLogger.log($tw.language.getString("Error/ZoominTextNode") + " " + node.textContent);
|
this.textNodeLogger.log($tw.language.getString("Error/ZoominTextNode") + " " + node.textContent);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.zoomin = ZoominListView;
|
exports.zoomin = ZoominListView;
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
// 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 if ((charCode > 55295) && (charCode < 57344) && string.length > i+1) {
|
|
||||||
// Surrogate pair
|
|
||||||
var hiSurrogate = charCode;
|
|
||||||
var loSurrogate = string.charCodeAt(i+1);
|
|
||||||
i++; // Skip the low surrogate on the next loop pass
|
|
||||||
var codePoint = (((hiSurrogate - 55296) << 10) | (loSurrogate - 56320)) + 65536;
|
|
||||||
output += String.fromCharCode((codePoint >> 18) | 240);
|
|
||||||
output += String.fromCharCode(((codePoint >> 12) & 63) | 128);
|
|
||||||
output += String.fromCharCode(((codePoint >> 6) & 63) | 128);
|
|
||||||
output += String.fromCharCode((codePoint & 63) | 128);
|
|
||||||
} else {
|
|
||||||
// Not a surrogate pair, or a dangling surrogate without its partner that we'll just encode as-is
|
|
||||||
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 if ((charCode > 223) && (charCode < 240)) {
|
|
||||||
output += String.fromCharCode(((charCode & 15) << 12) | ((string.charCodeAt(i + 1) & 63) << 6) | (string.charCodeAt(i + 2) & 63));
|
|
||||||
i += 3;
|
|
||||||
} else {
|
|
||||||
var codePoint = ((charCode & 7) << 18) | ((string.charCodeAt(i + 1) & 63) << 12) | ((string.charCodeAt(i + 2) & 63) << 6) | (string.charCodeAt(i + 3) & 63);
|
|
||||||
// output += String.fromCodePoint(codePoint); // Can't do this because Internet Explorer doesn't have String.fromCodePoint
|
|
||||||
output += String.fromCharCode(((codePoint - 65536) >> 10) + 55296) + String.fromCharCode(((codePoint - 65536) & 1023) + 56320); // So we do this instead
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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" ]);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
// 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++)if((e=r.charCodeAt(t))<128)o+=String.fromCharCode(e);else if(e>127&&e<2048)o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128);else if(e>55295&&e<57344&&r.length>t+1){var i=e,n=r.charCodeAt(t+1);t++;var d=65536+(i-55296<<10|n-56320);o+=String.fromCharCode(d>>18|240),o+=String.fromCharCode(d>>12&63|128),o+=String.fromCharCode(d>>6&63|128),o+=String.fromCharCode(63&d|128)}else 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;)if((t=r.charCodeAt(o))<128)e+=String.fromCharCode(t),o++;else if(t>191&&t<224)e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2;else if(t>223&&t<240)e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3;else{var i=(7&t)<<18|(63&r.charCodeAt(o+1))<<12|(63&r.charCodeAt(o+2))<<6|63&r.charCodeAt(o+3);e+=String.fromCharCode(55296+(i-65536>>10))+String.fromCharCode(56320+(i-65536&1023)),o+=4}return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var i=0;i<t.length;i++)o[t[i]]=o.require(t[i]);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,i,n,d,f,a,h,C="",c=0;c<r.length;)d=(t=r.charCodeAt(c++))>>2,f=(3&t)<<4|(i=r.charCodeAt(c++))>>4,a=(15&i)<<2|(n=r.charCodeAt(c++))>>6,h=63&n,isNaN(i)?a=h=64:isNaN(n)&&(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,i,n,d,f,a,h="",C=0;C<r.length;)t=o.indexOf(r.charAt(C++))<<2|(d=o.indexOf(r.charAt(C++)))>>4,i=(15&d)<<4|(f=o.indexOf(r.charAt(C++)))>>2,n=(3&f)<<6|(a=o.indexOf(r.charAt(C++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(i)),64!=a&&(h+=String.fromCharCode(n));return e.decode(h)}}},this,["utf8"]);
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"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);"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -24,6 +24,26 @@ exports.setStyle = function(element,styles) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove style properties of an element
|
||||||
|
element: dom node
|
||||||
|
styleProperties: ordered array of string property names
|
||||||
|
*/
|
||||||
|
exports.removeStyles = function(element, styleProperties) {
|
||||||
|
for (var i=0; i<styleProperties.length; i++) {
|
||||||
|
element.style.removeProperty($tw.utils.convertStyleNameToPropertyName(styleProperties[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove single style property of an element
|
||||||
|
element: dom node
|
||||||
|
styleProperty: string property name
|
||||||
|
*/
|
||||||
|
exports.removeStyle = function(element, styleProperty) {
|
||||||
|
$tw.utils.removeStyles(element, [styleProperty])
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Converts a standard CSS property name into the local browser-specific equivalent. For example:
|
Converts a standard CSS property name into the local browser-specific equivalent. For example:
|
||||||
"background-color" --> "backgroundColor"
|
"background-color" --> "backgroundColor"
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ Modal.prototype.display = function(title,options) {
|
|||||||
bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||||
footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||||
// Whether to close the modal dialog when the mask (area outside the modal) is clicked
|
// Whether to close the modal dialog when the mask (area outside the modal) is clicked
|
||||||
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true")) {
|
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true" || tiddler.fields["mask-closable"] === "" || "mask-closable" in tiddler.fields === false)) {
|
||||||
modalBackdrop.addEventListener("click",closeHandler,false);
|
modalBackdrop.addEventListener("click",closeHandler,false);
|
||||||
}
|
}
|
||||||
// Set the initial styles for the message
|
// Set the initial styles for the message
|
||||||
|
|||||||
126
core/modules/utils/messaging.js
Normal file
126
core/modules/utils/messaging.js
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/utils/messaging.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: utils-browser
|
||||||
|
|
||||||
|
Messaging utilities for use with window.postMessage() etc.
|
||||||
|
|
||||||
|
This module intentionally has no dependencies so that it can be included in non-TiddlyWiki projects
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var RESPONSE_TIMEOUT = 2 * 1000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class to handle subscribing to publishers
|
||||||
|
|
||||||
|
target: Target window (eg iframe.contentWindow)
|
||||||
|
type: String indicating type of item for which subscriptions are being provided (eg "SAVING")
|
||||||
|
onsubscribe: Function to be invoked with err parameter when the subscription is established, or there is a timeout
|
||||||
|
onmessage: Function to be invoked when a new message arrives, invoked with (data,callback). The callback is invoked with the argument (response)
|
||||||
|
*/
|
||||||
|
function BrowserMessagingSubscriber(options) {
|
||||||
|
var self = this;
|
||||||
|
this.target = options.target;
|
||||||
|
this.type = options.type;
|
||||||
|
this.onsubscribe = options.onsubscribe || function() {};
|
||||||
|
this.onmessage = options.onmessage;
|
||||||
|
this.hasConfirmed = false;
|
||||||
|
this.channel = new MessageChannel();
|
||||||
|
this.channel.port1.addEventListener("message",function(event) {
|
||||||
|
if(this.timerID) {
|
||||||
|
clearTimeout(this.timerID);
|
||||||
|
this.timerID = null;
|
||||||
|
}
|
||||||
|
if(event.data) {
|
||||||
|
if(event.data.verb === "SUBSCRIBED") {
|
||||||
|
self.hasConfirmed = true;
|
||||||
|
self.onsubscribe(null);
|
||||||
|
} else if(event.data.verb === self.type) {
|
||||||
|
self.onmessage(event.data,function(response) {
|
||||||
|
// Send the response back on the supplied port, and then close it
|
||||||
|
event.ports[0].postMessage(response);
|
||||||
|
event.ports[0].close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Set a timer so that if we don't hear from the iframe before a timeout we alert the user
|
||||||
|
this.timerID = setTimeout(function() {
|
||||||
|
if(!self.hasConfirmed) {
|
||||||
|
self.onsubscribe("NO_RESPONSE");
|
||||||
|
}
|
||||||
|
},RESPONSE_TIMEOUT);
|
||||||
|
this.channel.port1.start();
|
||||||
|
this.target.postMessage({verb: "SUBSCRIBE",to: self.type},"*",[this.channel.port2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.BrowserMessagingSubscriber = BrowserMessagingSubscriber;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class to handle publishing subscriptions
|
||||||
|
|
||||||
|
type: String indicating type of item for which subscriptions are being provided (eg "SAVING")
|
||||||
|
onsubscribe: Function to be invoked when a subscription occurs
|
||||||
|
*/
|
||||||
|
function BrowserMessagingPublisher(options) {
|
||||||
|
var self = this;
|
||||||
|
this.type = options.type;
|
||||||
|
this.hostIsListening = false;
|
||||||
|
this.port = null;
|
||||||
|
// Listen to connection requests from the host
|
||||||
|
window.addEventListener("message",function(event) {
|
||||||
|
if(event.data && event.data.verb === "SUBSCRIBE" && event.data.to === self.type) {
|
||||||
|
self.hostIsListening = true;
|
||||||
|
// Acknowledge
|
||||||
|
self.port = event.ports[0];
|
||||||
|
self.port.postMessage({verb: "SUBSCRIBED", to: self.type});
|
||||||
|
if(options.onsubscribe) {
|
||||||
|
options.onsubscribe(event.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserMessagingPublisher.prototype.canSend = function() {
|
||||||
|
return !!this.hostIsListening && !!this.port;
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserMessagingPublisher.prototype.send = function(data,callback) {
|
||||||
|
var self = this;
|
||||||
|
callback = callback || function() {};
|
||||||
|
// Check that we've been initialised by the host
|
||||||
|
if(!this.hostIsListening || !this.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Create a channel for the confirmation
|
||||||
|
var channel = new MessageChannel();
|
||||||
|
channel.port1.addEventListener("message",function(event) {
|
||||||
|
if(event.data && event.data.verb === "OK") {
|
||||||
|
callback(null);
|
||||||
|
} else {
|
||||||
|
callback("BrowserMessagingPublisher for " + self.type + " error: " + (event.data || {}).verb);
|
||||||
|
}
|
||||||
|
channel.port1.close();
|
||||||
|
});
|
||||||
|
channel.port1.start();
|
||||||
|
// Send the save request with the port for the response
|
||||||
|
this.port.postMessage(data,[channel.port2]);
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserMessagingPublisher.prototype.close = function() {
|
||||||
|
if(this.port) {
|
||||||
|
this.port.close();
|
||||||
|
this.hostIsListening = false;
|
||||||
|
this.port = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.BrowserMessagingPublisher = BrowserMessagingPublisher;
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -9,8 +9,6 @@ Various static utility functions.
|
|||||||
|
|
||||||
"use strict";
|
"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
|
Display a message, in colour if we're on a terminal
|
||||||
*/
|
*/
|
||||||
@@ -842,22 +840,50 @@ if(typeof window !== 'undefined') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.base64ToBytes = function(base64) {
|
||||||
|
const binString = exports.atob(base64);
|
||||||
|
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.bytesToBase64 = function(bytes) {
|
||||||
|
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
|
||||||
|
return exports.btoa(binString);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.base64EncodeUtf8 = function(str) {
|
||||||
|
if ($tw.browser) {
|
||||||
|
return exports.bytesToBase64(new TextEncoder().encode(str));
|
||||||
|
} else {
|
||||||
|
const buff = Buffer.from(str, "utf-8");
|
||||||
|
return buff.toString("base64");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.base64DecodeUtf8 = function(str) {
|
||||||
|
if ($tw.browser) {
|
||||||
|
return new TextDecoder().decode(exports.base64ToBytes(str));
|
||||||
|
} else {
|
||||||
|
const buff = Buffer.from(str, "base64");
|
||||||
|
return buff.toString("utf-8");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Decode a base64 string
|
Decode a base64 string
|
||||||
*/
|
*/
|
||||||
exports.base64Decode = function(string64,binary,urlsafe) {
|
exports.base64Decode = function(string64,binary,urlsafe) {
|
||||||
var encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
|
const encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
|
||||||
if(binary) return exports.atob(encoded)
|
if(binary) return exports.atob(encoded)
|
||||||
else return base64utf8.base64.decode.call(base64utf8,encoded);
|
else return exports.base64DecodeUtf8(encoded);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Encode a string to base64
|
Encode a string to base64
|
||||||
*/
|
*/
|
||||||
exports.base64Encode = function(string64,binary,urlsafe) {
|
exports.base64Encode = function(string64,binary,urlsafe) {
|
||||||
var encoded;
|
let encoded;
|
||||||
if(binary) encoded = exports.btoa(string64);
|
if(binary) encoded = exports.btoa(string64);
|
||||||
else encoded = base64utf8.base64.encode.call(base64utf8,string64);
|
else encoded = exports.base64EncodeUtf8(string64);
|
||||||
if(urlsafe) {
|
if(urlsafe) {
|
||||||
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
|
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
|
||||||
}
|
}
|
||||||
@@ -1023,7 +1049,7 @@ exports.makeCompareFunction = function(type,options) {
|
|||||||
return compare(dateA,dateB);
|
return compare(dateA,dateB);
|
||||||
},
|
},
|
||||||
"version": function(a,b) {
|
"version": function(a,b) {
|
||||||
return $tw.utils.compareVersions(a,b);
|
return compare($tw.utils.compareVersions(a,b),0);
|
||||||
},
|
},
|
||||||
"alphanumeric": function(a,b) {
|
"alphanumeric": function(a,b) {
|
||||||
if(!isCaseSensitive) {
|
if(!isCaseSensitive) {
|
||||||
|
|||||||
103
core/modules/widgets/audio.js
Normal file
103
core/modules/widgets/audio.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/audio.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Basic Audio widget for displaying audio files.
|
||||||
|
This is a simple implementation that can be overridden by plugins
|
||||||
|
for more advanced functionality.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var AudioWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
AudioWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
AudioWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.parentDomNode = parent;
|
||||||
|
this.computeAttributes();
|
||||||
|
this.execute();
|
||||||
|
|
||||||
|
// Create audio element
|
||||||
|
var audioElement = this.document.createElement("audio");
|
||||||
|
audioElement.setAttribute("controls", this.getAttribute("controls", "controls"));
|
||||||
|
audioElement.setAttribute("style", this.getAttribute("style", "width: 100%; object-fit: contain"));
|
||||||
|
audioElement.className = "tw-audio-element";
|
||||||
|
|
||||||
|
// Set source
|
||||||
|
if(this.audioSource) {
|
||||||
|
if (this.audioSource.indexOf("data:") === 0) {
|
||||||
|
audioElement.setAttribute("src", this.audioSource);
|
||||||
|
} else {
|
||||||
|
var sourceElement = this.document.createElement("source");
|
||||||
|
sourceElement.setAttribute("src", this.audioSource);
|
||||||
|
if(this.audioType) {
|
||||||
|
sourceElement.setAttribute("type", this.audioType);
|
||||||
|
}
|
||||||
|
audioElement.appendChild(sourceElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the audio into the DOM
|
||||||
|
parent.insertBefore(audioElement, nextSibling);
|
||||||
|
this.domNodes.push(audioElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compute the internal state of the widget
|
||||||
|
*/
|
||||||
|
AudioWidget.prototype.execute = function() {
|
||||||
|
// Get the audio source and type
|
||||||
|
this.audioSource = this.getAttribute("src");
|
||||||
|
this.audioType = this.getAttribute("type");
|
||||||
|
this.audioControls = this.getAttribute("controls", "controls");
|
||||||
|
|
||||||
|
// Try to get from tiddler attribute
|
||||||
|
if(!this.audioSource && this.getAttribute("tiddler")) {
|
||||||
|
var tiddlerTitle = this.getAttribute("tiddler");
|
||||||
|
var tiddler = this.wiki.getTiddler(tiddlerTitle);
|
||||||
|
if(tiddler) {
|
||||||
|
if(tiddler.fields._canonical_uri) {
|
||||||
|
this.audioSource = tiddler.fields._canonical_uri;
|
||||||
|
this.audioType = tiddler.fields.type;
|
||||||
|
} else if(tiddler.fields.text) {
|
||||||
|
this.audioSource = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
|
||||||
|
this.audioType = tiddler.fields.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have a tiddler for saving timestamps
|
||||||
|
this.tiddlerTitle = this.getAttribute("tiddler");
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
|
*/
|
||||||
|
AudioWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
var changedAttributes = this.computeAttributes();
|
||||||
|
if(changedAttributes.src || changedAttributes.type || changedAttributes.controls || changedAttributes.tiddler) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.audio = AudioWidget;
|
||||||
|
|
||||||
|
|
||||||
@@ -61,6 +61,10 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
sourcePrefix: "data-",
|
sourcePrefix: "data-",
|
||||||
destPrefix: "data-"
|
destPrefix: "data-"
|
||||||
});
|
});
|
||||||
|
this.assignAttributes(domNode,{
|
||||||
|
sourcePrefix: "aria-",
|
||||||
|
destPrefix: "aria-"
|
||||||
|
});
|
||||||
// Assign other attributes
|
// Assign other attributes
|
||||||
if(this.style) {
|
if(this.style) {
|
||||||
domNode.setAttribute("style",this.style);
|
domNode.setAttribute("style",this.style);
|
||||||
@@ -68,9 +72,6 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
if(this.tooltip) {
|
if(this.tooltip) {
|
||||||
domNode.setAttribute("title",this.tooltip);
|
domNode.setAttribute("title",this.tooltip);
|
||||||
}
|
}
|
||||||
if(this["aria-label"]) {
|
|
||||||
domNode.setAttribute("aria-label",this["aria-label"]);
|
|
||||||
}
|
|
||||||
if (this.role) {
|
if (this.role) {
|
||||||
domNode.setAttribute("role", this.role);
|
domNode.setAttribute("role", this.role);
|
||||||
}
|
}
|
||||||
@@ -215,7 +216,6 @@ ButtonWidget.prototype.execute = function() {
|
|||||||
this.setTo = this.getAttribute("setTo");
|
this.setTo = this.getAttribute("setTo");
|
||||||
this.popup = this.getAttribute("popup");
|
this.popup = this.getAttribute("popup");
|
||||||
this.hover = this.getAttribute("hover");
|
this.hover = this.getAttribute("hover");
|
||||||
this["aria-label"] = this.getAttribute("aria-label");
|
|
||||||
this.role = this.getAttribute("role");
|
this.role = this.getAttribute("role");
|
||||||
this.tooltip = this.getAttribute("tooltip");
|
this.tooltip = this.getAttribute("tooltip");
|
||||||
this.style = this.getAttribute("style");
|
this.style = this.getAttribute("style");
|
||||||
@@ -271,6 +271,10 @@ ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
sourcePrefix: "data-",
|
sourcePrefix: "data-",
|
||||||
destPrefix: "data-"
|
destPrefix: "data-"
|
||||||
});
|
});
|
||||||
|
this.assignAttributes(this.domNodes[0],{
|
||||||
|
sourcePrefix: "aria-",
|
||||||
|
destPrefix: "aria-"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return this.refreshChildren(changedTiddlers);
|
return this.refreshChildren(changedTiddlers);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ ElementWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
// Create the DOM node and render children
|
// Create the DOM node and render children
|
||||||
var domNode = this.document.createElementNS(this.namespace,this.tag);
|
var domNode = this.document.createElementNS(this.namespace,this.tag);
|
||||||
this.assignAttributes(domNode,{excludeEventAttributes: true});
|
this.assignAttributes(domNode,{excludeEventAttributes: true});
|
||||||
|
// Allow hooks to manipulate the DOM node. Eg: Add debug info
|
||||||
|
$tw.hooks.invokeHook("th-dom-rendering-element", domNode, this);
|
||||||
parent.insertBefore(domNode,nextSibling);
|
parent.insertBefore(domNode,nextSibling);
|
||||||
this.renderChildren(domNode,null);
|
this.renderChildren(domNode,null);
|
||||||
this.domNodes.push(domNode);
|
this.domNodes.push(domNode);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ EventWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
domNode.addEventListener(type,function(event) {
|
domNode.addEventListener(type,function(event) {
|
||||||
var selector = self.getAttribute("selector"),
|
var selector = self.getAttribute("selector"),
|
||||||
matchSelector = self.getAttribute("matchSelector"),
|
matchSelector = self.getAttribute("matchSelector"),
|
||||||
actions = self.getAttribute("$"+type) || self.getAttribute("actions-"+type),
|
actions = self.getAttribute("$"+type),
|
||||||
stopPropagation = self.getAttribute("stopPropagation","onaction"),
|
stopPropagation = self.getAttribute("stopPropagation","onaction"),
|
||||||
selectedNode = event.target,
|
selectedNode = event.target,
|
||||||
selectedNodeRect,
|
selectedNodeRect,
|
||||||
@@ -122,9 +122,6 @@ EventWidget.prototype.execute = function() {
|
|||||||
self.types.push(key.slice(1));
|
self.types.push(key.slice(1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(!this.types.length) {
|
|
||||||
this.types = this.getAttribute("events","").split(" ");
|
|
||||||
}
|
|
||||||
this.elementTag = this.getAttribute("tag");
|
this.elementTag = this.getAttribute("tag");
|
||||||
// Make child widgets
|
// Make child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ LinkWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
sourcePrefix: "data-",
|
sourcePrefix: "data-",
|
||||||
destPrefix: "data-"
|
destPrefix: "data-"
|
||||||
});
|
});
|
||||||
|
this.assignAttributes(domNode,{
|
||||||
|
sourcePrefix: "aria-",
|
||||||
|
destPrefix: "aria-"
|
||||||
|
});
|
||||||
parent.insertBefore(domNode,nextSibling);
|
parent.insertBefore(domNode,nextSibling);
|
||||||
this.renderChildren(domNode,null);
|
this.renderChildren(domNode,null);
|
||||||
this.domNodes.push(domNode);
|
this.domNodes.push(domNode);
|
||||||
@@ -125,9 +129,13 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
|||||||
});
|
});
|
||||||
domNode.setAttribute("title",tooltipText);
|
domNode.setAttribute("title",tooltipText);
|
||||||
}
|
}
|
||||||
if(this["aria-label"]) {
|
if(this.role) {
|
||||||
domNode.setAttribute("aria-label",this["aria-label"]);
|
domNode.setAttribute("role",this.role);
|
||||||
}
|
}
|
||||||
|
this.assignAttributes(domNode,{
|
||||||
|
sourcePrefix: "aria-",
|
||||||
|
destPrefix: "aria-"
|
||||||
|
})
|
||||||
// Add a click event handler
|
// Add a click event handler
|
||||||
$tw.utils.addEventListeners(domNode,[
|
$tw.utils.addEventListeners(domNode,[
|
||||||
{name: "click", handlerObject: this, handlerMethod: "handleClickEvent"},
|
{name: "click", handlerObject: this, handlerMethod: "handleClickEvent"},
|
||||||
@@ -139,6 +147,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
|||||||
dragTiddlerFn: function() {return self.to;},
|
dragTiddlerFn: function() {return self.to;},
|
||||||
widget: this
|
widget: this
|
||||||
});
|
});
|
||||||
|
} else if(this.draggable === "no") {
|
||||||
|
domNode.setAttribute("draggable","false");
|
||||||
}
|
}
|
||||||
// Assign data- attributes
|
// Assign data- attributes
|
||||||
this.assignAttributes(domNode,{
|
this.assignAttributes(domNode,{
|
||||||
@@ -188,7 +198,7 @@ LinkWidget.prototype.execute = function() {
|
|||||||
// Pick up our attributes
|
// Pick up our attributes
|
||||||
this.to = this.getAttribute("to",this.getVariable("currentTiddler"));
|
this.to = this.getAttribute("to",this.getVariable("currentTiddler"));
|
||||||
this.tooltip = this.getAttribute("tooltip");
|
this.tooltip = this.getAttribute("tooltip");
|
||||||
this["aria-label"] = this.getAttribute("aria-label");
|
this.role = this.getAttribute("role");
|
||||||
this.linkClasses = this.getAttribute("class");
|
this.linkClasses = this.getAttribute("class");
|
||||||
this.overrideClasses = this.getAttribute("overrideClass");
|
this.overrideClasses = this.getAttribute("overrideClass");
|
||||||
this.tabIndex = this.getAttribute("tabindex");
|
this.tabIndex = this.getAttribute("tabindex");
|
||||||
|
|||||||
@@ -94,8 +94,6 @@ RangeWidget.prototype.getActionVariables = function(options) {
|
|||||||
|
|
||||||
// actionsStart
|
// actionsStart
|
||||||
RangeWidget.prototype.handleMouseDownEvent = function(event) {
|
RangeWidget.prototype.handleMouseDownEvent = function(event) {
|
||||||
this.mouseDown = true; // TODO remove once IE is gone.
|
|
||||||
this.startValue = this.inputDomNode.value; // TODO remove this line once IE is gone!
|
|
||||||
this.handleEvent(event);
|
this.handleEvent(event);
|
||||||
// Trigger actions
|
// Trigger actions
|
||||||
if(this.actionsMouseDown) {
|
if(this.actionsMouseDown) {
|
||||||
@@ -106,26 +104,16 @@ RangeWidget.prototype.handleMouseDownEvent = function(event) {
|
|||||||
|
|
||||||
// actionsStop
|
// actionsStop
|
||||||
RangeWidget.prototype.handleMouseUpEvent = function(event) {
|
RangeWidget.prototype.handleMouseUpEvent = function(event) {
|
||||||
this.mouseDown = false; // TODO remove once IE is gone.
|
|
||||||
this.handleEvent(event);
|
this.handleEvent(event);
|
||||||
// Trigger actions
|
// Trigger actions
|
||||||
if(this.actionsMouseUp) {
|
if(this.actionsMouseUp) {
|
||||||
var variables = this.getActionVariables()
|
var variables = this.getActionVariables()
|
||||||
this.invokeActionString(this.actionsMouseUp,this,event,variables);
|
this.invokeActionString(this.actionsMouseUp,this,event,variables);
|
||||||
}
|
}
|
||||||
// TODO remove the following if() once IE is gone!
|
|
||||||
if ($tw.browser.isIE) {
|
|
||||||
if (this.startValue !== this.inputDomNode.value) {
|
|
||||||
this.handleChangeEvent(event);
|
|
||||||
this.startValue = this.inputDomNode.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeWidget.prototype.handleChangeEvent = function(event) {
|
RangeWidget.prototype.handleChangeEvent = function(event) {
|
||||||
if (this.mouseDown) { // TODO refactor this function once IE is gone.
|
this.handleInputEvent(event);
|
||||||
this.handleInputEvent(event);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RangeWidget.prototype.handleInputEvent = function(event) {
|
RangeWidget.prototype.handleInputEvent = function(event) {
|
||||||
@@ -152,8 +140,6 @@ RangeWidget.prototype.handleEvent = function(event) {
|
|||||||
Compute the internal state of the widget
|
Compute the internal state of the widget
|
||||||
*/
|
*/
|
||||||
RangeWidget.prototype.execute = function() {
|
RangeWidget.prototype.execute = function() {
|
||||||
// TODO remove the next 1 lines once IE is gone!
|
|
||||||
this.mouseUp = true; // Needed for IE10
|
|
||||||
// Get the parameters from the attributes
|
// Get the parameters from the attributes
|
||||||
this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
||||||
this.tiddlerField = this.getAttribute("field","text");
|
this.tiddlerField = this.getAttribute("field","text");
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ScrollableWidget.prototype.listenerFunction = function(event) {
|
ScrollableWidget.prototype.listenerFunction = function(event) {
|
||||||
self = this;
|
var self = this;
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
this.timeout = setTimeout(function() {
|
this.timeout = setTimeout(function() {
|
||||||
var existingTiddler = self.wiki.getTiddler(self.scrollableBind),
|
var existingTiddler = self.wiki.getTiddler(self.scrollableBind),
|
||||||
|
|||||||
@@ -1443,7 +1443,7 @@ exports.search = function(text,options) {
|
|||||||
// Don't search the text field if the content type is binary
|
// Don't search the text field if the content type is binary
|
||||||
var fieldName = searchFields[fieldIndex];
|
var fieldName = searchFields[fieldIndex];
|
||||||
if(fieldName === "text" && contentTypeInfo.encoding !== "utf8") {
|
if(fieldName === "text" && contentTypeInfo.encoding !== "utf8") {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
var str = tiddler.fields[fieldName],
|
var str = tiddler.fields[fieldName],
|
||||||
t;
|
t;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ modal-footer-background: #f5f5f5
|
|||||||
modal-footer-border: #dddddd
|
modal-footer-border: #dddddd
|
||||||
modal-header-border: #eeeeee
|
modal-header-border: #eeeeee
|
||||||
muted-foreground: #bbb
|
muted-foreground: #bbb
|
||||||
|
network-activity-foreground: <<colour primary>>
|
||||||
notification-background: #ffffdd
|
notification-background: #ffffdd
|
||||||
notification-border: #999999
|
notification-border: #999999
|
||||||
page-background: #6f6f70
|
page-background: #6f6f70
|
||||||
@@ -56,22 +57,26 @@ primary: #29a6ee
|
|||||||
select-tag-background:
|
select-tag-background:
|
||||||
select-tag-foreground:
|
select-tag-foreground:
|
||||||
sidebar-button-foreground: <<colour foreground>>
|
sidebar-button-foreground: <<colour foreground>>
|
||||||
sidebar-controls-foreground-hover: #000000
|
sidebar-controls-foreground-hover: #222222
|
||||||
sidebar-controls-foreground: #c2c1c2
|
sidebar-controls-foreground: #c2c1c2
|
||||||
sidebar-foreground-shadow: rgba(255,255,255,0)
|
sidebar-foreground-shadow: transparent
|
||||||
sidebar-foreground: #d3d2d4
|
sidebar-foreground: #d3d2d4
|
||||||
sidebar-muted-foreground-hover: #444444
|
sidebar-muted-foreground-hover: #333333
|
||||||
sidebar-muted-foreground: #c0c0c0
|
sidebar-muted-foreground: #c0c0c0
|
||||||
sidebar-tab-background-selected: #6f6f70
|
sidebar-tab-background-selected: #6f6f70
|
||||||
sidebar-tab-background: #666667
|
sidebar-tab-background: #666667
|
||||||
sidebar-tab-border-selected: #999
|
sidebar-tab-border-selected: #999
|
||||||
sidebar-tab-border: #515151
|
sidebar-tab-border: #515151
|
||||||
sidebar-tab-divider: #999
|
sidebar-tab-divider: #999
|
||||||
sidebar-tab-foreground-selected:
|
sidebar-tab-foreground-selected: #bfbfbf
|
||||||
sidebar-tab-foreground: #999
|
sidebar-tab-foreground: #b0b0b0
|
||||||
sidebar-tiddler-link-foreground-hover: #444444
|
sidebar-tiddler-link-foreground-hover: #444444
|
||||||
sidebar-tiddler-link-foreground: #d1d0d2
|
sidebar-tiddler-link-foreground: #aaaaaa
|
||||||
site-title-foreground: <<colour tiddler-title-foreground>>
|
site-title-foreground: <<colour tiddler-title-foreground>>
|
||||||
|
stability-deprecated: #bf616a
|
||||||
|
stability-experimental: #d08770
|
||||||
|
stability-legacy: #88c0d0
|
||||||
|
stability-stable: #a3be8c
|
||||||
static-alert-foreground: #aaaaaa
|
static-alert-foreground: #aaaaaa
|
||||||
tab-background-selected: #ffffff
|
tab-background-selected: #ffffff
|
||||||
tab-background: #d8d8d8
|
tab-background: #d8d8d8
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: $:/core/save/all-external-js
|
|||||||
\whitespace trim
|
\whitespace trim
|
||||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||||
\define saveTiddlerFilter()
|
\define saveTiddlerFilter()
|
||||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] +[sort[title]] $(publishFilter)$
|
||||||
\end
|
\end
|
||||||
|
|
||||||
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
|
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: $:/core/save/offline-external-js
|
|||||||
\whitespace trim
|
\whitespace trim
|
||||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||||
\define saveTiddlerFilter()
|
\define saveTiddlerFilter()
|
||||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] +[sort[title]] $(publishFilter)$
|
||||||
\end
|
\end
|
||||||
\define defaultCoreURL() tiddlywikicore-$(version)$.js
|
\define defaultCoreURL() tiddlywikicore-$(version)$.js
|
||||||
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
title: $:/core/templates/tiddlywiki5-external-js.html
|
title: $:/core/templates/tiddlywiki5-external-js.html
|
||||||
|
|
||||||
<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]">
|
<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]">
|
||||||
|
<$set name="rawMarkupFilter" filter="[enlist<saveTiddlerAndShadowsFilter>] +[[$:/core]plugintiddlers[]]">
|
||||||
`<!doctype html>
|
`<!doctype html>
|
||||||
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
|
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||||
<!--~~ Raw markup for the top of the head section ~~-->
|
<!--~~ Raw markup for the top of the head section ~~-->
|
||||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`
|
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
|
||||||
<meta name="application-name" content="TiddlyWiki" />
|
<meta name="application-name" content="TiddlyWiki" />
|
||||||
<meta name="generator" content="TiddlyWiki" />
|
<meta name="generator" content="TiddlyWiki" />
|
||||||
@@ -22,13 +23,13 @@ title: $:/core/templates/tiddlywiki5-external-js.html
|
|||||||
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
|
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
|
||||||
|
|
||||||
<!--~~ Raw markup ~~-->
|
<!--~~ Raw markup ~~-->
|
||||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
`{{{ [enlist<rawMarkupFilter>tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
||||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}`
|
||||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
|
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||||
</head>
|
</head>
|
||||||
<body class="tc-body">
|
<body class="tc-body">
|
||||||
<!--~~ Raw markup for the top of the body section ~~-->
|
<!--~~ Raw markup for the top of the body section ~~-->
|
||||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||||
<!--~~ Static styles ~~-->
|
<!--~~ Static styles ~~-->
|
||||||
<div id="styleArea">
|
<div id="styleArea">
|
||||||
`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`
|
`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`
|
||||||
@@ -42,9 +43,10 @@ title: $:/core/templates/tiddlywiki5-external-js.html
|
|||||||
<!--~~ Ordinary tiddlers ~~-->
|
<!--~~ Ordinary tiddlers ~~-->
|
||||||
`{{$:/core/templates/store.area.template.html}}`
|
`{{$:/core/templates/store.area.template.html}}`
|
||||||
<!--~~ Raw markup for the bottom of the body section ~~-->
|
<!--~~ Raw markup for the bottom of the body section ~~-->
|
||||||
`{{{ [enlist<saveTiddlerAndShadowsFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
`{{{ [enlist<rawMarkupFilter>tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}`
|
||||||
<!--~~ Load external JavaScripts ~~-->
|
<!--~~ Load external JavaScripts ~~-->
|
||||||
<script src="`{{{ [<coreURL>] }}}`" onerror="alert('Error: Cannot load `{{{ [<coreURL>] }}}`');"></script>
|
<script src="`{{{ [<coreURL>] }}}`" onerror="alert('Error: Cannot load `{{{ [<coreURL>] }}}`');"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>`
|
</html>`
|
||||||
|
</$set>
|
||||||
</$set>
|
</$set>
|
||||||
@@ -2,6 +2,6 @@ title: $:/core/save/all
|
|||||||
|
|
||||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||||
\define saveTiddlerFilter()
|
\define saveTiddlerFilter()
|
||||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] +[sort[title]] $(publishFilter)$
|
||||||
\end
|
\end
|
||||||
{{$:/core/templates/tiddlywiki5.html}}
|
{{$:/core/templates/tiddlywiki5.html}}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
title: $:/core/save/empty
|
title: $:/core/save/empty
|
||||||
|
|
||||||
\define saveTiddlerFilter()
|
\define saveTiddlerFilter()
|
||||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] +[sort[title]]
|
||||||
\end
|
\end
|
||||||
{{$:/core/templates/tiddlywiki5.html}}
|
{{$:/core/templates/tiddlywiki5.html}}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
title: $:/core/save/lazy-all
|
title: $:/core/save/lazy-all
|
||||||
|
|
||||||
\define saveTiddlerFilter()
|
\define saveTiddlerFilter()
|
||||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] [is[tiddler]type[application/javascript]] +[sort[title]]
|
[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] [is[tiddler]type[application/javascript]] +[sort[title]]
|
||||||
\end
|
\end
|
||||||
\define skinnySaveTiddlerFilter()
|
\define skinnySaveTiddlerFilter()
|
||||||
[!is[system]] -[type[application/javascript]]
|
[!is[system]] -[type[application/javascript]]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
title: $:/core/save/lazy-images
|
title: $:/core/save/lazy-images
|
||||||
|
|
||||||
\define saveTiddlerFilter()
|
\define saveTiddlerFilter()
|
||||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]]
|
[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[has[plugin-type]field:platform[server]] -[!is[system]is[image]] +[sort[title]]
|
||||||
\end
|
\end
|
||||||
\define skinnySaveTiddlerFilter()
|
\define skinnySaveTiddlerFilter()
|
||||||
[!is[system]is[image]]
|
[!is[system]is[image]]
|
||||||
|
|||||||
@@ -62,28 +62,34 @@ caption: {{$:/language/Search/Filter/Caption}}
|
|||||||
</$list>
|
</$list>
|
||||||
\end
|
\end
|
||||||
|
|
||||||
|
\procedure input-actions()
|
||||||
|
<%if [<event-key-descriptor>match[((input-tab-right))]] %>
|
||||||
|
<<set-next-input-tab>>
|
||||||
|
<%elseif [<event-key-descriptor>match[((input-tab-left))]] %>
|
||||||
|
<<set-previous-input-tab>>
|
||||||
|
<%endif%>
|
||||||
|
\end
|
||||||
|
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
|
|
||||||
<<lingo Filter/Hint>>
|
<<lingo Filter/Hint>>
|
||||||
|
|
||||||
<div class="tc-search tc-advanced-search">
|
<div class="tc-search tc-advanced-search">
|
||||||
<$keyboard key="((input-tab-right))" actions=<<set-next-input-tab>> class="tc-small-gap-right">
|
<$keyboard key="((input-tab-right)) ((input-tab-left))" actions=<<input-actions>> class="tc-small-gap-right">
|
||||||
<$keyboard key="((input-tab-left))" actions=<<set-previous-input-tab>>>
|
<$transclude $variable="keyboard-driven-input"
|
||||||
<$transclude $variable="keyboard-driven-input"
|
tiddler="$:/temp/advancedsearch/input"
|
||||||
tiddler="$:/temp/advancedsearch/input"
|
storeTitle="$:/temp/advancedsearch"
|
||||||
storeTitle="$:/temp/advancedsearch"
|
refreshTitle="$:/temp/advancedsearch/refresh"
|
||||||
refreshTitle="$:/temp/advancedsearch/refresh"
|
selectionStateTitle="$:/temp/advancedsearch/selected-item"
|
||||||
selectionStateTitle="$:/temp/advancedsearch/selected-item"
|
type="search"
|
||||||
type="search"
|
tag="input"
|
||||||
tag="input"
|
focus={{$:/config/Search/AutoFocus}}
|
||||||
focus={{$:/config/Search/AutoFocus}}
|
configTiddlerFilter="[[$:/temp/advancedsearch]]"
|
||||||
configTiddlerFilter="[[$:/temp/advancedsearch]]"
|
firstSearchFilterField="text"
|
||||||
firstSearchFilterField="text"
|
inputAcceptActions=<<input-accept-actions>>
|
||||||
inputAcceptActions=<<input-accept-actions>>
|
inputAcceptVariantActions=<<input-accept-variant-actions>>
|
||||||
inputAcceptVariantActions=<<input-accept-variant-actions>>
|
inputCancelActions=<<cancel-search-actions>>
|
||||||
inputCancelActions=<<cancel-search-actions>>
|
/>
|
||||||
/>
|
|
||||||
</$keyboard>
|
|
||||||
</$keyboard>
|
</$keyboard>
|
||||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch/FilterButton]!has[draft.of]]">
|
<$list filter="[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch/FilterButton]!has[draft.of]]">
|
||||||
<$transclude/>
|
<$transclude/>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user