1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-24 03:44:41 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
jeremy@jermolene.com
e26d0175eb First commit 2021-05-31 10:26:21 +01:00
878 changed files with 178626 additions and 16085 deletions

View File

@@ -1,8 +1,15 @@
# Ignore "third party" code whose style we will not change.
# Known minified files
/boot/sjcl.js
/core/modules/utils/base64-utf8/base64-utf8.module.js
/core/modules/utils/base64-utf8/base64-utf8.module.min.js
/core/modules/utils/diff-match-patch/diff_match_patch.js
/core/modules/utils/diff-match-patch/diff_match_patch_uncompressed.js
/core/modules/utils/dom/csscolorparser.js
/plugins/tiddlywiki/*/files/
/plugins/tiddlywiki/async/files/async.min.v1.5.0.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/anyword-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/css-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/html-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/javascript-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/show-hint.js
/plugins/tiddlywiki/codemirror-autocomplete/files/addon/hint/xml-hint.js
/plugins/tiddlywiki/codemirror-closebrackets/files/addon/edit/closebrackets.js
/plugins/tiddlywiki/codemirror-closebrackets/files/addon/edit/matchbrackets.js
/plugins/tiddlywiki/codemirror-closetag/files/addon/edit/closetag.js
/plugins/tiddlywiki/codemirror-closetag/files/addon/fold/xml-fold.js

View File

@@ -64,23 +64,7 @@ rules:
init-declarations: 'off'
jsx-quotes: error
key-spacing: 'off'
keyword-spacing:
- error
- before: true
after: false
overrides:
'case':
after: true
'do':
'after': true
'else':
after: true
'return':
after: true
'throw':
after: true
'try':
after: true
keyword-spacing: 'off'
line-comment-position: 'off'
linebreak-style: 'off'
lines-around-comment: 'off'

View File

@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.2.2
TW5_BUILD_VERSION=v5.1.24
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"

View File

@@ -68,26 +68,6 @@ $tw.utils.isArrayEqual = function(array1,array2) {
});
};
/*
Add an entry to a sorted array if it doesn't already exist, while maintaining the sort order
*/
$tw.utils.insertSortedArray = function(array,value) {
var low = 0, high = array.length - 1, mid, cmp;
while(low <= high) {
mid = (low + high) >> 1;
cmp = value.localeCompare(array[mid]);
if(cmp > 0) {
low = mid + 1;
} else if(cmp < 0) {
high = mid - 1;
} else {
return array;
}
}
array.splice(low,0,value);
return array;
};
/*
Push entries onto an array, removing them first if they already exist in the array
array: array to modify (assumed to be free of duplicates)
@@ -276,28 +256,6 @@ $tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
return object;
};
/*
Convert a URIComponent encoded string to a string safely
*/
$tw.utils.decodeURIComponentSafe = function(s) {
var v = s;
try {
v = decodeURIComponent(s);
} catch(e) {}
return v;
};
/*
Convert a URI encoded string to a string safely
*/
$tw.utils.decodeURISafe = function(s) {
var v = s;
try {
v = decodeURI(s);
} catch(e) {}
return v;
};
/*
Convert "&amp;" to &, "&nbsp;" to nbsp, "&lt;" to <, "&gt;" to > and "&quot;" to "
*/
@@ -429,19 +387,6 @@ $tw.utils.parseFields = function(text,fields) {
return fields;
};
// Safely parse a string as JSON
$tw.utils.parseJSONSafe = function(text,defaultJSON) {
try {
return JSON.parse(text);
} catch(e) {
if(typeof defaultJSON === "function") {
return defaultJSON(e);
} else {
return defaultJSON || {};
}
}
};
/*
Resolves a source filepath delimited with `/` relative to a specified absolute root filepath.
In relative paths, the special folder name `..` refers to immediate parent directory, and the
@@ -1114,7 +1059,7 @@ $tw.Wiki = function(options) {
tiddlerTitles = null, // Array of tiddler titles
getTiddlerTitles = function() {
if(!tiddlerTitles) {
tiddlerTitles = Object.keys(tiddlers).sort(function(a,b) {return a.localeCompare(b);});
tiddlerTitles = Object.keys(tiddlers);
}
return tiddlerTitles;
},
@@ -1167,8 +1112,10 @@ $tw.Wiki = function(options) {
}
// Save the new tiddler
tiddlers[title] = tiddler;
// Check we've got the title
tiddlerTitles = $tw.utils.insertSortedArray(tiddlerTitles || [],title);
// Check we've got it's title
if(tiddlerTitles && tiddlerTitles.indexOf(title) === -1) {
tiddlerTitles.push(title);
}
// Record the new tiddler state
updateDescriptor["new"] = {
tiddler: tiddler,
@@ -1265,12 +1212,8 @@ $tw.Wiki = function(options) {
index,titlesLength,title;
for(index = 0, titlesLength = titles.length; index < titlesLength; index++) {
title = titles[index];
if(tiddlers[title]) {
callback(tiddlers[title],title);
} else {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
};
@@ -1353,7 +1296,7 @@ $tw.Wiki = function(options) {
var tiddler = tiddlers[title];
if(tiddler) {
if(tiddler.fields.type === "application/json" && tiddler.hasField("plugin-type") && tiddler.fields.text) {
pluginInfo[tiddler.fields.title] = $tw.utils.parseJSONSafe(tiddler.fields.text);
pluginInfo[tiddler.fields.title] = JSON.parse(tiddler.fields.text);
results.modifiedPlugins.push(tiddler.fields.title);
}
} else {
@@ -1486,7 +1429,7 @@ $tw.Wiki.prototype.defineTiddlerModules = function() {
}
break;
case "application/json":
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseJSONSafe(tiddler.fields.text));
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],JSON.parse(tiddler.fields.text));
break;
case "application/x-tiddler-dictionary":
$tw.modules.define(tiddler.fields.title,tiddler.fields["module-type"],$tw.utils.parseFields(tiddler.fields.text));
@@ -1659,8 +1602,8 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
}
for(var f in data) {
if($tw.utils.hop(data,f)) {
// Check field name doesn't contain control characters
if(typeof(data[f]) !== "string" || /[\x00-\x1F]/.test(f)) {
// Check field name doesn't contain whitespace or control characters
if(typeof(data[f]) !== "string" || /[\x00-\x1F\s]/.test(f)) {
return false;
}
}
@@ -1675,7 +1618,7 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
}
return true;
},
data = $tw.utils.parseJSONSafe(text);
data = JSON.parse(text);
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
return data;
} else if(isTiddlerValid(data)) {
@@ -1715,7 +1658,7 @@ $tw.boot.decryptEncryptedTiddlers = function(callback) {
$tw.crypto.setPassword(data.password);
var decryptedText = $tw.crypto.decrypt(encryptedText);
if(decryptedText) {
var json = $tw.utils.parseJSONSafe(decryptedText);
var json = JSON.parse(decryptedText);
for(var title in json) {
$tw.preloadTiddler(json[title]);
}
@@ -1781,20 +1724,13 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
},
t,result = [];
if(node) {
var type = (node.getAttribute && node.getAttribute("type")) || null;
if(type) {
// A new-style container with an explicit deserialization type
result = $tw.wiki.deserializeTiddlers(type,node.textContent);
} else {
// An old-style container of classic DIV-based tiddlers
for(t = 0; t < node.childNodes.length; t++) {
for(t = 0; t < node.childNodes.length; t++) {
var childNode = node.childNodes[t],
tiddlers = extractTextTiddlers(childNode);
tiddlers = tiddlers || extractModuleTiddlers(childNode);
if(tiddlers) {
result.push.apply(result,tiddlers);
}
}
}
}
return result;
@@ -1803,23 +1739,17 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
$tw.loadTiddlersBrowser = function() {
// In the browser, we load tiddlers from certain elements
var containerSelectors = [
// IDs for old-style v5.1.x tiddler stores
"#libraryModules",
"#modules",
"#bootKernelPrefix",
"#bootKernel",
"#styleArea",
"#storeArea",
"#systemArea",
// Classes for new-style v5.2.x JSON tiddler stores
"script.tiddlywiki-tiddler-store"
var containerIds = [
"libraryModules",
"modules",
"bootKernelPrefix",
"bootKernel",
"styleArea",
"storeArea",
"systemArea"
];
for(var t=0; t<containerSelectors.length; t++) {
var nodes = document.querySelectorAll(containerSelectors[t]);
for(var n=0; n<nodes.length; n++) {
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",nodes[n]));
}
for(var t=0; t<containerIds.length; t++) {
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",document.getElementById(containerIds[t])));
}
};
@@ -1915,7 +1845,7 @@ filepath: pathname of the directory containing the specification file
$tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
var tiddlers = [];
// Read the specification
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
var filesInfo = JSON.parse(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
// Helper to process a file
var processFile = function(filename,isTiddlerFile,fields,isEditableFile) {
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
@@ -1942,13 +1872,13 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
value = path.basename(filename);
break;
case "filename-uri-decoded":
value = $tw.utils.decodeURIComponentSafe(path.basename(filename));
value = decodeURIComponent(path.basename(filename));
break;
case "basename":
value = path.basename(filename,path.extname(filename));
break;
case "basename-uri-decoded":
value = $tw.utils.decodeURIComponentSafe(path.basename(filename,path.extname(filename)));
value = decodeURIComponent(path.basename(filename,path.extname(filename)));
break;
case "extname":
value = path.extname(filename);
@@ -1976,20 +1906,6 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
tiddlers.push({tiddlers: fileTiddlers});
}
};
// Helper to recursively search subdirectories
var getAllFiles = function(dirPath, recurse, arrayOfFiles) {
recurse = recurse || false;
arrayOfFiles = arrayOfFiles || [];
var files = fs.readdirSync(dirPath);
files.forEach(function(file) {
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));
}
});
return arrayOfFiles;
}
// Process the listed tiddlers
$tw.utils.each(filesInfo.tiddlers,function(tidInfo) {
if(tidInfo.prefix && tidInfo.suffix) {
@@ -2013,14 +1929,13 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
// Process directory specifier
var dirPath = path.resolve(filepath,dirSpec.path);
if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
var files = getAllFiles(dirPath, dirSpec.searchSubdirectories),
var files = fs.readdirSync(dirPath),
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
metaRegExp = /^.*\.meta$/;
for(var t=0; t<files.length; t++) {
var thisPath = path.relative(filepath, files[t]),
filename = path.basename(thisPath);
var filename = files[t];
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
}
}
} else {
@@ -2045,7 +1960,7 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
console.log("Warning: missing plugin.info file in " + filepath);
return null;
}
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"));
var pluginInfo = JSON.parse(fs.readFileSync(infoPath,"utf8"));
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
@@ -2070,7 +1985,7 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
pluginInfo.dependents = pluginInfo.dependents || [];
pluginInfo.type = "application/json";
// Set plugin text
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers},null,4);
delete pluginInfo.tiddlers;
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginInfo) {
@@ -2162,7 +2077,7 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
pluginFields;
// Bail if we don't have a wiki info file
if(fs.existsSync(wikiInfoPath)) {
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"));
wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8"));
} else {
return null;
}
@@ -2675,4 +2590,3 @@ if(typeof(exports) !== "undefined") {
} else {
_boot(window.$tw);
}
//# sourceURL=$:/boot/boot.js

View File

@@ -117,4 +117,3 @@ if(typeof(exports) === "undefined") {
// Export functionality as a module
exports.bootprefix = _bootprefix;
}
//# sourceURL=$:/boot/bootprefix.js

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@ type: text/plain
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
Copyright (c) 2004-2007, Jeremy Ruston
Copyright (c) 2007-2022, UnaMesa Association
Copyright (c) 2007-2021, UnaMesa Association
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -27,15 +27,10 @@ Basics/Tiddlers/Prompt: Number of tiddlers
Basics/Title/Prompt: Title of this ~TiddlyWiki
Basics/Username/Prompt: Username for signing edits
Basics/Version/Prompt: ~TiddlyWiki version
Cascades/Caption: Cascades
Cascades/Hint: These global rules are used to dynamically choose certain templates. The result of the cascade is the result of the first filter in the sequence that returns a result
Cascades/TagPrompt: Filters tagged <$macrocall $name="tag" tag=<<currentTiddler>>/>
EditorTypes/Caption: Editor Types
EditorTypes/Editor/Caption: Editor
EditorTypes/Hint: These tiddlers determine which editor is used to edit specific tiddler types.
EditorTypes/Type/Caption: Type
EditTemplateBody/Caption: Edit Template Body
EditTemplateBody/Hint: This rule cascade is used by the default edit template to dynamically choose the template for editing the body of a tiddler.
Info/Caption: Info
Info/Hint: Information about this TiddlyWiki
KeyboardShortcuts/Add/Prompt: Type shortcut here
@@ -196,8 +191,6 @@ Settings/TitleLinks/Yes/Description: Display tiddler titles as links
Settings/MissingLinks/Caption: Wiki Links
Settings/MissingLinks/Hint: Choose whether to link to tiddlers that do not exist yet
Settings/MissingLinks/Description: Enable links to missing tiddlers
StoryTiddler/Caption: Story Tiddler
StoryTiddler/Hint: This rule cascade is used to dynamically choose the template for displaying a tiddler in the story river.
StoryView/Caption: Story View
StoryView/Prompt: Current view:
Stylesheets/Caption: Stylesheets
@@ -208,10 +201,6 @@ Theme/Caption: Theme
Theme/Prompt: Current theme:
TiddlerFields/Caption: Tiddler Fields
TiddlerFields/Hint: This is the full set of TiddlerFields in use in this wiki (including system tiddlers but excluding shadow tiddlers).
TiddlerColour/Caption: Tiddler Colour
TiddlerColour/Hint: This rules cascade is used to dynamically choose the colour for a tiddler (used for the icon and the associated tag pill).
TiddlerIcon/Caption: Tiddler Icon
TiddlerIcon/Hint: This rules cascade is used to dynamically choose the icon for a tiddler.
Toolbars/Caption: Toolbars
Toolbars/EditToolbar/Caption: Edit Toolbar
Toolbars/EditToolbar/Hint: Choose which buttons are displayed for tiddlers in edit mode. Drag and drop to change the ordering
@@ -223,7 +212,3 @@ Toolbars/EditorToolbar/Hint: Choose which buttons are displayed in the editor to
Toolbars/ViewToolbar/Caption: View Toolbar
Toolbars/ViewToolbar/Hint: Choose which buttons are displayed for tiddlers in view mode. Drag and drop to change the ordering
Tools/Download/Full/Caption: Download full wiki
ViewTemplateBody/Caption: View Template Body
ViewTemplateBody/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the body of a tiddler.
ViewTemplateTitle/Caption: View Template Title
ViewTemplateTitle/Hint: This rule cascade is used by the default view template to dynamically choose the template for displaying the title of a tiddler.

View File

@@ -3,7 +3,6 @@ title: $:/language/Docs/Fields/
_canonical_uri: The full URI of an external image tiddler
bag: The name of the bag from which a tiddler came
caption: The text to be displayed on a tab or button
code-body: The view template will display the tiddler as code if set to ''yes''
color: The CSS color value associated with a tiddler
component: The name of the component responsible for an [[alert tiddler|AlertMechanism]]
current-tiddler: Used to cache the top tiddler in a [[history list|HistoryMechanism]]
@@ -14,9 +13,9 @@ description: The descriptive text for a plugin, or a modal dialogue
draft.of: For draft tiddlers, contains the title of the tiddler of which this is a draft
draft.title: For draft tiddlers, contains the proposed new title of the tiddler
footer: The footer text for a wizard
hide-body: The view template will hide bodies of tiddlers if set to ''yes''
hide-body: The view template will hide bodies of tiddlers if set to: ''yes''
icon: The title of the tiddler containing the icon associated with a tiddler
library: Indicates that a tiddler should be saved as a JavaScript library if set to ''yes''
library: Indicates that a tiddler should be saved as a JavaScript library if set to: ''yes''
list: An ordered list of tiddler titles associated with a tiddler
list-before: If set, the title of a tiddler before which this tiddler should be added to the ordered list of tiddler titles, or at the start of the list if this field is present but empty
list-after: If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles, or at the end of the list if this field is present but empty
@@ -33,7 +32,7 @@ tags: A list of tags associated with a tiddler
text: The body text of a tiddler
throttle.refresh: If present, throttles refreshes of this tiddler
title: The unique name of a tiddler
toc-link: Suppresses the tiddler's link in a Table of Contents tree if set to ''no''
toc-link: Suppresses the tiddler's link in a Table of Contents tree if set to: ''no''
type: The content type of a tiddler
version: Version information for a plugin
_is_skinny: If present, indicates that the tiddler text field must be loaded from the server

View File

@@ -22,6 +22,7 @@ All parameters are optional with safe defaults, and can be specified in any orde
* ''readers'' - comma-separated list of principals allowed to read from this wiki
* ''writers'' - comma-separated list of principals allowed to write to this wiki
* ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no")
* ''sse-enabled'' - set to "yes" to enable Server-sent events (defaults to "no")
* ''root-tiddler'' - the tiddler to serve at the root (defaults to "$:/core/save/all")
* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to "text/plain")
* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to "text/html")

View File

@@ -3,7 +3,6 @@ title: $:/language/Import/
Editor/Import/Heading: Import images and insert them into the editor.
Imported/Hint: The following tiddlers were imported:
Listing/Cancel/Caption: Cancel
Listing/Cancel/Warning: Do you wish to cancel the import?
Listing/Hint: These tiddlers are ready to import:
Listing/Import/Caption: Import
Listing/Select/Caption: Select
@@ -30,5 +29,5 @@ Upgrader/System/Warning: Core module tiddler.
Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable.
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>.
Upgrader/Tiddler/Disabled: Disabled tiddler.
Upgrader/Tiddler/Selected: Selected tiddler.
Upgrader/Tiddler/Selected: User selected.
Upgrader/Tiddler/Unselected: Unselected tiddler.

View File

@@ -14,7 +14,7 @@ ConfirmAction: Do you wish to proceed?
Count: count
DefaultNewTiddlerTitle: New Tiddler
Diffs/CountMessage: <<diff-count>> differences
DropMessage: Drop now (or use the 'Escape' key to cancel)
DropMessage: Drop here (or use the 'Escape' key to cancel)
Encryption/Cancel: Cancel
Encryption/ConfirmClearPassword: Do you wish to clear the password? This will remove the encryption applied when saving this wiki
Encryption/PromptSetPassword: Set a new password for this TiddlyWiki
@@ -41,6 +41,7 @@ Error/WhileSaving: Error while saving
Error/XMLHttpRequest: XMLHttpRequest error code
InternalJavaScriptError/Title: Internal JavaScript Error
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)
LayoutSwitcher/Description: Open the layout switcher
LazyLoadingWarning: <p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p>
LoginToTiddlySpace: Login to TiddlySpace

View File

@@ -48,7 +48,7 @@ Command.prototype.execute = function() {
}
// Tweak the tiddlywiki.info to remove any included wikis
var packagePath = $tw.boot.wikiPath + "/tiddlywiki.info",
packageJson = $tw.utils.parseJSONSafe(fs.readFileSync(packagePath));
packageJson = JSON.parse(fs.readFileSync(packagePath));
delete packageJson.includeWikis;
fs.writeFileSync(packagePath,JSON.stringify(packageJson,null,$tw.config.preferences.jsonSpaces));
return null;

View File

@@ -8,59 +8,58 @@ Render individual tiddlers and save the results to the specified files
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "render",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing tiddler filter";
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "render",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing tiddler filter";
}
var self = this,
fs = require("fs"),
path = require("path"),
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
type = this.params[2] || "text/html",
template = this.params[3],
variableList = this.params.slice(4),
tiddlers = wiki.filterTiddlers(tiddlerFilter),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
var self = this,
fs = require("fs"),
path = require("path"),
wiki = this.commander.wiki,
tiddlerFilter = this.params[0],
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
type = this.params[2] || "text/html",
template = this.params[3],
variableList = this.params.slice(4),
tiddlers = wiki.filterTiddlers(tiddlerFilter),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
$tw.utils.each(tiddlers,function(title) {
var filepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);
if(self.commander.verbose) {
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
}
var parser = wiki.parseTiddler(template || title),
widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title})}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
var text = type === "text/html" ? container.innerHTML : container.textContent;
$tw.utils.createFileDirectories(filepath);
fs.writeFileSync(filepath,text,"utf8");
});
return null;
};
exports.Command = Command;
})();
$tw.utils.each(tiddlers,function(title) {
var parser = wiki.parseTiddler(template || title);
var widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title})}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
var text = type === "text/html" ? container.innerHTML : container.textContent,
filepath = path.resolve(self.commander.outputPath,wiki.filterTiddlers(filenameFilter,$tw.rootWidget,wiki.makeTiddlerIterator([title]))[0]);
if(self.commander.verbose) {
console.log("Rendering \"" + title + "\" to \"" + filepath + "\"");
}
$tw.utils.createFileDirectories(filepath);
fs.writeFileSync(filepath,text,"utf8");
});
return null;
};
exports.Command = Command;
})();

View File

@@ -69,7 +69,7 @@ Command.prototype.execute = function() {
$tw.utils.createFileDirectories(pathname);
fs.writeFileSync(pathname,JSON.stringify(tiddler),"utf8");
// Collect the skinny list data
var pluginTiddlers = $tw.utils.parseJSONSafe(tiddler.text),
var pluginTiddlers = JSON.parse(tiddler.text),
readmeContent = (pluginTiddlers.tiddlers[title + "/readme"] || {}).text,
doesRequireReload = !!self.commander.wiki.doesPluginInfoRequireReload(pluginTiddlers),
iconTiddler = pluginTiddlers.tiddlers[title + "/icon"] || {},

View File

@@ -151,7 +151,7 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
pluginInfo = pluginTiddler.getFieldStrings({exclude: ["text","type"]});
this.saveJSONFile(directory + path.sep + "plugin.info",pluginInfo);
self.log("Writing " + directory + path.sep + "plugin.info: " + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));
var pluginTiddlers = $tw.utils.parseJSONSafe(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
var pluginTiddlers = JSON.parse(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
$tw.utils.each(pluginTiddlers,function(tiddler) {
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
});

View File

@@ -12,121 +12,6 @@ Functions to deserialise tiddlers from a block of text
/*global $tw: false */
"use strict";
exports["application/x-tiddler-html-div"] = function(text,fields) {
return [deserializeTiddlerDiv(text,fields)];
};
exports["application/json"] = function(text,fields) {
var results = [],
incoming = $tw.utils.parseJSONSafe(text,function(err) {
return [{
title: "JSON error: " + err,
text: ""
}];
});
if(!$tw.utils.isArray(incoming)) {
incoming = [incoming];
}
for(var t=0; t<incoming.length; t++) {
var incomingFields = incoming[t],
fields = {};
for(var f in incomingFields) {
if(typeof incomingFields[f] === "string") {
fields[f] = incomingFields[f];
}
}
results.push(fields);
}
return results;
};
/*
Parse an HTML file into tiddlers. There are three possibilities:
# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers
# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) {
var results = [];
// Check if we've got an old-style store area
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
storeAreaMatch = storeAreaMarkerRegExp.exec(text);
if(storeAreaMatch) {
// If so, we've got tiddlers in classic TiddlyWiki format or unencrypted old-style TW5 format
results.push.apply(results,deserializeStoreArea(text,storeAreaMarkerRegExp.lastIndex,!!storeAreaMatch[1],fields));
}
// Check for new-style store areas
var newStoreAreaMarkerRegExp = /<script class="tiddlywiki-tiddler-store" type="([^"]*)">/gi,
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text),
haveHadNewStoreArea = !!newStoreAreaMatch;
while(newStoreAreaMatch) {
results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields));
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text);
}
// Return if we had either an old-style or a new-style store area
if(storeAreaMatch || haveHadNewStoreArea) {
return results;
}
// Otherwise, check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
return $tw.utils.decryptStoreArea(encryptedStoreArea);
} else {
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
}
};
function deserializeHtmlFile(text,fields) {
var result = {};
$tw.utils.each(fields,function(value,name) {
result[name] = value;
});
result.text = text;
result.type = "text/html";
return [result];
}
function deserializeNewStoreArea(text,storeAreaEnd,type,fields) {
var endOfScriptRegExp = /<\/script>/gi;
endOfScriptRegExp.lastIndex = storeAreaEnd;
var match = endOfScriptRegExp.exec(text);
if(match) {
var scriptContent = text.substring(storeAreaEnd,match.index);
return $tw.wiki.deserializeTiddlers(type,scriptContent);
} else {
return [];
}
}
function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
var results = [],
endOfDivRegExp = /(<\/div>\s*)/gi,
startPos = storeAreaEnd,
defaultType = isTiddlyWiki5 ? undefined : "text/x-tiddlywiki";
endOfDivRegExp.lastIndex = startPos;
var match = endOfDivRegExp.exec(text);
while(match) {
var endPos = endOfDivRegExp.lastIndex,
tiddlerFields = deserializeTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
if(!tiddlerFields) {
break;
}
$tw.utils.each(tiddlerFields,function(value,name) {
if(typeof value === "string") {
tiddlerFields[name] = $tw.utils.htmlDecode(value);
}
});
if(tiddlerFields.text !== null) {
results.push(tiddlerFields);
}
startPos = endPos;
match = endOfDivRegExp.exec(text);
}
return results;
}
/*
Utility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:
@@ -139,14 +24,14 @@ Note that the field attributes are HTML encoded, but that the body of the <PRE>
When these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.
*/
var deserializeTiddlerDiv = function(text /* [,fields] */) {
var parseTiddlerDiv = function(text /* [,fields] */) {
// Slot together the default results
var result = {};
if(arguments.length > 1) {
for(var f=1; f<arguments.length; f++) {
var fields = arguments[f];
for(var t in fields) {
result[t] = fields[t];
result[t] = fields[t];
}
}
}
@@ -182,4 +67,106 @@ var deserializeTiddlerDiv = function(text /* [,fields] */) {
return undefined;
};
exports["application/x-tiddler-html-div"] = function(text,fields) {
return [parseTiddlerDiv(text,fields)];
};
exports["application/json"] = function(text,fields) {
var incoming,
results = [];
try {
incoming = JSON.parse(text);
} catch(e) {
incoming = [{
title: "JSON error: " + e,
text: ""
}]
}
if(!$tw.utils.isArray(incoming)) {
incoming = [incoming];
}
for(var t=0; t<incoming.length; t++) {
var incomingFields = incoming[t],
fields = {};
for(var f in incomingFields) {
if(typeof incomingFields[f] === "string") {
fields[f] = incomingFields[f];
}
}
results.push(fields);
}
return results;
};
/*
Parse an HTML file into tiddlers. There are three possibilities:
# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers
# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) {
// Check if we've got a store area
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
match = storeAreaMarkerRegExp.exec(text);
if(match) {
// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file
// First read the normal tiddlers
var results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
// Then any system tiddlers
var systemAreaMarkerRegExp = /<div id=["']?systemArea['"]?( style=["']?display:none;["']?)?>/gi,
sysMatch = systemAreaMarkerRegExp.exec(text);
if(sysMatch) {
results.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));
}
return results;
} else {
// Check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
return $tw.utils.decryptStoreArea(encryptedStoreArea);
} else {
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
}
}
};
function deserializeHtmlFile(text,fields) {
var result = {};
$tw.utils.each(fields,function(value,name) {
result[name] = value;
});
result.text = text;
result.type = "text/html";
return [result];
}
function deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {
var results = [],
endOfDivRegExp = /(<\/div>\s*)/gi,
startPos = storeAreaEnd,
defaultType = isTiddlyWiki5 ? undefined : "text/x-tiddlywiki";
endOfDivRegExp.lastIndex = startPos;
var match = endOfDivRegExp.exec(text);
while(match) {
var endPos = endOfDivRegExp.lastIndex,
tiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
if(!tiddlerFields) {
break;
}
$tw.utils.each(tiddlerFields,function(value,name) {
if(typeof value === "string") {
tiddlerFields[name] = $tw.utils.htmlDecode(value);
}
});
if(tiddlerFields.text !== null) {
results.push(tiddlerFields);
}
startPos = endPos;
match = endOfDivRegExp.exec(text);
}
return results;
}
})();

View File

@@ -135,11 +135,7 @@ FramedEngine.prototype.setText = function(text,type) {
Update the DomNode with the new text
*/
FramedEngine.prototype.updateDomNodeText = function(text) {
try {
this.domNode.value = text;
} catch(e) {
// Ignore
}
this.domNode.value = text;
};
/*
@@ -205,7 +201,7 @@ FramedEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText());
this.fixHeight();
if(this.widget.editInputActions) {
this.widget.invokeActionString(this.widget.editInputActions,this,event,{actionValue: this.getText()});
this.widget.invokeActionString(this.widget.editInputActions);
}
return true;
};

View File

@@ -85,11 +85,7 @@ SimpleEngine.prototype.setText = function(text,type) {
Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) {
try {
this.domNode.value = text;
} catch(e) {
// Ignore
}
this.domNode.value = text;
};
/*
@@ -133,7 +129,7 @@ SimpleEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText());
this.fixHeight();
if(this.widget.editInputActions) {
this.widget.invokeActionString(this.widget.editInputActions,this,event,{actionValue: this.getText()});
this.widget.invokeActionString(this.widget.editInputActions);
}
return true;
};

View File

@@ -324,7 +324,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
If there are no Files, let the browser handle it.
*/
EditTextWidget.prototype.handleDropEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) {
if(event.dataTransfer.files.length) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
@@ -332,7 +332,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
};
EditTextWidget.prototype.handlePasteEvent = function(event) {
if(event.clipboardData && event.clipboardData.files && event.clipboardData.files.length) {
if(event.clipboardData.files.length) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["clipboardData"]));

View File

@@ -1,17 +0,0 @@
/*\
title: $:/core/modules/editor/operations/text/focus-editor.js
type: application/javascript
module-type: texteditoroperation
Simply focus the Text editor
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports["focus-editor"] = function(event,operation) {
operation = null;
};
})();

View File

@@ -13,17 +13,15 @@ Text editor operation to wrap the selected lines with a prefix and suffix
"use strict";
exports["wrap-lines"] = function(event,operation) {
var prefix = event.paramObject.prefix || "",
suffix = event.paramObject.suffix || "";
// Cut just past the preceding line break, or the start of the text
operation.cutStart = $tw.utils.findPrecedingLineBreak(operation.text,operation.selStart);
// Cut to just past the following line break, or to the end of the text
operation.cutEnd = $tw.utils.findFollowingLineBreak(operation.text,operation.selEnd);
// Add the prefix and suffix
operation.replacement = prefix + "\n" +
operation.replacement = event.paramObject.prefix + "\n" +
operation.text.substring(operation.cutStart,operation.cutEnd) + "\n" +
suffix + "\n";
operation.newSelStart = operation.cutStart + prefix.length + 1;
event.paramObject.suffix + "\n";
operation.newSelStart = operation.cutStart + event.paramObject.prefix.length + 1;
operation.newSelEnd = operation.newSelStart + (operation.cutEnd - operation.cutStart);
};

View File

@@ -1,53 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/cascade.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.cascade = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length !== 0) {
var filterList = operationSubFunction(source,widget),
filterFnList = [];
var inputResults = results.toArray();
results.clear();
$tw.utils.each(inputResults,function(title) {
var result = ""; // If no filter matches, we return an empty string
$tw.utils.each(filterList,function(filter,index) {
if(!filterFnList[index]) {
filterFnList[index] = options.wiki.compileFilter(filter);
}
var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
if(output.length !== 0) {
result = output[0];
return false;
}
});
results.push(result);
});
}
}
};
})();

View File

@@ -16,30 +16,23 @@ Export our filter function
exports.filter = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var resultsToRemove = [],
index = 0;
var resultsToRemove = [];
results.each(function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
default:
return widget.getVariable(name);
}
}
});
if(filtered.length === 0) {
resultsToRemove.push(title);
}
++index;
});
results.remove(resultsToRemove);
}

View File

@@ -1,46 +0,0 @@
/*\
title: $:/core/modules/filterrunprefixes/map.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.map = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var inputTitles = results.toArray(),
index = 0;
results.clear();
$tw.utils.each(inputTitles,function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (inputTitles.length - 1 - index),
"length": "" + inputTitles.length
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
results.push(filtered[0] || "");
++index;
});
}
}
};
})();

View File

@@ -15,24 +15,26 @@ Export our filter prefix function
exports.reduce = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var accumulator = "",
index = 0;
var accumulator = "";
var index = 0;
results.each(function(title) {
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length,
"accumulator": "" + accumulator
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return widget.getVariable(name);
}
}
});

View File

@@ -26,16 +26,14 @@ exports.sort = function(operationSubFunction,options) {
compareFn;
results.each(function(title) {
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
default:
return widget.getVariable(name);
}
}
});

View File

@@ -95,12 +95,10 @@ function parseFilterOperation(operators,filterString,p) {
if(nextBracketPos === -1) {
throw "Missing closing bracket in filter expression";
}
if(operator.regexp) {
operand.text = "";
} else {
if(!operator.regexp) {
operand.text = filterString.substring(p,nextBracketPos);
operator.operands.push(operand);
}
operator.operands.push(operand);
p = nextBracketPos + 1;
}
@@ -255,8 +253,7 @@ exports.compileFilter = function(filterString) {
if(operand.indirect) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
var varTree = $tw.utils.parseFilterVariable(operand.text);
operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""});
operand.value = widget.getVariable(operand.text,{defaultValue: ""});
} else {
operand.value = operand.text;
}

View File

@@ -52,7 +52,7 @@ exports.all = function(source,operator,options) {
results.pushTop(subop(source,operator.prefix,options));
}
}
return results.makeTiddlerIterator(options.wiki);
return results.toArray();
};
})();

View File

@@ -16,11 +16,11 @@ Filter operator for returning all the backlinks from a tiddler
Export our filter function
*/
exports.backlinks = function(source,operator,options) {
var results = new $tw.utils.LinkedList();
var results = [];
source(function(tiddler,title) {
results.pushTop(options.wiki.getTiddlerBacklinks(title));
$tw.utils.pushTop(results,options.wiki.getTiddlerBacklinks(title));
});
return results.makeTiddlerIterator(options.wiki);
return results;
};
})();

View File

@@ -17,7 +17,7 @@ Export our filter function
*/
exports.contains = function(source,operator,options) {
var results = [],
fieldname = operator.suffix || "list";
fieldname = (operator.suffix || "list").toLowerCase();
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(tiddler) {

View File

@@ -1,27 +0,0 @@
/*\
title: $:/core/modules/filters/crypto.js
type: application/javascript
module-type: filteroperator
Filter operators for cryptography, using the Stanford JavaScript library
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
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);
};
source(function(tiddler,title) {
results.push(sha256(title));
});
return results;
};
})();

View File

@@ -19,7 +19,12 @@ Export our filter functions
exports.decodeuricomponent = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.decodeURIComponentSafe(title));
var value = title;
try {
value = decodeURIComponent(title);
} catch(e) {
}
results.push(value);
});
return results;
};
@@ -35,7 +40,12 @@ exports.encodeuricomponent = function(source,operator,options) {
exports.decodeuri = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.decodeURISafe(title));
var value = title;
try {
value = decodeURI(title);
} catch(e) {
}
results.push(value);
});
return results;
};

View File

@@ -17,7 +17,7 @@ Export our filter function
*/
exports.field = function(source,operator,options) {
var results = [],indexedResults,
fieldname = operator.suffix || operator.operator || "title";
fieldname = (operator.suffix || operator.operator || "title").toLowerCase();
if(operator.prefix === "!") {
if(operator.regexp) {
source(function(tiddler,title) {

View File

@@ -20,7 +20,7 @@ exports.insertbefore = function(source,operator,options) {
source(function(tiddler,title) {
results.push(title);
});
var target = operator.operands[1] || (options.widget && options.widget.getVariable(operator.suffix || "currentTiddler"));
var target = options.widget && options.widget.getVariable(operator.suffix || "currentTiddler");
if(target !== operator.operand) {
// Remove the entry from the list if it is present
var pos = results.indexOf(operator.operand);

View File

@@ -19,13 +19,13 @@ exports.draft = function(source,prefix,options) {
var results = [];
if(prefix === "!") {
source(function(tiddler,title) {
if(!tiddler || !tiddler.isDraft()) {
if(!tiddler || !$tw.utils.hop(tiddler.fields,"draft.of")) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(tiddler && tiddler.isDraft()) {
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.of") && (tiddler.fields["draft.of"].length !== 0)) {
results.push(title);
}
});

View File

@@ -20,7 +20,7 @@ exports.links = function(source,operator,options) {
source(function(tiddler,title) {
results.pushTop(options.wiki.getTiddlerLinks(title));
});
return results.makeTiddlerIterator(options.wiki);
return results.toArray();
};
})();

View File

@@ -87,8 +87,7 @@ exports.butlast = function(source,operator,options) {
source(function(tiddler,title) {
results.push(title);
});
var index = count === 0 ? results.length : -count;
return results.slice(0,index);
return results.slice(0,-count);
};
exports.bl = exports.butlast;
@@ -104,16 +103,4 @@ exports.nth = function(source,operator,options) {
return results.slice(count - 1,count);
};
/*
The zero based nth member of the list
*/
exports.zth = function(source,operator,options) {
var count = $tw.utils.getInt(operator.operand,0),
results = [];
source(function(tiddler,title) {
results.push(title);
});
return results.slice(count,count + 1);
};
})();

View File

@@ -5,11 +5,9 @@ module-type: filteroperator
Filter operator that looks up values via a title prefix
[lookup:<defaultvalue>:<field OR index>[<prefix>],[<field-name OR index-name>]]
[lookup:<field>[<prefix>]]
Prepends the prefix to the selected items and returns the specified
field or index value. If the 2nd suffix does not exist, it defaults to field.
If the second operand is missing it defaults to "text" for fields, and "0" for indexes
Prepends the prefix to the selected items and returns the specified field value
\*/
(function(){
@@ -22,31 +20,10 @@ If the second operand is missing it defaults to "text" for fields, and "0" for i
Export our filter function
*/
exports.lookup = function(source,operator,options) {
var results = [],
suffixes = operator.suffixes || [],
defaultSuffix = suffixes[0] ? (suffixes[0][0] || "") : "",
indexSuffix = (suffixes[1] && suffixes[1][0] === "index") ? true : false,
target;
if(operator.operands.length == 2) {
target = operator.operands[1]
} else {
target = indexSuffix ? "0": "text";
}
if(indexSuffix) {
source(function(tiddler,title) {
var data = options.wiki.extractTiddlerDataItem(operator.operands[0]+title,target,defaultSuffix);
results.push(data);
});
} else {
source(function(tiddler,title) {
var value = defaultSuffix;
var targetTiddler = options.wiki.getTiddler(operator.operands[0]+title);
if(targetTiddler && targetTiddler.getFieldString(target)) {
value = targetTiddler.getFieldString(target);
}
results.push(value);
});
}
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix || '');
});
return results;
};

View File

@@ -165,35 +165,6 @@ exports["standard-deviation"] = makeNumericReducingOperator(
}
);
//trigonometry
exports.cos = makeNumericBinaryOperator(
function(a) {return Math.cos(a)}
);
exports.sin = makeNumericBinaryOperator(
function(a) {return Math.sin(a)}
);
exports.tan = makeNumericBinaryOperator(
function(a) {return Math.tan(a)}
);
exports.acos = makeNumericBinaryOperator(
function(a) {return Math.acos(a)}
);
exports.asin = makeNumericBinaryOperator(
function(a) {return Math.asin(a)}
);
exports.atan = makeNumericBinaryOperator(
function(a) {return Math.atan(a)}
);
exports.atan2 = makeNumericBinaryOperator(
function(a,b) {return Math.atan2(a,b)}
);
//Calculate the variance of a population of numbers in an array given its mean
function getVarianceFromArray(values,mean) {
var deviationTotal = values.reduce(function(accumulator,value) {

View File

@@ -1,30 +0,0 @@
/*\
title: $:/core/modules/filters/moduleproperty.js
type: application/javascript
module-type: filteroperator
Filter [[module-name]moduleproperty[name]] retrieve a module property
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.moduleproperty = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
var value = require(title)[operator.operand || ""];
if(value !== undefined) {
results.push(value);
}
});
results.sort();
return results;
};
})();

View File

@@ -17,23 +17,11 @@ Export our filter function
*/
exports.modules = function(source,operator,options) {
var results = [];
if(operator.operands.length >= 2) {
// Return the modules that have the module property specified in the first operand with the value in the second operand
source(function(tiddler,title) {
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
if(require(moduleName)[operator.operands[0]] === operator.operands[1]) {
results.push(moduleName);
}
});
source(function(tiddler,title) {
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
results.push(moduleName);
});
} else {
// Return all the module names without filtering
source(function(tiddler,title) {
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
results.push(moduleName);
});
});
}
});
results.sort();
return results;
};

View File

@@ -16,37 +16,19 @@ Filter operator for checking if a title starts with a prefix
Export our filter function
*/
exports.prefix = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if(suffixes.indexOf("caseinsensitive") !== -1) {
var operand = operator.operand.toLowerCase();
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.toLowerCase().substr(0,operand.length) !== operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.toLowerCase().substr(0,operand.length) === operand) {
results.push(title);
}
});
}
var results = [];
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) !== operator.operand) {
results.push(title);
}
});
} else {
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) !== operator.operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) === operator.operand) {
results.push(title);
}
});
}
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) === operator.operand) {
results.push(title);
}
});
}
return results;
};

View File

@@ -17,13 +17,9 @@ Export our filter function
*/
exports.range = function(source,operator,options) {
var results = [];
// For backwards compatibility, if there is only one operand, try to split it using one of the delimiters
var parts = operator.operands || [];
if(parts.length === 1) {
parts = operator.operand.split(/[,:;]/g);
}
// Process the parts
var beg, end, inc, i, fixed = 0;
// Split the operand into numbers delimited by these symbols
var parts = operator.operand.split(/[,:;]/g),
beg, end, inc, i, fixed = 0;
for (i=0; i<parts.length; i++) {
// Validate real number
if(!/^\s*[+-]?((\d+(\.\d*)?)|(\.\d+))\s*$/.test(parts[i])) {

View File

@@ -17,7 +17,7 @@ Export our filter function
*/
exports.regexp = function(source,operator,options) {
var results = [],
fieldname = operator.suffix || "title",
fieldname = (operator.suffix || "title").toLowerCase(),
regexpString, regexp, flags = "", match,
getFieldString = function(tiddler,title) {
if(tiddler) {

View File

@@ -16,22 +16,12 @@ Filter operator for removing a prefix from each title in the list. Titles that d
Export our filter function
*/
exports.removeprefix = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if(suffixes.indexOf("caseinsensitive") !== -1) {
var operand = operator.operand.toLowerCase();
source(function(tiddler,title) {
if(title.toLowerCase().substr(0,operand.length) === operand) {
results.push(title.substr(operand.length));
}
});
} else {
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) === operator.operand) {
results.push(title.substr(operator.operand.length));
}
});
}
var results = [];
source(function(tiddler,title) {
if(title.substr(0,operator.operand.length) === operator.operand) {
results.push(title.substr(operator.operand.length));
}
});
return results;
};

View File

@@ -16,26 +16,12 @@ Filter operator for removing a suffix from each title in the list. Titles that d
Export our filter function
*/
exports.removesuffix = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if (!operator.operand) {
source(function(tiddler,title) {
results.push(title);
});
} else if(suffixes.indexOf("caseinsensitive") !== -1) {
var operand = operator.operand.toLowerCase();
source(function(tiddler,title) {
if(title && title.toLowerCase().substr(-operand.length) === operand) {
results.push(title.substr(0,title.length - operand.length));
}
});
} else {
source(function(tiddler,title) {
if(title && title.substr(-operator.operand.length) === operator.operand) {
results.push(title.substr(0,title.length - operator.operand.length));
}
});
}
var results = [];
source(function(tiddler,title) {
if(title && title.substr(-operator.operand.length) === operator.operand) {
results.push(title.substr(0,title.length - operator.operand.length));
}
});
return results;
};

View File

@@ -40,7 +40,6 @@ exports.search = function(source,operator,options) {
invert: invert,
field: fields,
excludeField: excludeFields,
some: hasFlag("some"),
caseSensitive: hasFlag("casesensitive"),
literal: hasFlag("literal"),
whitespace: hasFlag("whitespace"),

View File

@@ -119,25 +119,23 @@ exports["search-replace"] = function(source,operator,options) {
var results = [],
suffixes = operator.suffixes || [],
flagSuffix = (suffixes[0] ? (suffixes[0][0] || "") : ""),
flags = (flagSuffix.indexOf("g") !== -1 ? "g" : "") + (flagSuffix.indexOf("i") !== -1 ? "i" : "") + (flagSuffix.indexOf("m") !== -1 ? "m" : ""),
flags = (flagSuffix.indexOf("g") !== -1 ? "g" : "") + (flagSuffix.indexOf("i") !== -1 ? "i" : ""),
isRegExp = (suffixes[1] && suffixes[1][0] === "regexp") ? true : false,
//Escape regexp characters if the operand is not a regular expression
searchTerm = isRegExp ? operator.operand : $tw.utils.escapeRegExp(operator.operand),
//Escape $ character in replacement string if not in regular expression mode
replacement = isRegExp ? operator.operands[1] : (operator.operands[1]||"").replace(/\$/g,"$$$$"),
searchTerm,
regExp;
try {
regExp = new RegExp(searchTerm,flags);
} catch(ex) {
return ["RegExp error: " + ex];
}
source(function(tiddler,title) {
if(title && (operator.operands.length > 1)) {
//Escape regexp characters if the operand is not a regular expression
searchTerm = isRegExp ? operator.operand : $tw.utils.escapeRegExp(operator.operand);
try {
regExp = new RegExp(searchTerm,flags);
} catch(ex) {
return ["RegExp error: " + ex];
}
results.push(
title.replace(regExp,replacement)
title.replace(regExp,operator.operands[1])
);
regExp.lastIndex = 0;
} else {
results.push(title);
}
@@ -174,14 +172,4 @@ exports.pad = function(source,operator,options) {
return results;
}
exports.charcode = function(source,operator,options) {
var chars = [];
$tw.utils.each(operator.operands,function(operand) {
if(operand !== "") {
chars.push(String.fromCharCode($tw.utils.parseInt(operand)));
}
});
return [chars.join("")];
};
})();

View File

@@ -16,41 +16,19 @@ Filter operator for checking if a title ends with a suffix
Export our filter function
*/
exports.suffix = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if (!operator.operand) {
var results = [];
if(operator.prefix === "!") {
source(function(tiddler,title) {
results.push(title);
if(title.substr(-operator.operand.length) !== operator.operand) {
results.push(title);
}
});
} else if(suffixes.indexOf("caseinsensitive") !== -1) {
var operand = operator.operand.toLowerCase();
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.toLowerCase().substr(-operand.length) !== operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.toLowerCase().substr(-operand.length) === operand) {
results.push(title);
}
});
}
} else {
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.substr(-operator.operand.length) !== operator.operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.substr(-operator.operand.length) === operator.operand) {
results.push(title);
}
});
}
source(function(tiddler,title) {
if(title.substr(-operator.operand.length) === operator.operand) {
results.push(title);
}
});
}
return results;
};

View File

@@ -16,13 +16,20 @@ Filter operator returning all the selected tiddlers that are untagged
Export our filter function
*/
exports.untagged = function(source,operator,options) {
var results = [],
expected = (operator.prefix === "!");
source(function(tiddler,title) {
if(((tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) === expected) || (!tiddler && !expected)) {
results.push(title);
}
});
var results = [];
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(tiddler && $tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length > 0) {
$tw.utils.pushTop(results,title);
}
});
} else {
source(function(tiddler,title) {
if(!tiddler || !tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
$tw.utils.pushTop(results,title);
}
});
}
return results;
};

View File

@@ -179,7 +179,7 @@ Key descriptors have the following format:
ctrl+enter
ctrl+shift+alt+A
*/
KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor,options) {
KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {
var components = keyDescriptor.split(/\+|\-/),
info = {
keyCode: 0,
@@ -206,9 +206,6 @@ KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor,options) {
info.keyCode = this.namedKeys[s];
}
}
if(options.keyDescriptor) {
info.keyDescriptor = options.keyDescriptor;
}
if(info.keyCode) {
return info;
} else {
@@ -240,7 +237,6 @@ KeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options)
lookupName = function(configName) {
var keyDescriptors = wiki.getTiddlerText("$:/config/" + configName + "/" + name);
if(keyDescriptors) {
options.keyDescriptor = keyDescriptor;
result.push.apply(result,self.parseKeyDescriptors(keyDescriptors,options));
}
};
@@ -249,7 +245,7 @@ KeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options)
});
}
} else {
result.push(self.parseKeyDescriptor(keyDescriptor,options));
result.push(self.parseKeyDescriptor(keyDescriptor));
}
});
return result;
@@ -280,16 +276,12 @@ KeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {
};
KeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {
return (this.getMatchingKeyDescriptor(event,keyInfoArray) !== null);
};
KeyboardManager.prototype.getMatchingKeyDescriptor = function(event,keyInfoArray) {
for(var t=0; t<keyInfoArray.length; t++) {
if(this.checkKeyDescriptor(event,keyInfoArray[t])) {
return keyInfoArray[t];
return true;
}
}
return null;
return false;
};
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
@@ -332,7 +324,7 @@ KeyboardManager.prototype.handleKeydownEvent = function(event) {
if(key !== undefined) {
event.preventDefault();
event.stopPropagation();
$tw.rootWidget.invokeActionString(action,$tw.rootWidget,event);
$tw.rootWidget.invokeActionString(action,$tw.rootWidget);
return true;
}
return false;

View File

@@ -123,19 +123,6 @@ exports.parseStringLiteral = function(source,pos) {
}
};
exports.parseMacroParameters = function(node,source,pos) {
// Process parameters
var parameter = $tw.utils.parseMacroParameter(source,pos);
while(parameter) {
node.params.push(parameter);
pos = parameter.end;
// Get the next parameter
parameter = $tw.utils.parseMacroParameter(source,pos);
}
node.end = pos;
return node;
}
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
*/
@@ -200,8 +187,14 @@ exports.parseMacroInvocation = function(source,pos) {
}
node.name = name.match[1];
pos = name.end;
node = $tw.utils.parseMacroParameters(node,source,pos);
pos = node.end;
// Process parameters
var parameter = $tw.utils.parseMacroParameter(source,pos);
while(parameter) {
node.params.push(parameter);
pos = parameter.end;
// Get the next parameter
parameter = $tw.utils.parseMacroParameter(source,pos);
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double greater than sign
@@ -215,31 +208,8 @@ exports.parseMacroInvocation = function(source,pos) {
return node;
};
exports.parseFilterVariable = function(source) {
var node = {
name: "",
params: [],
},
pos = 0,
reName = /([^\s"']+)/g;
// If there is no whitespace or it is an empty string then there are no macro parameters
if(/^\S*$/.test(source)) {
node.name = source;
return node;
}
// Get the variable name
var nameMatch = $tw.utils.parseTokenRegExp(source,pos,reName);
if(nameMatch) {
node.name = nameMatch.match[1];
pos = nameMatch.end;
node = $tw.utils.parseMacroParameters(node,source,pos);
delete node.end;
}
return node;
};
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, type: "filtered|string|indirect|macro", value|filter|textReference:, start:, end:,}
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
*/
exports.parseAttribute = function(source,pos) {
var node = {
@@ -248,7 +218,7 @@ exports.parseAttribute = function(source,pos) {
// Define our regexps
var reAttributeName = /([^\/\s>"'=]+)/g,
reUnquotedAttribute = /([^\/\s<>"'=]+)/g,
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g,
reFilteredValue = /\{\{\{(.+?)\}\}\}/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);

View File

@@ -7,12 +7,6 @@ Wiki text block rule for HTML comments. For example:
```
<!-- This is a comment -->
\define macroX()
<!-- This is a comment -->
xxxx
\end
<!-- This is a comment -->
```
Note that the syntax for comments is simplified to an opening "<!--" sequence and a closing "-->" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)
@@ -25,7 +19,7 @@ Note that the syntax for comments is simplified to an opening "<!--" sequence an
"use strict";
exports.name = "commentblock";
exports.types = {block:true, pragma:true};
exports.types = {block: true};
exports.init = function(parser) {
this.parser = parser;

View File

@@ -66,7 +66,7 @@ exports.parse = function() {
};
/*
Look for an HTML tag. Returns null if not found, otherwise returns {type: "element", name:, attributes: {}, orderedAttributes: [], isSelfClosing:, start:, end:,}
Look for an HTML tag. Returns null if not found, otherwise returns {type: "element", name:, attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseTag = function(source,pos,options) {
options = options || {};
@@ -74,8 +74,7 @@ exports.parseTag = function(source,pos,options) {
node = {
type: "element",
start: pos,
attributes: {},
orderedAttributes: []
attributes: {}
};
// Define our regexps
var reTagName = /([a-zA-Z0-9\-\$]+)/g;
@@ -107,7 +106,6 @@ exports.parseTag = function(source,pos,options) {
// Process attributes
var attribute = $tw.utils.parseAttribute(source,pos);
while(attribute) {
node.orderedAttributes.push(attribute);
node.attributes[attribute.name] = attribute;
pos = attribute.end;
// Get the next attribute

View File

@@ -231,10 +231,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
return nextMatch.rule.parse();
}
// Treat it as a paragraph if we didn't find a block rule
var start = this.pos;
var children = this.parseInlineRun(terminatorRegExp);
var end = this.pos;
return [{type: "element", tag: "p", children: children, start: start, end: end }];
return [{type: "element", tag: "p", children: this.parseInlineRun(terminatorRegExp)}];
};
/*
@@ -310,7 +307,7 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) {
while(this.pos < this.sourceLength && nextMatch) {
// Process the text preceding the run rule
if(nextMatch.matchIndex > this.pos) {
this.pushTextWidget(tree,this.source.substring(this.pos,nextMatch.matchIndex),this.pos,nextMatch.matchIndex);
this.pushTextWidget(tree,this.source.substring(this.pos,nextMatch.matchIndex));
this.pos = nextMatch.matchIndex;
}
// Process the run rule
@@ -320,7 +317,7 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) {
}
// Process the remaining text
if(this.pos < this.sourceLength) {
this.pushTextWidget(tree,this.source.substr(this.pos),this.pos,this.sourceLength);
this.pushTextWidget(tree,this.source.substr(this.pos));
}
this.pos = this.sourceLength;
return tree;
@@ -340,7 +337,7 @@ WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,option
if(terminatorMatch) {
if(!inlineRuleMatch || inlineRuleMatch.matchIndex >= terminatorMatch.index) {
if(terminatorMatch.index > this.pos) {
this.pushTextWidget(tree,this.source.substring(this.pos,terminatorMatch.index),this.pos,terminatorMatch.index);
this.pushTextWidget(tree,this.source.substring(this.pos,terminatorMatch.index));
}
this.pos = terminatorMatch.index;
if(options.eatTerminator) {
@@ -353,7 +350,7 @@ WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,option
if(inlineRuleMatch) {
// Preceding text
if(inlineRuleMatch.matchIndex > this.pos) {
this.pushTextWidget(tree,this.source.substring(this.pos,inlineRuleMatch.matchIndex),this.pos,inlineRuleMatch.matchIndex);
this.pushTextWidget(tree,this.source.substring(this.pos,inlineRuleMatch.matchIndex));
this.pos = inlineRuleMatch.matchIndex;
}
// Process the inline rule
@@ -367,7 +364,7 @@ WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,option
}
// Process the remaining text
if(this.pos < this.sourceLength) {
this.pushTextWidget(tree,this.source.substr(this.pos),this.pos,this.sourceLength);
this.pushTextWidget(tree,this.source.substr(this.pos));
}
this.pos = this.sourceLength;
return tree;
@@ -376,12 +373,12 @@ WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,option
/*
Push a text widget onto an array, respecting the configTrimWhiteSpace setting
*/
WikiParser.prototype.pushTextWidget = function(array,text,start,end) {
WikiParser.prototype.pushTextWidget = function(array,text) {
if(this.configTrimWhiteSpace) {
text = $tw.utils.trim(text);
}
if(text) {
array.push({type: "text", text: text, start: start, end: end});
array.push({type: "text", text: text});
}
};

View File

@@ -52,7 +52,7 @@ PluginSwitcher.prototype.switchPlugins = function() {
var tiddler = self.wiki.getTiddler(title);
if(tiddler && tiddler.isPlugin() && plugins.indexOf(title) === -1) {
plugins.push(title);
var pluginInfo = $tw.utils.parseJSONSafe(self.wiki.getTiddlerText(title)),
var pluginInfo = JSON.parse(self.wiki.getTiddlerText(title)),
dependents = $tw.utils.parseStringArray(tiddler.fields.dependents || "");
$tw.utils.each(dependents,function(title) {
accumulatePlugin(title);

View File

@@ -157,8 +157,7 @@ SaverHandler.prototype.saveWiki = function(options) {
return false;
}
var variables = options.variables || {},
template = (options.template ||
this.wiki.getTiddlerText("$:/config/SaveWikiButton/Template","$:/core/save/all")).trim(),
template = options.template || "$:/core/save/all",
downloadType = options.downloadType || "text/plain",
text = this.wiki.renderTiddler(downloadType,template,options),
callback = function(err) {

View File

@@ -42,7 +42,7 @@ AndTidWiki.prototype.save = function(text,method,callback,options) {
window.twi.saveWiki(text);
} else {
// Get the pathname of this document
var pathname = $tw.utils.decodeURIComponentSafe(document.location.toString().split("#")[0]);
var pathname = decodeURIComponent(document.location.toString().split("#")[0]);
// Strip the file://
if(pathname.indexOf("file://") === 0) {
pathname = pathname.substr(7);

View File

@@ -26,7 +26,7 @@ DownloadSaver.prototype.save = function(text,method,callback,options) {
var p = document.location.pathname.lastIndexOf("/");
if(p !== -1) {
// We decode the pathname because document.location is URL encoded by the browser
filename = $tw.utils.decodeURIComponentSafe(document.location.pathname.substr(p+1));
filename = decodeURIComponent(document.location.pathname.substr(p+1));
}
}
if(!filename) {

View File

@@ -61,7 +61,7 @@ GiteaSaver.prototype.save = function(text,method,callback) {
}
var use_put = true;
if(xhr.status !== 404) {
getResponseData = $tw.utils.parseJSONSafe(getResponseDataJson);
getResponseData = JSON.parse(getResponseDataJson);
$tw.utils.each(getResponseData,function(details) {
if(details.name === filename) {
sha = details.sha;
@@ -72,7 +72,7 @@ GiteaSaver.prototype.save = function(text,method,callback) {
}
}
var data = {
message: $tw.language.getString("ControlPanel/Saving/GitService/CommitMessage"),
message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
content: $tw.utils.base64Encode(text),
sha: sha
};
@@ -104,7 +104,7 @@ GiteaSaver.prototype.upload = function(uri,method,headers,data,callback) {
if(err) {
return callback(err);
}
var putResponseData = $tw.utils.parseJSONSafe(putResponseDataJson);
var putResponseData = JSON.parse(putResponseDataJson);
callback(null);
}
});

View File

@@ -61,7 +61,7 @@ GitHubSaver.prototype.save = function(text,method,callback) {
return callback(err);
}
if(xhr.status !== 404) {
getResponseData = $tw.utils.parseJSONSafe(getResponseDataJson);
getResponseData = JSON.parse(getResponseDataJson);
$tw.utils.each(getResponseData,function(details) {
if(details.name === filename) {
sha = details.sha;
@@ -69,7 +69,7 @@ GitHubSaver.prototype.save = function(text,method,callback) {
});
}
var data = {
message: $tw.language.getString("ControlPanel/Saving/GitService/CommitMessage"),
message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
content: $tw.utils.base64Encode(text),
branch: branch,
sha: sha
@@ -84,7 +84,7 @@ GitHubSaver.prototype.save = function(text,method,callback) {
if(err) {
return callback(err);
}
var putResponseData = $tw.utils.parseJSONSafe(putResponseDataJson);
var putResponseData = JSON.parse(putResponseDataJson);
callback(null);
}
});

View File

@@ -58,7 +58,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
}
var requestType = "POST";
if(xhr.status !== 404) {
getResponseData = $tw.utils.parseJSONSafe(getResponseDataJson);
getResponseData = JSON.parse(getResponseDataJson);
$tw.utils.each(getResponseData,function(details) {
if(details.name === filename) {
requestType = "PUT";
@@ -67,7 +67,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
});
}
var data = {
commit_message: $tw.language.getString("ControlPanel/Saving/GitService/CommitMessage"),
commit_message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
content: text,
branch: branch,
sha: sha
@@ -82,7 +82,7 @@ GitLabSaver.prototype.save = function(text,method,callback) {
if(err) {
return callback(err);
}
var putResponseData = $tw.utils.parseJSONSafe(putResponseDataJson);
var putResponseData = JSON.parse(putResponseDataJson);
callback(null);
}
});

View File

@@ -43,7 +43,7 @@ TiddlyFoxSaver.prototype.save = function(text,method,callback) {
}
// Create the message element and put it in the message box
var message = document.createElement("div");
message.setAttribute("data-tiddlyfox-path",$tw.utils.decodeURIComponentSafe(pathname));
message.setAttribute("data-tiddlyfox-path",decodeURIComponent(pathname));
message.setAttribute("data-tiddlyfox-content",text);
messageBox.appendChild(message);
// Add an event handler for when the file has been saved

View File

@@ -21,7 +21,7 @@ TWEditSaver.prototype.save = function(text,method,callback) {
return false;
}
// Get the pathname of this document
var pathname = $tw.utils.decodeURIComponentSafe(document.location.pathname);
var pathname = decodeURIComponent(document.location.pathname);
// Strip any query or location part
var p = pathname.indexOf("?");
if(p !== -1) {

View File

@@ -17,7 +17,7 @@ exports.method = "DELETE";
exports.path = /^\/bags\/default\/tiddlers\/(.+)$/;
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]);
var title = decodeURIComponent(state.params[0]);
state.wiki.deleteTiddler(title);
response.writeHead(204, "OK", {
"Content-Type": "text/plain"

View File

@@ -20,29 +20,22 @@ exports.handler = function(request,response,state) {
var path = require("path"),
fs = require("fs"),
util = require("util"),
suppliedFilename = $tw.utils.decodeURIComponentSafe(state.params[0]),
baseFilename = path.resolve(state.boot.wikiPath,"files"),
filename = path.resolve(baseFilename,suppliedFilename),
suppliedFilename = decodeURIComponent(state.params[0]),
filename = path.resolve(state.boot.wikiPath,"files",suppliedFilename),
extension = path.extname(filename);
// Check that the filename is inside the wiki files folder
if(path.relative(baseFilename,filename).indexOf("..") !== 0) {
// Send the file
fs.readFile(filename,function(err,content) {
var status,content,type = "text/plain";
if(err) {
console.log("Error accessing file " + filename + ": " + err.toString());
status = 404;
content = "File '" + suppliedFilename + "' not found";
} else {
status = 200;
content = content;
type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream");
}
state.sendResponse(status,{"Content-Type": type},content);
});
} else {
state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + suppliedFilename + "' not found");
}
fs.readFile(filename,function(err,content) {
var status,content,type = "text/plain";
if(err) {
console.log("Error accessing file " + filename + ": " + err.toString());
status = 404;
content = "File '" + suppliedFilename + "' not found";
} else {
status = 200;
content = content;
type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream");
}
state.sendResponse(status,{"Content-Type": type},content);
});
};
}());

View File

@@ -21,6 +21,7 @@ exports.handler = function(request,response,state) {
username: state.authenticatedUsername || state.server.get("anon-username") || "",
anonymous: !state.authenticatedUsername,
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
sse_enabled: state.server.get("sse-enabled") === "yes",
space: {
recipe: "default"
},

View File

@@ -17,7 +17,7 @@ exports.method = "GET";
exports.path = /^\/([^\/]+)$/;
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
var title = decodeURIComponent(state.params[0]),
tiddler = state.wiki.getTiddler(title);
if(tiddler) {
var renderType = tiddler.getFieldString("_render_type"),

View File

@@ -17,7 +17,7 @@ exports.method = "GET";
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
var title = decodeURIComponent(state.params[0]),
tiddler = state.wiki.getTiddler(title),
tiddlerFields = {},
knownFields = [

View File

@@ -17,8 +17,8 @@ exports.method = "PUT";
exports.path = /^\/recipes\/default\/tiddlers\/(.+)$/;
exports.handler = function(request,response,state) {
var title = $tw.utils.decodeURIComponentSafe(state.params[0]),
fields = $tw.utils.parseJSONSafe(state.data);
var title = decodeURIComponent(state.params[0]),
fields = JSON.parse(state.data);
// Pull up any subfields in the `fields` object
if(fields.fields) {
$tw.utils.each(fields.fields,function(field,name) {
@@ -30,7 +30,7 @@ exports.handler = function(request,response,state) {
if(fields.revision) {
delete fields.revision;
}
state.wiki.addTiddler(new $tw.Tiddler(fields,{title: title}));
state.wiki.addTiddler(new $tw.Tiddler(state.wiki.getCreationFields(),fields,{title: title},state.wiki.getModificationFields()));
var changeCount = state.wiki.getChangeCount(title).toString();
response.writeHead(204, "OK",{
Etag: "\"default/" + encodeURIComponent(title) + "/" + changeCount + ":\"",

View File

@@ -0,0 +1,70 @@
/*\
title: $:/core/modules/server/server-sent-events.js
type: application/javascript
module-type: library
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
parameters:
prefix - usually the plugin path, such as `plugins/tiddlywiki/tiddlyweb`. The
route will match `/events/${prefix}` exactly.
handler - a function that will be called each time a request comes in with the
request and state from the route and an emit function to call.
*/
var ServerSentEvents = function ServerSentEvents(prefix, handler) {
this.handler = handler;
this.prefix = prefix;
};
ServerSentEvents.prototype.getExports = function() {
return {
bodyFormat: "stream",
method: "GET",
path: new RegExp("^/events/" + this.prefix + "$"),
handler: this.handleEventRequest.bind(this)
};
};
ServerSentEvents.prototype.handleEventRequest = function(request,response,state) {
if(ServerSentEvents.prototype.isEventStreamRequest(request)) {
response.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
});
this.handler(request,state,this.emit.bind(this,response),this.end.bind(this,response));
} else {
response.writeHead(406,"Not Acceptable",{});
response.end();
}
};
ServerSentEvents.prototype.isEventStreamRequest = function(request) {
return request.headers.accept &&
request.headers.accept.match(/^text\/event-stream/);
};
ServerSentEvents.prototype.emit = function(response,event,data) {
if(typeof event !== "string" || event.indexOf("\n") !== -1) {
throw new Error("Type must be a single-line string");
}
if(typeof data !== "string" || data.indexOf("\n") !== -1) {
throw new Error("Data must be a single-line string");
}
response.write("event: " + event + "\ndata: " + data + "\n\n", "utf8");
};
ServerSentEvents.prototype.end = function(response) {
response.end();
};
exports.ServerSentEvents = ServerSentEvents;
})();

View File

@@ -34,6 +34,7 @@ function Server(options) {
this.authenticators = options.authenticators || [];
this.wiki = options.wiki;
this.boot = options.boot || $tw.boot;
this.servername = $tw.utils.transliterateToSafeASCII(this.wiki.getTiddlerText("$:/SiteTitle") || "TiddlyWiki5");
// Initialise the variables
this.variables = $tw.utils.extend({},this.defaultVariables);
if(options.variables) {
@@ -43,8 +44,7 @@ function Server(options) {
}
}
}
// Setup the default required plugins
this.requiredPlugins = this.get("required-plugins").split(',');
$tw.utils.extend({},this.defaultVariables,options.variables);
// Initialise CSRF
this.csrfDisable = this.get("csrf-disable") === "yes";
// Initialize Gzip compression
@@ -52,24 +52,14 @@ function Server(options) {
// Initialize browser-caching
this.enableBrowserCache = this.get("use-browser-cache") === "yes";
// Initialise authorization
var authorizedUserName;
if(this.get("username") && this.get("password")) {
authorizedUserName = this.get("username");
} else if(this.get("credentials")) {
authorizedUserName = "(authenticated)";
} else {
authorizedUserName = "(anon)";
}
var authorizedUserName = (this.get("username") && this.get("password")) ? this.get("username") : "(anon)";
this.authorizationPrincipals = {
readers: (this.get("readers") || authorizedUserName).split(",").map($tw.utils.trim),
writers: (this.get("writers") || authorizedUserName).split(",").map($tw.utils.trim)
}
if(this.get("admin") || authorizedUserName !== "(anon)") {
this.authorizationPrincipals["admin"] = (this.get("admin") || authorizedUserName).split(',').map($tw.utils.trim)
}
// Load and initialise authenticators
$tw.modules.forEachModuleOfType("authenticator", function(title,authenticatorDefinition) {
// console.log("Loading authenticator " + title);
// console.log("Loading server route " + title);
self.addAuthenticator(authenticatorDefinition.AuthenticatorClass);
});
// Load route handlers
@@ -81,21 +71,15 @@ function Server(options) {
this.listenOptions = null;
this.protocol = "http";
var tlsKeyFilepath = this.get("tls-key"),
tlsCertFilepath = this.get("tls-cert"),
tlsPassphrase = this.get("tls-passphrase");
tlsCertFilepath = this.get("tls-cert");
if(tlsCertFilepath && tlsKeyFilepath) {
this.listenOptions = {
key: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsKeyFilepath),"utf8"),
cert: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsCertFilepath),"utf8"),
passphrase: tlsPassphrase || ''
cert: fs.readFileSync(path.resolve(this.boot.wikiPath,tlsCertFilepath),"utf8")
};
this.protocol = "https";
}
this.transport = require(this.protocol);
// Name the server and init the boot state
this.servername = $tw.utils.transliterateToSafeASCII(this.get("server-name") || this.wiki.getTiddlerText("$:/SiteTitle") || "TiddlyWiki5");
this.boot.origin = this.get("origin")? this.get("origin"): this.protocol+"://"+this.get("host")+":"+this.get("port");
this.boot.pathPrefix = this.get("path-prefix") || "";
}
/*
@@ -166,7 +150,6 @@ function sendResponse(request,response,statusCode,headers,data,encoding) {
Server.prototype.defaultVariables = {
port: "8080",
host: "127.0.0.1",
"required-plugins": "$:/plugins/tiddlywiki/filesystem,$:/plugins/tiddlywiki/tiddlyweb",
"root-tiddler": "$:/core/save/all",
"root-render-type": "text/plain",
"root-serve-type": "text/html",
@@ -256,15 +239,15 @@ Server.prototype.requestHandler = function(request,response,options) {
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
state.sendResponse = sendResponse.bind(self,request,response);
// Get the principals authorized to access this resource
state.authorizationType = options.authorizationType || this.methodMappings[request.method] || "readers";
var authorizationType = this.methodMappings[request.method] || "readers";
// Check for the CSRF header if this is a write
if(!this.csrfDisable && state.authorizationType === "writers" && request.headers["x-requested-with"] !== "TiddlyWiki") {
if(!this.csrfDisable && authorizationType === "writers" && request.headers["x-requested-with"] !== "TiddlyWiki") {
response.writeHead(403,"'X-Requested-With' header required to login to '" + this.servername + "'");
response.end();
return;
}
// Check whether anonymous access is granted
state.allowAnon = this.isAuthorized(state.authorizationType,null);
state.allowAnon = this.isAuthorized(authorizationType,null);
// Authenticate with the first active authenticator
if(this.authenticators.length > 0) {
if(!this.authenticators[0].authenticateRequest(request,response,state)) {
@@ -273,7 +256,7 @@ Server.prototype.requestHandler = function(request,response,options) {
}
}
// Authorize with the authenticated username
if(!this.isAuthorized(state.authorizationType,state.authenticatedUsername)) {
if(!this.isAuthorized(authorizationType,state.authenticatedUsername)) {
response.writeHead(401,"'" + state.authenticatedUsername + "' is not authorized to access '" + this.servername + "'");
response.end();
return;
@@ -339,16 +322,8 @@ Server.prototype.listen = function(port,host,prefix) {
port = process.env[port] || 8080;
}
// Warn if required plugins are missing
var missing = [];
for (var index=0; index<this.requiredPlugins.length; index++) {
if (!this.wiki.getTiddler(this.requiredPlugins[index])) {
missing.push(this.requiredPlugins[index]);
}
}
if(missing.length > 0) {
var error = "Warning: Plugin(s) required for client-server operation are missing.\n"+
"\""+ missing.join("\", \"")+"\"";
$tw.utils.warning(error);
if(!this.wiki.getTiddler("$:/plugins/tiddlywiki/tiddlyweb") || !this.wiki.getTiddler("$:/plugins/tiddlywiki/filesystem")) {
$tw.utils.warning("Warning: Plugins required for client-server operation (\"tiddlywiki/filesystem\" and \"tiddlywiki/tiddlyweb\") are missing from tiddlywiki.info file");
}
// Create the server
var server;

View File

@@ -152,7 +152,7 @@ exports.startup = function() {
if(event.data.status.charAt(0) === "2") {
if(event.data.cookies) {
if(event.data.cookies.type === "save-info") {
var tiddlers = $tw.utils.parseJSONSafe(event.data.body);
var tiddlers = JSON.parse(event.data.body);
$tw.utils.each(tiddlers,function(tiddler) {
$tw.wiki.addTiddler(new $tw.Tiddler($tw.wiki.getCreationFields(),tiddler,{
title: event.data.cookies.infoTitlePrefix + event.data.cookies.url + "/" + tiddler.title,
@@ -170,7 +170,7 @@ exports.startup = function() {
},$tw.wiki.getModificationFields()));
});
} else if(event.data.cookies.type === "save-tiddler") {
var tiddler = $tw.utils.parseJSONSafe(event.data.body);
var tiddler = JSON.parse(event.data.body);
$tw.wiki.addTiddler(new $tw.Tiddler(tiddler));
}
}

View File

@@ -40,10 +40,9 @@ exports.startup = function() {
// Install the tm-focus-selector message
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
var selector = event.param || "",
element,
doc = event.event && event.event.target ? event.event.target.ownerDocument : document;
element;
try {
element = doc.querySelector(selector);
element = document.querySelector(selector);
} catch(e) {
console.log("Error in selector: ",selector)
}
@@ -51,20 +50,6 @@ exports.startup = function() {
element.focus(event.paramObject);
}
});
// Install the tm-rename-tiddler and tm-relink-tiddler messages
var makeRenameHandler = function(method) {
return function(event) {
var options = {},
paramObject = event.paramObject || {},
from = paramObject.from || event.tiddlerTitle,
to = paramObject.to;
options.dontRenameInTags = (paramObject.renameInTags === "false" || paramObject.renameInTags === "no") ? true : false;
options.dontRenameInLists = (paramObject.renameInLists === "false" || paramObject.renameInLists === "no") ? true : false;
$tw.wiki[method](from,to,options);
};
};
$tw.rootWidget.addEventListener("tm-rename-tiddler",makeRenameHandler("renameTiddler"));
$tw.rootWidget.addEventListener("tm-relink-tiddler",makeRenameHandler("relinkTiddler"));
// Install the scroller
$tw.pageScroller = new $tw.utils.PageScroller();
$tw.rootWidget.addEventListener("tm-scroll",function(event) {

View File

@@ -120,10 +120,10 @@ function openStartupTiddlers(options) {
var hash = $tw.locationHash.substr(1),
split = hash.indexOf(":");
if(split === -1) {
target = $tw.utils.decodeURIComponentSafe(hash.trim());
target = decodeURIComponent(hash.trim());
} else {
target = $tw.utils.decodeURIComponentSafe(hash.substr(0,split).trim());
storyFilter = $tw.utils.decodeURIComponentSafe(hash.substr(split + 1).trim());
target = decodeURIComponent(hash.substr(0,split).trim());
storyFilter = decodeURIComponent(hash.substr(split + 1).trim());
}
}
// If the story wasn't specified use the current tiddlers or a blank story

View File

@@ -20,8 +20,6 @@ exports.synchronous = true;
// Global to keep track of open windows (hashmap by title)
$tw.windows = {};
// Default template to use for new windows
var DEFAULT_WINDOW_TEMPLATE = "$:/core/templates/single.tiddler.window";
exports.startup = function() {
// Handle open window message
@@ -31,25 +29,22 @@ exports.startup = function() {
title = event.param || event.tiddlerTitle,
paramObject = event.paramObject || {},
windowTitle = paramObject.windowTitle || title,
windowID = paramObject.windowID || title,
template = paramObject.template || DEFAULT_WINDOW_TEMPLATE,
template = paramObject.template || "$:/core/templates/single.tiddler.window",
width = paramObject.width || "700",
height = paramObject.height || "600",
top = paramObject.top,
left = paramObject.left,
variables = $tw.utils.extend({},paramObject,{currentTiddler: title, "tv-window-id": windowID});
variables = $tw.utils.extend({},paramObject,{currentTiddler: title});
// Open the window
var srcWindow,
srcDocument;
// In case that popup blockers deny opening a new window
try {
srcWindow = window.open("","external-" + windowID,"scrollbars,width=" + width + ",height=" + height + (top ? ",top=" + top : "" ) + (left ? ",left=" + left : "" )),
srcWindow = window.open("","external-" + title,"scrollbars,width=" + width + ",height=" + height),
srcDocument = srcWindow.document;
}
catch(e) {
return;
}
$tw.windows[windowID] = srcWindow;
$tw.windows[title] = srcWindow;
// Check for reopening the same window
if(srcWindow.haveInitialisedWindow) {
return;
@@ -59,7 +54,7 @@ exports.startup = function() {
srcDocument.close();
srcDocument.title = windowTitle;
srcWindow.addEventListener("beforeunload",function(event) {
delete $tw.windows[windowID];
delete $tw.windows[title];
$tw.wiki.removeEventListener("change",refreshHandler);
},false);
// Set up the styles
@@ -93,21 +88,13 @@ exports.startup = function() {
srcWindow.document.documentElement.addEventListener("click",$tw.popup,true);
srcWindow.haveInitialisedWindow = true;
});
$tw.rootWidget.addEventListener("tm-close-window",function(event) {
var windowID = event.param,
win = $tw.windows[windowID];
if(win) {
win.close();
}
});
var closeAllWindows = function() {
// Close open windows when unloading main window
$tw.addUnloadTask(function() {
$tw.utils.each($tw.windows,function(win) {
win.close();
});
}
$tw.rootWidget.addEventListener("tm-close-all-windows",closeAllWindows);
// Close open windows when unloading main window
$tw.addUnloadTask(closeAllWindows);
});
};
})();

View File

@@ -27,7 +27,7 @@ ClassicStoryView.prototype.navigateTo = function(historyInfo) {
var listItemWidget = this.listWidget.children[listElementIndex],
targetElement = listItemWidget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
return;
}
if(duration) {
@@ -43,7 +43,7 @@ ClassicStoryView.prototype.insert = function(widget) {
if(duration) {
var targetElement = widget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
return;
}
// Get the current height of the tiddler
@@ -83,7 +83,7 @@ ClassicStoryView.prototype.remove = function(widget) {
widget.removeChildDomNodes();
};
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
removeElement();
return;
}
@@ -118,4 +118,4 @@ ClassicStoryView.prototype.remove = function(widget) {
exports.classic = ClassicStoryView;
})();
})();

View File

@@ -24,7 +24,7 @@ PopStoryView.prototype.navigateTo = function(historyInfo) {
var listItemWidget = this.listWidget.children[listElementIndex],
targetElement = listItemWidget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
return;
}
// Scroll the node into view
@@ -35,7 +35,7 @@ PopStoryView.prototype.insert = function(widget) {
var targetElement = widget.findFirstDomNode(),
duration = $tw.utils.getAnimationDuration();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
return;
}
// Reset once the transition is over
@@ -77,7 +77,7 @@ PopStoryView.prototype.remove = function(widget) {
}
};
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
removeElement();
return;
}

View File

@@ -48,7 +48,7 @@ ZoominListView.prototype.navigateTo = function(historyInfo) {
var listItemWidget = this.listWidget.children[listElementIndex],
targetElement = listItemWidget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
return;
}
// Make the new tiddler be position absolute and visible so that we can measure it
@@ -130,7 +130,7 @@ function findTitleDomNode(widget,targetClass) {
ZoominListView.prototype.insert = function(widget) {
var targetElement = widget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
return;
}
// Make the newly inserted node position absolute and hidden
@@ -147,7 +147,7 @@ ZoominListView.prototype.remove = function(widget) {
widget.removeChildDomNodes();
};
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!(targetElement instanceof Element)) {
removeElement();
return;
}

View File

@@ -20,6 +20,7 @@ Syncer.prototype.titleIsAnonymous = "$:/status/IsAnonymous";
Syncer.prototype.titleIsReadOnly = "$:/status/IsReadOnly";
Syncer.prototype.titleUserName = "$:/status/UserName";
Syncer.prototype.titleSyncFilter = "$:/config/SyncFilter";
Syncer.prototype.titleSyncDisablePolling = "$:/config/SyncDisablePolling";
Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval";
Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading";
Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done";
@@ -89,7 +90,7 @@ function Syncer(options) {
if(filteredChanges.length > 0) {
self.processTaskQueue();
} else {
// Look for deletions of tiddlers we're already syncing
// Look for deletions of tiddlers we're already syncing
var outstandingDeletion = false
$tw.utils.each(changes,function(change,title,object) {
if(change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) {
@@ -121,7 +122,7 @@ function Syncer(options) {
self.login(username,password,function() {});
} else {
// No username and password, so we display a prompt
self.handleLoginEvent();
self.handleLoginEvent();
}
});
$tw.rootWidget.addEventListener("tm-logout",function() {
@@ -138,7 +139,7 @@ function Syncer(options) {
if(!this.disableUI && this.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== "yes") {
this.wiki.addEventListener("lazyLoad",function(title) {
self.handleLazyLoadEvent(title);
});
});
}
// Get the login status
this.getStatus(function(err,isLoggedIn) {
@@ -173,8 +174,8 @@ Syncer.prototype.getTiddlerRevision = function(title) {
if(this.syncadaptor && this.syncadaptor.getTiddlerRevision) {
return this.syncadaptor.getTiddlerRevision(title);
} else {
return this.wiki.getTiddler(title).fields.revision;
}
return this.wiki.getTiddler(title).fields.revision;
}
};
/*
@@ -267,9 +268,9 @@ Syncer.prototype.getStatus = function(callback) {
// Mark us as not logged in
this.wiki.addTiddler({title: this.titleIsLoggedIn,text: "no"});
// Get login status
this.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous) {
this.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous,isPollingDisabled) {
if(err) {
self.displayError("Get Status Error",err);
self.logger.alert(err);
} else {
// Set the various status tiddlers
self.wiki.addTiddler({title: self.titleIsReadOnly,text: isReadOnly ? "yes" : "no"});
@@ -278,6 +279,9 @@ Syncer.prototype.getStatus = function(callback) {
if(isLoggedIn) {
self.wiki.addTiddler({title: self.titleUserName,text: username || ""});
}
if(isPollingDisabled) {
self.wiki.addTiddler({title: self.titleSyncDisablePolling, text: "yes"});
}
}
// Invoke the callback
if(callback) {
@@ -301,12 +305,15 @@ Syncer.prototype.syncFromServer = function() {
}
},
triggerNextSync = function() {
self.pollTimerId = setTimeout(function() {
self.pollTimerId = null;
self.syncFromServer.call(self);
},self.pollTimerInterval);
if(pollingEnabled) {
self.pollTimerId = setTimeout(function() {
self.pollTimerId = null;
self.syncFromServer.call(self);
},self.pollTimerInterval);
}
},
syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes" ? true : false);
syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes"),
pollingEnabled = (self.wiki.getTiddlerText(self.titleSyncDisablePolling) !== "yes");
if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {
this.logger.log("Retrieving updated tiddler list");
cancelNextSync();
@@ -329,7 +336,7 @@ Syncer.prototype.syncFromServer = function() {
});
if(updates.modifications.length > 0 || updates.deletions.length > 0) {
self.processTaskQueue();
}
}
}
});
} else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {
@@ -472,7 +479,7 @@ Syncer.prototype.handleLogoutEvent = function() {
if(this.syncadaptor.logout) {
this.syncadaptor.logout(function(err) {
if(err) {
self.displayError("Logout Error",err);
self.logger.alert(err);
} else {
self.getStatus();
}
@@ -509,7 +516,7 @@ Syncer.prototype.processTaskQueue = function() {
} else {
self.updateDirtyStatus();
// Process the next task
self.processTaskQueue.call(self);
self.processTaskQueue.call(self);
}
});
} else {
@@ -517,11 +524,11 @@ Syncer.prototype.processTaskQueue = function() {
this.updateDirtyStatus();
// And trigger a timeout if there is a pending task
if(task === true) {
this.triggerTimeout();
this.triggerTimeout();
}
}
} else {
this.updateDirtyStatus();
this.updateDirtyStatus();
}
};
@@ -555,7 +562,7 @@ Syncer.prototype.chooseNextTask = function() {
isReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;
if(hasChanged) {
if(isReadyToSave) {
return new SaveTiddlerTask(this,title);
return new SaveTiddlerTask(this,title);
} else {
havePending = true;
}
@@ -594,7 +601,10 @@ SaveTiddlerTask.prototype.run = function(callback) {
tiddler = this.syncer.wiki.tiddlerExists(this.title) && this.syncer.wiki.getTiddler(this.title);
this.syncer.logger.log("Dispatching 'save' task:",this.title);
if(tiddler) {
this.syncer.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {
this.syncer.syncadaptor.saveTiddler(tiddler,{
changeCount: changeCount,
tiddlerInfo: self.syncer.tiddlerInfo[self.title]
},function(err,adaptorInfo,revision) {
// If there's an error, exit without changing any internal state
if(err) {
return callback(err);
@@ -608,8 +618,6 @@ SaveTiddlerTask.prototype.run = function(callback) {
};
// Invoke the callback
callback(null);
},{
tiddlerInfo: self.syncer.tiddlerInfo[self.title]
});
} else {
this.syncer.logger.log(" Not Dispatching 'save' task:",this.title,"tiddler does not exist");
@@ -626,7 +634,9 @@ function DeleteTiddlerTask(syncer,title) {
DeleteTiddlerTask.prototype.run = function(callback) {
var self = this;
this.syncer.logger.log("Dispatching 'delete' task:",this.title);
this.syncer.syncadaptor.deleteTiddler(this.title,function(err) {
this.syncer.syncadaptor.deleteTiddler(this.title,{
tiddlerInfo: self.syncer.tiddlerInfo[this.title]
},function(err,adaptorInfo) {
// If there's an error, exit without changing any internal state
if(err) {
return callback(err);
@@ -635,8 +645,6 @@ DeleteTiddlerTask.prototype.run = function(callback) {
delete self.syncer.tiddlerInfo[self.title];
// Invoke the callback
callback(null);
},{
tiddlerInfo: self.syncer.tiddlerInfo[this.title]
});
};

View File

@@ -24,13 +24,13 @@ exports.isDraft = function() {
return this.hasField("draft.of");
};
exports.getFieldString = function(field,defaultValue) {
exports.getFieldString = function(field) {
var value = this.fields[field];
// Check for a missing field
if(value === undefined || value === null) {
return defaultValue || "";
return "";
}
// Stringify the field with the associated tiddler field module (if any)
// Parse the field with the associated module (if any)
var fieldModule = $tw.Tiddler.fieldModules[field];
if(fieldModule && fieldModule.stringify) {
return fieldModule.stringify.call(this,value);

View File

@@ -41,7 +41,7 @@ exports.upgrade = function(wiki,titles,tiddlers) {
// Check if we're dealing with a plugin
if(incomingTiddler && incomingTiddler["plugin-type"]) {
// Check whether the plugin contains JS modules
var requiresReload = wiki.doesPluginInfoRequireReload($tw.utils.parseJSONSafe(incomingTiddler.text)) ? (wiki.getTiddlerText("$:/language/ControlPanel/Plugins/PluginWillRequireReload") + " ") : "";
var requiresReload = wiki.doesPluginInfoRequireReload(JSON.parse(incomingTiddler.text)) ? (wiki.getTiddlerText("$:/language/ControlPanel/Plugins/PluginWillRequireReload") + " ") : "";
messages[title] = requiresReload;
if(incomingTiddler.version) {
// Upgrade the incoming plugin if it is in the upgrade library

View File

@@ -21,7 +21,7 @@ exports.extractEncryptedStoreArea = function(text) {
if(encryptedStoreAreaStart !== -1) {
var encryptedStoreAreaEnd = text.indexOf("</pre>",encryptedStoreAreaStart);
if(encryptedStoreAreaEnd !== -1) {
return $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd));
return $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1));
}
}
return null;
@@ -33,7 +33,7 @@ Attempt to extract the tiddlers from an encrypted store area using the current p
exports.decryptStoreArea = function(encryptedStoreArea,password) {
var decryptedText = $tw.crypto.decrypt(encryptedStoreArea,password);
if(decryptedText) {
var json = $tw.utils.parseJSONSafe(decryptedText),
var json = JSON.parse(decryptedText),
tiddlers = [];
for(var title in json) {
if(title !== "$:/isEncrypted") {

View File

@@ -16,23 +16,21 @@ Browser data transfer utilities, used with the clipboard and drag and drop
Options:
domNode: dom node to make draggable
selector: CSS selector to identify element within domNode to be used as drag handle (optional)
dragImageType: "pill", "blank" or "dom" (the default)
dragImageType: "pill" or "dom"
dragTiddlerFn: optional function to retrieve the title of tiddler to drag
dragFilterFn: optional function to retreive the filter defining a list of tiddlers to drag
widget: widget to use as the context for the filter
widget: widget to use as the contect for the filter
*/
exports.makeDraggable = function(options) {
var dragImageType = options.dragImageType || "dom",
dragImage,
domNode = options.domNode,
dragHandle = options.selector && domNode.querySelector(options.selector) || domNode;
domNode = options.domNode;
// Make the dom node draggable (not necessary for anchor tags)
if((domNode.tagName || "").toLowerCase() !== "a") {
dragHandle.setAttribute("draggable","true");
domNode.setAttribute("draggable","true");
}
// Add event handlers
$tw.utils.addEventListeners(dragHandle,[
$tw.utils.addEventListeners(domNode,[
{name: "dragstart", handlerFunction: function(event) {
if(event.dataTransfer === undefined) {
return false;
@@ -47,7 +45,7 @@ exports.makeDraggable = function(options) {
}
var titleString = $tw.utils.stringifyList(titles);
// Check that we've something to drag
if(titles.length > 0 && event.target === dragHandle) {
if(titles.length > 0 && event.target === domNode) {
// Mark the drag in progress
$tw.dragInProgress = domNode;
// Set the dragging class on the element being dragged
@@ -75,9 +73,6 @@ exports.makeDraggable = function(options) {
if(dataTransfer.setDragImage) {
if(dragImageType === "pill") {
dataTransfer.setDragImage(dragImage.firstChild,-16,-16);
} else if (dragImageType === "blank") {
dragImage.removeChild(dragImage.firstChild);
dataTransfer.setDragImage(dragImage,0,0);
} else {
var r = domNode.getBoundingClientRect();
dataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);
@@ -169,7 +164,7 @@ var importDataTypes = [
}},
{type: "URL", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {
// Check for tiddler data URI
var match = $tw.utils.decodeURIComponentSafe(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
if(match) {
return parseJSONTiddlers(match[1],fallbackTitle);
} else {
@@ -178,7 +173,7 @@ var importDataTypes = [
}},
{type: "text/x-moz-url", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
// Check for tiddler data URI
var match = $tw.utils.decodeURIComponentSafe(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
if(match) {
return parseJSONTiddlers(match[1],fallbackTitle);
} else {
@@ -200,7 +195,7 @@ var importDataTypes = [
];
function parseJSONTiddlers(json,fallbackTitle) {
var data = $tw.utils.parseJSONSafe(json);
var data = JSON.parse(json);
if(!$tw.utils.isArray(data)) {
data = [data];
}
@@ -210,10 +205,10 @@ function parseJSONTiddlers(json,fallbackTitle) {
return data;
};
function dragEventContainsType(event,targetType) {
exports.dragEventContainsFiles = function(event) {
if(event.dataTransfer.types) {
for(var i=0; i<event.dataTransfer.types.length; i++) {
if(event.dataTransfer.types[i] === targetType) {
if(event.dataTransfer.types[i] === "Files") {
return true;
break;
}
@@ -222,10 +217,4 @@ function dragEventContainsType(event,targetType) {
return false;
};
exports.dragEventContainsFiles = function(event) {
return (dragEventContainsType(event,"Files") && !dragEventContainsType(event,"text/plain"));
};
exports.dragEventContainsType = dragEventContainsType;
})();

View File

@@ -34,23 +34,6 @@ exports.httpRequest = function(options) {
});
return result;
},
getHeader = function(targetHeader) {
return headers[targetHeader] || headers[targetHeader.toLowerCase()];
},
isSimpleRequest = function(type,headers) {
if(["GET","HEAD","POST"].indexOf(type) === -1) {
return false;
}
for(var header in headers) {
if(["accept","accept-language","content-language","content-type"].indexOf(header.toLowerCase()) === -1) {
return false;
}
}
if(hasHeader("Content-Type") && ["application/x-www-form-urlencoded","multipart/form-data","text/plain"].indexOf(getHeader["Content-Type"]) === -1) {
return false;
}
return true;
},
returnProp = options.returnProp || "responseText",
request = new XMLHttpRequest(),
data = "",
@@ -93,7 +76,7 @@ exports.httpRequest = function(options) {
if(data && !hasHeader("Content-Type")) {
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
}
if(!hasHeader("X-Requested-With") && !isSimpleRequest(type,headers)) {
if(!hasHeader("X-Requested-With")) {
request.setRequestHeader("X-Requested-With","TiddlyWiki");
}
try {

View File

@@ -243,7 +243,6 @@ Modal.prototype.adjustPageClass = function() {
if(windowContainer) {
$tw.utils.toggleClass(windowContainer,"tc-modal-displayed",this.modalCount > 0);
}
$tw.utils.toggleClass(this.srcDocument.body,"tc-modal-prevent-scroll",this.modalCount > 0);
};
exports.Modal = Modal;

View File

@@ -49,14 +49,10 @@ Handle an event
*/
PageScroller.prototype.handleEvent = function(event) {
if(event.type === "tm-scroll") {
var options = {};
if($tw.utils.hop(event.paramObject,"animationDuration")) {
options.animationDuration = event.paramObject.animationDuration;
}
if(event.paramObject && event.paramObject.selector) {
this.scrollSelectorIntoView(null,event.paramObject.selector,null,options);
this.scrollSelectorIntoView(null,event.paramObject.selector);
} else {
this.scrollIntoView(event.target,null,options);
this.scrollIntoView(event.target);
}
return false; // Event was handled
}
@@ -66,10 +62,10 @@ PageScroller.prototype.handleEvent = function(event) {
/*
Handle a scroll event hitting the page document
*/
PageScroller.prototype.scrollIntoView = function(element,callback,options) {
PageScroller.prototype.scrollIntoView = function(element,callback) {
var self = this,
duration = $tw.utils.hop(options,"animationDuration") ? parseInt(options.animationDuration) : $tw.utils.getAnimationDuration(),
srcWindow = element ? element.ownerDocument.defaultView : window;
duration = $tw.utils.getAnimationDuration(),
srcWindow = element ? element.ownerDocument.defaultView : window;
// Now get ready to scroll the body
this.cancelScroll(srcWindow);
this.startTime = Date.now();
@@ -126,11 +122,11 @@ PageScroller.prototype.scrollIntoView = function(element,callback,options) {
drawFrame();
};
PageScroller.prototype.scrollSelectorIntoView = function(baseElement,selector,callback,options) {
PageScroller.prototype.scrollSelectorIntoView = function(baseElement,selector,callback) {
baseElement = baseElement || document.body;
var element = baseElement.querySelector(selector);
if(element) {
this.scrollIntoView(element,callback,options);
this.scrollIntoView(element,callback);
}
};

View File

@@ -30,7 +30,11 @@ exports.getEditionInfo = function() {
var entry = entries[entryIndex];
// Check if directories have a valid tiddlywiki.info
if(!editionInfo[entry] && $tw.utils.isDirectory(path.resolve(editionPath,entry))) {
var info = $tw.utils.parseJSONSafe(fs.readFileSync(path.resolve(editionPath,entry,"tiddlywiki.info"),"utf8"),null);
var info;
try {
info = JSON.parse(fs.readFileSync(path.resolve(editionPath,entry,"tiddlywiki.info"),"utf8"));
} catch(ex) {
}
if(info) {
editionInfo[entry] = info;
}

View File

@@ -235,7 +235,7 @@ Object.defineProperty(TW_Element.prototype, "innerHTML", {
if(node instanceof TW_Element) {
b.push(node.outerHTML);
} else if(node instanceof TW_TextNode) {
b.push($tw.utils.htmlTextEncode(node.textContent));
b.push($tw.utils.htmlEncode(node.textContent));
}
});
return b.join("");

View File

@@ -228,7 +228,6 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
}
hasUnsafeFields = hasUnsafeFields || /:/mg.test(fieldName);
});
// Check for field values
if(hasUnsafeFields) {

View File

@@ -95,15 +95,6 @@ LinkedList.prototype.toArray = function() {
return output;
};
LinkedList.prototype.makeTiddlerIterator = function(wiki) {
var self = this;
return function(callback) {
self.each(function(title) {
callback(wiki.getTiddler(title),title);
});
};
};
function _removeOne(list,value) {
var prevEntry = list.prev[value],
nextEntry = list.next[value],

View File

@@ -24,8 +24,10 @@ exports.repackPlugin = function(title,additionalTiddlers,excludeTiddlers) {
throw "No such tiddler as " + title;
}
// Extract the JSON
var jsonPluginTiddler = $tw.utils.parseJSONSafe(pluginTiddler.fields.text,null);
if(!jsonPluginTiddler) {
var jsonPluginTiddler;
try {
jsonPluginTiddler = JSON.parse(pluginTiddler.fields.text);
} catch(e) {
throw "Cannot parse plugin tiddler " + title + "\n" + $tw.language.getString("Error/Caption") + ": " + e;
}
// Get the list of tiddlers

View File

@@ -199,8 +199,6 @@ exports.transliterationPairs = {
"Nj":"N",
"Ñ":"N",
"NJ":"NJ",
"ð":"d",
"Ð":"D",
"Ó":"O",
"Ŏ":"O",
"Ǒ":"O",
@@ -267,8 +265,6 @@ exports.transliterationPairs = {
"Ɽ":"R",
"Ꜿ":"C",
"Ǝ":"E",
"ß":"ss",
"ẞ":"SS",
"Ś":"S",
"Ṥ":"S",
"Š":"S",
@@ -279,8 +275,6 @@ exports.transliterationPairs = {
"Ṡ":"S",
"Ṣ":"S",
"Ṩ":"S",
"þ": "th",
"Þ": "TH",
"Ť":"T",
"Ţ":"T",
"Ṱ":"T",
@@ -913,8 +907,7 @@ exports.transliterationPairs = {
"т":"t",
"ь":"'",
"б":"b",
"ю":"yu",
"…":"..."
"ю":"yu"
};
exports.transliterate = function(str) {

View File

@@ -223,7 +223,6 @@ exports.removeArrayEntries = function(array,value) {
array.splice(p,1);
}
}
return array;
};
/*
@@ -383,15 +382,6 @@ exports.formatDateString = function(date,template) {
[/^0WW/, function() {
return $tw.utils.pad($tw.utils.getWeek(date));
}],
[/^0ddddd/, function() {
return $tw.utils.pad(Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24),3);
}],
[/^ddddd/, function() {
return Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
}],
[/^dddd/, function() {
return [7,1,2,3,4,5,6][date.getDay()];
}],
[/^ddd/, function() {
return $tw.language.getString("Date/Short/Day/" + date.getDay());
}],
@@ -750,8 +740,9 @@ exports.isValidFieldName = function(name) {
if(!name || typeof name !== "string") {
return false;
}
// Since v5.2.x, there are no restrictions on characters in field names
return name;
name = name.toLowerCase().trim();
var fieldValidatorRegEx = /^[a-z0-9\-\._]+$/mg;
return fieldValidatorRegEx.test(name);
};
/*

View File

@@ -58,10 +58,9 @@ Invoke the action associated with this widget
*/
ConfirmWidget.prototype.invokeAction = function(triggeringWidget,event) {
var invokeActions = true,
handled = true,
win = event && event.event && event.event.view ? event.event.view : window;
handled = true;
if(this.prompt) {
invokeActions = win.confirm(this.message);
invokeActions = confirm(this.message);
}
if(invokeActions) {
handled = this.invokeActions(triggeringWidget,event);
@@ -75,4 +74,4 @@ ConfirmWidget.prototype.allowActionPropagation = function() {
exports["action-confirm"] = ConfirmWidget;
})();
})();

View File

@@ -27,11 +27,8 @@ CreateTiddlerWidget.prototype = new Widget();
Render this widget into the DOM
*/
CreateTiddlerWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
// Render children
this.renderChildren(parent,nextSibling);
};
/*
@@ -47,8 +44,7 @@ CreateTiddlerWidget.prototype.execute = function() {
this.actionTemplate = this.getAttribute("$template");
this.useTemplate = !!this.actionTemplate;
this.actionOverwrite = this.getAttribute("$overwrite","no");
// Construct the child widgets
this.makeChildWidgets();
};
/*
@@ -90,21 +86,18 @@ CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
if (!this.hasBase && this.useTemplate) {
title = this.wiki.generateNewTitle(this.actionTemplate);
} else if (!this.hasBase && !this.useTemplate) {
// If no $basetitle and no $template then use initial title
// If NO $basetitle AND NO $template use initial title
// DON'T overwrite any stuff
title = this.wiki.generateNewTitle(title);
}
var templateTiddler = this.wiki.getTiddler(this.actionTemplate) || {};
this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));
var draftTitle = this.wiki.generateDraftTitle(title);
var tiddler = this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));
if(this.actionSaveTitle) {
this.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable("currentTiddler"));
}
if(this.actionSaveDraftTitle) {
this.wiki.setTextReference(this.actionSaveDraftTitle,draftTitle,this.getVariable("currentTiddler"));
this.wiki.setTextReference(this.actionSaveDraftTitle,this.wiki.generateDraftTitle(title),this.getVariable("currentTiddler"));
}
this.setVariable("createTiddler-title",title);
this.setVariable("createTiddler-draftTitle",draftTitle);
this.refreshChildren();
return true; // Action was invoked
};

View File

@@ -70,18 +70,7 @@ NavigateWidget.prototype.invokeAction = function(triggeringWidget,event) {
navigateFromNode: triggeringWidget,
navigateFromClientRect: bounds && { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height
},
navigateFromClientTop: bounds && bounds.top,
navigateFromClientLeft: bounds && bounds.left,
navigateFromClientWidth: bounds && bounds.width,
navigateFromClientRight: bounds && bounds.right,
navigateFromClientBottom: bounds && bounds.bottom,
navigateFromClientHeight: bounds && bounds.height,
navigateSuppressNavigation: suppressNavigation,
metaKey: event.metaKey,
ctrlKey: event.ctrlKey,
altKey: event.altKey,
shiftKey: event.shiftKey,
event: event
navigateSuppressNavigation: suppressNavigation
});
return true; // Action was invoked
};

View File

@@ -39,8 +39,6 @@ SendMessageWidget.prototype.execute = function() {
this.actionParam = this.getAttribute("$param");
this.actionName = this.getAttribute("$name");
this.actionValue = this.getAttribute("$value","");
this.actionNames = this.getAttribute("$names");
this.actionValues = this.getAttribute("$values");
};
/*
@@ -61,20 +59,13 @@ Invoke the action associated with this widget
SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
// Get the string parameter
var param = this.actionParam;
// Assemble the parameters as a hashmap
// Assemble the attributes as a hashmap
var paramObject = Object.create(null);
// Add names/values pairs if present
if(this.actionNames && this.actionValues) {
var names = this.wiki.filterTiddlers(this.actionNames,this),
values = this.wiki.filterTiddlers(this.actionValues,this);
$tw.utils.each(names,function(name,index) {
paramObject[name] = values[index] || "";
});
}
// Add raw parameters
var count = 0;
$tw.utils.each(this.attributes,function(attribute,name) {
if(name.charAt(0) !== "$") {
paramObject[name] = attribute;
count++;
}
});
// Add name/value pair if present
@@ -82,15 +73,14 @@ SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
paramObject[this.actionName] = this.actionValue;
}
// Dispatch the message
var params = {
this.dispatchEvent({
type: this.actionMessage,
param: param,
paramObject: paramObject,
event: event,
tiddlerTitle: this.getVariable("currentTiddler"),
navigateFromTitle: this.getVariable("storyTiddler")
};
this.dispatchEvent(params);
navigateFromTitle: this.getVariable("storyTiddler"),
event: event
});
return true; // Action was invoked
};

View File

@@ -1,86 +0,0 @@
/*\
title: $:/core/modules/widgets/action-setmultiplefields.js
type: application/javascript
module-type: widget
Action widget to set multiple fields or indexes on a tiddler
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var SetMultipleFieldsWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
SetMultipleFieldsWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
SetMultipleFieldsWidget.prototype.render = function(parent,nextSibling) {
this.computeAttributes();
this.execute();
};
/*
Compute the internal state of the widget
*/
SetMultipleFieldsWidget.prototype.execute = function() {
this.actionTiddler = this.getAttribute("$tiddler",this.getVariable("currentTiddler"));
this.actionFields = this.getAttribute("$fields");
this.actionIndexes = this.getAttribute("$indexes");
this.actionValues = this.getAttribute("$values");
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
};
/*
Refresh the widget by ensuring our attributes are up to date
*/
SetMultipleFieldsWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["$tiddler"] || changedAttributes["$fields"] || changedAttributes["$indexes"] || changedAttributes["$values"] || changedAttributes["$timestamp"]) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
/*
Invoke the action associated with this widget
*/
SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event) {
var tiddler = this.wiki.getTiddler(this.actionTiddler),
names, values = this.wiki.filterTiddlers(this.actionValues,this);
if(this.actionFields) {
var additions = {};
names = this.wiki.filterTiddlers(this.actionFields,this);
$tw.utils.each(names,function(fieldname,index) {
additions[fieldname] = values[index] || "";
});
var creationFields = this.actionTimestamp ? this.wiki.getCreationFields() : undefined,
modificationFields = this.actionTimestamp ? this.wiki.getModificationFields() : undefined;
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,{title: this.actionTiddler},modificationFields,additions));
} else if(this.actionIndexes) {
var data = this.wiki.getTiddlerData(this.actionTiddler,Object.create(null));
names = this.wiki.filterTiddlers(this.actionIndexes,this);
$tw.utils.each(names,function(name,index) {
data[name] = values[index] || "";
});
this.wiki.setTiddlerData(this.actionTiddler,data,{},{suppressTimestamp: !this.actionTimestamp});
}
return true; // Action was invoked
};
exports["action-setmultiplefields"] = SetMultipleFieldsWidget;
})();

Some files were not shown because too many files have changed in this diff Show More