mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-24 03:44:41 +00:00
Compare commits
124 Commits
publishing
...
v5.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d095aa0182 | ||
|
|
15bf850280 | ||
|
|
62b273266e | ||
|
|
1d058177be | ||
|
|
14676b345a | ||
|
|
a50e6eed38 | ||
|
|
073a064ae8 | ||
|
|
e00a3d3cb4 | ||
|
|
68d9200a6b | ||
|
|
2551bb3e3f | ||
|
|
80b18e6315 | ||
|
|
e0561397f1 | ||
|
|
b9c3c38edc | ||
|
|
077ced0d1a | ||
|
|
e5ff84035c | ||
|
|
e18a983209 | ||
|
|
6f61fa07fb | ||
|
|
d5d73e02e9 | ||
|
|
4ba7454d8d | ||
|
|
5192a39830 | ||
|
|
aa5413b942 | ||
|
|
ef284e9bde | ||
|
|
9c41fe1d18 | ||
|
|
e577cf7302 | ||
|
|
ebf563ac70 | ||
|
|
909340c6fe | ||
|
|
df6d38df65 | ||
|
|
59a53e695b | ||
|
|
6d17505f7b | ||
|
|
36dd8ea1d2 | ||
|
|
b965ae926b | ||
|
|
f6eadbd1c9 | ||
|
|
bdbb884be0 | ||
|
|
0be39cfbc2 | ||
|
|
ef2aeac7de | ||
|
|
157afda2fc | ||
|
|
fb4d77ef46 | ||
|
|
575c233597 | ||
|
|
2e59d770f7 | ||
|
|
baf0ee9cde | ||
|
|
af89bb591d | ||
|
|
d0dec741ad | ||
|
|
33a82e395e | ||
|
|
f223896c26 | ||
|
|
de33b365ae | ||
|
|
e9d8547a81 | ||
|
|
dcff318a98 | ||
|
|
f725123690 | ||
|
|
e9e5d37ff0 | ||
|
|
f70cee6907 | ||
|
|
1491339f50 | ||
|
|
8a5ed59ff4 | ||
|
|
a2ca5e4d1e | ||
|
|
fba993502d | ||
|
|
9fae3a932b | ||
|
|
62610f0666 | ||
|
|
7282ec5286 | ||
|
|
9830e0104f | ||
|
|
e6fd0caf6b | ||
|
|
137df37bc7 | ||
|
|
d895706199 | ||
|
|
6ed7d418b5 | ||
|
|
62b8a83741 | ||
|
|
e795b501ac | ||
|
|
03228d8d20 | ||
|
|
c9c5d4cf79 | ||
|
|
f5cc5bc6a1 | ||
|
|
447494ad4d | ||
|
|
c9f178ec87 | ||
|
|
33be326ef6 | ||
|
|
c13f04d838 | ||
|
|
737685149c | ||
|
|
33eef0202d | ||
|
|
a67b1b8bb5 | ||
|
|
124b49456a | ||
|
|
24956087cc | ||
|
|
199ca57f1c | ||
|
|
64d53ac533 | ||
|
|
b3accbf9e0 | ||
|
|
99249a3160 | ||
|
|
f7cd8bad3a | ||
|
|
e9613d7f12 | ||
|
|
97dff042f7 | ||
|
|
32b36fb2af | ||
|
|
41535150dd | ||
|
|
8e69284e8c | ||
|
|
61cfac4eeb | ||
|
|
2720072b23 | ||
|
|
0413c3a38e | ||
|
|
f2b30c1fe0 | ||
|
|
3c86cf7d2e | ||
|
|
451074f7ed | ||
|
|
1e5601ca31 | ||
|
|
75c99cd235 | ||
|
|
bb2c2be9b6 | ||
|
|
53c247b9a1 | ||
|
|
82667d9d16 | ||
|
|
97ed2757f0 | ||
|
|
19fd5ca5f2 | ||
|
|
6ae78a770f | ||
|
|
04962b4cd6 | ||
|
|
f97850dd05 | ||
|
|
2cb3ed3ab9 | ||
|
|
a4421f50c6 | ||
|
|
cb726f40fa | ||
|
|
be026aa308 | ||
|
|
b95f6ca084 | ||
|
|
4a7f078abd | ||
|
|
54d8b8a373 | ||
|
|
dd6bd58140 | ||
|
|
4c56bd771a | ||
|
|
a70b26cd55 | ||
|
|
c4a7ae3164 | ||
|
|
8b8f654c9c | ||
|
|
f342fdc41d | ||
|
|
ca96f7f62b | ||
|
|
2f31eab8f4 | ||
|
|
c8528fd1f7 | ||
|
|
07ac85d9fa | ||
|
|
e84f214280 | ||
|
|
9cd65efad9 | ||
|
|
41200ab6d7 | ||
|
|
792171c8fc | ||
|
|
051a468c63 |
23
boot/boot.js
23
boot/boot.js
@@ -1212,8 +1212,12 @@ $tw.Wiki = function(options) {
|
||||
index,titlesLength,title;
|
||||
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
|
||||
title = titles[index];
|
||||
var shadowInfo = shadowTiddlers[title];
|
||||
callback(shadowInfo.tiddler,title);
|
||||
if(tiddlers[title]) {
|
||||
callback(tiddlers[title],title);
|
||||
} else {
|
||||
var shadowInfo = shadowTiddlers[title];
|
||||
callback(shadowInfo.tiddler,title);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1602,8 +1606,8 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
|
||||
}
|
||||
for(var f in data) {
|
||||
if($tw.utils.hop(data,f)) {
|
||||
// Check field name doesn't contain whitespace or control characters
|
||||
if(typeof(data[f]) !== "string" || /[\x00-\x1F\s]/.test(f)) {
|
||||
// Check field name doesn't contain control characters
|
||||
if(typeof(data[f]) !== "string" || /[\x00-\x1F]/.test(f)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1618,7 +1622,12 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
|
||||
}
|
||||
return true;
|
||||
},
|
||||
data = JSON.parse(text);
|
||||
data = {};
|
||||
try {
|
||||
data = JSON.parse(text);
|
||||
} catch(e) {
|
||||
// Ignore JSON parse errors
|
||||
}
|
||||
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
|
||||
return data;
|
||||
} else if(isTiddlerValid(data)) {
|
||||
@@ -1885,13 +1894,13 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||
value = path.basename(filename);
|
||||
break;
|
||||
case "filename-uri-decoded":
|
||||
value = decodeURIComponent(path.basename(filename));
|
||||
value = $tw.utils.decodeURIComponentSafe(path.basename(filename));
|
||||
break;
|
||||
case "basename":
|
||||
value = path.basename(filename,path.extname(filename));
|
||||
break;
|
||||
case "basename-uri-decoded":
|
||||
value = decodeURIComponent(path.basename(filename,path.extname(filename)));
|
||||
value = $tw.utils.decodeURIComponentSafe(path.basename(filename,path.extname(filename)));
|
||||
break;
|
||||
case "extname":
|
||||
value = path.extname(filename);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -32,8 +32,6 @@ ExportTiddler/Caption: export tiddler
|
||||
ExportTiddler/Hint: Export tiddler
|
||||
ExportTiddlers/Caption: export tiddlers
|
||||
ExportTiddlers/Hint: Export tiddlers
|
||||
ExportTiddlyWikiCore/Caption: export TiddlyWiki core
|
||||
ExportTiddlyWikiCore/Hint: Export the ~TiddlyWiki core code for running with external ~JavaScript
|
||||
SidebarSearch/Hint: Select the sidebar search field
|
||||
Fold/Caption: fold tiddler
|
||||
Fold/Hint: Fold the body of this tiddler
|
||||
|
||||
@@ -22,7 +22,6 @@ All parameters are optional with safe defaults, and can be specified in any orde
|
||||
* ''readers'' - comma-separated list of principals allowed to read from this wiki
|
||||
* ''writers'' - comma-separated list of principals allowed to write to this wiki
|
||||
* ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no")
|
||||
* ''sse-enabled'' - set to "yes" to enable Server-sent events (defaults to "no")
|
||||
* ''root-tiddler'' - the tiddler to serve at the root (defaults to "$:/core/save/all")
|
||||
* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to "text/plain")
|
||||
* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to "text/html")
|
||||
|
||||
@@ -30,5 +30,5 @@ Upgrader/System/Warning: Core module tiddler.
|
||||
Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable.
|
||||
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>.
|
||||
Upgrader/Tiddler/Disabled: Disabled tiddler.
|
||||
Upgrader/Tiddler/Selected: User selected.
|
||||
Upgrader/Tiddler/Selected: Selected tiddler.
|
||||
Upgrader/Tiddler/Unselected: Unselected tiddler.
|
||||
|
||||
@@ -8,58 +8,59 @@ Render individual tiddlers and save the results to the specified files
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var widget = require("$:/core/modules/widgets/widget.js");
|
||||
|
||||
exports.info = {
|
||||
name: "render",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
if(this.params.length < 1) {
|
||||
return "Missing tiddler filter";
|
||||
}
|
||||
var self = this,
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
wiki = this.commander.wiki,
|
||||
tiddlerFilter = this.params[0],
|
||||
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
|
||||
type = this.params[2] || "text/html",
|
||||
template = this.params[3],
|
||||
variableList = this.params.slice(4),
|
||||
tiddlers = wiki.filterTiddlers(tiddlerFilter),
|
||||
variables = Object.create(null);
|
||||
while(variableList.length >= 2) {
|
||||
variables[variableList[0]] = variableList[1];
|
||||
variableList = variableList.slice(2);
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var widget = require("$:/core/modules/widgets/widget.js");
|
||||
|
||||
exports.info = {
|
||||
name: "render",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
if(this.params.length < 1) {
|
||||
return "Missing tiddler filter";
|
||||
}
|
||||
$tw.utils.each(tiddlers,function(title) {
|
||||
var parser = wiki.parseTiddler(template || title);
|
||||
var widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title})}),
|
||||
container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
var text = type === "text/html" ? container.innerHTML : container.textContent,
|
||||
filepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);
|
||||
if(self.commander.verbose) {
|
||||
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
|
||||
}
|
||||
$tw.utils.createFileDirectories(filepath);
|
||||
fs.writeFileSync(filepath,text,"utf8");
|
||||
});
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
var self = this,
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
wiki = this.commander.wiki,
|
||||
tiddlerFilter = this.params[0],
|
||||
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
|
||||
type = this.params[2] || "text/html",
|
||||
template = this.params[3],
|
||||
variableList = this.params.slice(4),
|
||||
tiddlers = wiki.filterTiddlers(tiddlerFilter),
|
||||
variables = Object.create(null);
|
||||
while(variableList.length >= 2) {
|
||||
variables[variableList[0]] = variableList[1];
|
||||
variableList = variableList.slice(2);
|
||||
}
|
||||
$tw.utils.each(tiddlers,function(title) {
|
||||
var filepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);
|
||||
if(self.commander.verbose) {
|
||||
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
|
||||
}
|
||||
var parser = wiki.parseTiddler(template || title),
|
||||
widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title})}),
|
||||
container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
var text = type === "text/html" ? container.innerHTML : container.textContent;
|
||||
$tw.utils.createFileDirectories(filepath);
|
||||
fs.writeFileSync(filepath,text,"utf8");
|
||||
});
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
|
||||
@@ -135,7 +135,11 @@ FramedEngine.prototype.setText = function(text,type) {
|
||||
Update the DomNode with the new text
|
||||
*/
|
||||
FramedEngine.prototype.updateDomNodeText = function(text) {
|
||||
this.domNode.value = text;
|
||||
try {
|
||||
this.domNode.value = text;
|
||||
} catch(e) {
|
||||
// Ignore
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -85,7 +85,11 @@ SimpleEngine.prototype.setText = function(text,type) {
|
||||
Update the DomNode with the new text
|
||||
*/
|
||||
SimpleEngine.prototype.updateDomNodeText = function(text) {
|
||||
this.domNode.value = text;
|
||||
try {
|
||||
this.domNode.value = text;
|
||||
} catch(e) {
|
||||
// Ignore
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -332,7 +332,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
};
|
||||
|
||||
EditTextWidget.prototype.handlePasteEvent = function(event) {
|
||||
if(event.clipboardData.files.length) {
|
||||
if(event.clipboardData && event.clipboardData.files && event.clipboardData.files.length) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.dispatchDOMEvent(this.cloneEvent(event,["clipboardData"]));
|
||||
|
||||
@@ -52,7 +52,7 @@ exports.all = function(source,operator,options) {
|
||||
results.pushTop(subop(source,operator.prefix,options));
|
||||
}
|
||||
}
|
||||
return results.toArray();
|
||||
return results.makeTiddlerIterator(options.wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -16,11 +16,11 @@ Filter operator for returning all the backlinks from a tiddler
|
||||
Export our filter function
|
||||
*/
|
||||
exports.backlinks = function(source,operator,options) {
|
||||
var results = [];
|
||||
var results = new $tw.utils.LinkedList();
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.pushTop(results,options.wiki.getTiddlerBacklinks(title));
|
||||
results.pushTop(options.wiki.getTiddlerBacklinks(title));
|
||||
});
|
||||
return results;
|
||||
return results.makeTiddlerIterator(options.wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -19,12 +19,7 @@ Export our filter functions
|
||||
exports.decodeuricomponent = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
var value = title;
|
||||
try {
|
||||
value = decodeURIComponent(title);
|
||||
} catch(e) {
|
||||
}
|
||||
results.push(value);
|
||||
results.push($tw.utils.decodeURIComponentSafe(title));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
@@ -40,12 +35,7 @@ exports.encodeuricomponent = function(source,operator,options) {
|
||||
exports.decodeuri = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
var value = title;
|
||||
try {
|
||||
value = decodeURI(title);
|
||||
} catch(e) {
|
||||
}
|
||||
results.push(value);
|
||||
results.push($tw.utils.decodeURISafe(title));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ exports.links = function(source,operator,options) {
|
||||
source(function(tiddler,title) {
|
||||
results.pushTop(options.wiki.getTiddlerLinks(title));
|
||||
});
|
||||
return results.toArray();
|
||||
return results.makeTiddlerIterator(options.wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
30
core/modules/filters/moduleproperty.js
Normal file
30
core/modules/filters/moduleproperty.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/moduleproperty.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter [[module-name]moduleproperty[name]] retrieve a module property
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.moduleproperty = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
var value = require(title)[operator.operand || ""];
|
||||
if(value !== undefined) {
|
||||
results.push(value);
|
||||
}
|
||||
});
|
||||
results.sort();
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -17,11 +17,23 @@ Export our filter function
|
||||
*/
|
||||
exports.modules = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
|
||||
results.push(moduleName);
|
||||
if(operator.operands.length >= 2) {
|
||||
// Return the modules that have the module property specified in the first operand with the value in the second operand
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
|
||||
if(require(moduleName)[operator.operands[0]] === operator.operands[1]) {
|
||||
results.push(moduleName);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Return all the module names without filtering
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
|
||||
results.push(moduleName);
|
||||
});
|
||||
});
|
||||
}
|
||||
results.sort();
|
||||
return results;
|
||||
};
|
||||
|
||||
@@ -17,9 +17,13 @@ Export our filter function
|
||||
*/
|
||||
exports.range = function(source,operator,options) {
|
||||
var results = [];
|
||||
// Split the operand into numbers delimited by these symbols
|
||||
var parts = operator.operand.split(/[,:;]/g),
|
||||
beg, end, inc, i, fixed = 0;
|
||||
// For backwards compatibility, if there is only one operand, try to split it using one of the delimiters
|
||||
var parts = operator.operands || [];
|
||||
if(parts.length === 1) {
|
||||
parts = operator.operand.split(/[,:;]/g);
|
||||
}
|
||||
// Process the parts
|
||||
var beg, end, inc, i, fixed = 0;
|
||||
for (i=0; i<parts.length; i++) {
|
||||
// Validate real number
|
||||
if(!/^\s*[+-]?((\d+(\.\d*)?)|(\.\d+))\s*$/.test(parts[i])) {
|
||||
|
||||
@@ -119,7 +119,7 @@ exports["search-replace"] = function(source,operator,options) {
|
||||
var results = [],
|
||||
suffixes = operator.suffixes || [],
|
||||
flagSuffix = (suffixes[0] ? (suffixes[0][0] || "") : ""),
|
||||
flags = (flagSuffix.indexOf("g") !== -1 ? "g" : "") + (flagSuffix.indexOf("i") !== -1 ? "i" : ""),
|
||||
flags = (flagSuffix.indexOf("g") !== -1 ? "g" : "") + (flagSuffix.indexOf("i") !== -1 ? "i" : "") + (flagSuffix.indexOf("m") !== -1 ? "m" : ""),
|
||||
isRegExp = (suffixes[1] && suffixes[1][0] === "regexp") ? true : false,
|
||||
searchTerm,
|
||||
regExp;
|
||||
|
||||
@@ -16,20 +16,13 @@ Filter operator returning all the selected tiddlers that are untagged
|
||||
Export our filter function
|
||||
*/
|
||||
exports.untagged = function(source,operator,options) {
|
||||
var results = [];
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) {
|
||||
$tw.utils.pushTop(results,title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
source(function(tiddler,title) {
|
||||
if(!tiddler || !tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
|
||||
$tw.utils.pushTop(results,title);
|
||||
}
|
||||
});
|
||||
}
|
||||
var results = [],
|
||||
expected = (operator.prefix === "!");
|
||||
source(function(tiddler,title) {
|
||||
if((tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) === expected) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ AndTidWiki.prototype.save = function(text,method,callback,options) {
|
||||
window.twi.saveWiki(text);
|
||||
} else {
|
||||
// Get the pathname of this document
|
||||
var pathname = decodeURIComponent(document.location.toString().split("#")[0]);
|
||||
var pathname = $tw.utils.decodeURIComponentSafe(document.location.toString().split("#")[0]);
|
||||
// Strip the file://
|
||||
if(pathname.indexOf("file://") === 0) {
|
||||
pathname = pathname.substr(7);
|
||||
|
||||
@@ -26,7 +26,7 @@ DownloadSaver.prototype.save = function(text,method,callback,options) {
|
||||
var p = document.location.pathname.lastIndexOf("/");
|
||||
if(p !== -1) {
|
||||
// We decode the pathname because document.location is URL encoded by the browser
|
||||
filename = decodeURIComponent(document.location.pathname.substr(p+1));
|
||||
filename = $tw.utils.decodeURIComponentSafe(document.location.pathname.substr(p+1));
|
||||
}
|
||||
}
|
||||
if(!filename) {
|
||||
|
||||
@@ -72,7 +72,7 @@ GiteaSaver.prototype.save = function(text,method,callback) {
|
||||
}
|
||||
}
|
||||
var data = {
|
||||
message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
message: $tw.language.getString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
content: $tw.utils.base64Encode(text),
|
||||
sha: sha
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ GitHubSaver.prototype.save = function(text,method,callback) {
|
||||
});
|
||||
}
|
||||
var data = {
|
||||
message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
message: $tw.language.getString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
content: $tw.utils.base64Encode(text),
|
||||
branch: branch,
|
||||
sha: sha
|
||||
|
||||
@@ -67,7 +67,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
|
||||
});
|
||||
}
|
||||
var data = {
|
||||
commit_message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
commit_message: $tw.language.getString("ControlPanel/Saving/GitService/CommitMessage"),
|
||||
content: text,
|
||||
branch: branch,
|
||||
sha: sha
|
||||
|
||||
@@ -43,7 +43,7 @@ TiddlyFoxSaver.prototype.save = function(text,method,callback) {
|
||||
}
|
||||
// Create the message element and put it in the message box
|
||||
var message = document.createElement("div");
|
||||
message.setAttribute("data-tiddlyfox-path",decodeURIComponent(pathname));
|
||||
message.setAttribute("data-tiddlyfox-path",$tw.utils.decodeURIComponentSafe(pathname));
|
||||
message.setAttribute("data-tiddlyfox-content",text);
|
||||
messageBox.appendChild(message);
|
||||
// Add an event handler for when the file has been saved
|
||||
|
||||
@@ -21,7 +21,7 @@ TWEditSaver.prototype.save = function(text,method,callback) {
|
||||
return false;
|
||||
}
|
||||
// Get the pathname of this document
|
||||
var pathname = decodeURIComponent(document.location.pathname);
|
||||
var pathname = $tw.utils.decodeURIComponentSafe(document.location.pathname);
|
||||
// Strip any query or location part
|
||||
var p = pathname.indexOf("?");
|
||||
if(p !== -1) {
|
||||
|
||||
@@ -17,7 +17,7 @@ exports.method = "DELETE";
|
||||
exports.path = /^\/bags\/default\/tiddlers\/(.+)$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = decodeURIComponent(state.params[0]);
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]);
|
||||
state.wiki.deleteTiddler(title);
|
||||
response.writeHead(204, "OK", {
|
||||
"Content-Type": "text/plain"
|
||||
|
||||
@@ -20,22 +20,29 @@ exports.handler = function(request,response,state) {
|
||||
var path = require("path"),
|
||||
fs = require("fs"),
|
||||
util = require("util"),
|
||||
suppliedFilename = decodeURIComponent(state.params[0]),
|
||||
filename = path.resolve(state.boot.wikiPath,"files",suppliedFilename),
|
||||
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
baseFilename = path.resolve(state.boot.wikiPath,"files"),
|
||||
filename = path.resolve(baseFilename,suppliedFilename),
|
||||
extension = path.extname(filename);
|
||||
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);
|
||||
});
|
||||
// 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");
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
@@ -21,7 +21,6 @@ exports.handler = function(request,response,state) {
|
||||
username: state.authenticatedUsername || state.server.get("anon-username") || "",
|
||||
anonymous: !state.authenticatedUsername,
|
||||
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
|
||||
sse_enabled: state.server.get("sse-enabled") === "yes",
|
||||
space: {
|
||||
recipe: "default"
|
||||
},
|
||||
|
||||
@@ -17,7 +17,7 @@ exports.method = "GET";
|
||||
exports.path = /^\/([^\/]+)$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = decodeURIComponent(state.params[0]),
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
tiddler = state.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
var renderType = tiddler.getFieldString("_render_type"),
|
||||
|
||||
@@ -17,7 +17,7 @@ exports.method = "GET";
|
||||
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = decodeURIComponent(state.params[0]),
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
tiddler = state.wiki.getTiddler(title),
|
||||
tiddlerFields = {},
|
||||
knownFields = [
|
||||
|
||||
@@ -17,7 +17,7 @@ exports.method = "PUT";
|
||||
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = decodeURIComponent(state.params[0]),
|
||||
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||
fields = JSON.parse(state.data);
|
||||
// Pull up any subfields in the `fields` object
|
||||
if(fields.fields) {
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/server/server-sent-events.js
|
||||
type: application/javascript
|
||||
module-type: library
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
parameters:
|
||||
prefix - usually the plugin path, such as `plugins/tiddlywiki/tiddlyweb`. The
|
||||
route will match `/events/${prefix}` exactly.
|
||||
|
||||
handler - a function that will be called each time a request comes in with the
|
||||
request and state from the route and an emit function to call.
|
||||
*/
|
||||
|
||||
var ServerSentEvents = function ServerSentEvents(prefix, handler) {
|
||||
this.handler = handler;
|
||||
this.prefix = prefix;
|
||||
};
|
||||
|
||||
ServerSentEvents.prototype.getExports = function() {
|
||||
return {
|
||||
bodyFormat: "stream",
|
||||
method: "GET",
|
||||
path: new RegExp("^/events/" + this.prefix + "$"),
|
||||
handler: this.handleEventRequest.bind(this)
|
||||
};
|
||||
};
|
||||
|
||||
ServerSentEvents.prototype.handleEventRequest = function(request,response,state) {
|
||||
if(ServerSentEvents.prototype.isEventStreamRequest(request)) {
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive"
|
||||
});
|
||||
this.handler(request,state,this.emit.bind(this,response),this.end.bind(this,response));
|
||||
} else {
|
||||
response.writeHead(406,"Not Acceptable",{});
|
||||
response.end();
|
||||
}
|
||||
};
|
||||
|
||||
ServerSentEvents.prototype.isEventStreamRequest = function(request) {
|
||||
return request.headers.accept &&
|
||||
request.headers.accept.match(/^text\/event-stream/);
|
||||
};
|
||||
|
||||
ServerSentEvents.prototype.emit = function(response,event,data) {
|
||||
if(typeof event !== "string" || event.indexOf("\n") !== -1) {
|
||||
throw new Error("Type must be a single-line string");
|
||||
}
|
||||
if(typeof data !== "string" || data.indexOf("\n") !== -1) {
|
||||
throw new Error("Data must be a single-line string");
|
||||
}
|
||||
response.write("event: " + event + "\ndata: " + data + "\n\n", "utf8");
|
||||
};
|
||||
|
||||
ServerSentEvents.prototype.end = function(response) {
|
||||
response.end();
|
||||
};
|
||||
|
||||
exports.ServerSentEvents = ServerSentEvents;
|
||||
|
||||
})();
|
||||
@@ -120,10 +120,10 @@ function openStartupTiddlers(options) {
|
||||
var hash = $tw.locationHash.substr(1),
|
||||
split = hash.indexOf(":");
|
||||
if(split === -1) {
|
||||
target = decodeURIComponent(hash.trim());
|
||||
target = $tw.utils.decodeURIComponentSafe(hash.trim());
|
||||
} else {
|
||||
target = decodeURIComponent(hash.substr(0,split).trim());
|
||||
storyFilter = decodeURIComponent(hash.substr(split + 1).trim());
|
||||
target = $tw.utils.decodeURIComponentSafe(hash.substr(0,split).trim());
|
||||
storyFilter = $tw.utils.decodeURIComponentSafe(hash.substr(split + 1).trim());
|
||||
}
|
||||
}
|
||||
// If the story wasn't specified use the current tiddlers or a blank story
|
||||
|
||||
@@ -20,7 +20,6 @@ Syncer.prototype.titleIsAnonymous = "$:/status/IsAnonymous";
|
||||
Syncer.prototype.titleIsReadOnly = "$:/status/IsReadOnly";
|
||||
Syncer.prototype.titleUserName = "$:/status/UserName";
|
||||
Syncer.prototype.titleSyncFilter = "$:/config/SyncFilter";
|
||||
Syncer.prototype.titleSyncDisablePolling = "$:/config/SyncDisablePolling";
|
||||
Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval";
|
||||
Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading";
|
||||
Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done";
|
||||
@@ -90,7 +89,7 @@ function Syncer(options) {
|
||||
if(filteredChanges.length > 0) {
|
||||
self.processTaskQueue();
|
||||
} else {
|
||||
// Look for deletions of tiddlers we're already syncing
|
||||
// Look for deletions of tiddlers we're already syncing
|
||||
var outstandingDeletion = false
|
||||
$tw.utils.each(changes,function(change,title,object) {
|
||||
if(change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) {
|
||||
@@ -122,7 +121,7 @@ function Syncer(options) {
|
||||
self.login(username,password,function() {});
|
||||
} else {
|
||||
// No username and password, so we display a prompt
|
||||
self.handleLoginEvent();
|
||||
self.handleLoginEvent();
|
||||
}
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tm-logout",function() {
|
||||
@@ -139,7 +138,7 @@ function Syncer(options) {
|
||||
if(!this.disableUI && this.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== "yes") {
|
||||
this.wiki.addEventListener("lazyLoad",function(title) {
|
||||
self.handleLazyLoadEvent(title);
|
||||
});
|
||||
});
|
||||
}
|
||||
// Get the login status
|
||||
this.getStatus(function(err,isLoggedIn) {
|
||||
@@ -174,8 +173,8 @@ Syncer.prototype.getTiddlerRevision = function(title) {
|
||||
if(this.syncadaptor && this.syncadaptor.getTiddlerRevision) {
|
||||
return this.syncadaptor.getTiddlerRevision(title);
|
||||
} else {
|
||||
return this.wiki.getTiddler(title).fields.revision;
|
||||
}
|
||||
return this.wiki.getTiddler(title).fields.revision;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -268,9 +267,9 @@ Syncer.prototype.getStatus = function(callback) {
|
||||
// Mark us as not logged in
|
||||
this.wiki.addTiddler({title: this.titleIsLoggedIn,text: "no"});
|
||||
// Get login status
|
||||
this.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous,isPollingDisabled) {
|
||||
this.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous) {
|
||||
if(err) {
|
||||
self.logger.alert(err);
|
||||
self.displayError("Get Status Error",err);
|
||||
} else {
|
||||
// Set the various status tiddlers
|
||||
self.wiki.addTiddler({title: self.titleIsReadOnly,text: isReadOnly ? "yes" : "no"});
|
||||
@@ -279,9 +278,6 @@ Syncer.prototype.getStatus = function(callback) {
|
||||
if(isLoggedIn) {
|
||||
self.wiki.addTiddler({title: self.titleUserName,text: username || ""});
|
||||
}
|
||||
if(isPollingDisabled) {
|
||||
self.wiki.addTiddler({title: self.titleSyncDisablePolling, text: "yes"});
|
||||
}
|
||||
}
|
||||
// Invoke the callback
|
||||
if(callback) {
|
||||
@@ -305,15 +301,12 @@ Syncer.prototype.syncFromServer = function() {
|
||||
}
|
||||
},
|
||||
triggerNextSync = function() {
|
||||
if(pollingEnabled) {
|
||||
self.pollTimerId = setTimeout(function() {
|
||||
self.pollTimerId = null;
|
||||
self.syncFromServer.call(self);
|
||||
},self.pollTimerInterval);
|
||||
}
|
||||
self.pollTimerId = setTimeout(function() {
|
||||
self.pollTimerId = null;
|
||||
self.syncFromServer.call(self);
|
||||
},self.pollTimerInterval);
|
||||
},
|
||||
syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes"),
|
||||
pollingEnabled = (self.wiki.getTiddlerText(self.titleSyncDisablePolling) !== "yes");
|
||||
syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes" ? true : false);
|
||||
if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {
|
||||
this.logger.log("Retrieving updated tiddler list");
|
||||
cancelNextSync();
|
||||
@@ -336,7 +329,7 @@ Syncer.prototype.syncFromServer = function() {
|
||||
});
|
||||
if(updates.modifications.length > 0 || updates.deletions.length > 0) {
|
||||
self.processTaskQueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {
|
||||
@@ -479,7 +472,7 @@ Syncer.prototype.handleLogoutEvent = function() {
|
||||
if(this.syncadaptor.logout) {
|
||||
this.syncadaptor.logout(function(err) {
|
||||
if(err) {
|
||||
self.logger.alert(err);
|
||||
self.displayError("Logout Error",err);
|
||||
} else {
|
||||
self.getStatus();
|
||||
}
|
||||
@@ -516,7 +509,7 @@ Syncer.prototype.processTaskQueue = function() {
|
||||
} else {
|
||||
self.updateDirtyStatus();
|
||||
// Process the next task
|
||||
self.processTaskQueue.call(self);
|
||||
self.processTaskQueue.call(self);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -524,11 +517,11 @@ Syncer.prototype.processTaskQueue = function() {
|
||||
this.updateDirtyStatus();
|
||||
// And trigger a timeout if there is a pending task
|
||||
if(task === true) {
|
||||
this.triggerTimeout();
|
||||
this.triggerTimeout();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.updateDirtyStatus();
|
||||
this.updateDirtyStatus();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -562,7 +555,7 @@ Syncer.prototype.chooseNextTask = function() {
|
||||
isReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;
|
||||
if(hasChanged) {
|
||||
if(isReadyToSave) {
|
||||
return new SaveTiddlerTask(this,title);
|
||||
return new SaveTiddlerTask(this,title);
|
||||
} else {
|
||||
havePending = true;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ Browser data transfer utilities, used with the clipboard and drag and drop
|
||||
Options:
|
||||
|
||||
domNode: dom node to make draggable
|
||||
dragImageType: "pill" or "dom"
|
||||
dragImageType: "pill", "blank" or "dom" (the default)
|
||||
dragTiddlerFn: optional function to retrieve the title of tiddler to drag
|
||||
dragFilterFn: optional function to retreive the filter defining a list of tiddlers to drag
|
||||
widget: widget to use as the contect for the filter
|
||||
@@ -73,6 +73,9 @@ exports.makeDraggable = function(options) {
|
||||
if(dataTransfer.setDragImage) {
|
||||
if(dragImageType === "pill") {
|
||||
dataTransfer.setDragImage(dragImage.firstChild,-16,-16);
|
||||
} else if (dragImageType === "blank") {
|
||||
dragImage.removeChild(dragImage.firstChild);
|
||||
dataTransfer.setDragImage(dragImage,0,0);
|
||||
} else {
|
||||
var r = domNode.getBoundingClientRect();
|
||||
dataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);
|
||||
@@ -164,7 +167,7 @@ var importDataTypes = [
|
||||
}},
|
||||
{type: "URL", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
var match = $tw.utils.decodeURIComponentSafe(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return parseJSONTiddlers(match[1],fallbackTitle);
|
||||
} else {
|
||||
@@ -173,7 +176,7 @@ var importDataTypes = [
|
||||
}},
|
||||
{type: "text/x-moz-url", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
var match = $tw.utils.decodeURIComponentSafe(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return parseJSONTiddlers(match[1],fallbackTitle);
|
||||
} else {
|
||||
|
||||
@@ -34,6 +34,23 @@ exports.httpRequest = function(options) {
|
||||
});
|
||||
return result;
|
||||
},
|
||||
getHeader = function(targetHeader) {
|
||||
return headers[targetHeader] || headers[targetHeader.toLowerCase()];
|
||||
},
|
||||
isSimpleRequest = function(type,headers) {
|
||||
if(["GET","HEAD","POST"].indexOf(type) === -1) {
|
||||
return false;
|
||||
}
|
||||
for(var header in headers) {
|
||||
if(["accept","accept-language","content-language","content-type"].indexOf(header.toLowerCase()) === -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(hasHeader("Content-Type") && ["application/x-www-form-urlencoded","multipart/form-data","text/plain"].indexOf(getHeader["Content-Type"]) === -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
returnProp = options.returnProp || "responseText",
|
||||
request = new XMLHttpRequest(),
|
||||
data = "",
|
||||
@@ -76,7 +93,7 @@ exports.httpRequest = function(options) {
|
||||
if(data && !hasHeader("Content-Type")) {
|
||||
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
|
||||
}
|
||||
if(!hasHeader("X-Requested-With")) {
|
||||
if(!hasHeader("X-Requested-With") && !isSimpleRequest(type,headers)) {
|
||||
request.setRequestHeader("X-Requested-With","TiddlyWiki");
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -235,7 +235,7 @@ Object.defineProperty(TW_Element.prototype, "innerHTML", {
|
||||
if(node instanceof TW_Element) {
|
||||
b.push(node.outerHTML);
|
||||
} else if(node instanceof TW_TextNode) {
|
||||
b.push($tw.utils.htmlEncode(node.textContent));
|
||||
b.push($tw.utils.htmlTextEncode(node.textContent));
|
||||
}
|
||||
});
|
||||
return b.join("");
|
||||
|
||||
@@ -95,6 +95,15 @@ LinkedList.prototype.toArray = function() {
|
||||
return output;
|
||||
};
|
||||
|
||||
LinkedList.prototype.makeTiddlerIterator = function(wiki) {
|
||||
var self = this;
|
||||
return function(callback) {
|
||||
self.each(function(title) {
|
||||
callback(wiki.getTiddler(title),title);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
function _removeOne(list,value) {
|
||||
var prevEntry = list.prev[value],
|
||||
nextEntry = list.next[value],
|
||||
|
||||
@@ -199,6 +199,8 @@ exports.transliterationPairs = {
|
||||
"Nj":"N",
|
||||
"Ñ":"N",
|
||||
"NJ":"NJ",
|
||||
"ð":"d",
|
||||
"Ð":"D",
|
||||
"Ó":"O",
|
||||
"Ŏ":"O",
|
||||
"Ǒ":"O",
|
||||
@@ -265,6 +267,8 @@ exports.transliterationPairs = {
|
||||
"Ɽ":"R",
|
||||
"Ꜿ":"C",
|
||||
"Ǝ":"E",
|
||||
"ß":"ss",
|
||||
"ẞ":"SS",
|
||||
"Ś":"S",
|
||||
"Ṥ":"S",
|
||||
"Š":"S",
|
||||
@@ -275,6 +279,8 @@ exports.transliterationPairs = {
|
||||
"Ṡ":"S",
|
||||
"Ṣ":"S",
|
||||
"Ṩ":"S",
|
||||
"þ": "th",
|
||||
"Þ": "TH",
|
||||
"Ť":"T",
|
||||
"Ţ":"T",
|
||||
"Ṱ":"T",
|
||||
@@ -907,7 +913,8 @@ exports.transliterationPairs = {
|
||||
"т":"t",
|
||||
"ь":"'",
|
||||
"б":"b",
|
||||
"ю":"yu"
|
||||
"ю":"yu",
|
||||
"…":"..."
|
||||
};
|
||||
|
||||
exports.transliterate = function(str) {
|
||||
|
||||
@@ -383,6 +383,15 @@ exports.formatDateString = function(date,template) {
|
||||
[/^0WW/, function() {
|
||||
return $tw.utils.pad($tw.utils.getWeek(date));
|
||||
}],
|
||||
[/^0ddddd/, function() {
|
||||
return $tw.utils.pad(Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24),3);
|
||||
}],
|
||||
[/^ddddd/, function() {
|
||||
return Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
|
||||
}],
|
||||
[/^dddd/, function() {
|
||||
return [7,1,2,3,4,5,6][date.getDay()];
|
||||
}],
|
||||
[/^ddd/, function() {
|
||||
return $tw.language.getString("Date/Short/Day/" + date.getDay());
|
||||
}],
|
||||
@@ -969,4 +978,22 @@ exports.makeCompareFunction = function(type,options) {
|
||||
return (types[type] || types[options.defaultType] || types.number);
|
||||
};
|
||||
|
||||
exports.decodeURIComponentSafe = function(str) {
|
||||
var value = str;
|
||||
try {
|
||||
value = decodeURIComponent(str);
|
||||
} catch(e) {
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
exports.decodeURISafe = function(str) {
|
||||
var value = str;
|
||||
try {
|
||||
value = decodeURI(str);
|
||||
} catch(e) {
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -59,7 +59,7 @@ Invoke the action associated with this widget
|
||||
ConfirmWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
var invokeActions = true,
|
||||
handled = true,
|
||||
win = event.event && event.event.view ? event.event.view : window;
|
||||
win = event && event.event && event.event.view ? event.event.view : window;
|
||||
if(this.prompt) {
|
||||
invokeActions = win.confirm(this.message);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ DraggableWidget.prototype.render = function(parent,nextSibling) {
|
||||
dragFilterFn: function() {return self.getAttribute("filter");},
|
||||
startActions: self.startActions,
|
||||
endActions: self.endActions,
|
||||
dragImageType: self.dragImageType,
|
||||
widget: this
|
||||
});
|
||||
// Insert the link into the DOM and render any children
|
||||
@@ -71,6 +72,7 @@ DraggableWidget.prototype.execute = function() {
|
||||
this.draggableClasses = this.getAttribute("class");
|
||||
this.startActions = this.getAttribute("startactions");
|
||||
this.endActions = this.getAttribute("endactions");
|
||||
this.dragImageType = this.getAttribute("dragimagetype");
|
||||
// Make the child widgets
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
@@ -76,16 +76,22 @@ EventWidget.prototype.render = function(parent,nextSibling) {
|
||||
variables["tv-selectednode-posy"] = selectedNode.offsetTop.toString();
|
||||
variables["tv-selectednode-width"] = selectedNode.offsetWidth.toString();
|
||||
variables["tv-selectednode-height"] = selectedNode.offsetHeight.toString();
|
||||
|
||||
if(event.clientX && event.clientY) {
|
||||
//Add variables for event X and Y position relative to selected node
|
||||
selectedNodeRect = selectedNode.getBoundingClientRect();
|
||||
variables["event-fromselected-posx"] = (event.clientX - selectedNodeRect.left).toString();
|
||||
variables["event-fromselected-posy"] = (event.clientY - selectedNodeRect.top).toString();
|
||||
|
||||
//Add variables for event X and Y position relative to selected node
|
||||
selectedNodeRect = selectedNode.getBoundingClientRect();
|
||||
variables["event-fromselected-posx"] = (event.clientX - selectedNodeRect.left).toString();
|
||||
variables["event-fromselected-posy"] = (event.clientY - selectedNodeRect.top).toString();
|
||||
//Add variables for event X and Y position relative to event catcher node
|
||||
catcherNodeRect = self.domNode.getBoundingClientRect();
|
||||
variables["event-fromcatcher-posx"] = (event.clientX - catcherNodeRect.left).toString();
|
||||
variables["event-fromcatcher-posy"] = (event.clientY - catcherNodeRect.top).toString();
|
||||
|
||||
//Add variables for event X and Y position relative to event catcher node
|
||||
catcherNodeRect = self.domNode.getBoundingClientRect();
|
||||
variables["event-fromcatcher-posx"] = (event.clientX - catcherNodeRect.left).toString();
|
||||
variables["event-fromcatcher-posy"] = (event.clientY - catcherNodeRect.top).toString();
|
||||
//Add variables for event X and Y position relative to the viewport
|
||||
variables["event-fromviewport-posx"] = event.clientX.toString();
|
||||
variables["event-fromviewport-posy"] = event.clientY.toString();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -32,13 +32,7 @@ JSONTiddlerWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Collect the fields from the optional base tiddler
|
||||
var fields = {};
|
||||
if(this.attTiddler) {
|
||||
var tiddler = this.wiki.getTiddler(this.attTiddler);
|
||||
if(tiddler) {
|
||||
fields = tiddler.getFieldStrings({exclude: this.attExclude.split(" ")});
|
||||
}
|
||||
}
|
||||
var fields = this.getTiddlerFields();
|
||||
// Add custom fields specified in attributes starting with $
|
||||
$tw.utils.each(this.attributes,function(attribute,name) {
|
||||
if(name.charAt(0) === "$") {
|
||||
@@ -79,6 +73,19 @@ JSONTiddlerWidget.prototype.refresh = function(changedTiddlers) {
|
||||
}
|
||||
};
|
||||
|
||||
JSONTiddlerWidget.prototype.getTiddlerFields = function() {
|
||||
var fields = {};
|
||||
if(this.attTiddler) {
|
||||
var tiddler = this.wiki.getTiddler(this.attTiddler);
|
||||
if(tiddler) {
|
||||
fields = tiddler.getFieldStrings({exclude: this.attExclude.split(" ")});
|
||||
} else {
|
||||
fields = {title: this.attTiddler};
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
};
|
||||
|
||||
exports.jsontiddler = JSONTiddlerWidget;
|
||||
|
||||
})();
|
||||
@@ -236,6 +236,11 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) {
|
||||
hasRefreshed = hasRefreshed || refreshed;
|
||||
}
|
||||
}
|
||||
// If there are items to remove and we have not refreshed then recreate the item that will now be at the last position
|
||||
if(!hasRefreshed && this.children.length > this.list.length) {
|
||||
this.removeListItem(this.list.length-1);
|
||||
this.insertListItem(this.list.length-1,this.list[this.list.length-1]);
|
||||
}
|
||||
} else {
|
||||
// Cycle through the list, inserting and removing list items as needed
|
||||
for(t=0; t<this.list.length; t++) {
|
||||
|
||||
@@ -36,28 +36,38 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Helper to add an event handler
|
||||
var addEventHandler = function(type,actions) {
|
||||
if(type && actions) {
|
||||
var isActionStringExecuting = false;
|
||||
self.addEventListener(
|
||||
type,
|
||||
function(event) {
|
||||
// Don't trap the event if it came from one of our action handlers
|
||||
if(isActionStringExecuting) {
|
||||
return true;
|
||||
}
|
||||
// Collect all the event properties into variables
|
||||
var collectProps = function(obj,prefix) {
|
||||
prefix = prefix || "";
|
||||
var props = {};
|
||||
var props = {},
|
||||
names = [];
|
||||
$tw.utils.each(obj,function(value,name) {
|
||||
if(["string","boolean","number"].indexOf(typeof value) !== -1) {
|
||||
props[prefix + name] = value.toString();
|
||||
names.push(name);
|
||||
props[prefix + "-" + name] = value.toString();
|
||||
}
|
||||
});
|
||||
props["list-" + prefix] = $tw.utils.stringifyList(names);
|
||||
return props;
|
||||
};
|
||||
var variables = $tw.utils.extend(
|
||||
{},
|
||||
collectProps(event.paramObject,"event-paramObject-"),
|
||||
collectProps(event,"event-"),
|
||||
collectProps(event.paramObject,"event-paramObject"),
|
||||
collectProps(event,"event"),
|
||||
{
|
||||
modifier: $tw.keyboardManager.getEventModifierKeyDescriptor(event)
|
||||
});
|
||||
isActionStringExecuting = true;
|
||||
self.invokeActionString(actions,self,event,variables);
|
||||
isActionStringExecuting = false;
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -122,6 +122,7 @@ RadioWidget.prototype.refresh = function(changedTiddlers) {
|
||||
return true;
|
||||
} else if(changedTiddlers[this.radioTitle]) {
|
||||
this.inputDomNode.checked = this.getValue() === this.radioValue;
|
||||
$tw.utils.toggleClass(this.labelDomNode,"tc-radio-selected",this.inputDomNode.checked);
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
} else {
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
|
||||
@@ -226,7 +226,7 @@ RevealWidget.prototype.refresh = function(changedTiddlers) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
}
|
||||
} else if(this.type === "popup" && this.updatePopupPosition && (changedTiddlers[this.state] || changedTiddlers[this.stateTitle])) {
|
||||
} else if(this.type === "popup" && this.isOpen && this.updatePopupPosition && (changedTiddlers[this.state] || changedTiddlers[this.stateTitle])) {
|
||||
this.positionPopup(this.domNode);
|
||||
}
|
||||
if(changedAttributes.style) {
|
||||
|
||||
@@ -365,47 +365,108 @@ Sort an array of tiddler titles by a specified field
|
||||
*/
|
||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {
|
||||
var self = this;
|
||||
titles.sort(function(a,b) {
|
||||
var x,y,
|
||||
compareNumbers = function(x,y) {
|
||||
var result =
|
||||
isNaN(x) && !isNaN(y) ? (isDescending ? -1 : 1) :
|
||||
!isNaN(x) && isNaN(y) ? (isDescending ? 1 : -1) :
|
||||
(isDescending ? y - x : x - y);
|
||||
return result;
|
||||
};
|
||||
if(sortField !== "title") {
|
||||
var tiddlerA = self.getTiddler(a),
|
||||
tiddlerB = self.getTiddler(b);
|
||||
if(tiddlerA) {
|
||||
a = tiddlerA.getFieldString(sortField) || "";
|
||||
if(sortField === "title") {
|
||||
if(!isNumeric && !isAlphaNumeric) {
|
||||
if(isCaseSensitive) {
|
||||
if(isDescending) {
|
||||
titles.sort(function(a,b) {
|
||||
return b.localeCompare(a);
|
||||
});
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
a = "";
|
||||
if(isDescending) {
|
||||
titles.sort(function(a,b) {
|
||||
return b.toLowerCase().localeCompare(a.toLowerCase());
|
||||
});
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
});
|
||||
}
|
||||
}
|
||||
if(tiddlerB) {
|
||||
b = tiddlerB.getFieldString(sortField) || "";
|
||||
} else {
|
||||
b = "";
|
||||
}
|
||||
}
|
||||
x = Number(a);
|
||||
y = Number(b);
|
||||
if(isNumeric && (!isNaN(x) || !isNaN(y))) {
|
||||
return compareNumbers(x,y);
|
||||
} else if($tw.utils.isDate(a) && $tw.utils.isDate(b)) {
|
||||
return isDescending ? b - a : a - b;
|
||||
} else if(isAlphaNumeric) {
|
||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
var x,y;
|
||||
if(isNumeric) {
|
||||
x = Number(a);
|
||||
y = Number(b);
|
||||
if(isNaN(x)) {
|
||||
if(isNaN(y)) {
|
||||
// If neither value is a number then fall through to a textual comparison
|
||||
} else {
|
||||
return isDescending ? -1 : 1;
|
||||
}
|
||||
} else {
|
||||
if(isNaN(y)) {
|
||||
return isDescending ? 1 : -1;
|
||||
} else {
|
||||
return isDescending ? y - x : x - y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isAlphaNumeric) {
|
||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
||||
}
|
||||
if(!isCaseSensitive) {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
}
|
||||
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
titles.sort(function(a,b) {
|
||||
var x,y;
|
||||
if(sortField !== "title") {
|
||||
var tiddlerA = self.getTiddler(a),
|
||||
tiddlerB = self.getTiddler(b);
|
||||
if(tiddlerA) {
|
||||
a = tiddlerA.fields[sortField] || "";
|
||||
} else {
|
||||
a = "";
|
||||
}
|
||||
if(tiddlerB) {
|
||||
b = tiddlerB.fields[sortField] || "";
|
||||
} else {
|
||||
b = "";
|
||||
}
|
||||
}
|
||||
if(isNumeric) {
|
||||
x = Number(a);
|
||||
y = Number(b);
|
||||
if(isNaN(x)) {
|
||||
if(isNaN(y)) {
|
||||
// If neither value is a number then fall through to a textual comparison
|
||||
} else {
|
||||
return isDescending ? -1 : 1;
|
||||
}
|
||||
} else {
|
||||
if(isNaN(y)) {
|
||||
return isDescending ? 1 : -1;
|
||||
} else {
|
||||
return isDescending ? y - x : x - y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(Object.prototype.toString.call(a) === "[object Date]" && Object.prototype.toString.call(b) === "[object Date]") {
|
||||
return isDescending ? b - a : a - b;
|
||||
}
|
||||
a = String(a);
|
||||
b = String(b);
|
||||
if(isAlphaNumeric) {
|
||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
||||
}
|
||||
if(!isCaseSensitive) {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
}
|
||||
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -844,7 +905,7 @@ exports.clearGlobalCache = function() {
|
||||
exports.getCacheForTiddler = function(title,cacheName,initializer) {
|
||||
this.caches = this.caches || Object.create(null);
|
||||
var caches = this.caches[title];
|
||||
if(caches && caches[cacheName]) {
|
||||
if(caches && caches[cacheName] !== undefined) {
|
||||
return caches[cacheName];
|
||||
} else {
|
||||
if(!caches) {
|
||||
|
||||
@@ -19,71 +19,73 @@ $:/config/Plugins/Disabled/$(currentTiddler)$
|
||||
\end
|
||||
|
||||
\define plugin-table-body(type,disabledMessage,default-popup-state)
|
||||
\whitespace trim
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-toggle">
|
||||
<$reveal type="nomatch" state=<<popup-state>> text="yes" default="""$default-popup-state$""">
|
||||
<$button class="tc-btn-invisible tc-btn-dropdown" set=<<popup-state>> setTo="yes">
|
||||
{{$:/core/images/chevron-right}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<popup-state>> text="yes" default="""$default-popup-state$""">
|
||||
<$button class="tc-btn-invisible tc-btn-dropdown" set=<<popup-state>> setTo="no">
|
||||
{{$:/core/images/chevron-down}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="nomatch" state=<<popup-state>> text="yes" default="""$default-popup-state$""">
|
||||
<$button class="tc-btn-invisible tc-btn-dropdown" set=<<popup-state>> setTo="yes">
|
||||
{{$:/core/images/chevron-right}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<popup-state>> text="yes" default="""$default-popup-state$""">
|
||||
<$button class="tc-btn-invisible tc-btn-dropdown" set=<<popup-state>> setTo="no">
|
||||
{{$:/core/images/chevron-down}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
</div>
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-icon">
|
||||
<$transclude tiddler=<<currentTiddler>> subtiddler=<<plugin-icon-title>>>
|
||||
<$transclude tiddler="$:/core/images/plugin-generic-$type$"/>
|
||||
</$transclude>
|
||||
<$transclude tiddler=<<currentTiddler>> subtiddler=<<plugin-icon-title>>>
|
||||
<$transclude tiddler="$:/core/images/plugin-generic-$type$"/>
|
||||
</$transclude>
|
||||
</div>
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-description">
|
||||
<h1>
|
||||
''<$text text={{{ [<currentTiddler>get[name]] ~[<currentTiddler>split[/]last[1]] }}}/>'': <$view field="description"><$view field="title"/></$view> $disabledMessage$
|
||||
</h1>
|
||||
<h2>
|
||||
<$view field="title"/>
|
||||
</h2>
|
||||
<h2>
|
||||
<div><em><$view field="version"/></em></div>
|
||||
</h2>
|
||||
<h1>
|
||||
''<$text text={{{ [<currentTiddler>get[name]] ~[<currentTiddler>split[/]last[1]] }}}/>'': <$view field="description"><$view field="title"/></$view> $disabledMessage$
|
||||
</h1>
|
||||
<h2>
|
||||
<$view field="title"/>
|
||||
</h2>
|
||||
<h2>
|
||||
<div><em><$view field="version"/></em></div>
|
||||
</h2>
|
||||
</div>
|
||||
\end
|
||||
|
||||
\define plugin-info(type,default-popup-state)
|
||||
\whitespace trim
|
||||
<$set name="popup-state" value=<<popup-state-macro>>>
|
||||
<$reveal type="nomatch" state=<<plugin-disable-title>> text="yes">
|
||||
<$link to={{!!title}} class="tc-plugin-info">
|
||||
<<plugin-table-body type:"$type$" default-popup-state:"""$default-popup-state$""">>
|
||||
</$link>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<plugin-disable-title>> text="yes">
|
||||
<$link to={{!!title}} class="tc-plugin-info tc-plugin-info-disabled">
|
||||
<<plugin-table-body type:"$type$" default-popup-state:"""$default-popup-state$""" disabledMessage:"<$macrocall $name='lingo' title='Disabled/Status'/>">>
|
||||
</$link>
|
||||
</$reveal>
|
||||
<$reveal type="match" text="yes" state=<<popup-state>> default="""$default-popup-state$""">
|
||||
<div class="tc-plugin-info-dropdown">
|
||||
<div class="tc-plugin-info-dropdown-body">
|
||||
<$list filter="[all[current]] -[[$:/core]]">
|
||||
<div style="float:right;">
|
||||
<$reveal type="nomatch" state=<<plugin-disable-title>> text="yes">
|
||||
<$button set=<<plugin-disable-title>> setTo="yes" tooltip={{$:/language/ControlPanel/Plugins/Disable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Disable/Caption}}>
|
||||
<<lingo Disable/Caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<plugin-disable-title>> text="yes">
|
||||
<$button set=<<plugin-disable-title>> setTo="no" tooltip={{$:/language/ControlPanel/Plugins/Enable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Enable/Caption}}>
|
||||
<<lingo Enable/Caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
</div>
|
||||
</$list>
|
||||
<$set name="tabsList" filter="[<currentTiddler>list[]] contents">
|
||||
<$macrocall $name="tabs" state=<<tabs-state-macro>> tabsList=<<tabsList>> default={{{ [enlist<tabsList>] }}} template="$:/core/ui/PluginInfo"/>
|
||||
</$set>
|
||||
</div>
|
||||
</div>
|
||||
</$reveal>
|
||||
<$reveal type="nomatch" state=<<plugin-disable-title>> text="yes">
|
||||
<$link to={{!!title}} class="tc-plugin-info">
|
||||
<<plugin-table-body type:"$type$" default-popup-state:"""$default-popup-state$""">>
|
||||
</$link>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<plugin-disable-title>> text="yes">
|
||||
<$link to={{!!title}} class="tc-plugin-info tc-plugin-info-disabled">
|
||||
<<plugin-table-body type:"$type$" default-popup-state:"""$default-popup-state$""" disabledMessage:"<$macrocall $name='lingo' title='Disabled/Status'/>">>
|
||||
</$link>
|
||||
</$reveal>
|
||||
<$reveal type="match" text="yes" state=<<popup-state>> default="""$default-popup-state$""">
|
||||
<div class="tc-plugin-info-dropdown">
|
||||
<div class="tc-plugin-info-dropdown-body">
|
||||
<$list filter="[all[current]] -[[$:/core]]">
|
||||
<div style="float:right;">
|
||||
<$reveal type="nomatch" state=<<plugin-disable-title>> text="yes">
|
||||
<$button set=<<plugin-disable-title>> setTo="yes" tooltip={{$:/language/ControlPanel/Plugins/Disable/Hint}} aria-label={{$:/language/ControlPanel/Plugins/Disable/Caption}}>
|
||||
<<lingo Disable/Caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" state=<<plugin-disable-title>> text="yes">
|
||||
<$button set=<<plugin-disable-title>> setTo="no" tooltip={{$:/language/ControlPanel/Plugins/Enable Hint}} aria-label={{$:/language/ControlPanel/Plugins/Enable/Caption}}>
|
||||
<<lingo Enable/Caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
</div>
|
||||
</$list>
|
||||
<$set name="tabsList" filter="[<currentTiddler>list[]] contents">
|
||||
<$macrocall $name="tabs" state=<<tabs-state-macro>> tabsList=<<tabsList>> default={{{ [enlist<tabsList>] }}} template="$:/core/ui/PluginInfo"/>
|
||||
</$set>
|
||||
</div>
|
||||
</div>
|
||||
</$reveal>
|
||||
</$set>
|
||||
\end
|
||||
|
||||
|
||||
@@ -16,4 +16,4 @@ caption: {{$:/language/ControlPanel/Plugins/Caption}}
|
||||
|
||||
<<lingo Installed/Hint>>
|
||||
|
||||
<$macrocall $name="tabs" tabsList="[[$:/core/ui/ControlPanel/Plugins/Installed/Plugins]] [[$:/core/ui/ControlPanel/Plugins/Installed/Themes]] [[$:/core/ui/ControlPanel/Plugins/Installed/Languages]]" default="$:/core/ui/ControlPanel/Plugins/Installed/Plugins" explicitState="$:/state/tab--86143343"/>
|
||||
<$macrocall $name="tabs" tabsList="[all[tiddlers+shadows]tag[$:/tags/ControlPanel/Plugins]!has[draft.of]]" default="$:/core/ui/ControlPanel/Plugins/Installed/Plugins" explicitState="$:/state/tab--86143343"/>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
title: $:/core/ui/ControlPanel/Plugins/Installed/Languages
|
||||
tags: $:/tags/ControlPanel/Plugins
|
||||
caption: {{$:/language/ControlPanel/Plugins/Languages/Caption}} (<$count filter="[!has[draft.of]plugin-type[language]]"/>)
|
||||
|
||||
<<plugin-table language>>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
title: $:/core/ui/ControlPanel/Plugins/Installed/Plugins
|
||||
tags: $:/tags/ControlPanel/Plugins
|
||||
caption: {{$:/language/ControlPanel/Plugins/Plugins/Caption}} (<$count filter="[!has[draft.of]plugin-type[plugin]]"/>)
|
||||
|
||||
<<plugin-table plugin>>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
title: $:/core/ui/ControlPanel/Plugins/Installed/Themes
|
||||
tags: $:/tags/ControlPanel/Plugins
|
||||
caption: {{$:/language/ControlPanel/Plugins/Themes/Caption}} (<$count filter="[!has[draft.of]plugin-type[theme]]"/>)
|
||||
|
||||
<<plugin-table theme>>
|
||||
|
||||
53
core/ui/EditorToolbar/stamp-dropdown-item-template.tid
Normal file
53
core/ui/EditorToolbar/stamp-dropdown-item-template.tid
Normal file
@@ -0,0 +1,53 @@
|
||||
title: $:/core/ui/EditorToolbar/StampDropdown/ItemTemplate
|
||||
|
||||
<$linkcatcher actions="""
|
||||
|
||||
<$list filter="[<modifier>!match[ctrl]]" variable="ignore">
|
||||
|
||||
<$list filter="[<currentTiddler>addsuffix[/prefix]!is[tiddler]!is[shadow]removesuffix[/prefix]addsuffix[/suffix]!is[tiddler]!is[shadow]]" variable="ignore">
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="replace-selection"
|
||||
text={{{ [<currentTiddler>get[text]] }}}
|
||||
/>
|
||||
|
||||
</$list>
|
||||
|
||||
|
||||
<$list filter="[<currentTiddler>addsuffix[/prefix]] [<currentTiddler>addsuffix[/suffix]] +[is[shadow]] :else[is[tiddler]] +[limit[1]]" variable="ignore">
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix={{{ [<currentTiddler>addsuffix[/prefix]get[text]] }}}
|
||||
suffix={{{ [<currentTiddler>addsuffix[/suffix]get[text]] }}}
|
||||
/>
|
||||
|
||||
</$list>
|
||||
|
||||
</$list>
|
||||
|
||||
<$list filter="[<modifier>match[ctrl]]" variable="ignore">
|
||||
|
||||
<$action-sendmessage $message="tm-edit-tiddler"/>
|
||||
|
||||
</$list>
|
||||
|
||||
<$action-deletetiddler
|
||||
$tiddler=<<dropdown-state>>
|
||||
/>
|
||||
|
||||
""">
|
||||
|
||||
<$link tooltip={{{ [<currentTiddler>get[description]] }}}>
|
||||
|
||||
<$transclude tiddler=<<currentTiddler>> field="caption" mode="inline">
|
||||
|
||||
<$view tiddler=<<currentTiddler>> field="title" />
|
||||
|
||||
</$transclude>
|
||||
|
||||
</$link>
|
||||
|
||||
</$linkcatcher>
|
||||
@@ -1,48 +1,6 @@
|
||||
title: $:/core/ui/EditorToolbar/stamp-dropdown
|
||||
|
||||
\define toolbar-button-stamp-inner()
|
||||
<$button tag="a">
|
||||
|
||||
<$list filter="[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]]">
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="replace-selection"
|
||||
text={{$(snippetTitle)$}}
|
||||
/>
|
||||
|
||||
</$list>
|
||||
|
||||
|
||||
<$list filter="[[$(snippetTitle)$]addsuffix[/prefix]is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]is[missing]] [[$(snippetTitle)$]addsuffix[/prefix]!is[missing]removesuffix[/prefix]addsuffix[/suffix]!is[missing]]">
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix={{{ [[$(snippetTitle)$]addsuffix[/prefix]get[text]] }}}
|
||||
suffix={{{ [[$(snippetTitle)$]addsuffix[/suffix]get[text]] }}}
|
||||
/>
|
||||
|
||||
</$list>
|
||||
|
||||
<$action-deletetiddler
|
||||
$tiddler=<<dropdown-state>>
|
||||
/>
|
||||
|
||||
<$transclude tiddler=<<snippetTitle>> field="caption" mode="inline">
|
||||
|
||||
<$view tiddler=<<snippetTitle>> field="title" />
|
||||
|
||||
</$transclude>
|
||||
|
||||
</$button>
|
||||
\end
|
||||
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/TextEditor/Snippet]!has[draft.of]sort[caption]]" variable="snippetTitle">
|
||||
|
||||
<<toolbar-button-stamp-inner>>
|
||||
|
||||
</$list>
|
||||
<$macrocall $name="list-tagged-draggable" tag="$:/tags/TextEditor/Snippet" subFilter="!is[draft]" itemTemplate="$:/core/ui/EditorToolbar/StampDropdown/ItemTemplate"/>
|
||||
|
||||
----
|
||||
|
||||
|
||||
@@ -6,4 +6,5 @@ description: {{$:/language/Buttons/Stamp/Hint}}
|
||||
condition: [<targetTiddler>type[]] [<targetTiddler>get[type]prefix[text/]] [<targetTiddler>get[type]match[application/javascript]] [<targetTiddler>get[type]match[application/json]] [<targetTiddler>get[type]match[application/x-tiddler-dictionary]] [<targetTiddler>get[type]match[image/svg+xml]] +[first[]]
|
||||
shortcuts: ((stamp))
|
||||
dropdown: $:/core/ui/EditorToolbar/stamp-dropdown
|
||||
button-classes: tc-editortoolbar-stamp-button
|
||||
text:
|
||||
|
||||
22
core/ui/ExportTiddlyWikiCore.tid
Normal file
22
core/ui/ExportTiddlyWikiCore.tid
Normal file
@@ -0,0 +1,22 @@
|
||||
title: $:/core/ui/ExportTiddlyWikiCore
|
||||
|
||||
\define jsFileName() tiddlywikicore-$(version)$.js
|
||||
\define noExportMsg()
|
||||
It appears that you have a wiki with an external ~TiddlyWiki core. The export action cannot be performed.
|
||||
<p>You will need to view the page source in your browser. Then go to the very bottom the the source, find the last `<script>`
|
||||
element, and right-click its `src` URI. Save the link as ''$(jsFileName)$''</p>
|
||||
\end
|
||||
|
||||
''For advanced users''
|
||||
|
||||
Export the ~TiddlyWiki core ~JavaScript code for running with external ~JavaScript:
|
||||
|
||||
<$button tooltip="Export the ~TiddlyWiki core code for running with external ~JavaScript" aria-label="export TiddlyWiki core" class="tc-btn-big-green">
|
||||
<$list filter="[[$:/boot/boot.js]is[missing]]" variable="ignore" emptyMessage="""<$action-sendmessage $message="tm-download-file" $param="$:/core/templates/tiddlywiki5.js" filename=<<jsFileName>>/>""" >
|
||||
<$action-setfield $tiddler=<<qualify "$:/temp/alert">> text=<<noExportMsg>> subtitle="Export ~TiddllyWiki Core"/>
|
||||
<$action-sendmessage $message="tm-modal" $param=<<qualify "$:/temp/alert">>/>
|
||||
</$list>
|
||||
{{$:/core/images/download-button}} Download ~TiddlyWiki core
|
||||
</$button>
|
||||
|
||||
[[Further information|https://tiddlywiki.com/#Using%20the%20external%20JavaScript%20template]]
|
||||
@@ -1,9 +1,5 @@
|
||||
title: $:/core/ui/Buttons/export-tiddlywikicore
|
||||
tags: $:/tags/PageControls
|
||||
caption: {{$:/core/images/star-filled}} {{$:/language/Buttons/ExportTiddlyWikiCore/Caption}}
|
||||
description: {{$:/language/Buttons/ExportTiddlyWikiCore/Hint}}
|
||||
title: $:/core/ui/ExportTiddlyWikiCore
|
||||
|
||||
\whitespace trim
|
||||
\define jsFileName() tiddlywikicore-$(version)$.js
|
||||
\define noExportMsg()
|
||||
It appears that you have a wiki with an external ~TiddlyWiki core. The export action cannot be performed.
|
||||
@@ -11,15 +7,16 @@ It appears that you have a wiki with an external ~TiddlyWiki core. The export ac
|
||||
element, and right-click its `src` URI. Save the link as ''$(jsFileName)$''</p>
|
||||
\end
|
||||
|
||||
<$button tooltip={{$:/language/Buttons/ExportTiddlyWikiCore/Hint}} aria-label={{$:/language/Buttons/ExportTiddlyWikiCore/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
''For advanced users''
|
||||
|
||||
Export the ~TiddlyWiki core ~JavaScript code for running with external ~JavaScript:
|
||||
|
||||
<$button tooltip="Export the ~TiddlyWiki core code for running with external ~JavaScript" aria-label="export TiddlyWiki core" class="tc-btn-big-green">
|
||||
<$list filter="[[$:/boot/boot.js]is[missing]]" variable="ignore" emptyMessage="""<$action-sendmessage $message="tm-download-file" $param="$:/core/templates/tiddlywiki5.js" filename=<<jsFileName>>/>""" >
|
||||
<$action-setfield $tiddler=<<qualify "$:/temp/alert">> text=<<noExportMsg>> subtitle="Export ~TiddllyWiki Core"/>
|
||||
<$action-sendmessage $message="tm-modal" $param=<<qualify "$:/temp/alert">>/>
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]" variable="listItem">
|
||||
{{$:/core/images/star-filled}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/ExportTiddlyWikiCore/Caption}}/></span>
|
||||
</$list>
|
||||
{{$:/core/images/download-button}} Download ~TiddlyWiki core
|
||||
</$button>
|
||||
|
||||
[[Further information|https://tiddlywiki.com/#Using%20the%20external%20JavaScript%20template]]
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
title: $:/core/ui/ViewTemplate
|
||||
|
||||
\whitespace trim
|
||||
\define folded-state()
|
||||
$:/state/folded/$(currentTiddler)$
|
||||
\end
|
||||
\define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/>
|
||||
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]
|
||||
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>><div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}><$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
|
||||
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>>
|
||||
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}>
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem">
|
||||
<$transclude tiddler=<<listItem>>/>
|
||||
</$list>
|
||||
</div>
|
||||
</$vars>
|
||||
|
||||
@@ -5,13 +5,10 @@ tags: $:/tags/ViewTemplate
|
||||
\define title-styles()
|
||||
fill:$(foregroundColor)$;
|
||||
\end
|
||||
\define config-title()
|
||||
$:/config/ViewToolbarButtons/Visibility/$(listItem)$
|
||||
\end
|
||||
<div class="tc-tiddler-title">
|
||||
<div class="tc-titlebar">
|
||||
<span class="tc-tiddler-controls">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]" variable="listItem"><$reveal type="nomatch" state=<<config-title>> text="hide"><$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]"><$transclude tiddler=<<listItem>>/></$set></$reveal></$list>
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]] :filter[lookup[$:/config/ViewToolbarButtons/Visibility/]!match[hide]]" storyview="pop" variable="listItem"><$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]"><$transclude tiddler=<<listItem>>/></$set></$list>
|
||||
</span>
|
||||
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
|
||||
<$link>
|
||||
@@ -43,4 +40,4 @@ $:/config/ViewToolbarButtons/Visibility/$(listItem)$
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]" variable="listItem"><$transclude tiddler=<<listItem>> mode="block"/></$list>
|
||||
|
||||
</$reveal>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
title: $:/config/EditTabIndex
|
||||
|
||||
1
|
||||
text: 1
|
||||
@@ -4,7 +4,6 @@ core/ui/Buttons/advanced-search: hide
|
||||
core/ui/Buttons/close-all: hide
|
||||
core/ui/Buttons/encryption: hide
|
||||
core/ui/Buttons/export-page: hide
|
||||
core/ui/Buttons/export-tiddlywikicore: hide
|
||||
core/ui/Buttons/fold-all: hide
|
||||
core/ui/Buttons/full-screen: hide
|
||||
core/ui/Buttons/home: hide
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
title: $:/config/shortcuts-mac/
|
||||
|
||||
bold: meta-B
|
||||
input-tab-left: ctrl-Left
|
||||
input-tab-right: ctrl-Right
|
||||
italic: meta-I
|
||||
underline: meta-U
|
||||
new-image: ctrl-I
|
||||
|
||||
@@ -18,8 +18,8 @@ input-accept: Enter
|
||||
input-accept-variant: ctrl-Enter
|
||||
input-cancel: Escape
|
||||
input-down: Down
|
||||
input-tab-left: alt-Left
|
||||
input-tab-right: alt-Right
|
||||
input-tab-left: alt-ctrl-Left
|
||||
input-tab-right: alt-ctrl-Right
|
||||
input-up: Up
|
||||
layout-switcher: ctrl-shift-L
|
||||
link: ctrl-L
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
title: $:/tags/ControlPanel/Plugins
|
||||
list: [[$:/core/ui/ControlPanel/Plugins/Installed]] [[$:/core/ui/ControlPanel/Plugins/Add]]
|
||||
list: $:/core/ui/ControlPanel/Plugins/Installed/Plugins $:/core/ui/ControlPanel/Plugins/Installed/Themes $:/core/ui/ControlPanel/Plugins/Installed/Languages
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
title: $:/tags/PageControls
|
||||
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/export-tiddlywikicore]] [[$:/core/ui/Buttons/more-page-actions]]
|
||||
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]
|
||||
|
||||
@@ -14,6 +14,7 @@ Welcome to the developer documentation for TiddlyWiki (https://tiddlywiki.com/).
|
||||
** HookMechanism
|
||||
** [[Using ES2016 for Writing Plugins]]
|
||||
** [[Adding Babel Polyfill to TiddlyWiki]]
|
||||
** [[TiddlyWiki Drag and Drop Interoperability]]
|
||||
* The original developer documentation from https://tiddlywiki.com:
|
||||
** [[TiddlyWiki for Developers]]
|
||||
** [[TiddlyWiki Coding Style Guidelines]]
|
||||
|
||||
@@ -37,8 +37,6 @@ Example:
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
|
||||
!!! With encryption
|
||||
|
||||
If the ~TiddlyWiki is configured to encrypt its content, the tiddlers are stored as as an encrypted JSON string in a `<pre>` tag with the `id` attribute "encryptedStoreArea".
|
||||
@@ -83,15 +81,20 @@ Any tiddlers in the older format `<div>` store area are also loaded before tiddl
|
||||
|
||||
Tiddlers from the new `<script>` tag store areas are loaded in the order of their store areas in the HTML file. Therefore if the same tiddler exists in two different `<script>` tag store areas, the tiddler from the later store area takes precedence. Note however that tiddlers from `<script>` tag store areas always take precedence over tiddlers from the older format `<div>` store area. Therefore a tiddler from the older `<div>` store area can never overwrite a tiddler from a `<script>` tag store area.
|
||||
|
||||
Note that all `<script>` tags with the `class` attribute "tiddlywiki-tiddler-store" have their content parsed as JSON and loaded as tiddlers. This allows external tools to easily insert tiddlers into an HTML file by appending additional `<script>` tag(s) at the very end of the HTML file:
|
||||
Note that all `<script>` tags with the `class` attribute "tiddlywiki-tiddler-store" that precede the `$:/boot.js` module in the HTML file will have their content parsed as JSON and loaded as tiddlers.
|
||||
|
||||
This allows external tools to easily insert tiddlers into an HTML file by prepending an additional `<script>` tag(s) at the very start of the HTML file:
|
||||
|
||||
```html
|
||||
</html>
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[
|
||||
{"created":"20210525212411223","text":"This is some test text","tags":"[[test tag]] [[another tag]]","title":"My new tiddler to insert","modified":"20210525212430577"}
|
||||
]</script>
|
||||
<!doctype html>
|
||||
...
|
||||
```
|
||||
|
||||
Although invalid HTML, all known browsers will silently move the script tag to a valid position within the
|
||||
|
||||
Additional topics:
|
||||
|
||||
* [[Extracting tiddlers from a single file TiddlyWiki]]
|
||||
@@ -0,0 +1,15 @@
|
||||
title: TiddlyWiki Drag and Drop Interoperability
|
||||
|
||||
It is straightforward to allow any HTML file to interoperate with TiddlyWiki's drag and drop implementation.
|
||||
|
||||
This example shows how to attach draggable data to a DOM element. The data is provided in two different forms:
|
||||
|
||||
* the string data is used if the element is dragged onto a text editing area
|
||||
* the tiddler data is used if the element is dragged into TiddlyWiki's import area
|
||||
|
||||
<$button>
|
||||
<$action-sendmessage $message="tm-download-file" $param="$:/dev/save/dragndropinterop" filename="index.html"/>
|
||||
Download this sample code
|
||||
</$button>
|
||||
|
||||
<$codeblock code={{DragAndDropInterop}} language="text/html"/>
|
||||
35
editions/dev/tiddlers/new/dragndropinterop.html
Normal file
35
editions/dev/tiddlers/new/dragndropinterop.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Drag and Drop Interoperability with TiddlyWiki Demo</title>
|
||||
<style>
|
||||
#draggable {
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
background: #ecc;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="draggable" draggable="true">
|
||||
Drag me to a TiddlyWiki window
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
var titleString = "This is the string that appears when the block is dragged to a text input";
|
||||
var tiddlerData = [
|
||||
{title: "Tiddler One", text: "This is one of the payload tiddlers"},
|
||||
{title: "Tiddler Two", text: "This is another of the payload tiddlers", "custom-field": "A custom field value"}
|
||||
];
|
||||
|
||||
document.getElementById("draggable").addEventListener("dragstart",function(event) {
|
||||
event.dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(JSON.stringify(tiddlerData)));
|
||||
event.dataTransfer.setData("Text",titleString);
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
|
||||
</script>
|
||||
</html>
|
||||
3
editions/dev/tiddlers/new/dragndropinterop.html.meta
Normal file
3
editions/dev/tiddlers/new/dragndropinterop.html.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
title: DragAndDropInterop
|
||||
type: text/html
|
||||
|
||||
3
editions/dev/tiddlers/new/save-dragndropinterop.tid
Normal file
3
editions/dev/tiddlers/new/save-dragndropinterop.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/dev/save/dragndropinterop
|
||||
|
||||
<$view tiddler="DragAndDropInterop" field="text"/>
|
||||
@@ -1,15 +1,13 @@
|
||||
title: $:/core/ui/ViewTemplate
|
||||
|
||||
\whitespace trim
|
||||
\define frame-classes()
|
||||
tc-tiddler-frame tc-tiddler-view-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$ $(tiddlerTagClasses)$ $(userClass)$
|
||||
\end
|
||||
\define folded-state()
|
||||
$:/state/folded/$(currentTiddler)$
|
||||
\end
|
||||
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">> userClass={{!!class}}>
|
||||
<$tiddler tiddler=<<currentTiddler>>>
|
||||
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class=<<frame-classes>>>
|
||||
\define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/>
|
||||
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]
|
||||
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>>
|
||||
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}>
|
||||
<$set name="state" value={{{ [[$:/state/viewtemplate/visibility/]addsuffix<currentTiddler>] }}}>
|
||||
<$reveal stateTitle=<<state>> type="nomatch" text="" default="" tag="div">
|
||||
<div class="tc-dynaview-track-tiddler-when-visible" data-dynaview-track-tiddler=<<state>>>
|
||||
@@ -24,5 +22,4 @@ $:/state/folded/$(currentTiddler)$
|
||||
</$reveal>
|
||||
</$set>
|
||||
</div>
|
||||
</$tiddler>
|
||||
</$vars>
|
||||
|
||||
@@ -54,7 +54,7 @@ title="New tiddler"
|
||||
|
||||
#* Asígnale la etiqueta <<.tag ~$:/tags/ViewToolbar]]>>
|
||||
|
||||
# Hay que crear un tiddler que le diga a ~TiddlyWIki si el botón será o no visible en la barra. Llamémosle por ejemplo <<.tid "~$:/config/ViewToolbarButtons/Visibility/Receta"">>. Escribe `reveal` en el cuerpo y guárdalo.
|
||||
# Hay que crear un tiddler que le diga a ~TiddlyWIki si el botón será o no visible en la barra. Llamémosle por ejemplo <<.tid "~$:/config/ViewToolbarButtons/Visibility/Receta"">>. Escribe `show` en el cuerpo y guárdalo.
|
||||
|
||||
# Habrá que posicionar el botón adecuadamente. Abre el tiddler <<.tid ~$:/tags/ViewToolbar>> e inserta el nombre de tu botón en el lugar adecuado del campo <<.field list>>.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Imaginons que vous ayez un tiddler squelette appelé 'Modèle Recette', et que v
|
||||
|
||||
# Pour illustrer votre bouton, si aucune des images du noyau (tiddlers shadow préfixés par $:/core/images/ ) n'est à votre convenance, vous devrez la créer ou en obtenir une au format SVG (par exemple, une de celles de http://flaticon.com), glissez-la dans votre fichier pour la transformer en tiddler, modifiez le tiddler et ajustez sa hauteur et sa largeur à 22px
|
||||
#Passons au tiddler contenant votre tiddler. Créez-le, titrez-le et ajoutez le code du bouton (voir le code ci-dessous par exemple, en l'adaptant à vos besoins si nécessaire) Étiquetez-le par [[$:/tags/ViewToolbar]]
|
||||
#Contrôlons la visibilité de votre tiddler dans la barre d'outil par la création d'un tiddler à titrer [[$:/config/ViewToolbarButtons/Visibility/Recette]]. Saisissez `reveal`dans la zone texte et sauvegardez.
|
||||
#Contrôlons la visibilité de votre tiddler dans la barre d'outil par la création d'un tiddler à titrer [[$:/config/ViewToolbarButtons/Visibility/Recette]]. Saisissez `show`dans la zone texte et sauvegardez.
|
||||
#Enfin, positionnons le bouton proprement. Ouvrez le tiddler $:/tags/ViewToolbar et insérez le titre de votre tiddler bouton (cf. titre étape précédente) dans le champ field au bon endroit.
|
||||
|
||||
```
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"description": "Innerwiki Plugin Demo",
|
||||
"plugins": [
|
||||
"tiddlywiki/innerwiki"
|
||||
"tiddlywiki/innerwiki",
|
||||
"tiddlywiki/railroad"
|
||||
],
|
||||
"themes": [
|
||||
"tiddlywiki/vanilla",
|
||||
|
||||
@@ -7,7 +7,7 @@ title: TiddlyWiki
|
||||
<$scrollable class="tc-cecily-demo">
|
||||
<div class="tc-cecily-demo-inner">
|
||||
<$linkcatcher>
|
||||
<$list filter="[list[$:/StoryList]] -[[TiddlyWiki]]" template="$:/core/ui/ViewTemplate" storyview="cecily" cecily-width="550px" cecily-map="CecilyMap"/>
|
||||
<$list filter="[{$:/DefaultTiddlers}enlist-input[]] -[[ ]] -[[TiddlyWiki]]" template="$:/core/ui/ViewTemplate" storyview="cecily" cecily-width="550px" cecily-map="CecilyMap"/>
|
||||
</$linkcatcher>
|
||||
</div>
|
||||
</$scrollable>
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
"tiddlywiki/readonly"
|
||||
],
|
||||
"languages": [
|
||||
"ar-PS",
|
||||
"ca-ES",
|
||||
"cs-CZ",
|
||||
"da-DK",
|
||||
"de-AT",
|
||||
"de-CH",
|
||||
"de-DE",
|
||||
"el-GR",
|
||||
"en-GB",
|
||||
@@ -27,6 +29,7 @@
|
||||
"es-ES",
|
||||
"fa-IR",
|
||||
"fr-FR",
|
||||
"he-IL",
|
||||
"hi-IN",
|
||||
"ia-IA",
|
||||
"it-IT",
|
||||
@@ -34,12 +37,16 @@
|
||||
"ko-KR",
|
||||
"nl-NL",
|
||||
"pa-IN",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ru-RU",
|
||||
"sk-SK",
|
||||
"sv-SE",
|
||||
"zh-CN",
|
||||
"zh-Hans",
|
||||
"zh-Hant"
|
||||
"zh-Hant",
|
||||
"zh-HK",
|
||||
"zh-TW"
|
||||
],
|
||||
"build": {
|
||||
"index": [
|
||||
|
||||
62
editions/prerelease/tiddlers/Release 5.2.1.tid
Normal file
62
editions/prerelease/tiddlers/Release 5.2.1.tid
Normal file
@@ -0,0 +1,62 @@
|
||||
caption: 5.2.1
|
||||
created: 20211003152250369
|
||||
modified: 20211003152250369
|
||||
tags: ReleaseNotes
|
||||
title: Release 5.2.1
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define contributor(username)
|
||||
<a href="https://github.com/$username$" style="text-decoration:none;font-size:24px;" class="tc-tiddlylink-external" target="_blank" rel="noopener noreferrer"><img src="https://github.com/$username$.png?size=32" width="32" height="32"/> @<$text text=<<__username__>>/></a>
|
||||
\end
|
||||
|
||||
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.0...master]]//
|
||||
|
||||
! Highlights
|
||||
|
||||
! Performance Improvements
|
||||
|
||||
*
|
||||
|
||||
! Usability Improvements
|
||||
|
||||
*
|
||||
|
||||
! Widget Improvements
|
||||
|
||||
*
|
||||
|
||||
! Filter improvements
|
||||
|
||||
*
|
||||
|
||||
! Hackability Improvements
|
||||
|
||||
*
|
||||
|
||||
! Client-server Improvements
|
||||
|
||||
*
|
||||
|
||||
! Node.js Improvements
|
||||
|
||||
*
|
||||
|
||||
! Plugin Improvements
|
||||
|
||||
! Developer Experience Improvements
|
||||
|
||||
*
|
||||
|
||||
! Translation improvements
|
||||
|
||||
*
|
||||
|
||||
! Other Bug Fixes
|
||||
|
||||
*
|
||||
|
||||
! Acknowledgements
|
||||
|
||||
[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki:
|
||||
|
||||
* <<contributor Jermolene>>
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/LocalPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: http://127.0.0.1:8080/prerelease/library/v5.1.23/index.html
|
||||
url: http://127.0.0.1:8080/prerelease/library/v5.2.1/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease Local)
|
||||
|
||||
A locally installed version of the official ~TiddlyWiki plugin library at tiddlywiki.com for testing and debugging. //Requires a local web server to share the library//
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.2.0/index.html
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.2.1/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease)
|
||||
|
||||
The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -465,6 +465,31 @@ describe("Widget module", function() {
|
||||
expect(wrapper.children[0].children[13].sequenceNumber).toBe(43);
|
||||
expect(wrapper.children[0].children[14].sequenceNumber).toBe(44);
|
||||
expect(wrapper.children[0].children[15].sequenceNumber).toBe(45);
|
||||
//Remove last tiddler
|
||||
wiki.deleteTiddler("TiddlerTwo");
|
||||
//Refresh
|
||||
refreshWidgetNode(widgetNode,wrapper,["TiddlerTwo"]);
|
||||
//Test the refreshing
|
||||
expect(wrapper.innerHTML).toBe("<p>Jalapeno Peppers1yesnoLemon Squash2nonoJolly Old World3nonoSomething4noyes</p>");
|
||||
// Test the sequence numbers in the DOM
|
||||
expect(wrapper.sequenceNumber).toBe(0);
|
||||
expect(wrapper.children[0].sequenceNumber).toBe(1);
|
||||
expect(wrapper.children[0].children[0].sequenceNumber).toBe(18);
|
||||
expect(wrapper.children[0].children[1].sequenceNumber).toBe(19);
|
||||
expect(wrapper.children[0].children[2].sequenceNumber).toBe(20);
|
||||
expect(wrapper.children[0].children[3].sequenceNumber).toBe(21);
|
||||
expect(wrapper.children[0].children[4].sequenceNumber).toBe(22);
|
||||
expect(wrapper.children[0].children[5].sequenceNumber).toBe(23);
|
||||
expect(wrapper.children[0].children[6].sequenceNumber).toBe(24);
|
||||
expect(wrapper.children[0].children[7].sequenceNumber).toBe(25);
|
||||
expect(wrapper.children[0].children[8].sequenceNumber).toBe(26);
|
||||
expect(wrapper.children[0].children[9].sequenceNumber).toBe(27);
|
||||
expect(wrapper.children[0].children[10].sequenceNumber).toBe(28);
|
||||
expect(wrapper.children[0].children[11].sequenceNumber).toBe(29);
|
||||
expect(wrapper.children[0].children[12].sequenceNumber).toBe(50);
|
||||
expect(wrapper.children[0].children[13].sequenceNumber).toBe(51);
|
||||
expect(wrapper.children[0].children[14].sequenceNumber).toBe(52);
|
||||
expect(wrapper.children[0].children[15].sequenceNumber).toBe(53);
|
||||
});
|
||||
|
||||
it("should deal with the list widget followed by other widgets", function() {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
created: 20210525102327864
|
||||
modified: 20210525102327884
|
||||
title: $:/key-test
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -1,11 +0,0 @@
|
||||
created: 20210525102659716
|
||||
modified: 20210525102701077
|
||||
title: $:/key-test/action
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<$vars tv-wikilinks="no">
|
||||
|
||||
* event-key:
|
||||
* event-code:
|
||||
* modifier:
|
||||
</$vars>
|
||||
@@ -1,66 +0,0 @@
|
||||
created: 20210427092418146
|
||||
modified: 20210525130708186
|
||||
tags: KeyboardWidget
|
||||
title: Key Codes (Example 1)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define key-test() $:/key-test
|
||||
|
||||
\import [[Keyboard Codes (Macros)]]
|
||||
|
||||
\define keys()
|
||||
backspace tab clear return enter pause escape space
|
||||
page_up page_down end home printscreen insert delete
|
||||
|
||||
left up right down results in: ArrowLeft ArrowUp ArrowRight ArrowDown
|
||||
|
||||
0 1 2 3
|
||||
shift+0 shift+1 shift+2 shift+3 results in: = ! " with modifierKey: shift
|
||||
ctrl+0 ctrl+1 ctrl+2 ctrl+3
|
||||
alt+0 alt+1 alt+2 alt+3
|
||||
|
||||
ctrl+alt+0 ctrl+alt+1 ctrl+alt+2 ctrl+alt+3
|
||||
alt+shift+0 alt+shift+1 alt+shift+2 alt+shift+3
|
||||
ctrl+shift+0 ctrl+shift+1 ctrl+shift+2 ctrl+shift+3 INFO: ctrl-shift-0 is eaten by windows!!
|
||||
ctrl+alt+shift+0 ctrl+alt+shift+1 ctrl+alt+shift+2 ctrl+alt+shift+3
|
||||
|
||||
a s d
|
||||
shift+a shift+s shift+d
|
||||
ctrl+a ctrl+s ctrl+d
|
||||
alt+a alt+s alt+d
|
||||
|
||||
ctrl+shift+a ctrl+shift+s ctrl+shift+d
|
||||
alt+shift+a alt+shift+s alt+shift+d
|
||||
ctrl+alt+a ctrl+alt+s ctrl+alt+d
|
||||
ctrl+alt+shift+a ctrl+alt+shift+s ctrl+alt+shift+d
|
||||
|
||||
numpad0 numpad1 numpad2 numpad3
|
||||
|
||||
multiply add separator subtract decimal divide
|
||||
|
||||
f1 f2 f3
|
||||
|
||||
semicolon equals comma dash period slash backquote openbracket backslash closebracket quote
|
||||
\end
|
||||
|
||||
! Key Codes
|
||||
|
||||
{{$:/key-test/action}}
|
||||
|
||||
! Input Area
|
||||
|
||||
Depending on your OS and browser keyboard settings, some combinations may be "eaten" by the OS, or the browser!
|
||||
|
||||
--> <$keyboard key={{{ [enlist<keys>join[ ]] }}} actions=<<actionKey>> >
|
||||
<$edit-text tiddler=<<key-test>> placeholder="- Click here. Try keys from list below -" tag=input focus />
|
||||
</$keyboard> <--
|
||||
|
||||
!! Keys to be used
|
||||
|
||||
<pre><code><$vars tv-wikilinks="no"><<keys>></$vars></code></pre>
|
||||
|
||||
All possible keys can be found at: [[Keyboard Codes]]
|
||||
|
||||
! Example Code
|
||||
|
||||
<<showCode>>
|
||||
@@ -1,43 +0,0 @@
|
||||
created: 20210427130002905
|
||||
modified: 20210525130748774
|
||||
tags: KeyboardWidget
|
||||
title: Key Codes (Example)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define key-test() $:/key-test
|
||||
|
||||
\import [[Keyboard Codes (Macros)]]
|
||||
|
||||
\define keys()
|
||||
1 2 3
|
||||
shift+1 shift+2 shift+3
|
||||
a s d
|
||||
f1 f2 f3
|
||||
\end
|
||||
|
||||
! Key Codes
|
||||
|
||||
{{$:/key-test/action}}
|
||||
|
||||
! Input Area
|
||||
|
||||
Depending on your OS and browser keyboard settings, some combinations may be "eaten" by the OS, or the browser
|
||||
|
||||
--> <$keyboard key={{{ [enlist<keys>join[ ]] }}} actions=<<actionKey>> >
|
||||
<$edit-text tiddler=<<key-test>> placeholder="- Click here to try keys -" tag=input />
|
||||
</$keyboard> <--
|
||||
|
||||
|
||||
!! Keys to be tested
|
||||
|
||||
<$list filter="[enlist<keys>]"><kbd><<currentTiddler>></kbd>, </$list>
|
||||
|
||||
-----
|
||||
|
||||
All usable keys can be found at: [[Keyboard Codes]]
|
||||
|
||||
A more advanced example can be found at: [[Key Codes (Example 1)]]
|
||||
|
||||
! Code
|
||||
|
||||
<<showCode>>
|
||||
@@ -1,50 +0,0 @@
|
||||
created: 20210429084127864
|
||||
modified: 20210525130830934
|
||||
tags:
|
||||
title: Keyboard Codes (Macros)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define key-test-prefix() $:/key-test
|
||||
|
||||
\define codeState() $:/state/code/$(currentTiddler)$
|
||||
|
||||
\define getText()
|
||||
<$vars tv-wikilinks="no">
|
||||
|
||||
* event-key: ''$(event-key)$''
|
||||
* event-code: ''$(event-code)$''
|
||||
* modifier: ''$(modifier)$''
|
||||
</$vars>
|
||||
\end
|
||||
|
||||
\define pinDetails()
|
||||
<$action-setfield $tiddler=<<codeState>> text="open"/>
|
||||
\end
|
||||
|
||||
\define unpinDetails()
|
||||
<$action-deletetiddler $tiddler=<<codeState>> />
|
||||
\end
|
||||
|
||||
\define toggleDetails(text)
|
||||
<$list filter="[<codeState>!has[title]]" variable="ignore">
|
||||
<$button class="tc-btn-invisible" actions=<<pinDetails>> >$text$ {{$:/core/images/unfold-button}}</$button>
|
||||
</$list>
|
||||
<$list filter="[<codeState>has[title]]" variable="ignore">
|
||||
<$button class="tc-btn-invisible" actions=<<unpinDetails>> >$text$ {{$:/core/images/fold-button}}</$button>
|
||||
</$list>
|
||||
\end
|
||||
|
||||
\define actionKey()
|
||||
<$action-setfield $tiddler="$:/key-test/action" text=<<getText>> />
|
||||
\end
|
||||
|
||||
\define showCode()
|
||||
|
||||
''<<toggleDetails """Toggle this tiddler code""">>''
|
||||
|
||||
<$list filter="[<codeState>has[title]]" variable=ignore>
|
||||
<pre><code><$view /></code></pre>
|
||||
</$list>
|
||||
\end
|
||||
|
||||
<pre><code><$view /></code></pre>
|
||||
@@ -4,7 +4,7 @@ tags: KeyboardWidget
|
||||
title: Keyboard Codes
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
! All Key Codes known by the KeyboardWidget
|
||||
This is a list of all the key codes supported by the KeyboardWidget:
|
||||
|
||||
<kbd>cancel</kbd>, <kbd>help</kbd>, <kbd>backspace</kbd>, <kbd>tab</kbd>, <kbd>clear</kbd>, <kbd>return</kbd>, <kbd>enter</kbd>, <kbd>pause</kbd>, <kbd>escape</kbd>, <kbd>space</kbd>,
|
||||
<kbd>page_up</kbd>, <kbd>page_down</kbd>, <kbd>end</kbd>, <kbd>home</kbd>, <kbd>left</kbd>, <kbd>up</kbd>, <kbd>right</kbd>, <kbd>down</kbd>, <kbd>printscreen</kbd>, <kbd>insert</kbd>, <kbd>delete</kbd>
|
||||
@@ -25,7 +25,3 @@ type: text/vnd.tiddlywiki
|
||||
<kbd>semicolon</kbd>, <kbd>equals</kbd>, <kbd>comma</kbd>, <kbd>dash</kbd>, <kbd>period</kbd>, <kbd>slash</kbd>, <kbd>backquote</kbd>, <kbd>openbracket</kbd>, <kbd>backslash</kbd>, <kbd>closebracket</kbd>, <kbd>quote</kbd>
|
||||
|
||||
<kbd>shift</kbd>, <kbd>ctrl</kbd>, <kbd>alt</kbd>, <kbd>meta</kbd>
|
||||
|
||||
! Examples
|
||||
|
||||
<<list-links "[tag[KeyboardWidget]prefix[Key Codes (Example]]">>
|
||||
@@ -0,0 +1,16 @@
|
||||
created: 20210519110226889
|
||||
modified: 20210519110226889
|
||||
tags: [[Other Resources]]
|
||||
title: "Grok TiddlyWiki" by Soren Bjornstad
|
||||
type: text/vnd.tiddlywiki
|
||||
url: https://groktiddlywiki.com/read/
|
||||
|
||||
This new textbook from Soren Bjornstad is highly recommended for learning ~TiddlyWiki. The presentation and design are also a first class example of using ~TiddlyWiki.
|
||||
|
||||
From the site:
|
||||
|
||||
> Grok ~TiddlyWiki is a textbook that helps you build a deep, lasting understanding of and proficiency with ~TiddlyWiki through a combination of detailed explanations, practical exercises, and spaced-repetition reviews of prompts called takeaways.
|
||||
|
||||
{{!!url}}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
caption: ~TW5-firebase
|
||||
caption: TW5-firebase
|
||||
color: #FFEB3B
|
||||
community-author: Peter Neumark
|
||||
created: 20210115121027582
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
title: ShadowTiddlers
|
||||
tags: Concepts
|
||||
modified: 201308091623
|
||||
|
||||
\define actions()
|
||||
<$action-setfield $tiddler="$:/state/tab/moresidebar-1850697562" $field="text" $value="$:/core/ui/MoreSideBar/Shadows"/>
|
||||
<$action-setfield $tiddler="$:/state/tab/sidebar--595412856" $field="text" $value="$:/core/ui/SideBar/More"/>
|
||||
\end
|
||||
\define click(text)
|
||||
<$button actions=<<actions>>>$text$</$button>
|
||||
\end
|
||||
|
||||
ShadowTiddlers are tiddlers that are loaded from within [[Plugins]]. Unlike ordinary tiddlers, they don't appear in most lists.
|
||||
|
||||
ShadowTiddlers can be overridden with an ordinary tiddler of the same name. If that tiddler is subsequently deleted then the original shadow tiddler is automatically restored.
|
||||
|
||||
The current shadow tiddlers are:
|
||||
!! Overridden Shadow Tiddlers
|
||||
|
||||
<$list filter="[all[shadows]sort[title]]"/>
|
||||
<<list-links "[is[tiddler]is[shadow]sort[title]]">>
|
||||
|
||||
!! Shadow Tiddlers
|
||||
|
||||
A full list of shadow tiddlers can be found in the sidebar in the "More" -> "Shadows" tab
|
||||
|
||||
@@ -26,7 +26,7 @@ Let's say you have a skeleton tiddler called 'Recipe template', and you want to
|
||||
|
||||
# You will want an image for your button. If none of the core images (shadow tiddlers with the prefix $:/core/images/) work for you, then you will need to create or acquire an SVG image (for example, one of the images at http://flaticon.com), drag it into your file so that it becomes a tiddler, edit the tiddler and adjust the height and width to 22px
|
||||
# You will want to create the tiddler that contains your tiddler. Create it, title it, and add the button code (see the code at the bottom of this tiddler for an example, with hints where you will need to adapt it). Tag it [[$:/tags/ViewToolbar]]
|
||||
# You will need to create a tiddler that tells TiddlyWiki whether your button should be visible in the toolbar or hidden. Let's title it [[$:/config/ViewToolbarButtons/Visibility/Recipe]]. Type `reveal` into the text area, and save.
|
||||
# You will need to create a tiddler that tells TiddlyWiki whether your button should be visible in the toolbar or hidden. Let's title it [[$:/config/ViewToolbarButtons/Visibility/Recipe]]. Type `show` into the text area, and save. If you want to hide it, type `hide` into the text area and save. The button will also be accessable from the ''ControlPanel : Appearance : Toolbars : ViewToolbar'' tab
|
||||
# You will want to position the button properly. Open the tiddler $:/tags/ViewToolbar and insert your button tiddler's title in the appropriate place in the list field.
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
created: 20210222140234737
|
||||
modified: 20210520174049056
|
||||
tags: Learning
|
||||
title: Demonstration: keyboard-driven-input Macro
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define allshortcuts(descriptor)
|
||||
<$wikify name=scutlist text=<<displayshortcuts (($descriptor$)) '' ' ' ''>> >
|
||||
<$list filter="[<scutlist>split[ ]join[</kbd> or <kbd>]addprefix[<kbd>]addsuffix[</kbd>]]" variable=scts><<scts>></$list>
|
||||
</$wikify>
|
||||
\end
|
||||
|
||||
\define kdi-demo-textmacrocall()
|
||||
```
|
||||
<$macrocall $name=keyboard-driven-input
|
||||
tiddler="$(tiddler)$"
|
||||
storeTitle="$(storeTitle)$"
|
||||
selectionStateTitle="$(selectionStateTitle)$"
|
||||
configTiddlerFilter="$(configTiddlerFilter)$"
|
||||
/>
|
||||
```
|
||||
\end
|
||||
|
||||
<$vars configTiddlerFilter="[[kdi-demo-configtid]]" tiddler="kdi-demo-tiddler" storeTitle="kdi-demo-storeTitle" selectionStateTitle="kdi-demo-selectionStateTitle" >
|
||||
|
||||
The [[keyboard-driven-input Macro]] is used to create filtered lists that update as the user types. It also allows navigating the lists, and invoking macros using list items, with the keyboard.
|
||||
|
||||
It consists of an ''[[edit-text widget|EditTextWidget]]'' wrapped in [[keyboard widgets|KeyboardWidget]]. There are <<.def keyboard>> widgets to listen for `((input-accept))`, `((input-accept-variant))`, and `((input-cancel))` keyboard shortcuts, but there is no default behaviour in response to these events; macros must be written to suit the use-case. There is also no default visualisation of the filtered options list.
|
||||
|
||||
!!Types of keyboard input handled by the <<.var keyboard-driven-input>> macro:
|
||||
|
||||
!!!Non-configurable:
|
||||
|
||||
The following keyboard events invoke macros defined alongside <<.var keyboard-driven-input>> in [[$:/core/macros/keyboard-driven-input]].
|
||||
|
||||
|Input |Purpose |Macro |h
|
||||
|typing input |composing a string to be used within list filters |<<.var keyboard-input-actions>> |
|
||||
|`((input-up))` (<<allshortcuts input-up>>) |temporarily selecting the previous item in the filtered list |<<.var input-next-actions>> with parameters <<.param afterOrBefore>>=`"before"`, <<.param reverse>>=`"reverse[]"` |
|
||||
|`((input-down))` (<<allshortcuts input-down>>) |temporarily selecting the next item in the filtered list |<<.var input-next-actions>> with <<.param afterOrBefore>>=`"after"`, <<.param reverse>>=`""` |
|
||||
|
||||
All of the above actions generate or modify data which <<.var keyboard-driven-input>> keeps in tiddlers specified using the macro's parameters. The data can then be accessed not only by the macros invoked by keyboard shortcuts, but also outside of these, e.g. a macro to display the filtered list(s).
|
||||
|
||||
!!!Configurable through parameters:
|
||||
|
||||
The following keyboard events invoke macros whose names are specified in parameters to <<.var keyboard-driven-input>>. The intended purpose is suggested by the parameter name, but there are no default macros defined within [[$:/core/macros/keyboard-driven-input]].
|
||||
|
||||
|[[Keyboard shortcut descriptor |Keyboard Shortcut Descriptor]] |Key combination |Parameter |h
|
||||
|`((input-accept))` |<<allshortcuts input-accept>> |<<.param inputAcceptActions>> |
|
||||
|`((input-accept-variant))` |<<allshortcuts input-accept-variant>> |<<.param inputAcceptVariantActions>> |
|
||||
|`((input-cancel))` |<<allshortcuts input-cancel>> |<<.param inputCancelActions>> |
|
||||
|
||||
<<.var keyboard-driven-input>> can be seen in action as part of various core features in TiddlyWiki, e.g.: the [[search feature|Searching in TiddlyWiki]], the [[tag-picker Macro]], and dropdown interfaces in the [[Editor toolbar]] such as [[Insert link]].
|
||||
|
||||
!!Minimal ingredients for a demonstration
|
||||
|
||||
Keeping in mind that the <<.var keyboard-driven-input>> macro does not, by itself, display list results, or do anything with a selected option, a minimal demonstration of the <<.var keyboard-driven-input>> macro requires:
|
||||
|
||||
# ''a tiddler, containing a filter'' whose results depend on the user's text input, to generate the options from which the user can select
|
||||
# ''several parameters:''
|
||||
#*''a filter'' to return the title of the tiddler where the filter described in step 1 can be found, and
|
||||
#*''tiddler titles'' to use for storing state information in response to input events. These tiddlers do not need to exist already. If they do exist, the <<.var keyboard-driven-input>> macro will change their contents.
|
||||
|
||||
!!The search filter(s)
|
||||
|
||||
By default, <<.var keyboard-driven-input>> will look for filters in the <<.field first-search-filter>> and <<.field second-search-filter>> fields of a tiddler (whose title is specified by a parameter discussed below).
|
||||
|
||||
This filter can refer to a variable called <<.var userInput>>, which shows the contents of the <<.def edit-text>> widget, as stored in a state tiddler (discussed below), at the time of the latest <kbd><<displayshortcuts ((input-up))>></kbd> or <kbd><<displayshortcuts ((input-down))>></kbd> event.
|
||||
|
||||
''Note:'' If this filter is to be referred to in a context outside the <<.var keyboard-driven-input>> macro (such as in a popup showing the filtered options), the variable <<.var userInput>> has to be defined in those contexts as well (by reading it from a state tiddler).
|
||||
|
||||
!!Minimal parameters
|
||||
|
||||
|Parameter name |Notes |h
|
||||
|<<.param configTiddlerFilter>> |This is a filter, rather than a tiddler title, allowing conditional behaviour (e.g. checking for an active tab, or preferring a filter that may not be present, with a fallback).<br>The title returned must belong to an existing tiddler, containing at least one filter with which <<.var keyboard-driven-input>> can generate its results list. |
|
||||
|<<.param tiddler>> |This tiddler contains either the typed input, or the instantaneous result selection, depending upon the most recent event. It is updated with each keystroke in the ''edit-text'' widget, //and// when the user uses the <kbd><<displayshortcuts ((input-up))>></kbd> or <kbd><<displayshortcuts ((input-down))>></kbd> key to cycle through filtered results. |
|
||||
|<<.param storeTitle>> |This tiddler always reflects the user input (transcluded from the tiddler <<.param tiddler>> after each keystroke into the ''edit-text'' widget). |
|
||||
|<<.param selectionStateTitle>> |This tiddler is updated on <kbd><<displayshortcuts ((input-up))>></kbd> or <kbd><<displayshortcuts ((input-down))>></kbd> events and contains either the user input with the suffix `-userInput`, or the instantaneous selection with the suffix `-primaryList` or `-secondaryList`, depending on which of up to two filters generated the list it came from. |
|
||||
|
||||
!!Demonstration setup
|
||||
|
||||
I have created a tiddler called <$list filter=<<configTiddlerFilter>> /> and put the following filter into its <<.field first-search-filter>> field:
|
||||
|
||||
<code><$list filter=<<configTiddlerFilter>> ><$text text={{!!first-search-filter}}/></$list></code>.
|
||||
|
||||
This filters for non-system tiddlers whose titles contain the text the user has typed.
|
||||
|
||||
To use the above filter with <<.var keyboard-driven-input>>, the value of the parameter <<.param configTiddlerFilter>> should be a filter that returns <$list filter=<<configTiddlerFilter>> />.
|
||||
|
||||
I can select <<.param tiddler>>, <<.param storeTitle>>, and <<.param selectionStateTitle>> fairly arbitrarily (just making sure not to use titles of tiddlers that I do not want changed).
|
||||
|
||||
This demonstration can now be invoked with the following macro call:
|
||||
|
||||
<<kdi-demo-textmacrocall>>
|
||||
|
||||
!!Demo
|
||||
|
||||
Try typing in here: <$macrocall $name=keyboard-driven-input
|
||||
tiddler=<<tiddler>>
|
||||
storeTitle=<<storeTitle>>
|
||||
selectionStateTitle=<<selectionStateTitle>>
|
||||
configTiddlerFilter=<<configTiddlerFilter>>
|
||||
/>
|
||||
|
||||
Observe the changes in the various state tiddlers in the below table. Use <kbd><<displayshortcuts ((input-up))>></kbd> and <kbd><<displayshortcuts ((input-down))>></kbd> keys to navigate among filter results. If nothing changes, try a shorter input to widen the filter. If the input has zero length, the list will contain all non-system tiddlers.
|
||||
|
||||
@@.tablestyle
|
||||
|
||||
|Parameter name |Tiddler title |Contents of <<.field text>> field of the tiddler |h
|
||||
|<<.param tiddler>> |{{{[<tiddler>]}}} |<pre><$text text={{{[<tiddler>get[text]]}}}/></pre>|
|
||||
|<<.param storeTitle>> |{{{[<storeTitle>]}}} |<pre><$text text= {{{[<storeTitle>get[text]]}}}/></pre>|
|
||||
|<<.param selectionStateTitle>> |{{{[<selectionStateTitle>]}}} |<pre><$text text={{{[<selectionStateTitle>get[text]]}}}/></pre>|
|
||||
@@
|
||||
|
||||
The <<.var keyboard-driven-input>> macro has many parameters available, including all the attributes of the enclosed ''edit-text'' widget, which make it very flexible in how it is used and how results can be displayed and interacted with.
|
||||
|
||||
See also: [[Customising search results]] and [[$:/core/ui/DefaultSearchResultList]]
|
||||
|
||||
<style>
|
||||
.tablestyle {width:100%;}
|
||||
.tablestyle td + td + td {width: 50%;}
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
created: 20210131043724146
|
||||
first-search-filter: [!is[system]search:title<userInput>sort[]]
|
||||
modified: 20210204012422020
|
||||
tags:
|
||||
title: kdi-demo-configtid
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20140418142957325
|
||||
modified: 20201201154521138
|
||||
modified: 20210912115121622
|
||||
tags: Features
|
||||
title: DateFormat
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -7,8 +7,11 @@ type: text/vnd.tiddlywiki
|
||||
When used to display date values (with the `format` attribute set to ''date''), the ViewWidget accepts a `template` attribute that allows the format of the date values to be specified. The format string is processed with the following substitutions:
|
||||
|
||||
|!Token |!Substituted Value |
|
||||
|`ddddd` |<<.from-version "5.2.0">> Day of year (1 to 365, or 366 for leap years) |
|
||||
|`0ddddd` |<<.from-version "5.2.0">> Zero padded day of year (001 to 365, or 366 for leap years) |
|
||||
|`DDD` |Day of week in full (eg, "Monday") |
|
||||
|`ddd` |Short day of week (eg, "Mon") |
|
||||
|`dddd` |<<.from-version "5.2.0">> Weekday number from 1 through 7, beginning with Monday and ending with Sunday |
|
||||
|`DD` |Day of month |
|
||||
|`0DD` |Adds a leading zero |
|
||||
|`DDth` |Adds a suffix |
|
||||
|
||||
@@ -18,7 +18,7 @@ The information above should be interpreted as follows:
|
||||
|
||||
* mainRender is the time taken for the initial display of the page template
|
||||
* styleRefresh is the time taken to refresh the page stylesheet
|
||||
* mainRender is the time taken to refresh the main page template
|
||||
* mainRefresh is the time taken to refresh the main page template
|
||||
|
||||
As an example, try switching between the sidebar tabs to compare how long they take to render.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20140410103123179
|
||||
modified: 20190206140446821
|
||||
modified: 20210830010231559
|
||||
tags: Filters
|
||||
title: Filter Operators
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -36,9 +36,9 @@ The following table lists all core operators, the most common ones marked ✓. T
|
||||
<<.group-heading "Listops Operators">>
|
||||
<<.operator-rows "[tag[Filter Operators]tag[Listops Operators]tag[Order Operators]!tag[Mathematics Operators]!tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>
|
||||
<<.group-heading "String Operators">>
|
||||
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]!tag[Mathematics Operators]tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>
|
||||
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>
|
||||
<<.group-heading "Mathematics Operators">>
|
||||
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]tag[Mathematics Operators]!tag[String Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>
|
||||
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]tag[Mathematics Operators]!tag[Tag Operators]!tag[Special Operators]sort[]]">>
|
||||
<<.group-heading "Tag Operators">>
|
||||
<<.operator-rows "[tag[Filter Operators]!tag[Order Operators]!tag[Mathematics Operators]!tag[String Operators]tag[Tag Operators]!tag[Special Operators]sort[]]">>
|
||||
<<.group-heading "Special Operators">>
|
||||
|
||||
@@ -2,13 +2,13 @@ caption: duplicateslugs
|
||||
created: 20200509141702846
|
||||
modified: 20200509141702846
|
||||
op-input: a [[selection of titles|Title Selection]]
|
||||
op-output: the input titles transformed so that they only contain lower case letters, numbers, periods, dashes and underscores
|
||||
op-purpose: returns each item in the list in a human-readable form for use in URLs or filenames
|
||||
op-output: input titles that yield duplicate slugs
|
||||
op-purpose: find titles that yield duplicate slugs
|
||||
tags: [[Filter Operators]]
|
||||
title: duplicateslugs Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.1.23">> The <<.olink slugify>> can be used to transform arbitrary tiddler titles into human readable strings suitable for use in URLs or filenames. However, itis possible for multiple different titles to slugify to the same string. The <<.olink duplicateslugs>> operator can be used to display a warning. For example:
|
||||
<<.from-version "5.1.23">> The <<.olink slugify>> operator can be used to transform arbitrary tiddler titles into human readable strings suitable for use in URLs or filenames. However, it is possible for multiple different titles to slugify to the same string. The <<.olink duplicateslugs>> operator can be used to display a warning. For example:
|
||||
|
||||
<$macrocall $name='wikitext-example-without-html'
|
||||
src='<$list filter="[!is[system]duplicateslugs[]limit[1]]" emptyMessage="There are no duplicate slugs">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user