mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-04-14 06:43:15 +00:00
Merge branch 'master' into toc-v5.3.x-rewrite
This commit is contained in:
commit
54b35695fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
$__StoryList.tid
|
||||
|
@ -393,6 +393,17 @@ node $TW5_BUILD_TIDDLYWIKI \
|
||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/highlight/empty.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# /plugins/tiddlywiki/geospatial/index.html Demo wiki with geospatial plugin
|
||||
# /plugins/tiddlywiki/geospatial/empty.html Empty wiki with geospatial plugin
|
||||
node $TW5_BUILD_TIDDLYWIKI \
|
||||
./editions/geospatialdemo \
|
||||
--verbose \
|
||||
--load $TW5_BUILD_OUTPUT/build.tid \
|
||||
--output $TW5_BUILD_OUTPUT \
|
||||
--rendertiddler $:/core/save/all plugins/tiddlywiki/geospatial/index.html text/plain \
|
||||
--rendertiddler $:/core/save/empty plugins/tiddlywiki/geospatial/empty.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
######################################################
|
||||
#
|
||||
# Language editions
|
||||
|
86
boot/boot.js
86
boot/boot.js
@ -142,15 +142,15 @@ $tw.utils.each = function(object,callback) {
|
||||
var next,f,length;
|
||||
if(object) {
|
||||
if(Object.prototype.toString.call(object) == "[object Array]") {
|
||||
for (f=0, length=object.length; f<length; f++) {
|
||||
for(f=0, length=object.length; f<length; f++) {
|
||||
next = callback(object[f],f,object);
|
||||
if(next === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var keys = Object.keys(object);
|
||||
for (f=0, length=keys.length; f<length; f++) {
|
||||
for(f=0, length=keys.length; f<length; f++) {
|
||||
var key = keys[f];
|
||||
next = callback(object[key],key,object);
|
||||
if(next === false) {
|
||||
@ -177,6 +177,7 @@ document: defaults to current document
|
||||
eventListeners: array of event listeners (this option won't work until $tw.utils.addEventListeners() has been loaded)
|
||||
*/
|
||||
$tw.utils.domMaker = function(tag,options) {
|
||||
var options = options || {};
|
||||
var doc = options.document || document;
|
||||
var element = doc.createElementNS(options.namespace || "http://www.w3.org/1999/xhtml",tag);
|
||||
if(options["class"]) {
|
||||
@ -218,9 +219,34 @@ $tw.utils.error = function(err) {
|
||||
heading = dm("h1",{text: errHeading}),
|
||||
prompt = dm("div",{text: promptMsg, "class": "tc-error-prompt"}),
|
||||
message = dm("div",{text: err, "class":"tc-error-message"}),
|
||||
button = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "close" : $tw.language.getString("Buttons/Close/Caption") )})], "class": "tc-error-prompt"}),
|
||||
form = dm("form",{children: [heading,prompt,message,button], "class": "tc-error-form"});
|
||||
closeButton = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "close" : $tw.language.getString("Buttons/Close/Caption") )})], "class": "tc-error-prompt"}),
|
||||
downloadButton = dm("div",{children: [dm("button",{text: ( $tw.language == undefined ? "download tiddlers" : $tw.language.getString("Buttons/EmergencyDownload/Caption") )})], "class": "tc-error-prompt"}),
|
||||
form = dm("form",{children: [heading,prompt,downloadButton,message,closeButton], "class": "tc-error-form"});
|
||||
document.body.insertBefore(form,document.body.firstChild);
|
||||
downloadButton.addEventListener("click",function(event) {
|
||||
if($tw && $tw.wiki) {
|
||||
var tiddlers = [];
|
||||
$tw.wiki.each(function(tiddler,title) {
|
||||
tiddlers.push(tiddler.fields);
|
||||
});
|
||||
var link = dm("a"),
|
||||
text = JSON.stringify(tiddlers);
|
||||
if(Blob !== undefined) {
|
||||
var blob = new Blob([text], {type: "text/html"});
|
||||
link.setAttribute("href", URL.createObjectURL(blob));
|
||||
} else {
|
||||
link.setAttribute("href","data:text/html," + encodeURIComponent(text));
|
||||
}
|
||||
link.setAttribute("download","emergency-tiddlers-" + (new Date()) + ".json");
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
} else {
|
||||
alert("Emergency tiddler download is not available");
|
||||
}
|
||||
event.preventDefault();
|
||||
return false;
|
||||
},true);
|
||||
form.addEventListener("submit",function(event) {
|
||||
document.body.removeChild(form);
|
||||
event.preventDefault();
|
||||
@ -249,7 +275,7 @@ Extend an object with the properties from a list of source objects
|
||||
$tw.utils.extend = function(object /*, sourceObjectList */) {
|
||||
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
|
||||
if(source) {
|
||||
for (var p in source) {
|
||||
for(var p in source) {
|
||||
object[p] = source[p];
|
||||
}
|
||||
}
|
||||
@ -263,7 +289,7 @@ Fill in any null or undefined properties of an object with the properties from a
|
||||
$tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
|
||||
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
|
||||
if(source) {
|
||||
for (var p in source) {
|
||||
for(var p in source) {
|
||||
if(object[p] === null || object[p] === undefined) {
|
||||
object[p] = source[p];
|
||||
}
|
||||
@ -786,6 +812,7 @@ $tw.utils.Crypto = function() {
|
||||
}
|
||||
return outputText;
|
||||
};
|
||||
$tw.sjcl = sjcl;
|
||||
this.setPassword = function(newPassword) {
|
||||
currentPassword = newPassword;
|
||||
this.updateCryptoStateTiddler();
|
||||
@ -866,8 +893,8 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
|
||||
} else {
|
||||
/*
|
||||
CommonJS optional require.main property:
|
||||
In a browser we offer a fake main module which points back to the boot function
|
||||
(Theoretically, this may allow TW to eventually load itself as a module in the browser)
|
||||
In a browser we offer a fake main module which points back to the boot function
|
||||
(Theoretically, this may allow TW to eventually load itself as a module in the browser)
|
||||
*/
|
||||
Object.defineProperty(sandbox.require, "main", {
|
||||
value: (typeof(require) !== "undefined") ? require.main : {TiddlyWiki: _boot},
|
||||
@ -909,9 +936,9 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
|
||||
moduleInfo.exports = moduleInfo.definition;
|
||||
}
|
||||
} catch(e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
if(e instanceof SyntaxError) {
|
||||
var line = e.lineNumber || e.line; // Firefox || Safari
|
||||
if (typeof(line) != "undefined" && line !== null) {
|
||||
if(typeof(line) != "undefined" && line !== null) {
|
||||
$tw.utils.error("Syntax error in boot module " + name + ":" + line + ":\n" + e.stack);
|
||||
} else if(!$tw.browser) {
|
||||
// this is the only way to get node.js to display the line at which the syntax error appeared,
|
||||
@ -1506,7 +1533,7 @@ Define all modules stored in ordinary tiddlers
|
||||
$tw.Wiki.prototype.defineTiddlerModules = function() {
|
||||
this.each(function(tiddler,title) {
|
||||
if(tiddler.hasField("module-type")) {
|
||||
switch (tiddler.fields.type) {
|
||||
switch(tiddler.fields.type) {
|
||||
case "application/javascript":
|
||||
// We only define modules that haven't already been defined, because in the browser modules in system tiddlers are defined in inline script
|
||||
if(!$tw.utils.hop($tw.modules.titles,tiddler.fields.title)) {
|
||||
@ -1967,10 +1994,10 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||
var value = tiddler[name];
|
||||
switch(fieldInfo.source) {
|
||||
case "subdirectories":
|
||||
value = path.relative(rootPath, filename).split('/').slice(0, -1);
|
||||
value = path.relative(rootPath, filename).split(path.sep).slice(0, -1);
|
||||
break;
|
||||
case "filepath":
|
||||
value = path.relative(rootPath, filename);
|
||||
value = path.relative(rootPath, filename).split(path.sep).join('/');
|
||||
break;
|
||||
case "filename":
|
||||
value = path.basename(filename);
|
||||
@ -2016,7 +2043,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
||||
arrayOfFiles = arrayOfFiles || [];
|
||||
var files = fs.readdirSync(dirPath);
|
||||
files.forEach(function(file) {
|
||||
if (recurse && fs.statSync(dirPath + path.sep + file).isDirectory()) {
|
||||
if(recurse && fs.statSync(dirPath + path.sep + file).isDirectory()) {
|
||||
arrayOfFiles = getAllFiles(dirPath + path.sep + file, recurse, arrayOfFiles);
|
||||
} else if(fs.statSync(dirPath + path.sep + file).isFile()){
|
||||
arrayOfFiles.push(path.join(dirPath, path.sep, file));
|
||||
@ -2161,13 +2188,16 @@ Returns an array of search paths
|
||||
*/
|
||||
$tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
|
||||
var pluginPaths = [path.resolve($tw.boot.corePath,libraryPath)],
|
||||
env;
|
||||
if(envVar) {
|
||||
env = process.env[envVar];
|
||||
if(env) {
|
||||
env.split(path.delimiter).map(function(item) {
|
||||
if(item) {
|
||||
pluginPaths.push(item);
|
||||
}
|
||||
});
|
||||
if(env) {
|
||||
env.split(path.delimiter).map(function(item) {
|
||||
if(item) {
|
||||
pluginPaths.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return pluginPaths;
|
||||
};
|
||||
@ -2253,7 +2283,7 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
|
||||
}
|
||||
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
|
||||
});
|
||||
if ($tw.boot.wikiPath == wikiPath) {
|
||||
if($tw.boot.wikiPath == wikiPath) {
|
||||
// Save the original tiddler file locations if requested
|
||||
var output = {}, relativePath, fileInfo;
|
||||
for(var title in $tw.boot.files) {
|
||||
@ -2453,8 +2483,12 @@ $tw.boot.initStartup = function(options) {
|
||||
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
|
||||
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");
|
||||
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.wordprocessingml.document","base64",".docx");
|
||||
$tw.utils.registerFileType("application/msword","base64",".doc");
|
||||
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","base64",".xlsx");
|
||||
$tw.utils.registerFileType("application/excel","base64",".xls");
|
||||
$tw.utils.registerFileType("application/vnd.ms-excel","base64",".xls");
|
||||
$tw.utils.registerFileType("application/vnd.openxmlformats-officedocument.presentationml.presentation","base64",".pptx");
|
||||
$tw.utils.registerFileType("application/mspowerpoint","base64",".ppt");
|
||||
$tw.utils.registerFileType("text/x-bibtex","utf8",".bib",{deserializerType:"application/x-bibtex"});
|
||||
$tw.utils.registerFileType("application/x-bibtex","utf8",".bib");
|
||||
$tw.utils.registerFileType("application/epub+zip","base64",".epub");
|
||||
@ -2603,14 +2637,14 @@ $tw.boot.doesTaskMatchPlatform = function(taskModule) {
|
||||
var platforms = taskModule.platforms;
|
||||
if(platforms) {
|
||||
for(var t=0; t<platforms.length; t++) {
|
||||
switch (platforms[t]) {
|
||||
switch(platforms[t]) {
|
||||
case "browser":
|
||||
if ($tw.browser) {
|
||||
if($tw.browser) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "node":
|
||||
if ($tw.node) {
|
||||
if($tw.node) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@ -2693,7 +2727,7 @@ Invoke the hook by key
|
||||
$tw.hooks.invokeHook = function(hookName /*, value,... */) {
|
||||
var args = Array.prototype.slice.call(arguments,1);
|
||||
if($tw.utils.hop($tw.hooks.names,hookName)) {
|
||||
for (var i = 0; i < $tw.hooks.names[hookName].length; i++) {
|
||||
for(var i = 0; i < $tw.hooks.names[hookName].length; i++) {
|
||||
args[0] = $tw.hooks.names[hookName][i].apply(null,args);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
title: $:/library/sjcl.js
|
||||
type: application/javascript
|
||||
library: yes
|
32
boot/tiddlywiki.files
Normal file
32
boot/tiddlywiki.files
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "sjcl.js",
|
||||
"fields": {
|
||||
"title": "$:/library/sjcl.js",
|
||||
"type": "application/javascript",
|
||||
"library": "yes"
|
||||
},
|
||||
"prefix": "(function(define) {\n",
|
||||
"suffix": "\n})(function (_,defined){window.sjcl = defined()})\n"
|
||||
},
|
||||
{
|
||||
"file": "boot.js",
|
||||
"fields": {
|
||||
"title": "$:/boot/boot.js",
|
||||
"type": "application/javascript"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "bootprefix.js",
|
||||
"fields": {
|
||||
"title": "$:/boot/bootprefix.js",
|
||||
"type": "application/javascript"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "boot.css.tid",
|
||||
"isTiddlerFile": true
|
||||
}
|
||||
]
|
||||
}
|
7
core/images/standard-layout.tid
Normal file
7
core/images/standard-layout.tid
Normal file
@ -0,0 +1,7 @@
|
||||
title: $:/core/images/standard-layout
|
||||
tags: $:/tags/Image
|
||||
|
||||
\parameters (size:"22pt")
|
||||
<svg width=<<size>> height=<<size>> class="tc-image-standard-layout tc-image-button" viewBox="0 0 128 128">
|
||||
<path d="M71.93 72A8.07 8.07 0 0 1 80 80.07v7.86A8.071 8.071 0 0 1 71.93 96H8.07A8.067 8.067 0 0 1 0 87.93v-7.86A8.072 8.072 0 0 1 8.07 72h63.86Zm0 32a8.07 8.07 0 0 1 8.07 8.07v7.86a8.071 8.071 0 0 1-8.07 8.07H8.07A8.067 8.067 0 0 1 0 119.93v-7.86A8.072 8.072 0 0 1 8.07 104h63.86Zm0-104A8.068 8.068 0 0 1 80 8.07v47.86A8.073 8.073 0 0 1 71.93 64H8.07A8.07 8.07 0 0 1 0 55.93V8.07A8.072 8.072 0 0 1 8.07 0h63.86Zm48 0c2.14 0 4.193.85 5.706 2.364A8.067 8.067 0 0 1 128 8.07v111.86c0 2.14-.85 4.193-2.364 5.706A8.067 8.067 0 0 1 119.93 128H96.07c-2.14 0-4.193-.85-5.706-2.364A8.067 8.067 0 0 1 88 119.93V8.07c0-2.14.85-4.193 2.364-5.706A8.067 8.067 0 0 1 96.07 0h23.86ZM116 24h-16a3.995 3.995 0 0 0-2.828 1.172 3.995 3.995 0 0 0 0 5.656A3.995 3.995 0 0 0 100 32h16a3.995 3.995 0 0 0 2.828-1.172 3.995 3.995 0 0 0 0-5.656A3.995 3.995 0 0 0 116 24Z"/>
|
||||
</svg>
|
@ -28,6 +28,7 @@ Encryption/ClearPassword/Caption: clear password
|
||||
Encryption/ClearPassword/Hint: Clear the password and save this wiki without encryption
|
||||
Encryption/SetPassword/Caption: set password
|
||||
Encryption/SetPassword/Hint: Set a password for saving this wiki with encryption
|
||||
EmergencyDownload/Caption: download tiddlers as json
|
||||
ExportPage/Caption: export all
|
||||
ExportPage/Hint: Export all tiddlers
|
||||
ExportTiddler/Caption: export tiddler
|
||||
|
@ -206,6 +206,12 @@ Stylesheets/Caption: Stylesheets
|
||||
Stylesheets/Expand/Caption: Expand All
|
||||
Stylesheets/Hint: This is the rendered CSS of the current stylesheet tiddlers tagged with <<tag "$:/tags/Stylesheet">>
|
||||
Stylesheets/Restore/Caption: Restore
|
||||
TestCases/Caption: Test Cases
|
||||
TestCases/Hint: Test cases are self contained examples for testing and learning
|
||||
TestCases/All/Caption: All Test Cases
|
||||
TestCases/All/Hint: All Test Cases
|
||||
TestCases/Failed/Caption: Failed Test Cases
|
||||
TestCases/Failed/Hint: Only Failed Test Cases
|
||||
Theme/Caption: Theme
|
||||
Theme/Prompt: Current theme:
|
||||
TiddlerFields/Caption: Tiddler Fields
|
||||
|
@ -9,7 +9,7 @@ config: Data to be inserted into `$tw.config`.
|
||||
filteroperator: Individual filter operator methods.
|
||||
global: Global data to be inserted into `$tw`.
|
||||
info: Publishes system information via the [[$:/temp/info-plugin]] pseudo-plugin.
|
||||
isfilteroperator: Operands for the ''is'' filter operator.
|
||||
isfilteroperator: Parameters for the ''is'' filter operator.
|
||||
library: Generic module type for general purpose JavaScript modules.
|
||||
macro: JavaScript macro definitions.
|
||||
parser: Parsers for different content types.
|
||||
|
@ -65,6 +65,9 @@ sidebar-tab-foreground-selected: Sidebar tab foreground for selected tabs
|
||||
sidebar-tab-foreground: Sidebar tab foreground
|
||||
sidebar-tiddler-link-foreground-hover: Sidebar tiddler link foreground hover
|
||||
sidebar-tiddler-link-foreground: Sidebar tiddler link foreground
|
||||
testcase-accent-level-1: Test case accent colour with no nesting
|
||||
testcase-accent-level-2: Test case accent colour with 2nd level nesting
|
||||
testcase-accent-level-3: Test case accent colour with 3rd level nesting or higher
|
||||
site-title-foreground: Site title foreground
|
||||
static-alert-foreground: Static alert foreground
|
||||
tab-background-selected: Tab background for selected tabs
|
||||
|
@ -30,6 +30,7 @@ name: The human readable name associated with a plugin tiddler
|
||||
parent-plugin: For a plugin, specifies which plugin of which it is a sub-plugin
|
||||
plugin-priority: A numerical value indicating the priority of a plugin tiddler
|
||||
plugin-type: The type of plugin in a plugin tiddler
|
||||
stability: The development status of a plugin: deprecated, experimental, stable, or legacy
|
||||
revision: The revision of the tiddler held at the server
|
||||
released: Date of a TiddlyWiki release
|
||||
source: The source URL associated with a tiddler
|
||||
|
@ -30,7 +30,7 @@ Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserialize
|
||||
Error/Filter: Filter error
|
||||
Error/FilterSyntax: Syntax error in filter expression
|
||||
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
|
||||
Error/IsFilterOperator: Filter Error: Unknown operand for the 'is' filter operator
|
||||
Error/IsFilterOperator: Filter Error: Unknown parameter for the 'is' filter operator
|
||||
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
|
||||
Error/LoadingPluginLibrary: Error loading plugin library
|
||||
Error/NetworkErrorAlert: `<h2>''Network Error''</h2>It looks like the connection to the server has been lost. This may indicate a problem with your network connection. Please attempt to restore network connectivity before continuing.<br><br>''Any unsaved changes will be automatically synchronised when connectivity is restored''.`
|
||||
@ -70,7 +70,7 @@ No: No
|
||||
OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library
|
||||
OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
||||
PageTemplate/Description: the default ~TiddlyWiki layout
|
||||
PageTemplate/Name: Default ~PageTemplate
|
||||
PageTemplate/Name: Standard Layout
|
||||
PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect
|
||||
RecentChanges/DateFormat: DDth MMM YYYY
|
||||
Shortcuts/Input/AdvancedSearch/Hint: Open the ~AdvancedSearch panel from within the sidebar search field
|
||||
|
@ -18,7 +18,7 @@ exports.info = {
|
||||
name: "listen",
|
||||
synchronous: true,
|
||||
namedParameterMode: true,
|
||||
mandatoryParameters: [],
|
||||
mandatoryParameters: []
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
|
@ -27,33 +27,8 @@ var Command = function(params,commander,callback) {
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var wiki = this.commander.wiki,
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
upgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,
|
||||
tiddlers = {};
|
||||
// Collect up the library plugins
|
||||
var collectPlugins = function(folder) {
|
||||
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var p=0; p<pluginFolders.length; p++) {
|
||||
if(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {
|
||||
pluginFields = $tw.loadPluginFolder(path.resolve(folder,"./" + pluginFolders[p]));
|
||||
if(pluginFields && pluginFields.title) {
|
||||
tiddlers[pluginFields.title] = pluginFields;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
collectPublisherPlugins = function(folder) {
|
||||
var publisherFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var t=0; t<publisherFolders.length; t++) {
|
||||
if(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {
|
||||
collectPlugins(path.resolve(folder,"./" + publisherFolders[t]));
|
||||
}
|
||||
}
|
||||
};
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,$tw.config.pluginsEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,$tw.config.themesEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,$tw.config.languagesEnvVar),collectPlugins);
|
||||
tiddlers = $tw.utils.getAllPlugins();
|
||||
// Save the upgrade library tiddler
|
||||
var pluginFields = {
|
||||
title: upgradeLibraryTitle,
|
||||
|
@ -43,7 +43,9 @@ Saves individual tiddlers in their raw text or binary format to the specified fi
|
||||
directory: path.resolve(self.commander.outputPath),
|
||||
pathFilters: [filenameFilter],
|
||||
wiki: wiki,
|
||||
fileInfo: {}
|
||||
fileInfo: {
|
||||
overwrite: true
|
||||
}
|
||||
});
|
||||
if(self.commander.verbose) {
|
||||
console.log("Saving \"" + title + "\" to \"" + fileInfo.filepath + "\"");
|
||||
|
@ -176,7 +176,10 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
|
||||
this.saveJSONFile(directory + path.sep + "plugin.info",pluginInfo);
|
||||
self.log("Writing " + directory + path.sep + "plugin.info: " + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));
|
||||
var pluginTiddlers = $tw.utils.parseJSONSafe(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
|
||||
$tw.utils.each(pluginTiddlers,function(tiddler) {
|
||||
$tw.utils.each(pluginTiddlers,function(tiddler,title) {
|
||||
if(!tiddler.title) {
|
||||
tiddler.title = title;
|
||||
}
|
||||
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
|
||||
});
|
||||
};
|
||||
|
26
core/modules/filters/backtranscludes.js
Normal file
26
core/modules/filters/backtranscludes.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/backtranscludes.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for returning all the backtranscludes from a tiddler
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.backtranscludes = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.pushTop(results,options.wiki.getTiddlerBacktranscludes(title));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
@ -14,12 +14,9 @@ Filter operators for cryptography, using the Stanford JavaScript library
|
||||
|
||||
exports.sha256 = function(source,operator,options) {
|
||||
var results = [],
|
||||
length = parseInt(operator.operand,10) || 20,
|
||||
sha256 = function(text) {
|
||||
return sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(text)).substr(0,length);
|
||||
};
|
||||
length = parseInt(operator.operand,10) || 20;
|
||||
source(function(tiddler,title) {
|
||||
results.push(sha256(title));
|
||||
results.push($tw.utils.sha256(title,{length: length}));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
@ -127,7 +127,7 @@ function diffPartsToChars(text1,text2,mode) {
|
||||
if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) {
|
||||
chars += String.fromCharCode(lineHash[line]);
|
||||
} else {
|
||||
if (lineArrayLength == maxLines) {
|
||||
if(lineArrayLength == maxLines) {
|
||||
line = text.substring(lineStart);
|
||||
lineEnd = text.length;
|
||||
}
|
||||
@ -217,7 +217,10 @@ exports.splitregexp = function(source,operator,options) {
|
||||
return ["RegExp error: " + ex];
|
||||
}
|
||||
source(function(tiddler,title) {
|
||||
Array.prototype.push.apply(result,title.split(regExp));
|
||||
var parts = title.split(regExp).map(function(part){
|
||||
return part || ""; // make sure it's a string
|
||||
});
|
||||
Array.prototype.push.apply(result,parts);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
@ -264,7 +267,7 @@ exports.pad = function(source,operator,options) {
|
||||
} else {
|
||||
var padString = "",
|
||||
padStringLength = targetLength - title.length;
|
||||
while (padStringLength > padString.length) {
|
||||
while(padStringLength > padString.length) {
|
||||
padString += fill;
|
||||
}
|
||||
//make sure we do not exceed the specified length
|
||||
|
26
core/modules/filters/transcludes.js
Normal file
26
core/modules/filters/transcludes.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/transcludes.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for returning all the transcludes from a tiddler
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.transcludes = function(source,operator,options) {
|
||||
var results = new $tw.utils.LinkedList();
|
||||
source(function(tiddler,title) {
|
||||
results.pushTop(options.wiki.getTiddlerTranscludes(title));
|
||||
});
|
||||
return results.toArray();
|
||||
};
|
||||
|
||||
})();
|
@ -202,7 +202,7 @@ Extended filter operators to manipulate the current list.
|
||||
}
|
||||
if(resultsIndex !== -1) {
|
||||
i = i + step;
|
||||
nextOperandIndex = (i < opLength ? i : i - opLength);
|
||||
nextOperandIndex = (i < opLength ? i : i % opLength);
|
||||
if(operands.length > 1) {
|
||||
results.splice(resultsIndex,1,operands[nextOperandIndex]);
|
||||
} else {
|
||||
|
122
core/modules/indexers/back-indexer.js
Normal file
122
core/modules/indexers/back-indexer.js
Normal file
@ -0,0 +1,122 @@
|
||||
/*\
|
||||
title: $:/core/modules/indexers/back-indexer.js
|
||||
type: application/javascript
|
||||
module-type: indexer
|
||||
|
||||
By parsing the tiddler text, indexes the tiddlers' back links, back transclusions, block level back links.
|
||||
|
||||
\*/
|
||||
function BackIndexer(wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
|
||||
BackIndexer.prototype.init = function() {
|
||||
this.subIndexers = {
|
||||
link: new BackSubIndexer(this,"extractLinks"),
|
||||
transclude: new BackSubIndexer(this,"extractTranscludes"),
|
||||
};
|
||||
};
|
||||
|
||||
BackIndexer.prototype.rebuild = function() {
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.rebuild();
|
||||
});
|
||||
};
|
||||
|
||||
BackIndexer.prototype.update = function(updateDescriptor) {
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.update(updateDescriptor);
|
||||
});
|
||||
};
|
||||
function BackSubIndexer(indexer,extractor) {
|
||||
this.wiki = indexer.wiki;
|
||||
this.indexer = indexer;
|
||||
this.extractor = extractor;
|
||||
/**
|
||||
* {
|
||||
* [target title, e.g. tiddler title being linked to]:
|
||||
* {
|
||||
* [source title, e.g. tiddler title that has link syntax in its text]: true
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.init = function() {
|
||||
// lazy init until first lookup
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype._init = function() {
|
||||
this.index = Object.create(null);
|
||||
var self = this;
|
||||
this.wiki.forEachTiddler(function(sourceTitle,tiddler) {
|
||||
var newTargets = self._getTarget(tiddler);
|
||||
$tw.utils.each(newTargets, function(target) {
|
||||
if(!self.index[target]) {
|
||||
self.index[target] = Object.create(null);
|
||||
}
|
||||
self.index[target][sourceTitle] = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.rebuild = function() {
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get things that is being referenced in the text, e.g. tiddler names in the link syntax.
|
||||
*/
|
||||
BackSubIndexer.prototype._getTarget = function(tiddler) {
|
||||
if(this.wiki.isBinaryTiddler(tiddler.fields.text)) {
|
||||
return [];
|
||||
}
|
||||
var parser = this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});
|
||||
if(parser) {
|
||||
return this.wiki[this.extractor](parser.tree);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.update = function(updateDescriptor) {
|
||||
// lazy init/update until first lookup
|
||||
if(!this.index) {
|
||||
return;
|
||||
}
|
||||
var newTargets = [],
|
||||
oldTargets = [],
|
||||
self = this;
|
||||
if(updateDescriptor.old.exists) {
|
||||
oldTargets = this._getTarget(updateDescriptor.old.tiddler);
|
||||
}
|
||||
if(updateDescriptor.new.exists) {
|
||||
newTargets = this._getTarget(updateDescriptor.new.tiddler);
|
||||
}
|
||||
|
||||
$tw.utils.each(oldTargets,function(target) {
|
||||
if(self.index[target]) {
|
||||
delete self.index[target][updateDescriptor.old.tiddler.fields.title];
|
||||
}
|
||||
});
|
||||
$tw.utils.each(newTargets,function(target) {
|
||||
if(!self.index[target]) {
|
||||
self.index[target] = Object.create(null);
|
||||
}
|
||||
self.index[target][updateDescriptor.new.tiddler.fields.title] = true;
|
||||
});
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.lookup = function(title) {
|
||||
if(!this.index) {
|
||||
this._init();
|
||||
}
|
||||
if(this.index[title]) {
|
||||
return Object.keys(this.index[title]);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
exports.BackIndexer = BackIndexer;
|
@ -1,86 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/indexers/backlinks-indexer.js
|
||||
type: application/javascript
|
||||
module-type: indexer
|
||||
|
||||
Indexes the tiddlers' backlinks
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global modules: false */
|
||||
"use strict";
|
||||
|
||||
|
||||
function BacklinksIndexer(wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.init = function() {
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.rebuild = function() {
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype._getLinks = function(tiddler) {
|
||||
var parser = this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});
|
||||
if(parser) {
|
||||
return this.wiki.extractLinks(parser.tree);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.update = function(updateDescriptor) {
|
||||
if(!this.index) {
|
||||
return;
|
||||
}
|
||||
var newLinks = [],
|
||||
oldLinks = [],
|
||||
self = this;
|
||||
if(updateDescriptor.old.exists) {
|
||||
oldLinks = this._getLinks(updateDescriptor.old.tiddler);
|
||||
}
|
||||
if(updateDescriptor.new.exists) {
|
||||
newLinks = this._getLinks(updateDescriptor.new.tiddler);
|
||||
}
|
||||
|
||||
$tw.utils.each(oldLinks,function(link) {
|
||||
if(self.index[link]) {
|
||||
delete self.index[link][updateDescriptor.old.tiddler.fields.title];
|
||||
}
|
||||
});
|
||||
$tw.utils.each(newLinks,function(link) {
|
||||
if(!self.index[link]) {
|
||||
self.index[link] = Object.create(null);
|
||||
}
|
||||
self.index[link][updateDescriptor.new.tiddler.fields.title] = true;
|
||||
});
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.lookup = function(title) {
|
||||
if(!this.index) {
|
||||
this.index = Object.create(null);
|
||||
var self = this;
|
||||
this.wiki.forEachTiddler(function(title,tiddler) {
|
||||
var links = self._getLinks(tiddler);
|
||||
$tw.utils.each(links, function(link) {
|
||||
if(!self.index[link]) {
|
||||
self.index[link] = Object.create(null);
|
||||
}
|
||||
self.index[link][title] = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
if(this.index[title]) {
|
||||
return Object.keys(this.index[title]);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
exports.BacklinksIndexer = BacklinksIndexer;
|
||||
|
||||
})();
|
@ -35,9 +35,11 @@ exports.run = function(filter,format) {
|
||||
// Collect all the fields
|
||||
for(t=0;t<tiddlers.length; t++) {
|
||||
tiddler = this.wiki.getTiddler(tiddlers[t]);
|
||||
for(f in tiddler.fields) {
|
||||
if(fields.indexOf(f) === -1) {
|
||||
fields.push(f);
|
||||
if(tiddler) {
|
||||
for(f in tiddler.fields) {
|
||||
if(fields.indexOf(f) === -1) {
|
||||
fields.push(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,8 +62,10 @@ exports.run = function(filter,format) {
|
||||
for(var t=0;t<tiddlers.length; t++) {
|
||||
row = [];
|
||||
tiddler = this.wiki.getTiddler(tiddlers[t]);
|
||||
for(f=0; f<fields.length; f++) {
|
||||
row.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || "" : ""));
|
||||
if(tiddler) {
|
||||
for(f=0; f<fields.length; f++) {
|
||||
row.push(quoteAndEscape(tiddler ? tiddler.getFieldString(fields[f]) || "" : ""));
|
||||
}
|
||||
}
|
||||
output.push(row.join(","));
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ exports.parseStringLiteral = function(source,pos) {
|
||||
var match = reString.exec(source);
|
||||
if(match && match.index === pos) {
|
||||
node.value = match[1] !== undefined ? match[1] :(
|
||||
match[2] !== undefined ? match[2] : match[3]
|
||||
match[2] !== undefined ? match[2] : match[3]
|
||||
);
|
||||
node.end = pos + match[0].length;
|
||||
return node;
|
||||
|
@ -29,13 +29,16 @@ exports.init = function(parser) {
|
||||
|
||||
exports.parse = function() {
|
||||
var reEnd = /(\r?\n```$)/mg;
|
||||
var languageStart = this.parser.pos + 3,
|
||||
languageEnd = languageStart + this.match[1].length;
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
// Look for the end of the block
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source),
|
||||
text;
|
||||
text,
|
||||
codeStart = this.parser.pos;
|
||||
// Process the block
|
||||
if(match) {
|
||||
text = this.parser.source.substring(this.parser.pos,match.index);
|
||||
@ -48,8 +51,8 @@ exports.parse = function() {
|
||||
return [{
|
||||
type: "codeblock",
|
||||
attributes: {
|
||||
code: {type: "string", value: text},
|
||||
language: {type: "string", value: this.match[1]}
|
||||
code: {type: "string", value: text, start: codeStart, end: this.parser.pos},
|
||||
language: {type: "string", value: this.match[1], start: languageStart, end: languageEnd}
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
@ -33,7 +33,8 @@ exports.parse = function() {
|
||||
// Look for the end marker
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source),
|
||||
text;
|
||||
text,
|
||||
start = this.parser.pos;
|
||||
// Process the text
|
||||
if(match) {
|
||||
text = this.parser.source.substring(this.parser.pos,match.index);
|
||||
@ -47,7 +48,9 @@ exports.parse = function() {
|
||||
tag: "code",
|
||||
children: [{
|
||||
type: "text",
|
||||
text: text
|
||||
text: text,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}]
|
||||
}];
|
||||
};
|
||||
|
@ -31,6 +31,7 @@ exports.init = function(parser) {
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
var start = this.parser.pos;
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Create the link unless it is suppressed
|
||||
if(this.match[0].substr(0,1) === "~") {
|
||||
@ -46,7 +47,7 @@ exports.parse = function() {
|
||||
rel: {type: "string", value: "noopener noreferrer"}
|
||||
},
|
||||
children: [{
|
||||
type: "text", text: this.match[0]
|
||||
type: "text", text: this.match[0], start: start, end: this.parser.pos
|
||||
}]
|
||||
}];
|
||||
}
|
||||
|
@ -31,6 +31,16 @@ exports.init = function(parser) {
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
var filterStart = this.parser.pos + 3;
|
||||
var filterEnd = filterStart + this.match[1].length;
|
||||
var toolTipStart = filterEnd + 1;
|
||||
var toolTipEnd = toolTipStart + (this.match[2] ? this.match[2].length : 0);
|
||||
var templateStart = toolTipEnd + 2;
|
||||
var templateEnd = templateStart + (this.match[3] ? this.match[3].length : 0);
|
||||
var styleStart = templateEnd + 2;
|
||||
var styleEnd = styleStart + (this.match[4] ? this.match[4].length : 0);
|
||||
var classesStart = styleEnd + 1;
|
||||
var classesEnd = classesStart + (this.match[5] ? this.match[5].length : 0);
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Get the match details
|
||||
var filter = this.match[1],
|
||||
@ -42,21 +52,21 @@ exports.parse = function() {
|
||||
var node = {
|
||||
type: "list",
|
||||
attributes: {
|
||||
filter: {type: "string", value: filter}
|
||||
filter: {type: "string", value: filter, start: filterStart, end: filterEnd},
|
||||
},
|
||||
isBlock: true
|
||||
};
|
||||
if(tooltip) {
|
||||
node.attributes.tooltip = {type: "string", value: tooltip};
|
||||
node.attributes.tooltip = {type: "string", value: tooltip, start: toolTipStart, end: toolTipEnd};
|
||||
}
|
||||
if(template) {
|
||||
node.attributes.template = {type: "string", value: template};
|
||||
node.attributes.template = {type: "string", value: template, start: templateStart, end: templateEnd};
|
||||
}
|
||||
if(style) {
|
||||
node.attributes.style = {type: "string", value: style};
|
||||
node.attributes.style = {type: "string", value: style, start: styleStart, end: styleEnd};
|
||||
}
|
||||
if(classes) {
|
||||
node.attributes.itemClass = {type: "string", value: classes.split(".").join(" ")};
|
||||
node.attributes.itemClass = {type: "string", value: classes.split(".").join(" "), start: classesStart, end: classesEnd};
|
||||
}
|
||||
return [node];
|
||||
};
|
||||
|
@ -30,6 +30,16 @@ exports.init = function(parser) {
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
var filterStart = this.parser.pos + 3;
|
||||
var filterEnd = filterStart + this.match[1].length;
|
||||
var toolTipStart = filterEnd + 1;
|
||||
var toolTipEnd = toolTipStart + (this.match[2] ? this.match[2].length : 0);
|
||||
var templateStart = toolTipEnd + 2;
|
||||
var templateEnd = templateStart + (this.match[3] ? this.match[3].length : 0);
|
||||
var styleStart = templateEnd + 2;
|
||||
var styleEnd = styleStart + (this.match[4] ? this.match[4].length : 0);
|
||||
var classesStart = styleEnd + 1;
|
||||
var classesEnd = classesStart + (this.match[5] ? this.match[5].length : 0);
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Get the match details
|
||||
@ -42,20 +52,20 @@ exports.parse = function() {
|
||||
var node = {
|
||||
type: "list",
|
||||
attributes: {
|
||||
filter: {type: "string", value: filter}
|
||||
filter: {type: "string", value: filter, start: filterStart, end: filterEnd},
|
||||
}
|
||||
};
|
||||
if(tooltip) {
|
||||
node.attributes.tooltip = {type: "string", value: tooltip};
|
||||
node.attributes.tooltip = {type: "string", value: tooltip, start: toolTipStart, end: toolTipEnd};
|
||||
}
|
||||
if(template) {
|
||||
node.attributes.template = {type: "string", value: template};
|
||||
node.attributes.template = {type: "string", value: template, start: templateStart, end: templateEnd};
|
||||
}
|
||||
if(style) {
|
||||
node.attributes.style = {type: "string", value: style};
|
||||
node.attributes.style = {type: "string", value: style, start: styleStart, end: styleEnd};
|
||||
}
|
||||
if(classes) {
|
||||
node.attributes.itemClass = {type: "string", value: classes.split(".").join(" ")};
|
||||
node.attributes.itemClass = {type: "string", value: classes.split(".").join(" "), start: classesStart, end: classesEnd};
|
||||
}
|
||||
return [node];
|
||||
};
|
||||
|
@ -45,10 +45,11 @@ exports.parse = function() {
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
match = reEnd.exec(this.parser.source);
|
||||
if(match) {
|
||||
var start = this.parser.pos;
|
||||
this.parser.pos = reEnd.lastIndex;
|
||||
// Add a line break if the terminator was a line break
|
||||
if(match[2]) {
|
||||
tree.push({type: "element", tag: "br"});
|
||||
tree.push({type: "element", tag: "br", start: start, end: this.parser.pos});
|
||||
}
|
||||
}
|
||||
} while(match && !match[1]);
|
||||
|
@ -30,15 +30,17 @@ exports.parse = function() {
|
||||
// Move past the !s
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Parse any classes, whitespace and then the heading itself
|
||||
var classStart = this.parser.pos;
|
||||
var classes = this.parser.parseClasses();
|
||||
var classEnd = this.parser.pos;
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
var tree = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
// Return the heading
|
||||
return [{
|
||||
type: "element",
|
||||
tag: "h" + headingLevel,
|
||||
tag: "h" + headingLevel,
|
||||
attributes: {
|
||||
"class": {type: "string", value: classes.join(" ")}
|
||||
"class": {type: "string", value: classes.join(" "), start: classStart, end: classEnd}
|
||||
},
|
||||
children: tree
|
||||
}];
|
||||
|
@ -44,6 +44,10 @@ Parse the most recent match
|
||||
exports.parse = function() {
|
||||
// Retrieve the most recent match so that recursive calls don't overwrite it
|
||||
var tag = this.nextTag;
|
||||
if (!tag.isSelfClosing) {
|
||||
tag.openTagStart = tag.start;
|
||||
tag.openTagEnd = tag.end;
|
||||
}
|
||||
this.nextTag = null;
|
||||
// Advance the parser position to past the tag
|
||||
this.parser.pos = tag.end;
|
||||
@ -60,6 +64,27 @@ exports.parse = function() {
|
||||
var reEnd = new RegExp("(" + reEndString + ")","mg");
|
||||
tag.children = this.parser.parseInlineRun(reEnd,{eatTerminator: true});
|
||||
}
|
||||
tag.end = this.parser.pos;
|
||||
tag.closeTagEnd = tag.end;
|
||||
if (tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') {
|
||||
tag.closeTagStart = tag.end;
|
||||
} else {
|
||||
tag.closeTagStart = tag.closeTagEnd - 2;
|
||||
var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd;
|
||||
if (!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
|
||||
while (tag.closeTagStart >= closeTagMinPos) {
|
||||
var char = this.parser.source[tag.closeTagStart];
|
||||
if (char === '>') {
|
||||
tag.closeTagStart = -1;
|
||||
break;
|
||||
}
|
||||
if (char === '<') break;
|
||||
tag.closeTagStart -= 1;
|
||||
}
|
||||
if (tag.closeTagStart < closeTagMinPos) {
|
||||
tag.closeTagStart = tag.end;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the tag
|
||||
return [tag];
|
||||
|
@ -122,9 +122,9 @@ exports.parseImage = function(source,pos) {
|
||||
}
|
||||
pos = token.end;
|
||||
if(token.match[1]) {
|
||||
node.attributes.tooltip = {type: "string", value: token.match[1].trim()};
|
||||
node.attributes.tooltip = {type: "string", value: token.match[1].trim(),start: token.start,end:token.start + token.match[1].length - 1};
|
||||
}
|
||||
node.attributes.source = {type: "string", value: (token.match[2] || "").trim()};
|
||||
node.attributes.source = {type: "string", value: (token.match[2] || "").trim(), start: token.start + (token.match[1] ? token.match[1].length : 0), end: token.end - 2};
|
||||
// Update the end position
|
||||
node.end = pos;
|
||||
return node;
|
||||
|
@ -38,13 +38,14 @@ exports.parse = function() {
|
||||
// Parse the filter terminated by a line break
|
||||
var reMatch = /(.*)(?:$|\r?\n)/mg;
|
||||
reMatch.lastIndex = this.parser.pos;
|
||||
var filterStart = this.parser.source;
|
||||
var match = reMatch.exec(this.parser.source);
|
||||
this.parser.pos = reMatch.lastIndex;
|
||||
// Parse tree nodes to return
|
||||
return [{
|
||||
type: "importvariables",
|
||||
attributes: {
|
||||
filter: {type: "string", value: match[1]}
|
||||
filter: {type: "string", value: match[1], start: filterStart, end: this.parser.pos}
|
||||
},
|
||||
children: []
|
||||
}];
|
||||
|
@ -74,6 +74,7 @@ exports.parse = function() {
|
||||
// Match the list marker
|
||||
var reMatch = /([\*#;:>]+)/mg;
|
||||
reMatch.lastIndex = this.parser.pos;
|
||||
var start = this.parser.pos;
|
||||
var match = reMatch.exec(this.parser.source);
|
||||
if(!match || match.index !== this.parser.pos) {
|
||||
break;
|
||||
@ -94,9 +95,21 @@ exports.parse = function() {
|
||||
}
|
||||
// Construct the list element or reuse the previous one at this level
|
||||
if(listStack.length <= t) {
|
||||
var listElement = {type: "element", tag: listInfo.listTag, children: [
|
||||
{type: "element", tag: listInfo.itemTag, children: []}
|
||||
]};
|
||||
var listElement = {
|
||||
type: "element",
|
||||
tag: listInfo.listTag,
|
||||
children: [
|
||||
{
|
||||
type: "element",
|
||||
tag: listInfo.itemTag,
|
||||
children: [],
|
||||
start: start,
|
||||
end: this.parser.pos,
|
||||
}
|
||||
],
|
||||
start: start,
|
||||
end: this.parser.pos,
|
||||
};
|
||||
// Link this list element into the last child item of the parent list item
|
||||
if(t) {
|
||||
var prevListItem = listStack[t-1].children[listStack[t-1].children.length-1];
|
||||
@ -105,21 +118,33 @@ exports.parse = function() {
|
||||
// Save this element in the stack
|
||||
listStack[t] = listElement;
|
||||
} else if(t === (match[0].length - 1)) {
|
||||
listStack[t].children.push({type: "element", tag: listInfo.itemTag, children: []});
|
||||
listStack[t].children.push({
|
||||
type: "element",
|
||||
tag: listInfo.itemTag,
|
||||
children: [],
|
||||
start: start,
|
||||
end: this.parser.pos,
|
||||
});
|
||||
}
|
||||
}
|
||||
if(listStack.length > match[0].length) {
|
||||
listStack.splice(match[0].length,listStack.length - match[0].length);
|
||||
}
|
||||
// Process the body of the list item into the last list item
|
||||
var classStart = this.parser.pos;
|
||||
var lastListChildren = listStack[listStack.length-1].children,
|
||||
lastListItem = lastListChildren[lastListChildren.length-1],
|
||||
classes = this.parser.parseClasses();
|
||||
var classEnd = this.parser.pos;
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
var tree = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
lastListItem.children.push.apply(lastListItem.children,tree);
|
||||
lastListItem.end = this.parser.pos;
|
||||
listStack[listStack.length-1].end = this.parser.pos;
|
||||
if(classes.length > 0) {
|
||||
$tw.utils.addClassToParseTreeNode(lastListItem,classes.join(" "));
|
||||
lastListItem.attributes.class.start = classStart;
|
||||
lastListItem.attributes.class.end = classEnd;
|
||||
}
|
||||
// Consume any whitespace following the list item
|
||||
this.parser.skipWhitespace();
|
||||
|
@ -96,15 +96,20 @@ exports.parseLink = function(source,pos) {
|
||||
splitPos = null;
|
||||
}
|
||||
// Pull out the tooltip and URL
|
||||
var tooltip, URL;
|
||||
var tooltip, URL, urlStart;
|
||||
textNode.start = pos;
|
||||
if(splitPos) {
|
||||
urlStart = splitPos + 1;
|
||||
URL = source.substring(splitPos + 1,closePos).trim();
|
||||
textNode.text = source.substring(pos,splitPos).trim();
|
||||
textNode.end = splitPos;
|
||||
} else {
|
||||
urlStart = pos;
|
||||
URL = source.substring(pos,closePos).trim();
|
||||
textNode.text = URL;
|
||||
textNode.end = closePos;
|
||||
}
|
||||
node.attributes.href = {type: "string", value: URL};
|
||||
node.attributes.href = {type: "string", value: URL, start: urlStart, end: closePos};
|
||||
node.attributes.target = {type: "string", value: "_blank"};
|
||||
node.attributes.rel = {type: "string", value: "noopener noreferrer"};
|
||||
// Update the end position
|
||||
|
@ -29,32 +29,39 @@ exports.init = function(parser) {
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
var start = this.parser.pos + 2;
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Process the link
|
||||
var text = this.match[1],
|
||||
link = this.match[2] || text;
|
||||
link = this.match[2] || text,
|
||||
textEndPos = this.parser.source.indexOf("|", start);
|
||||
if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) {
|
||||
textEndPos = this.matchRegExp.lastIndex - 2;
|
||||
}
|
||||
var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start;
|
||||
var linkEnd = linkStart + link.length;
|
||||
if($tw.utils.isLinkExternal(link)) {
|
||||
return [{
|
||||
type: "element",
|
||||
tag: "a",
|
||||
attributes: {
|
||||
href: {type: "string", value: link},
|
||||
href: {type: "string", value: link, start: linkStart, end: linkEnd},
|
||||
"class": {type: "string", value: "tc-tiddlylink-external"},
|
||||
target: {type: "string", value: "_blank"},
|
||||
rel: {type: "string", value: "noopener noreferrer"}
|
||||
},
|
||||
children: [{
|
||||
type: "text", text: text
|
||||
type: "text", text: text, start: start, end: textEndPos
|
||||
}]
|
||||
}];
|
||||
} else {
|
||||
return [{
|
||||
type: "link",
|
||||
attributes: {
|
||||
to: {type: "string", value: link}
|
||||
to: {type: "string", value: link, start: linkStart, end: linkEnd}
|
||||
},
|
||||
children: [{
|
||||
type: "text", text: text
|
||||
type: "text", text: text, start: start, end: textEndPos
|
||||
}]
|
||||
}];
|
||||
}
|
||||
|
@ -3,30 +3,7 @@ title: $:/core/modules/parsers/wikiparser/rules/quoteblock.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki text rule for quote blocks. For example:
|
||||
|
||||
```
|
||||
<<<.optionalClass(es) optional cited from
|
||||
a quote
|
||||
<<<
|
||||
|
||||
<<<.optionalClass(es)
|
||||
a quote
|
||||
<<< optional cited from
|
||||
```
|
||||
|
||||
Quotes can be quoted by putting more <s
|
||||
|
||||
```
|
||||
<<<
|
||||
Quote Level 1
|
||||
|
||||
<<<<
|
||||
QuoteLevel 2
|
||||
<<<<
|
||||
|
||||
<<<
|
||||
```
|
||||
Wiki text rule for quote blocks.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
@ -47,33 +24,42 @@ exports.init = function(parser) {
|
||||
exports.parse = function() {
|
||||
var classes = ["tc-quote"];
|
||||
// Get all the details of the match
|
||||
var reEndString = "^" + this.match[1] + "(?!<)";
|
||||
var reEndString = "^\\s*" + this.match[1] + "(?!<)";
|
||||
// Move past the <s
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
// Parse any classes, whitespace and then the optional cite itself
|
||||
var classStart = this.parser.pos;
|
||||
classes.push.apply(classes, this.parser.parseClasses());
|
||||
var classEnd = this.parser.pos;
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
var citeStart = this.parser.pos;
|
||||
var cite = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
var citeEnd = this.parser.pos;
|
||||
// before handling the cite, parse the body of the quote
|
||||
var tree= this.parser.parseBlocks(reEndString);
|
||||
var tree = this.parser.parseBlocks(reEndString);
|
||||
// If we got a cite, put it before the text
|
||||
if(cite.length > 0) {
|
||||
tree.unshift({
|
||||
type: "element",
|
||||
tag: "cite",
|
||||
children: cite
|
||||
children: cite,
|
||||
start: citeStart,
|
||||
end: citeEnd
|
||||
});
|
||||
}
|
||||
// Parse any optional cite
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
citeStart = this.parser.pos;
|
||||
cite = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
citeEnd = this.parser.pos;
|
||||
// If we got a cite, push it
|
||||
if(cite.length > 0) {
|
||||
tree.push({
|
||||
type: "element",
|
||||
tag: "cite",
|
||||
children: cite
|
||||
children: cite,
|
||||
start: citeStart,
|
||||
end: citeEnd
|
||||
});
|
||||
}
|
||||
// Return the blockquote element
|
||||
@ -81,7 +67,7 @@ exports.parse = function() {
|
||||
type: "element",
|
||||
tag: "blockquote",
|
||||
attributes: {
|
||||
class: { type: "string", value: classes.join(" ") },
|
||||
class: { type: "string", value: classes.join(" "), start: classStart, end: classEnd },
|
||||
},
|
||||
children: tree
|
||||
}];
|
||||
|
@ -29,10 +29,11 @@ exports.init = function(parser) {
|
||||
exports.parse = function() {
|
||||
var match = this.match[0];
|
||||
// Move past the match
|
||||
var start = this.parser.pos;
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Create the link unless it is suppressed
|
||||
if(match.substr(0,1) === "~") {
|
||||
return [{type: "text", text: match.substr(1)}];
|
||||
return [{type: "text", text: match.substr(1), start: start+1, end: this.parser.pos}];
|
||||
} else {
|
||||
return [{
|
||||
type: "link",
|
||||
@ -41,10 +42,12 @@ exports.parse = function() {
|
||||
},
|
||||
children: [{
|
||||
type: "text",
|
||||
text: match
|
||||
text: match,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}]
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
})();
|
||||
|
@ -150,7 +150,7 @@ exports.parse = function() {
|
||||
} else {
|
||||
// Otherwise, create a new row if this one is of a different type
|
||||
if(rowType !== currRowType) {
|
||||
rowContainer = {type: "element", tag: rowContainerTypes[rowType], children: []};
|
||||
rowContainer = {type: "element", tag: rowContainerTypes[rowType], children: [], start: this.parser.pos, end: this.parser.pos};
|
||||
table.children.push(rowContainer);
|
||||
currRowType = rowType;
|
||||
}
|
||||
@ -178,6 +178,7 @@ exports.parse = function() {
|
||||
// Increment the row count
|
||||
rowCount++;
|
||||
}
|
||||
rowContainer.end = this.parser.pos;
|
||||
}
|
||||
rowMatch = rowRegExp.exec(this.parser.source);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ exports.parse = function() {
|
||||
renderType = this.match[2];
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
var start = this.parser.pos;
|
||||
// Look for the end of the block
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source),
|
||||
@ -74,7 +75,9 @@ exports.parse = function() {
|
||||
tag: "pre",
|
||||
children: [{
|
||||
type: "text",
|
||||
text: text
|
||||
text: text,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}]
|
||||
}];
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ exports.parse = function() {
|
||||
// Get the details of the match
|
||||
var linkText = this.match[0];
|
||||
// Move past the macro call
|
||||
var start = this.parser.pos;
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// If the link starts with the unwikilink character then just output it as plain text
|
||||
if(linkText.substr(0,1) === $tw.config.textPrimitives.unWikiLink) {
|
||||
@ -57,7 +58,9 @@ exports.parse = function() {
|
||||
},
|
||||
children: [{
|
||||
type: "text",
|
||||
text: linkText
|
||||
text: linkText,
|
||||
start: start,
|
||||
end: this.parser.pos
|
||||
}]
|
||||
}];
|
||||
};
|
||||
|
@ -91,6 +91,11 @@ var WikiParser = function(type,text,options) {
|
||||
} else {
|
||||
topBranch.push.apply(topBranch,this.parseBlocks());
|
||||
}
|
||||
// Build rules' name map
|
||||
this.usingRuleMap = {};
|
||||
$tw.utils.each(this.pragmaRules, function (ruleInfo) { self.usingRuleMap[ruleInfo.rule.name] = Object.getPrototypeOf(ruleInfo.rule); });
|
||||
$tw.utils.each(this.blockRules, function (ruleInfo) { self.usingRuleMap[ruleInfo.rule.name] = Object.getPrototypeOf(ruleInfo.rule); });
|
||||
$tw.utils.each(this.inlineRules, function (ruleInfo) { self.usingRuleMap[ruleInfo.rule.name] = Object.getPrototypeOf(ruleInfo.rule); });
|
||||
// Return the parse tree
|
||||
};
|
||||
|
||||
@ -209,8 +214,13 @@ WikiParser.prototype.parsePragmas = function() {
|
||||
break;
|
||||
}
|
||||
// Process the pragma rule
|
||||
var start = this.pos;
|
||||
var subTree = nextMatch.rule.parse();
|
||||
if(subTree.length > 0) {
|
||||
// Set the start and end positions of the pragma rule if
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||
// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment
|
||||
currentTreeBranch.push.apply(currentTreeBranch,subTree);
|
||||
subTree[0].children = [];
|
||||
@ -235,7 +245,15 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
|
||||
// Look for a block rule that applies at the current position
|
||||
var nextMatch = this.findNextMatch(this.blockRules,this.pos);
|
||||
if(nextMatch && nextMatch.matchIndex === this.pos) {
|
||||
return nextMatch.rule.parse();
|
||||
var start = this.pos;
|
||||
var subTree = nextMatch.rule.parse();
|
||||
// Set the start and end positions of the first and last blocks if they're not already set
|
||||
if (subTree.length > 0) {
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
}
|
||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||
return subTree;
|
||||
}
|
||||
// Treat it as a paragraph if we didn't find a block rule
|
||||
var start = this.pos;
|
||||
@ -332,7 +350,16 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) {
|
||||
this.pos = nextMatch.matchIndex;
|
||||
}
|
||||
// Process the run rule
|
||||
tree.push.apply(tree,nextMatch.rule.parse());
|
||||
var start = this.pos;
|
||||
var subTree = nextMatch.rule.parse();
|
||||
// Set the start and end positions of the first and last child if they're not already set
|
||||
if (subTree.length > 0) {
|
||||
// Set the start and end positions of the first and last child if they're not already set
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
}
|
||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||
tree.push.apply(tree,subTree);
|
||||
// Look for the next run rule
|
||||
nextMatch = this.findNextMatch(this.inlineRules,this.pos);
|
||||
}
|
||||
@ -383,7 +410,15 @@ WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegEx
|
||||
this.pos = inlineRuleMatch.matchIndex;
|
||||
}
|
||||
// Process the inline rule
|
||||
tree.push.apply(tree,inlineRuleMatch.rule.parse());
|
||||
var start = this.pos;
|
||||
var subTree = inlineRuleMatch.rule.parse();
|
||||
// Set the start and end positions of the first and last child if they're not already set
|
||||
if (subTree.length > 0) {
|
||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||
}
|
||||
$tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; });
|
||||
tree.push.apply(tree,subTree);
|
||||
// Look for the next inline rule
|
||||
inlineRuleMatch = this.findNextMatch(this.inlineRules,this.pos);
|
||||
// Look for the next terminator match
|
||||
@ -409,7 +444,7 @@ WikiParser.prototype.pushTextWidget = function(array,text,start,end) {
|
||||
text = $tw.utils.trim(text);
|
||||
}
|
||||
if(text) {
|
||||
array.push({type: "text", text: text, start: start, end: end});
|
||||
array.push({type: "text", text: text, start: start, end: end});
|
||||
}
|
||||
};
|
||||
|
||||
@ -462,4 +497,3 @@ WikiParser.prototype.amendRules = function(type,names) {
|
||||
exports["text/vnd.tiddlywiki"] = WikiParser;
|
||||
|
||||
})();
|
||||
|
||||
|
@ -140,6 +140,11 @@ function sendResponse(request,response,statusCode,headers,data,encoding) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// RFC 7231, 6.1. Overview of Status Codes:
|
||||
// Browser clients may cache 200, 203, 204, 206, 300, 301,
|
||||
// 404, 405, 410, 414, and 501 unless given explicit cache controls
|
||||
headers["Cache-Control"] = headers["Cache-Control"] || "no-store";
|
||||
}
|
||||
/*
|
||||
If the gzip=yes is set, check if the user agent permits compression. If so,
|
||||
|
@ -29,7 +29,11 @@ var THROTTLE_REFRESH_TIMEOUT = 400;
|
||||
|
||||
exports.startup = function() {
|
||||
// Set up the title
|
||||
$tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE,{document: $tw.fakeDocument, parseAsInline: true});
|
||||
$tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE, {
|
||||
document: $tw.fakeDocument,
|
||||
parseAsInline: true,
|
||||
importPageMacros: true,
|
||||
});
|
||||
$tw.titleContainer = $tw.fakeDocument.createElement("div");
|
||||
$tw.titleWidgetNode.render($tw.titleContainer,null);
|
||||
document.title = $tw.titleContainer.textContent;
|
||||
@ -81,6 +85,8 @@ exports.startup = function() {
|
||||
deferredChanges = Object.create(null);
|
||||
$tw.hooks.invokeHook("th-page-refreshed");
|
||||
}
|
||||
var throttledRefresh = $tw.perf.report("throttledRefresh",refresh);
|
||||
|
||||
// Add the change event handler
|
||||
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
|
||||
// Check if only tiddlers that are throttled have changed
|
||||
@ -101,7 +107,7 @@ exports.startup = function() {
|
||||
if(isNaN(timeout)) {
|
||||
timeout = THROTTLE_REFRESH_TIMEOUT;
|
||||
}
|
||||
timerId = setTimeout(refresh,timeout);
|
||||
timerId = setTimeout(throttledRefresh,timeout);
|
||||
$tw.utils.extend(deferredChanges,changes);
|
||||
} else {
|
||||
$tw.utils.extend(deferredChanges,changes);
|
||||
|
@ -39,6 +39,7 @@ exports.startup = function() {
|
||||
method: params.method,
|
||||
body: params.body,
|
||||
binary: params.binary,
|
||||
useDefaultHeaders: params.useDefaultHeaders,
|
||||
oncompletion: params.oncompletion,
|
||||
onprogress: params.onprogress,
|
||||
bindStatus: params["bind-status"],
|
||||
@ -47,7 +48,11 @@ exports.startup = function() {
|
||||
headers: getPropertiesWithPrefix(params,"header-"),
|
||||
passwordHeaders: getPropertiesWithPrefix(params,"password-header-"),
|
||||
queryStrings: getPropertiesWithPrefix(params,"query-"),
|
||||
passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-")
|
||||
passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-"),
|
||||
basicAuthUsername: params["basic-auth-username"],
|
||||
basicAuthUsernameFromStore: params["basic-auth-username-from-store"],
|
||||
basicAuthPassword: params["basic-auth-password"],
|
||||
basicAuthPasswordFromStore: params["basic-auth-password-from-store"]
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tm-http-cancel-all-requests",function(event) {
|
||||
@ -68,7 +73,10 @@ exports.startup = function() {
|
||||
});
|
||||
// Install the copy-to-clipboard mechanism
|
||||
$tw.rootWidget.addEventListener("tm-copy-to-clipboard",function(event) {
|
||||
$tw.utils.copyToClipboard(event.param);
|
||||
$tw.utils.copyToClipboard(event.param,{
|
||||
successNotification: event.paramObject && event.paramObject.successNotification,
|
||||
failureNotification: event.paramObject && event.paramObject.failureNotification
|
||||
});
|
||||
});
|
||||
// Install the tm-focus-selector message
|
||||
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
|
||||
|
@ -93,7 +93,9 @@ exports.startup = function() {
|
||||
updateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,"yes").trim() === "yes" ? "permalink" : "none",
|
||||
updateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,"no").trim(),
|
||||
targetTiddler: event.param || event.tiddlerTitle,
|
||||
copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permalink" : "none"
|
||||
copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permalink" : "none",
|
||||
successNotification: event.paramObject && event.paramObject.successNotification,
|
||||
failureNotification: event.paramObject && event.paramObject.failureNotification
|
||||
});
|
||||
});
|
||||
// Listen for the tm-permaview message
|
||||
@ -102,7 +104,9 @@ exports.startup = function() {
|
||||
updateAddressBar: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_UPDATE_ADDRESS_BAR,"yes").trim() === "yes" ? "permaview" : "none",
|
||||
updateHistory: $tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,"no").trim(),
|
||||
targetTiddler: event.param || event.tiddlerTitle,
|
||||
copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permaview" : "none"
|
||||
copyToClipboard: $tw.wiki.getTiddlerText(CONFIG_PERMALINKVIEW_COPY_TO_CLIPBOARD,"yes").trim() === "yes" ? "permaview" : "none",
|
||||
successNotification: event.paramObject && event.paramObject.successNotification,
|
||||
failureNotification: event.paramObject && event.paramObject.failureNotification
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -177,6 +181,8 @@ options.updateAddressBar: "permalink", "permaview" or "no" (defaults to "permavi
|
||||
options.updateHistory: "yes" or "no" (defaults to "no")
|
||||
options.copyToClipboard: "permalink", "permaview" or "no" (defaults to "no")
|
||||
options.targetTiddler: optional title of target tiddler for permalink
|
||||
options.successNotification: optional title of tiddler to use as the notification in case of success
|
||||
options.failureNotification: optional title of tiddler to use as the notification in case of failure
|
||||
*/
|
||||
function updateLocationHash(options) {
|
||||
// Get the story and the history stack
|
||||
@ -205,14 +211,18 @@ function updateLocationHash(options) {
|
||||
break;
|
||||
}
|
||||
// Copy URL to the clipboard
|
||||
var url = "";
|
||||
switch(options.copyToClipboard) {
|
||||
case "permalink":
|
||||
$tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler));
|
||||
url = $tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler);
|
||||
break;
|
||||
case "permaview":
|
||||
$tw.utils.copyToClipboard($tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList)));
|
||||
url = $tw.utils.getLocationPath() + "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList));
|
||||
break;
|
||||
}
|
||||
if(url) {
|
||||
$tw.utils.copyToClipboard(url,{successNotification: options.successNotification, failureNotification: options.failureNotification});
|
||||
}
|
||||
// Only change the location hash if we must, thus avoiding unnecessary onhashchange events
|
||||
if($tw.utils.getLocationHash() !== $tw.locationHash) {
|
||||
if(options.updateHistory === "yes") {
|
||||
|
@ -56,7 +56,7 @@ exports.startup = function() {
|
||||
return;
|
||||
}
|
||||
// Initialise the document
|
||||
srcDocument.write("<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.close();
|
||||
srcDocument.title = windowTitle;
|
||||
srcWindow.addEventListener("beforeunload",function(event) {
|
||||
|
@ -292,7 +292,9 @@ exports.copyToClipboard = function(text,options) {
|
||||
} catch (err) {
|
||||
}
|
||||
if(!options.doNotNotify) {
|
||||
$tw.notifier.display(succeeded ? "$:/language/Notifications/CopiedToClipboard/Succeeded" : "$:/language/Notifications/CopiedToClipboard/Failed");
|
||||
var successNotification = options.successNotification || "$:/language/Notifications/CopiedToClipboard/Succeeded",
|
||||
failureNotification = options.failureNotification || "$:/language/Notifications/CopiedToClipboard/Failed"
|
||||
$tw.notifier.display(succeeded ? successNotification : failureNotification);
|
||||
}
|
||||
document.body.removeChild(textArea);
|
||||
};
|
||||
|
@ -69,7 +69,7 @@ HttpClient.prototype.cancelAllHttpRequests = function() {
|
||||
for(var t=this.requests.length - 1; t--; t>=0) {
|
||||
var requestInfo = this.requests[t];
|
||||
requestInfo.request.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.requests = [];
|
||||
this.updateRequestTracker();
|
||||
@ -100,6 +100,10 @@ headers: hashmap of header name to header value to be sent with the request
|
||||
passwordHeaders: hashmap of header name to password store name to be sent with the request
|
||||
queryStrings: hashmap of query string parameter name to parameter value to be sent with the request
|
||||
passwordQueryStrings: hashmap of query string parameter name to password store name to be sent with the request
|
||||
basicAuthUsername: plain username for basic authentication
|
||||
basicAuthUsernameFromStore: name of password store entry containing username
|
||||
basicAuthPassword: plain password for basic authentication
|
||||
basicAuthPasswordFromStore: name of password store entry containing password
|
||||
*/
|
||||
function HttpClientRequest(options) {
|
||||
var self = this;
|
||||
@ -112,6 +116,7 @@ function HttpClientRequest(options) {
|
||||
this.method = options.method || "GET";
|
||||
this.body = options.body || "";
|
||||
this.binary = options.binary || "";
|
||||
this.useDefaultHeaders = options.useDefaultHeaders !== "false" ? true : false,
|
||||
this.variables = options.variables;
|
||||
var url = options.url;
|
||||
$tw.utils.each(options.queryStrings,function(value,name) {
|
||||
@ -128,6 +133,11 @@ function HttpClientRequest(options) {
|
||||
$tw.utils.each(options.passwordHeaders,function(value,name) {
|
||||
self.requestHeaders[name] = $tw.utils.getPassword(value) || "";
|
||||
});
|
||||
this.basicAuthUsername = options.basicAuthUsername || (options.basicAuthUsernameFromStore && $tw.utils.getPassword(options.basicAuthUsernameFromStore)) || "";
|
||||
this.basicAuthPassword = options.basicAuthPassword || (options.basicAuthPasswordFromStore && $tw.utils.getPassword(options.basicAuthPasswordFromStore)) || "";
|
||||
if(this.basicAuthUsername && this.basicAuthPassword) {
|
||||
this.requestHeaders.Authorization = "Basic " + $tw.utils.base64Encode(this.basicAuthUsername + ":" + this.basicAuthPassword);
|
||||
}
|
||||
}
|
||||
|
||||
HttpClientRequest.prototype.send = function(callback) {
|
||||
@ -156,6 +166,7 @@ HttpClientRequest.prototype.send = function(callback) {
|
||||
this.xhr = $tw.utils.httpRequest({
|
||||
url: this.url,
|
||||
type: this.method,
|
||||
useDefaultHeaders: this.useDefaultHeaders,
|
||||
headers: this.requestHeaders,
|
||||
data: this.body,
|
||||
returnProp: this.binary === "" ? "responseText" : "response",
|
||||
@ -231,7 +242,8 @@ Make an HTTP request. Options are:
|
||||
exports.httpRequest = function(options) {
|
||||
var type = options.type || "GET",
|
||||
url = options.url,
|
||||
headers = options.headers || {accept: "application/json"},
|
||||
useDefaultHeaders = options.useDefaultHeaders !== false ? true : false,
|
||||
headers = options.headers || (useDefaultHeaders ? {accept: "application/json"} : {}),
|
||||
hasHeader = function(targetHeader) {
|
||||
targetHeader = targetHeader.toLowerCase();
|
||||
var result = false;
|
||||
@ -257,7 +269,7 @@ exports.httpRequest = function(options) {
|
||||
if(hasHeader("Content-Type") && ["application/x-www-form-urlencoded","multipart/form-data","text/plain"].indexOf(getHeader["Content-Type"]) === -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
},
|
||||
returnProp = options.returnProp || "responseText",
|
||||
request = new XMLHttpRequest(),
|
||||
@ -283,7 +295,7 @@ exports.httpRequest = function(options) {
|
||||
// Set up the state change handler
|
||||
request.onreadystatechange = function() {
|
||||
if(this.readyState === 4) {
|
||||
if(this.status === 200 || this.status === 201 || this.status === 204) {
|
||||
if(this.status >= 200 && this.status < 300) {
|
||||
// Success!
|
||||
options.callback(null,this[returnProp],this);
|
||||
return;
|
||||
@ -307,10 +319,10 @@ exports.httpRequest = function(options) {
|
||||
request.setRequestHeader(headerTitle,header);
|
||||
});
|
||||
}
|
||||
if(data && !hasHeader("Content-Type")) {
|
||||
if(data && !hasHeader("Content-Type") && useDefaultHeaders) {
|
||||
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
|
||||
}
|
||||
if(!hasHeader("X-Requested-With") && !isSimpleRequest(type,headers)) {
|
||||
if(!hasHeader("X-Requested-With") && !isSimpleRequest(type,headers) && useDefaultHeaders) {
|
||||
request.setRequestHeader("X-Requested-With","TiddlyWiki");
|
||||
}
|
||||
// Send data
|
||||
|
23
core/modules/utils/errors.js
Normal file
23
core/modules/utils/errors.js
Normal file
@ -0,0 +1,23 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/errors.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Custom errors for TiddlyWiki.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
function TranscludeRecursionError() {
|
||||
Error.apply(this,arguments);
|
||||
this.signatures = Object.create(null);
|
||||
};
|
||||
|
||||
/* Maximum permitted depth of the widget tree for recursion detection */
|
||||
TranscludeRecursionError.MAX_WIDGET_TREE_DEPTH = 1000;
|
||||
|
||||
TranscludeRecursionError.prototype = Object.create(Error);
|
||||
|
||||
exports.TranscludeRecursionError = TranscludeRecursionError;
|
||||
|
||||
})();
|
@ -42,7 +42,7 @@ var TW_TextNode = function(text) {
|
||||
this.textContent = text + "";
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(TW_TextNode,TW_Node.prototype);
|
||||
Object.setPrototypeOf(TW_TextNode.prototype,TW_Node.prototype);
|
||||
|
||||
Object.defineProperty(TW_TextNode.prototype, "nodeType", {
|
||||
get: function() {
|
||||
@ -67,7 +67,7 @@ var TW_Element = function(tag,namespace) {
|
||||
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
|
||||
};
|
||||
|
||||
Object.setPrototypeOf(TW_Element,TW_Node.prototype);
|
||||
Object.setPrototypeOf(TW_Element.prototype,TW_Node.prototype);
|
||||
|
||||
Object.defineProperty(TW_Element.prototype, "style", {
|
||||
get: function() {
|
||||
|
@ -316,11 +316,13 @@ Options include:
|
||||
pathFilters: optional array of filters to be used to generate the base path
|
||||
wiki: optional wiki for evaluating the pathFilters
|
||||
fileInfo: an existing fileInfo object to check against
|
||||
fileInfo.overwrite: if true, turns off filename clash numbers (defaults to false)
|
||||
*/
|
||||
exports.generateTiddlerFilepath = function(title,options) {
|
||||
var directory = options.directory || "",
|
||||
extension = options.extension || "",
|
||||
originalpath = (options.fileInfo && options.fileInfo.originalpath) ? options.fileInfo.originalpath : "",
|
||||
overwrite = options.fileInfo && options.fileInfo.overwrite || false,
|
||||
filepath;
|
||||
// Check if any of the pathFilters applies
|
||||
if(options.pathFilters && options.wiki) {
|
||||
@ -381,19 +383,20 @@ exports.generateTiddlerFilepath = function(title,options) {
|
||||
filepath += char.charCodeAt(0).toString();
|
||||
});
|
||||
}
|
||||
// Add a uniquifier if the file already exists
|
||||
var fullPath, oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
|
||||
// Add a uniquifier if the file already exists (default)
|
||||
var fullPath = path.resolve(directory, filepath + extension);
|
||||
if (!overwrite) {
|
||||
var oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
|
||||
count = 0;
|
||||
do {
|
||||
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
||||
if(oldPath && oldPath == fullPath) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
} while(fs.existsSync(fullPath));
|
||||
do {
|
||||
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
||||
if(oldPath && oldPath == fullPath) break;
|
||||
count++;
|
||||
} while(fs.existsSync(fullPath));
|
||||
}
|
||||
// If the last write failed with an error, or if path does not start with:
|
||||
// the resolved options.directory, the resolved wikiPath directory, the wikiTiddlersPath directory,
|
||||
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to tiddler directory.
|
||||
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to options.directory.
|
||||
var writePath = $tw.hooks.invokeHook("th-make-tiddler-path",fullPath,fullPath),
|
||||
encode = (options.fileInfo || {writeError: false}).writeError == true;
|
||||
if(!encode) {
|
||||
|
52
core/modules/utils/repository.js
Normal file
52
core/modules/utils/repository.js
Normal file
@ -0,0 +1,52 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/repository.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Utilities for working with the TiddlyWiki repository file structure
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Get an object containing all the plugins as a hashmap by title of the JSON representation of the plugin
|
||||
Options:
|
||||
|
||||
ignoreEnvironmentVariables: defaults to false
|
||||
*/
|
||||
exports.getAllPlugins = function(options) {
|
||||
options = options || {};
|
||||
var fs = require("fs"),
|
||||
path = require("path"),
|
||||
tiddlers = {};
|
||||
// Collect up the library plugins
|
||||
var collectPlugins = function(folder) {
|
||||
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var p=0; p<pluginFolders.length; p++) {
|
||||
if(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {
|
||||
var pluginFields = $tw.loadPluginFolder(path.resolve(folder,"./" + pluginFolders[p]));
|
||||
if(pluginFields && pluginFields.title) {
|
||||
tiddlers[pluginFields.title] = pluginFields;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
collectPublisherPlugins = function(folder) {
|
||||
var publisherFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var t=0; t<publisherFolders.length; t++) {
|
||||
if(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {
|
||||
collectPlugins(path.resolve(folder,"./" + publisherFolders[t]));
|
||||
}
|
||||
}
|
||||
};
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,options.ignoreEnvironmentVariables ? undefined : $tw.config.pluginsEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,options.ignoreEnvironmentVariables ? undefined : $tw.config.themesEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,options.ignoreEnvironmentVariables ? undefined : $tw.config.languagesEnvVar),collectPlugins);
|
||||
return tiddlers;
|
||||
};
|
||||
|
||||
})();
|
@ -819,6 +819,15 @@ exports.hashString = function(str) {
|
||||
},0);
|
||||
};
|
||||
|
||||
/*
|
||||
Cryptographic hash function as used by sha256 filter operator
|
||||
options.length .. number of characters returned defaults to 64
|
||||
*/
|
||||
exports.sha256 = function(str, options) {
|
||||
options = options || {}
|
||||
return $tw.sjcl.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(str)).substr(0,options.length || 64);
|
||||
}
|
||||
|
||||
/*
|
||||
Base64 utility functions that work in either browser or Node.js
|
||||
*/
|
||||
@ -922,7 +931,7 @@ IE does not have sign function
|
||||
*/
|
||||
exports.sign = Math.sign || function(x) {
|
||||
x = +x; // convert to a number
|
||||
if (x === 0 || isNaN(x)) {
|
||||
if(x === 0 || isNaN(x)) {
|
||||
return x;
|
||||
}
|
||||
return x > 0 ? 1 : -1;
|
||||
@ -935,7 +944,7 @@ exports.strEndsWith = function(str,ending,position) {
|
||||
if(str.endsWith) {
|
||||
return str.endsWith(ending,position);
|
||||
} else {
|
||||
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {
|
||||
if(typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {
|
||||
position = str.length;
|
||||
}
|
||||
position -= ending.length;
|
||||
|
@ -37,6 +37,7 @@ Compute the internal state of the widget
|
||||
DeleteFieldWidget.prototype.execute = function() {
|
||||
this.actionTiddler = this.getAttribute("$tiddler",this.getVariable("currentTiddler"));
|
||||
this.actionField = this.getAttribute("$field",null);
|
||||
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
|
||||
};
|
||||
|
||||
/*
|
||||
@ -69,11 +70,15 @@ DeleteFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
$tw.utils.each(this.attributes,function(attribute,name) {
|
||||
if(name.charAt(0) !== "$" && name !== "title") {
|
||||
removeFields[name] = undefined;
|
||||
hasChanged = true;
|
||||
if(name in tiddler.fields) {
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if(hasChanged) {
|
||||
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,removeFields,this.wiki.getModificationFields()));
|
||||
var creationFields = this.actionTimestamp ? this.wiki.getCreationFields() : {};
|
||||
var modificationFields = this.actionTimestamp ? this.wiki.getModificationFields() : {};
|
||||
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,removeFields,modificationFields));
|
||||
}
|
||||
}
|
||||
return true; // Action was invoked
|
||||
|
@ -66,7 +66,12 @@ LogWidget.prototype.log = function() {
|
||||
});
|
||||
|
||||
for(var v in this.variables) {
|
||||
allVars[v] = this.getVariable(v,{defaultValue:""});
|
||||
var variable = this.parentWidget && this.parentWidget.variables[v];
|
||||
if(variable && variable.isFunctionDefinition) {
|
||||
allVars[v] = variable.value;
|
||||
} else {
|
||||
allVars[v] = this.getVariable(v,{defaultValue:""});
|
||||
}
|
||||
}
|
||||
if(this.filter) {
|
||||
filteredVars = this.wiki.compileFilter(this.filter).call(this.wiki,this.wiki.makeTiddlerIterator(allVars));
|
||||
|
@ -262,7 +262,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
*/
|
||||
ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
if(changedAttributes.tooltip || changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
|
182
core/modules/widgets/data.js
Normal file
182
core/modules/widgets/data.js
Normal file
@ -0,0 +1,182 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/data.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Widget to dynamically represent one or more tiddlers
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var DataWidget = function(parseTreeNode,options) {
|
||||
this.dataWidgetTag = parseTreeNode.type;
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
DataWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
DataWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.dataPayload = this.computeDataTiddlerValues(); // Array of $tw.Tiddler objects
|
||||
this.domNode = this.document.createTextNode(this.readDataTiddlerValuesAsJson());
|
||||
parent.insertBefore(this.domNode,nextSibling);
|
||||
this.domNodes.push(this.domNode);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
DataWidget.prototype.execute = function() {
|
||||
// Nothing to do here
|
||||
};
|
||||
|
||||
/*
|
||||
Read the tiddler value(s) from a data widget as an array of tiddler field objects (not $tw.Tiddler objects)
|
||||
*/
|
||||
DataWidget.prototype.readDataTiddlerValues = function() {
|
||||
var results = [];
|
||||
$tw.utils.each(this.dataPayload,function(tiddler,index) {
|
||||
results.push(tiddler.getFieldStrings());
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
/*
|
||||
Read the tiddler value(s) from a data widget as an array of tiddler field objects (not $tw.Tiddler objects)
|
||||
*/
|
||||
DataWidget.prototype.readDataTiddlerValuesAsJson = function() {
|
||||
return JSON.stringify(this.readDataTiddlerValues(),null,4);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute list of tiddlers from a data widget
|
||||
*/
|
||||
DataWidget.prototype.computeDataTiddlerValues = function() {
|
||||
var self = this;
|
||||
// Read any attributes not prefixed with $
|
||||
var item = Object.create(null);
|
||||
$tw.utils.each(this.attributes,function(value,name) {
|
||||
if(name.charAt(0) !== "$") {
|
||||
item[name] = value;
|
||||
}
|
||||
});
|
||||
// Deal with $tiddler, $filter or $compound-tiddler attributes
|
||||
var tiddlers = [],title;
|
||||
if(this.hasAttribute("$tiddler")) {
|
||||
title = this.getAttribute("$tiddler");
|
||||
if(title) {
|
||||
var tiddler = this.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
tiddlers.push(tiddler);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.hasAttribute("$filter")) {
|
||||
var filter = this.getAttribute("$filter");
|
||||
if(filter) {
|
||||
var titles = this.wiki.filterTiddlers(filter);
|
||||
$tw.utils.each(titles,function(title) {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
tiddlers.push(tiddler);
|
||||
});
|
||||
}
|
||||
}
|
||||
if(this.hasAttribute("$compound-tiddler")) {
|
||||
title = this.getAttribute("$compound-tiddler");
|
||||
if(title) {
|
||||
tiddlers.push.apply(tiddlers,this.extractCompoundTiddler(title));
|
||||
}
|
||||
}
|
||||
// Return the literal item if none of the special attributes were used
|
||||
if(!this.hasAttribute("$tiddler") && !this.hasAttribute("$filter") && !this.hasAttribute("$compound-tiddler")) {
|
||||
if(Object.keys(item).length > 0 && !!item.title) {
|
||||
return [new $tw.Tiddler(item)];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
// Apply the item fields to each of the tiddlers
|
||||
delete item.title; // Do not overwrite the title
|
||||
if(Object.keys(item).length > 0) {
|
||||
$tw.utils.each(tiddlers,function(tiddler,index) {
|
||||
tiddlers[index] = new $tw.Tiddler(tiddler,item);
|
||||
});
|
||||
}
|
||||
return tiddlers;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Helper to extract tiddlers from text/vnd.tiddlywiki-multiple tiddlers
|
||||
*/
|
||||
DataWidget.prototype.extractCompoundTiddler = function(title) {
|
||||
var tiddler = this.wiki.getTiddler(title);
|
||||
if(tiddler && tiddler.fields.type === "text/vnd.tiddlywiki-multiple") {
|
||||
var text = tiddler.fields.text || "",
|
||||
rawTiddlers = text.split(/\r?\n\+\r?\n/),
|
||||
tiddlers = [];
|
||||
$tw.utils.each(rawTiddlers,function(rawTiddler) {
|
||||
var fields = Object.create(null),
|
||||
split = rawTiddler.split(/\r?\n\r?\n/mg);
|
||||
if(split.length >= 1) {
|
||||
fields = $tw.utils.parseFields(split[0],fields);
|
||||
}
|
||||
if(split.length >= 2) {
|
||||
fields.text = split.slice(1).join("\n\n");
|
||||
}
|
||||
tiddlers.push(new $tw.Tiddler(fields));
|
||||
});
|
||||
return tiddlers;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
DataWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
var newPayload = this.computeDataTiddlerValues();
|
||||
if(hasPayloadChanged(this.dataPayload,newPayload)) {
|
||||
this.dataPayload = newPayload;
|
||||
this.domNode.textContent = this.readDataTiddlerValuesAsJson();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Compare two arrays of tiddlers and return true if they are different
|
||||
*/
|
||||
function hasPayloadChanged(a,b) {
|
||||
if(a.length === b.length) {
|
||||
for(var t=0; t<a.length; t++) {
|
||||
if(!(a[t].isEqual(b[t]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
exports.data = DataWidget;
|
||||
|
||||
})();
|
@ -119,7 +119,7 @@ DraggableWidget.prototype.refresh = function(changedTiddlers) {
|
||||
return true;
|
||||
} else {
|
||||
if(changedAttributes["class"]) {
|
||||
this.assignDomNodeClasses();
|
||||
this.updateDomNodeClasses();
|
||||
}
|
||||
this.assignAttributes(this.domNodes[0],{
|
||||
changedAttributes: changedAttributes,
|
||||
@ -132,4 +132,4 @@ DraggableWidget.prototype.refresh = function(changedTiddlers) {
|
||||
|
||||
exports.draggable = DraggableWidget;
|
||||
|
||||
})();
|
||||
})();
|
||||
|
@ -49,7 +49,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
||||
this.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this);
|
||||
// Accumulate the <$set> widgets from each tiddler
|
||||
$tw.utils.each(this.tiddlerList,function(title) {
|
||||
var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:true});
|
||||
var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:false});
|
||||
if(parser) {
|
||||
var parseTreeNode = parser.tree[0];
|
||||
while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) {
|
||||
|
@ -74,6 +74,18 @@ ParametersWidget.prototype.execute = function() {
|
||||
self.setVariable(variableName,getValue(name));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// There is no parent transclude. i.e. direct rendering.
|
||||
// We use default values only.
|
||||
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(self.parseTreeNode),function(attr,index) {
|
||||
var name = attr.name;
|
||||
// If the attribute name starts with $$ then reduce to a single dollar
|
||||
if(name.substr(0,2) === "$$") {
|
||||
name = name.substr(1);
|
||||
}
|
||||
var value = self.getAttribute(attr.name,"");
|
||||
self.setVariable(name,value);
|
||||
});
|
||||
}
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets();
|
||||
|
165
core/modules/widgets/testcase.js
Normal file
165
core/modules/widgets/testcase.js
Normal file
@ -0,0 +1,165 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/testcase.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Widget to display a test case
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var TestCaseWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
TestCaseWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
TestCaseWidget.prototype.render = function(parent,nextSibling) {
|
||||
var self = this;
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Create container DOM node
|
||||
var domNode = this.document.createElement("div");
|
||||
this.domNodes.push(domNode);
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
// Render the children into a hidden DOM node
|
||||
var parser = {
|
||||
tree: [{
|
||||
type: "widget",
|
||||
attributes: {},
|
||||
orderedAttributes: [],
|
||||
children: this.parseTreeNode.children || []
|
||||
}]
|
||||
};
|
||||
this.contentRoot = this.wiki.makeWidget(parser,{
|
||||
document: $tw.fakeDocument,
|
||||
parentWidget: this
|
||||
});
|
||||
this.contentContainer = $tw.fakeDocument.createElement("div");
|
||||
this.contentRoot.render(this.contentContainer,null);
|
||||
// Create a wiki
|
||||
this.testcaseWiki = new $tw.Wiki();
|
||||
// Always load the core plugin
|
||||
var loadTiddler = function(title) {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
self.testcaseWiki.addTiddler(tiddler);
|
||||
}
|
||||
}
|
||||
loadTiddler("$:/core");
|
||||
loadTiddler("$:/plugins/tiddlywiki/codemirror");
|
||||
// Load tiddlers from child data widgets
|
||||
var tiddlers = [];
|
||||
this.findChildrenDataWidgets(this.contentRoot.children,"data",function(widget) {
|
||||
Array.prototype.push.apply(tiddlers,widget.readDataTiddlerValues());
|
||||
});
|
||||
var jsonPayload = JSON.stringify(tiddlers);
|
||||
this.testcaseWiki.addTiddlers(tiddlers);
|
||||
// Unpack plugin tiddlers
|
||||
this.testcaseWiki.readPluginInfo();
|
||||
this.testcaseWiki.registerPluginTiddlers("plugin");
|
||||
this.testcaseWiki.unpackPluginTiddlers();
|
||||
this.testcaseWiki.addIndexersToWiki();
|
||||
// Generate a `transclusion` variable that depends on the values of the payload tiddlers so that the template can easily make unique state tiddlers
|
||||
this.setVariable("transclusion",$tw.utils.hashString(jsonPayload));
|
||||
// Generate a `payloadTiddlers` variable that contains the payload in JSON format
|
||||
this.setVariable("payloadTiddlers",jsonPayload);
|
||||
// Only run the tests if the testcase output and expected results were specified, and those tiddlers actually exist in the wiki
|
||||
var shouldRunTests = false;
|
||||
if(this.testcaseTestOutput && this.testcaseWiki.tiddlerExists(this.testcaseTestOutput) && this.testcaseTestExpectedResult && this.testcaseWiki.tiddlerExists(this.testcaseTestExpectedResult)) {
|
||||
shouldRunTests = true;
|
||||
}
|
||||
// Render the test rendering if required
|
||||
if(shouldRunTests) {
|
||||
var testcaseOutputContainer = $tw.fakeDocument.createElement("div");
|
||||
var testcaseOutputWidget = this.testcaseWiki.makeTranscludeWidget(this.testcaseTestOutput,{
|
||||
document: $tw.fakeDocument,
|
||||
parseAsInline: false,
|
||||
parentWidget: this,
|
||||
variables: {
|
||||
currentTiddler: this.testcaseTestOutput
|
||||
}
|
||||
});
|
||||
testcaseOutputWidget.render(testcaseOutputContainer);
|
||||
}
|
||||
// Clear changes queue
|
||||
this.testcaseWiki.clearTiddlerEventQueue();
|
||||
// Run the actions if provided
|
||||
if(this.testcaseWiki.tiddlerExists(this.testcaseTestActions)) {
|
||||
testcaseOutputWidget.invokeActionString(this.testcaseWiki.getTiddlerText(this.testcaseTestActions));
|
||||
testcaseOutputWidget.refresh(this.testcaseWiki.changedTiddlers,testcaseOutputContainer);
|
||||
}
|
||||
// Set up the test result variables
|
||||
var testResult = "",
|
||||
outputHTML = "",
|
||||
expectedHTML = "";
|
||||
if(shouldRunTests) {
|
||||
outputHTML = testcaseOutputContainer.children[0].innerHTML;
|
||||
expectedHTML = this.testcaseWiki.getTiddlerText(this.testcaseTestExpectedResult);
|
||||
if(outputHTML === expectedHTML) {
|
||||
testResult = "pass";
|
||||
} else {
|
||||
testResult = "fail";
|
||||
}
|
||||
this.setVariable("outputHTML",outputHTML);
|
||||
this.setVariable("expectedHTML",expectedHTML);
|
||||
this.setVariable("testResult",testResult);
|
||||
this.setVariable("currentTiddler",this.testcaseTestOutput);
|
||||
}
|
||||
// Don't display anything if testHideIfPass is "yes" and the tests have passed
|
||||
if(this.testcaseHideIfPass === "yes" && testResult !== "fail") {
|
||||
return;
|
||||
}
|
||||
// Render the page root template of the subwiki
|
||||
var rootWidget = this.testcaseWiki.makeTranscludeWidget(this.testcaseTemplate,{
|
||||
document: this.document,
|
||||
parseAsInline: false,
|
||||
parentWidget: this
|
||||
});
|
||||
rootWidget.render(domNode);
|
||||
// Trap changes in the wiki and refresh the rendering
|
||||
this.testcaseWiki.addEventListener("change",function(changes) {
|
||||
rootWidget.refresh(changes,domNode);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
TestCaseWidget.prototype.execute = function() {
|
||||
this.testcaseTemplate = this.getAttribute("template","$:/core/ui/testcases/DefaultTemplate");
|
||||
this.testcaseTestOutput = this.getAttribute("testOutput");
|
||||
this.testcaseTestActions = this.getAttribute("testActions");
|
||||
this.testcaseTestExpectedResult = this.getAttribute("testExpectedResult");
|
||||
this.testcaseHideIfPass = this.getAttribute("testHideIfPass");
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
TestCaseWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if($tw.utils.count(changedAttributes) > 0) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
return this.contentRoot.refresh(changedTiddlers);
|
||||
}
|
||||
};
|
||||
|
||||
exports["testcase"] = TestCaseWidget;
|
||||
|
||||
})();
|
@ -30,7 +30,30 @@ TranscludeWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
try {
|
||||
this.renderChildren(parent,nextSibling);
|
||||
} catch(error) {
|
||||
if(error instanceof $tw.utils.TranscludeRecursionError) {
|
||||
// We were infinite looping.
|
||||
// We need to try and abort as much of the loop as we can, so we will keep "throwing" upward until we find a transclusion that has a different signature.
|
||||
// Hopefully that will land us just outside where the loop began. That's where we want to issue an error.
|
||||
// Rendering widgets beneath this point may result in a freezing browser if they explode exponentially.
|
||||
var transcludeSignature = this.getVariable("transclusion");
|
||||
if(this.getAncestorCount() > $tw.utils.TranscludeRecursionError.MAX_WIDGET_TREE_DEPTH - 50) {
|
||||
// For the first fifty transcludes we climb up, we simply collect signatures.
|
||||
// We're assuming that those first 50 will likely include all transcludes involved in the loop.
|
||||
error.signatures[transcludeSignature] = true;
|
||||
} else if(!error.signatures[transcludeSignature]) {
|
||||
// Now that we're past the first 50, let's look for the first signature that wasn't in the loop. That'll be where we print the error and resume rendering.
|
||||
this.children = [this.makeChildWidget({type: "error", attributes: {
|
||||
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
|
||||
}})];
|
||||
this.renderChildren(parent,nextSibling);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -12,9 +12,6 @@ Widget base class
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/* Maximum permitted depth of the widget tree for recursion detection */
|
||||
var MAX_WIDGET_TREE_DEPTH = 1000;
|
||||
|
||||
/*
|
||||
Create a widget object for a parse tree node
|
||||
parseTreeNode: reference to the parse tree node to be rendered
|
||||
@ -166,6 +163,8 @@ Widget.prototype.getVariableInfo = function(name,options) {
|
||||
});
|
||||
resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source);
|
||||
value = resultList[0] || "";
|
||||
} else {
|
||||
params = variable.params;
|
||||
}
|
||||
return {
|
||||
text: value,
|
||||
@ -317,7 +316,8 @@ Widget.prototype.getStateQualifier = function(name) {
|
||||
Make a fake widget with specified variables, suitable for variable lookup in filters
|
||||
*/
|
||||
Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
|
||||
var self = this;
|
||||
var self = this,
|
||||
variables = variables || {};
|
||||
return {
|
||||
getVariable: function(name,opts) {
|
||||
if($tw.utils.hop(variables,name)) {
|
||||
@ -335,7 +335,7 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
|
||||
};
|
||||
} else {
|
||||
opts = opts || {};
|
||||
opts.variables = variables;
|
||||
opts.variables = $tw.utils.extend(variables,opts.variables);
|
||||
return self.getVariableInfo(name,opts);
|
||||
};
|
||||
},
|
||||
@ -494,10 +494,8 @@ Widget.prototype.makeChildWidgets = function(parseTreeNodes,options) {
|
||||
this.children = [];
|
||||
var self = this;
|
||||
// Check for too much recursion
|
||||
if(this.getAncestorCount() > MAX_WIDGET_TREE_DEPTH) {
|
||||
this.children.push(this.makeChildWidget({type: "error", attributes: {
|
||||
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")}
|
||||
}}));
|
||||
if(this.getAncestorCount() > $tw.utils.TranscludeRecursionError.MAX_WIDGET_TREE_DEPTH) {
|
||||
throw new $tw.utils.TranscludeRecursionError();
|
||||
} else {
|
||||
// Create set variable widgets for each variable
|
||||
$tw.utils.each(options.variables,function(value,name) {
|
||||
@ -813,6 +811,21 @@ Widget.prototype.allowActionPropagation = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Find child <$data> widgets recursively. The tag name allows aliased versions of the widget to be found too
|
||||
*/
|
||||
Widget.prototype.findChildrenDataWidgets = function(children,tag,callback) {
|
||||
var self = this;
|
||||
$tw.utils.each(children,function(child) {
|
||||
if(child.dataWidgetTag === tag) {
|
||||
callback(child);
|
||||
}
|
||||
if(child.children) {
|
||||
self.findChildrenDataWidgets(child.children,tag,callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Evaluate a variable with parameters. This is a static convenience method that attempts to evaluate a variable as a function, returning an array of strings
|
||||
*/
|
||||
|
@ -534,8 +534,8 @@ Return an array of tiddler titles that link to the specified tiddler
|
||||
*/
|
||||
exports.getTiddlerBacklinks = function(targetTitle) {
|
||||
var self = this,
|
||||
backlinksIndexer = this.getIndexer("BacklinksIndexer"),
|
||||
backlinks = backlinksIndexer && backlinksIndexer.lookup(targetTitle);
|
||||
backIndexer = this.getIndexer("BackIndexer"),
|
||||
backlinks = backIndexer && backIndexer.subIndexers.link.lookup(targetTitle);
|
||||
|
||||
if(!backlinks) {
|
||||
backlinks = [];
|
||||
@ -549,6 +549,68 @@ exports.getTiddlerBacklinks = function(targetTitle) {
|
||||
return backlinks;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Return an array of tiddler titles that are directly transcluded within the given parse tree
|
||||
*/
|
||||
exports.extractTranscludes = function(parseTreeRoot) {
|
||||
// Count up the transcludes
|
||||
var transcludes = [],
|
||||
checkParseTree = function(parseTree, parentNode) {
|
||||
for(var t=0; t<parseTree.length; t++) {
|
||||
var parseTreeNode = parseTree[t];
|
||||
if(parseTreeNode.type === "transclude" && parseTreeNode.attributes.$tiddler && parseTreeNode.attributes.$tiddler.type === "string") {
|
||||
var value;
|
||||
// if it is Transclusion with Templates like `{{Index||$:/core/ui/TagTemplate}}`, the `$tiddler` will point to the template. We need to find the actual target tiddler from parent node
|
||||
if(parentNode && parentNode.type === "tiddler" && parentNode.attributes.tiddler && parentNode.attributes.tiddler.type === "string") {
|
||||
value = parentNode.attributes.tiddler.value;
|
||||
} else {
|
||||
value = parseTreeNode.attributes.$tiddler.value;
|
||||
}
|
||||
if(transcludes.indexOf(value) === -1 && value !== undefined) {
|
||||
transcludes.push(value);
|
||||
}
|
||||
}
|
||||
if(parseTreeNode.children) {
|
||||
checkParseTree(parseTreeNode.children, parseTreeNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
checkParseTree(parseTreeRoot);
|
||||
return transcludes;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Return an array of tiddler titles that are transcluded from the specified tiddler
|
||||
*/
|
||||
exports.getTiddlerTranscludes = function(title) {
|
||||
var self = this;
|
||||
// We'll cache the transcludes so they only get computed if the tiddler changes
|
||||
return this.getCacheForTiddler(title,"transcludes",function() {
|
||||
// Parse the tiddler
|
||||
var parser = self.parseTiddler(title);
|
||||
if(parser) {
|
||||
return self.extractTranscludes(parser.tree);
|
||||
}
|
||||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Return an array of tiddler titles that transclude to the specified tiddler
|
||||
*/
|
||||
exports.getTiddlerBacktranscludes = function(targetTitle) {
|
||||
var self = this,
|
||||
backIndexer = this.getIndexer("BackIndexer"),
|
||||
backtranscludes = backIndexer && backIndexer.subIndexers.transclude.lookup(targetTitle);
|
||||
|
||||
if(!backtranscludes) {
|
||||
backtranscludes = [];
|
||||
}
|
||||
return backtranscludes;
|
||||
};
|
||||
|
||||
/*
|
||||
Return a hashmap of tiddler titles that are referenced but not defined. Each value is the number of times the missing tiddler is referenced
|
||||
*/
|
||||
|
@ -95,6 +95,9 @@ table-footer-background: #a8a8a8
|
||||
table-header-background: #f0f0f0
|
||||
tag-background: #ec6
|
||||
tag-foreground: #ffffff
|
||||
testcase-accent-level-1: #84C5E6
|
||||
testcase-accent-level-2: #E3B740
|
||||
testcase-accent-level-3: #5FD564
|
||||
tiddler-background: <<colour background>>
|
||||
tiddler-border: <<colour background>>
|
||||
tiddler-controls-foreground-hover: #888888
|
||||
|
@ -5,5 +5,6 @@
|
||||
"author": "JeremyRuston",
|
||||
"core-version": ">=5.0.0",
|
||||
"plugin-priority": "0",
|
||||
"list": "readme"
|
||||
"list": "readme",
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ title: $:/core/save/all-external-js
|
||||
\whitespace trim
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
|
||||
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
|
||||
|
@ -3,7 +3,7 @@ title: $:/core/save/offline-external-js
|
||||
\whitespace trim
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define defaultCoreURL() tiddlywikicore-$(version)$.js
|
||||
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
||||
|
@ -2,6 +2,6 @@ title: $:/core/save/all
|
||||
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
{{$:/core/templates/tiddlywiki5.html}}
|
||||
|
@ -1,6 +1,6 @@
|
||||
title: $:/core/save/empty
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
\end
|
||||
{{$:/core/templates/tiddlywiki5.html}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
title: $:/core/save/lazy-all
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] [is[tiddler]type[application/javascript]] +[sort[title]]
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] [is[tiddler]type[application/javascript]] +[sort[title]]
|
||||
\end
|
||||
\define skinnySaveTiddlerFilter()
|
||||
[!is[system]] -[type[application/javascript]]
|
||||
|
@ -1,7 +1,7 @@
|
||||
title: $:/core/save/lazy-images
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]]
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]]
|
||||
\end
|
||||
\define skinnySaveTiddlerFilter()
|
||||
[!is[system]is[image]]
|
||||
|
@ -40,10 +40,8 @@ caption: {{$:/language/Search/Filter/Caption}}
|
||||
<$action-sendmessage $message="tm-edit-tiddler" $param={{{ [<__tiddler__>get[text]] }}}/>
|
||||
</$list></$list>
|
||||
\end
|
||||
|
||||
\whitespace trim
|
||||
<<lingo Filter/Hint>>
|
||||
|
||||
<div class="tc-search tc-advanced-search">
|
||||
<$keyboard key="((input-tab-right))" actions=<<set-next-input-tab>>>
|
||||
<$keyboard key="((input-tab-left))" actions=<<set-next-input-tab "before">>>
|
||||
@ -65,11 +63,10 @@ caption: {{$:/language/Search/Filter/Caption}}
|
||||
 
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch/FilterButton]!has[draft.of]]"><$transclude/></$list>
|
||||
</div>
|
||||
|
||||
<$reveal state="$:/temp/advancedsearch" type="nomatch" text="">
|
||||
<$set name="resultCount" value="<$count filter={{$:/temp/advancedsearch}}/>">
|
||||
<div class="tc-search-results">
|
||||
<<lingo Filter/Matches>>
|
||||
<p><<lingo Filter/Matches>></p>
|
||||
<$list filter={{$:/temp/advancedsearch}}>
|
||||
<span class={{{[<currentTiddler>addsuffix[-primaryList]] -[[$:/temp/advancedsearch/selected-item]get[text]] +[then[]else[tc-list-item-selected]] }}}>
|
||||
<$transclude tiddler="$:/core/ui/ListItemTemplate"/>
|
||||
|
@ -54,17 +54,18 @@ caption: {{$:/language/Search/Standard/Caption}}
|
||||
variable="listItem">
|
||||
<$vars
|
||||
userInput={{{ [[$:/temp/advancedsearch]get[text]] }}}
|
||||
configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}
|
||||
configTiddler={{{ [[$:/state/advancedsearch/standard/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}
|
||||
searchListState="$:/temp/advancedsearch/selected-item">
|
||||
<$list
|
||||
filter="[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]"
|
||||
emptyMessage="<$list filter='[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]'><$transclude/></$list>">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]">
|
||||
<$macrocall $name="tabs"
|
||||
tabsList="[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]"
|
||||
default={{$:/config/SearchResults/Default}}
|
||||
actions="<$action-setfield $tiddler='$:/state/advancedsearch/standard/currentTab' text=<<currentTab>>/>"
|
||||
explicitState="$:/state/tab/search-results/advancedsearch" />
|
||||
</$list>
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]] :else[[]]">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]]"><$transclude mode="block"/></$list>
|
||||
</$list>
|
||||
</$vars>
|
||||
</$list>
|
||||
</$reveal>
|
||||
|
@ -45,7 +45,17 @@ $:/config/Plugins/Disabled/$(currentTiddler)$
|
||||
<$view field="title"/>
|
||||
</h2>
|
||||
<h2>
|
||||
<div><em><$view field="version"/></em></div>
|
||||
<div>
|
||||
<%if [<currentTiddler>get[stability]match[STABILITY_0_DEPRECATED]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-deprecated">DEPRECATED</span>
|
||||
<%elseif [<currentTiddler>get[stability]match[STABILITY_1_EXPERIMENTAL]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-experimental">EXPERIMENTAL</span>
|
||||
<%elseif [<currentTiddler>get[stability]match[STABILITY_2_STABLE]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-stable">STABLE</span>
|
||||
<%elseif [<currentTiddler>get[stability]match[STABILITY_3_LEGACY]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-legacy">LEGACY</span>
|
||||
<%endif%>
|
||||
<em><$view field="version"/></em></div>
|
||||
</h2>
|
||||
</div>
|
||||
\end
|
||||
|
@ -70,9 +70,20 @@ $:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-description">
|
||||
<h1><strong><$text text={{{ [<assetInfo>get[name]] ~[<assetInfo>get[original-title]split[/]last[1]] }}}/></strong>:
|
||||
 
|
||||
<$view tiddler=<<assetInfo>> field="description"/></h1>
|
||||
<$view tiddler=<<assetInfo>> field="description"/>
|
||||
</h1>
|
||||
<h2><$view tiddler=<<assetInfo>> field="original-title"/></h2>
|
||||
<div><em><$view tiddler=<<assetInfo>> field="version"/></em></div>
|
||||
<div>
|
||||
<%if [<assetInfo>get[stability]match[STABILITY_0_DEPRECATED]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-deprecated">DEPRECATED</span>
|
||||
<%elseif [<assetInfo>get[stability]match[STABILITY_1_EXPERIMENTAL]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-experimental">EXPERIMENTAL</span>
|
||||
<%elseif [<assetInfo>get[stability]match[STABILITY_2_STABLE]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-stable">STABLE</span>
|
||||
<%elseif [<assetInfo>get[stability]match[STABILITY_3_LEGACY]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-legacy">LEGACY</span>
|
||||
<%endif%>
|
||||
<em><$view tiddler=<<assetInfo>> field="version"/></em></div>
|
||||
<$list filter="[<assetInfo>get[original-title]get[version]]" variable="installedVersion"><div><em>{{$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint}}</em></div></$list>
|
||||
</div>
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-buttons">
|
||||
|
@ -2,10 +2,19 @@ title: $:/core/ui/ControlPanel/Saving/DownloadSaver
|
||||
tags: $:/tags/ControlPanel/Saving
|
||||
caption: {{$:/language/ControlPanel/Saving/DownloadSaver/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Saving/DownloadSaver/
|
||||
|
||||
<div class="tc-control-panel-saving" data-setting-title=<<currentTab>>>
|
||||
|
||||
<<lingo Hint>>
|
||||
|
||||
!! <$link to="$:/config/DownloadSaver/AutoSave"><<lingo AutoSave/Hint>></$link>
|
||||
!!.tc-control-panel-accent <$link to="$:/config/DownloadSaver/AutoSave"><<lingo AutoSave/Hint>></$link>
|
||||
|
||||
<$checkbox tiddler="$:/config/DownloadSaver/AutoSave" field="text" checked="yes" unchecked="no" default="no"> <<lingo AutoSave/Description>> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/DownloadSaver/AutoSave"
|
||||
field="text" checked="yes" unchecked="no" default="no"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<span class="tc-tiny-gap-left"><<lingo AutoSave/Description>></span>
|
||||
</$checkbox>
|
||||
</div>
|
@ -3,14 +3,22 @@ tags: $:/tags/ControlPanel/Saving
|
||||
caption: {{$:/language/ControlPanel/Saving/General/Caption}}
|
||||
list-before:
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/
|
||||
|
||||
<div class="tc-control-panel-saving" data-setting-title=<<currentTab>>>
|
||||
|
||||
{{$:/language/ControlPanel/Saving/General/Hint}}
|
||||
|
||||
!! <$link to="$:/config/AutoSave"><<lingo AutoSave/Caption>></$link>
|
||||
!!.tc-control-panel-accent <$link to="$:/config/AutoSave"><<lingo AutoSave/Caption>></$link>
|
||||
|
||||
<<lingo AutoSave/Hint>>
|
||||
|
||||
<$radio tiddler="$:/config/AutoSave" value="yes"> <<lingo AutoSave/Enabled/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/AutoSave" value="yes">
|
||||
<span class="tc-tiny-gap-left"><<lingo AutoSave/Enabled/Description>></span>
|
||||
</$radio>
|
||||
|
||||
<$radio tiddler="$:/config/AutoSave" value="no"> <<lingo AutoSave/Disabled/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/AutoSave" value="no">
|
||||
<span class="tc-tiny-gap-left"><<lingo AutoSave/Disabled/Description>></span>
|
||||
</$radio>
|
||||
</div>
|
@ -2,7 +2,16 @@ title: $:/core/ui/ControlPanel/Settings/CamelCase
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/CamelCase/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/CamelCase/
|
||||
|
||||
<<lingo Hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/WikiParserRules/Inline/wikilink" field="text" checked="enable" unchecked="disable" default="enable"> <$link to="$:/config/WikiParserRules/Inline/wikilink"><<lingo Description>></$link> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/WikiParserRules/Inline/wikilink"
|
||||
field="text" checked="enable" unchecked="disable" default="enable"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/WikiParserRules/Inline/wikilink" class="tc-tiny-gap-left">
|
||||
<<lingo Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
@ -2,13 +2,18 @@ caption: {{$:/language/ControlPanel/Settings/DefaultMoreSidebarTab/Caption}}
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
title: $:/core/ui/ControlPanel/Settings/DefaultMoreSidebarTab
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/DefaultMoreSidebarTab/
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/DefaultMoreSidebarTab/
|
||||
|
||||
<$link to="$:/config/DefaultMoreSidebarTab"><<lingo Hint>></$link>
|
||||
<$link to="$:/config/DefaultMoreSidebarTab" class="tc-control-panel-item">
|
||||
<<lingo Hint>>
|
||||
</$link>
|
||||
|
||||
<$select tiddler="$:/config/DefaultMoreSidebarTab">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]">
|
||||
<option value=<<currentTiddler>>><$transclude field="caption"><$text text=<<currentTiddler>>/></$transclude></option>
|
||||
</$list>
|
||||
<$select tiddler="$:/config/DefaultMoreSidebarTab" class="tc-select">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]">
|
||||
<option value=<<currentTiddler>>><$transclude field="caption">
|
||||
<$text text=<<currentTiddler>>/>
|
||||
</$transclude>
|
||||
</option>
|
||||
</$list>
|
||||
</$select>
|
||||
|
@ -5,10 +5,16 @@ title: $:/core/ui/ControlPanel/Settings/DefaultSidebarTab
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/DefaultSidebarTab/
|
||||
\whitespace trim
|
||||
|
||||
<$link to="$:/config/DefaultSidebarTab"><<lingo Hint>></$link>
|
||||
<$link to="$:/config/DefaultSidebarTab" class="tc-control-panel-item">
|
||||
<<lingo Hint>>
|
||||
</$link>
|
||||
|
||||
<$select tiddler="$:/config/DefaultSidebarTab">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]">
|
||||
<option value=<<currentTiddler>>><$transclude field="caption"><$text text=<<currentTiddler>>/></$transclude></option>
|
||||
</$list>
|
||||
<$select tiddler="$:/config/DefaultSidebarTab" class="tc-select">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]">
|
||||
<option value=<<currentTiddler>>>
|
||||
<$transclude field="caption">
|
||||
<$text text=<<currentTiddler>>/>
|
||||
</$transclude>
|
||||
</option>
|
||||
</$list>
|
||||
</$select>
|
||||
|
@ -2,8 +2,15 @@ title: $:/core/ui/ControlPanel/Settings/EditorToolbar
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/EditorToolbar/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/EditorToolbar/
|
||||
<<lingo Hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/TextEditor/EnableToolbar" field="text" checked="yes" unchecked="no" default="yes"> <$link to="$:/config/TextEditor/EnableToolbar"><<lingo Description>></$link> </$checkbox>
|
||||
|
||||
<$checkbox tiddler="$:/config/TextEditor/EnableToolbar"
|
||||
field="text" checked="yes" unchecked="no" default="yes"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/TextEditor/EnableToolbar" class="tc-tiny-gap-left">
|
||||
<<lingo Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
@ -2,9 +2,17 @@ title: $:/core/ui/ControlPanel/Settings/InfoPanelMode
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/InfoPanelMode/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/InfoPanelMode/
|
||||
<$link to="$:/config/TiddlerInfo/Mode"><<lingo Hint>></$link>
|
||||
|
||||
<$radio tiddler="$:/config/TiddlerInfo/Mode" value="popup"> <<lingo Popup/Description>> </$radio>
|
||||
<$link to="$:/config/TiddlerInfo/Mode" class="tc-control-panel-item">
|
||||
<<lingo Hint>>
|
||||
</$link>
|
||||
|
||||
<$radio tiddler="$:/config/TiddlerInfo/Mode" value="sticky"> <<lingo Sticky/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/TiddlerInfo/Mode" value="popup">
|
||||
<span class="tc-tiny-gap-left"><<lingo Popup/Description>></span>
|
||||
</$radio>
|
||||
|
||||
<$radio tiddler="$:/config/TiddlerInfo/Mode" value="sticky">
|
||||
<span class="tc-tiny-gap-left"><<lingo Sticky/Description>></span>
|
||||
</$radio>
|
||||
|
@ -2,21 +2,25 @@ title: $:/core/ui/ControlPanel/Settings/LinkToBehaviour
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/LinkToBehaviour/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/LinkToBehaviour/
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/LinkToBehaviour/
|
||||
|
||||
<$link to="$:/config/Navigation/openLinkFromInsideRiver"><<lingo "InsideRiver/Hint">></$link>
|
||||
<$link to="$:/config/Navigation/openLinkFromInsideRiver" class="tc-control-panel-item">
|
||||
<<lingo "InsideRiver/Hint">>
|
||||
</$link>
|
||||
|
||||
<$select tiddler="$:/config/Navigation/openLinkFromInsideRiver">
|
||||
<option value="above"><<lingo "OpenAbove">></option>
|
||||
<option value="below"><<lingo "OpenBelow">></option>
|
||||
<option value="top"><<lingo "OpenAtTop">></option>
|
||||
<option value="bottom"><<lingo "OpenAtBottom">></option>
|
||||
<$select tiddler="$:/config/Navigation/openLinkFromInsideRiver" class="tc-select">
|
||||
<option value="above"><<lingo "OpenAbove">></option>
|
||||
<option value="below"><<lingo "OpenBelow">></option>
|
||||
<option value="top"><<lingo "OpenAtTop">></option>
|
||||
<option value="bottom"><<lingo "OpenAtBottom">></option>
|
||||
</$select>
|
||||
|
||||
<$link to="$:/config/Navigation/openLinkFromOutsideRiver"><<lingo "OutsideRiver/Hint">></$link>
|
||||
<$link to="$:/config/Navigation/openLinkFromOutsideRiver" class="tc-control-panel-item">
|
||||
<<lingo "OutsideRiver/Hint">>
|
||||
</$link>
|
||||
|
||||
<$select tiddler="$:/config/Navigation/openLinkFromOutsideRiver">
|
||||
<option value="top"><<lingo "OpenAtTop">></option>
|
||||
<option value="bottom"><<lingo "OpenAtBottom">></option>
|
||||
<$select tiddler="$:/config/Navigation/openLinkFromOutsideRiver" class="tc-select">
|
||||
<option value="top"><<lingo "OpenAtTop">></option>
|
||||
<option value="bottom"><<lingo "OpenAtBottom">></option>
|
||||
</$select>
|
||||
|
@ -2,8 +2,12 @@ title: $:/core/ui/ControlPanel/Settings/MissingLinks
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/MissingLinks/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/MissingLinks/
|
||||
<<lingo Hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/MissingLinks" field="text" checked="yes" unchecked="no" default="yes"> <$link to="$:/config/MissingLinks"><<lingo Description>></$link> </$checkbox>
|
||||
|
||||
<$checkbox tiddler="$:/config/MissingLinks" field="text" checked="yes" unchecked="no" default="yes">
|
||||
<$link to="$:/config/MissingLinks" class="tc-control-panel-item">
|
||||
<span class="tc-tiny-gap-left"><<lingo Description>></span>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
@ -2,12 +2,21 @@ title: $:/core/ui/ControlPanel/Settings/NavigationAddressBar
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/NavigationAddressBar/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/NavigationAddressBar/
|
||||
|
||||
<$link to="$:/config/Navigation/UpdateAddressBar"><<lingo Hint>></$link>
|
||||
<$link to="$:/config/Navigation/UpdateAddressBar" class="tc-control-panel-item">
|
||||
<<lingo Hint>>
|
||||
</$link>
|
||||
|
||||
<$radio tiddler="$:/config/Navigation/UpdateAddressBar" value="permaview"> <<lingo Permaview/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/Navigation/UpdateAddressBar" value="permaview">
|
||||
<span class="tc-tiny-gap-left"><<lingo Permaview/Description>></span>
|
||||
</$radio>
|
||||
|
||||
<$radio tiddler="$:/config/Navigation/UpdateAddressBar" value="permalink"> <<lingo Permalink/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/Navigation/UpdateAddressBar" value="permalink">
|
||||
<span class="tc-tiny-gap-left"><<lingo Permalink/Description>></span>
|
||||
</$radio>
|
||||
|
||||
<$radio tiddler="$:/config/Navigation/UpdateAddressBar" value="no"> <<lingo No/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/Navigation/UpdateAddressBar" value="no">
|
||||
<span class="tc-tiny-gap-left"><<lingo No/Description>></span>
|
||||
</$radio>
|
||||
|
@ -2,9 +2,17 @@ title: $:/core/ui/ControlPanel/Settings/NavigationHistory
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/NavigationHistory/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/NavigationHistory/
|
||||
<$link to="$:/config/Navigation/UpdateHistory"><<lingo Hint>></$link>
|
||||
|
||||
<$radio tiddler="$:/config/Navigation/UpdateHistory" value="yes"> <<lingo Yes/Description>> </$radio>
|
||||
<$link to="$:/config/Navigation/UpdateHistory" class="tc-control-panel-item">
|
||||
<<lingo Hint>>
|
||||
</$link>
|
||||
|
||||
<$radio tiddler="$:/config/Navigation/UpdateHistory" value="no"> <<lingo No/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/Navigation/UpdateHistory" value="yes">
|
||||
<span class="tc-tiny-gap-left"><<lingo Yes/Description>></span>
|
||||
</$radio>
|
||||
|
||||
<$radio tiddler="$:/config/Navigation/UpdateHistory" value="no">
|
||||
<span class="tc-tiny-gap-left"><<lingo No/Description>></span>
|
||||
</$radio>
|
||||
|
@ -2,9 +2,24 @@ title: $:/core/ui/ControlPanel/Settings/NavigationPermalinkviewMode
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/NavigationPermalinkviewMode/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/NavigationPermalinkviewMode/
|
||||
<<lingo Hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/Navigation/Permalinkview/CopyToClipboard" field="text" checked="yes" unchecked="no" default="yes"> <$link to="$:/config/Navigation/Permalinkview/CopyToClipboard"><<lingo CopyToClipboard/Description>></$link> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/Navigation/Permalinkview/CopyToClipboard"
|
||||
field="text" checked="yes" unchecked="no" default="yes"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/Navigation/Permalinkview/CopyToClipboard" class="tc-tiny-gap-left">
|
||||
<<lingo CopyToClipboard/Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
||||
<$checkbox tiddler="$:/config/Navigation/Permalinkview/UpdateAddressBar" field="text" checked="yes" unchecked="no" default="yes"> <$link to="$:/config/Navigation/Permalinkview/UpdateAddressBar"><<lingo UpdateAddressBar/Description>></$link> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/Navigation/Permalinkview/UpdateAddressBar"
|
||||
field="text" checked="yes" unchecked="no" default="yes"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/Navigation/Permalinkview/UpdateAddressBar" class="tc-tiny-gap-left">
|
||||
<<lingo UpdateAddressBar/Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
@ -2,7 +2,15 @@ title: $:/core/ui/ControlPanel/Settings/PerformanceInstrumentation
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/PerformanceInstrumentation/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/PerformanceInstrumentation/
|
||||
<<lingo Hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/Performance/Instrumentation" field="text" checked="yes" unchecked="no" default="no"> <$link to="$:/config/Performance/Instrumentation"><<lingo Description>></$link> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/Performance/Instrumentation"
|
||||
field="text" checked="yes" unchecked="no" default="no"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/Performance/Instrumentation" class="tc-tiny-gap-left">
|
||||
<<lingo Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
@ -2,9 +2,17 @@ title: $:/core/ui/ControlPanel/Settings/TitleLinks
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/TitleLinks/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/TitleLinks/
|
||||
<$link to="$:/config/Tiddlers/TitleLinks"><<lingo Hint>></$link>
|
||||
|
||||
<$radio tiddler="$:/config/Tiddlers/TitleLinks" value="yes"> <<lingo Yes/Description>> </$radio>
|
||||
<$link to="$:/config/Tiddlers/TitleLinks" class="tc-control-panel-item">
|
||||
<<lingo Hint>>
|
||||
</$link>
|
||||
|
||||
<$radio tiddler="$:/config/Tiddlers/TitleLinks" value="no"> <<lingo No/Description>> </$radio>
|
||||
<$radio tiddler="$:/config/Tiddlers/TitleLinks" value="yes">
|
||||
<span class="tc-tiny-gap-left"><<lingo Yes/Description>></span>
|
||||
</$radio>
|
||||
|
||||
<$radio tiddler="$:/config/Tiddlers/TitleLinks" value="no">
|
||||
<span class="tc-tiny-gap-left"><<lingo No/Description>></span>
|
||||
</$radio>
|
||||
|
@ -2,12 +2,15 @@ title: $:/core/ui/ControlPanel/Settings/ToolbarButtonStyle
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/ToolbarButtonStyle/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtonStyle/
|
||||
\whitespace trim
|
||||
<$link to="$:/config/Toolbar/ButtonClass"><<lingo "Hint">></$link>
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtonStyle/
|
||||
|
||||
<$select tiddler="$:/config/Toolbar/ButtonClass">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ToolbarButtonStyle]]">
|
||||
<option value={{!!text}}>{{!!caption}}</option>
|
||||
</$list>
|
||||
<$link to="$:/config/Toolbar/ButtonClass" class="tc-control-panel-item">
|
||||
<<lingo "Hint">>
|
||||
</$link>
|
||||
|
||||
<$select tiddler="$:/config/Toolbar/ButtonClass" class="tc-select">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ToolbarButtonStyle]]">
|
||||
<option value={{!!text}}>{{!!caption}}</option>
|
||||
</$list>
|
||||
</$select>
|
||||
|
@ -2,9 +2,24 @@ title: $:/core/ui/ControlPanel/Settings/ToolbarButtons
|
||||
tags: $:/tags/ControlPanel/Settings
|
||||
caption: {{$:/language/ControlPanel/Settings/ToolbarButtons/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
\define lingo-base() $:/language/ControlPanel/Settings/ToolbarButtons/
|
||||
<<lingo Hint>>
|
||||
|
||||
<$checkbox tiddler="$:/config/Toolbar/Icons" field="text" checked="yes" unchecked="no" default="yes"> <$link to="$:/config/Toolbar/Icons"><<lingo Icons/Description>></$link> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/Toolbar/Icons"
|
||||
field="text" checked="yes" unchecked="no" default="yes"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/Toolbar/Icons" class="tc-tiny-gap-left">
|
||||
<<lingo Icons/Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
||||
<$checkbox tiddler="$:/config/Toolbar/Text" field="text" checked="yes" unchecked="no" default="no"> <$link to="$:/config/Toolbar/Text"><<lingo Text/Description>></$link> </$checkbox>
|
||||
<$checkbox tiddler="$:/config/Toolbar/Text"
|
||||
field="text" checked="yes" unchecked="no" default="no"
|
||||
class="tc-control-panel-item"
|
||||
>
|
||||
<$link to="$:/config/Toolbar/Text" class="tc-tiny-gap-left">
|
||||
<<lingo Text/Description>>
|
||||
</$link>
|
||||
</$checkbox>
|
||||
|
10
core/ui/ControlPanel/TestCases.tid
Normal file
10
core/ui/ControlPanel/TestCases.tid
Normal file
@ -0,0 +1,10 @@
|
||||
title: $:/core/ui/ControlPanel/TestCases
|
||||
tags: $:/tags/ControlPanel/Advanced
|
||||
caption: {{$:/language/ControlPanel/TestCases/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
{{$:/language/ControlPanel/TestCases/Hint}}
|
||||
|
||||
<div class="tc-control-panel">
|
||||
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/TestCases]!has[draft.of]]" default="$:/core/ui/ControlPanel/TestCases/All"/>
|
||||
</div>
|
24
core/ui/ControlPanel/TestCasesAll.tid
Normal file
24
core/ui/ControlPanel/TestCasesAll.tid
Normal file
@ -0,0 +1,24 @@
|
||||
title: $:/core/ui/ControlPanel/TestCases/All
|
||||
tags: $:/tags/ControlPanel/TestCases
|
||||
caption: {{$:/language/ControlPanel/TestCases/All/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/
|
||||
<<lingo TestCases/All/Hint>>
|
||||
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/wiki-test-spec]type[text/vnd.tiddlywiki-multiple]] [all[tiddlers+shadows]tag[$:/tags/wiki-test-spec-failing]type[text/vnd.tiddlywiki-multiple]]">
|
||||
|
||||
<h2>
|
||||
|
||||
<$link>
|
||||
|
||||
<$text text=<<currentTiddler>>/>
|
||||
|
||||
</$link>
|
||||
|
||||
</h2>
|
||||
|
||||
<$transclude
|
||||
$tiddler="$:/core/ui/TestCaseTemplate"
|
||||
/>
|
||||
|
||||
</$list>
|
15
core/ui/ControlPanel/TestCasesFailed.tid
Normal file
15
core/ui/ControlPanel/TestCasesFailed.tid
Normal file
@ -0,0 +1,15 @@
|
||||
title: $:/core/ui/ControlPanel/TestCases/Failed
|
||||
tags: $:/tags/ControlPanel/TestCases
|
||||
caption: {{$:/language/ControlPanel/TestCases/Failed/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/
|
||||
<<lingo TestCases/Failed/Hint>>
|
||||
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/wiki-test-spec]type[text/vnd.tiddlywiki-multiple]] [all[tiddlers+shadows]tag[$:/tags/wiki-test-spec-failing]type[text/vnd.tiddlywiki-multiple]]">
|
||||
|
||||
<$transclude
|
||||
$tiddler="$:/core/ui/TestCaseTemplate"
|
||||
hideIfPass="yes"
|
||||
/>
|
||||
|
||||
</$list>
|
@ -9,9 +9,9 @@ list-before:
|
||||
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]">
|
||||
|
||||
<div style="border-top:1px solid #eee;">
|
||||
<div class="tc-control-panel-setting" data-setting-title=<<currentTiddler>> style="border-top:1px solid #eee;">
|
||||
|
||||
!! <$link><$transclude field="caption"/></$link>
|
||||
!!.tc-control-panel-accent <$link><$transclude field="caption"/></$link>
|
||||
|
||||
<$transclude/>
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
title: $:/core/ui/EditTemplate/body/default
|
||||
|
||||
\function edit-preview-state()
|
||||
[{$:/config/ShowEditPreview/PerTiddler}!match[yes]then[$:/state/showeditpreview]] :else[<qualified-preview-state>] +[get[text]] :else[[no]]
|
||||
\end
|
||||
|
||||
\define config-visibility-title()
|
||||
$:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
|
||||
\end
|
||||
@ -10,12 +14,13 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
|
||||
|
||||
\whitespace trim
|
||||
<$let
|
||||
editPreviewStateTiddler={{{ [{$:/config/ShowEditPreview/PerTiddler}!match[yes]then[$:/state/showeditpreview]] :else[<qualify "$:/state/showeditpreview">] }}}
|
||||
qualified-preview-state=<<qualify "$:/state/showeditpreview">>
|
||||
editPreviewStateTiddler={{{ [{$:/config/ShowEditPreview/PerTiddler}!match[yes]then[$:/state/showeditpreview]] :else[<qualified-preview-state>] }}}
|
||||
importTitle=<<qualify $:/ImportImage>>
|
||||
importState=<<qualify $:/state/ImportImage>> >
|
||||
<$dropzone importTitle=<<importTitle>> autoOpenOnImport="no" contentTypesFilter={{$:/config/Editor/ImportContentTypesFilter}} class="tc-dropzone-editor" enable={{{ [{$:/config/DragAndDrop/Enable}match[no]] :else[subfilter{$:/config/Editor/EnableImportFilter}then[yes]else[no]] }}} filesOnly="yes" actions=<<importFileActions>> >
|
||||
<div>
|
||||
<div class={{{ [<editPreviewStateTiddler>get[text]match[yes]then[tc-tiddler-preview]else[tc-tiddler-preview-hidden]] [[tc-tiddler-editor]] +[join[ ]] }}}>
|
||||
<div class={{{ [<edit-preview-state>match[yes]then[tc-tiddler-preview]else[tc-tiddler-preview-hidden]] [[tc-tiddler-editor]] +[join[ ]] }}}>
|
||||
|
||||
<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user