mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-01-11 18:00:26 +00:00
Merge remote-tracking branch 'origin/master' into parser-ranges
This commit is contained in:
commit
79f5e6b498
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -23,6 +23,11 @@ A clear and concise description of what you expected to happen.
|
|||||||
**Screenshots**
|
**Screenshots**
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**TiddlyWiki Configuration (please complete the following information):**
|
||||||
|
- Version [e.g. v5.1.24]
|
||||||
|
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
|
||||||
|
- Plugins installed [e.g. Freelinks, TiddlyMap]
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**Desktop (please complete the following information):**
|
||||||
- OS: [e.g. iOS]
|
- OS: [e.g. iOS]
|
||||||
- Browser [e.g. chrome, safari]
|
- Browser [e.g. chrome, safari]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# Default to the current version number for building the plugin library
|
# Default to the current version number for building the plugin library
|
||||||
|
|
||||||
if [ -z "$TW5_BUILD_VERSION" ]; then
|
if [ -z "$TW5_BUILD_VERSION" ]; then
|
||||||
TW5_BUILD_VERSION=v5.1.23
|
TW5_BUILD_VERSION=v5.1.24
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
||||||
@ -107,7 +107,7 @@ node $TW5_BUILD_TIDDLYWIKI \
|
|||||||
# /empty.html Empty
|
# /empty.html Empty
|
||||||
# /empty.hta For Internet Explorer
|
# /empty.hta For Internet Explorer
|
||||||
node $TW5_BUILD_TIDDLYWIKI \
|
node $TW5_BUILD_TIDDLYWIKI \
|
||||||
./editions/empty \
|
$TW5_BUILD_MAIN_EDITION \
|
||||||
--verbose \
|
--verbose \
|
||||||
--output $TW5_BUILD_OUTPUT \
|
--output $TW5_BUILD_OUTPUT \
|
||||||
--build empty \
|
--build empty \
|
||||||
|
@ -5,52 +5,52 @@ Optimise the SVGs in ./core/images using SVGO from https://github.com/svg/svgo
|
|||||||
|
|
||||||
Install SVGO with the following command in the root of the repo:
|
Install SVGO with the following command in the root of the repo:
|
||||||
|
|
||||||
npm install svgo
|
npm install svgo@2.3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var fs = require("fs"),
|
var fs = require("fs"),
|
||||||
path = require("path"),
|
path = require("path"),
|
||||||
SVGO = require("svgo"),
|
{ optimize } = require("svgo"),
|
||||||
svgo = new SVGO({
|
config = {
|
||||||
plugins: [
|
plugins: [
|
||||||
{cleanupAttrs: true},
|
'cleanupAttrs',
|
||||||
{removeDoctype: true},
|
'removeDoctype',
|
||||||
{removeXMLProcInst: true},
|
'removeXMLProcInst',
|
||||||
{removeComments: true},
|
'removeComments',
|
||||||
{removeMetadata: true},
|
'removeMetadata',
|
||||||
{removeTitle: true},
|
'removeTitle',
|
||||||
{removeDesc: true},
|
'removeDesc',
|
||||||
{removeUselessDefs: true},
|
'removeUselessDefs',
|
||||||
{removeEditorsNSData: true},
|
'removeEditorsNSData',
|
||||||
{removeEmptyAttrs: true},
|
'removeEmptyAttrs',
|
||||||
{removeHiddenElems: true},
|
'removeHiddenElems',
|
||||||
{removeEmptyText: true},
|
'removeEmptyText',
|
||||||
{removeEmptyContainers: true},
|
'removeEmptyContainers',
|
||||||
{removeViewBox: false},
|
// 'removeViewBox',
|
||||||
{cleanupEnableBackground: true},
|
'cleanupEnableBackground',
|
||||||
{convertStyleToAttrs: true},
|
'convertStyleToAttrs',
|
||||||
{convertColors: true},
|
'convertColors',
|
||||||
{convertPathData: true},
|
'convertPathData',
|
||||||
{convertTransform: true},
|
'convertTransform',
|
||||||
{removeUnknownsAndDefaults: true},
|
'removeUnknownsAndDefaults',
|
||||||
{removeNonInheritableGroupAttrs: true},
|
'removeNonInheritableGroupAttrs',
|
||||||
{removeUselessStrokeAndFill: true},
|
'removeUselessStrokeAndFill',
|
||||||
{removeUnusedNS: true},
|
'removeUnusedNS',
|
||||||
{cleanupIDs: true},
|
'cleanupIDs',
|
||||||
{cleanupNumericValues: true},
|
'cleanupNumericValues',
|
||||||
{moveElemsAttrsToGroup: true},
|
'moveElemsAttrsToGroup',
|
||||||
{moveGroupAttrsToElems: true},
|
'moveGroupAttrsToElems',
|
||||||
{collapseGroups: true},
|
'collapseGroups',
|
||||||
{removeRasterImages: false},
|
// 'removeRasterImages',
|
||||||
{mergePaths: true},
|
'mergePaths',
|
||||||
{convertShapeToPath: true},
|
'convertShapeToPath',
|
||||||
{sortAttrs: true},
|
'sortAttrs',
|
||||||
{removeDimensions: false},
|
//'removeDimensions',
|
||||||
{removeAttrs: {attrs: "(stroke|fill)"}}
|
{name: 'removeAttrs', params: { attrs: '(stroke|fill)' } }
|
||||||
]
|
]
|
||||||
});
|
};
|
||||||
|
|
||||||
var basepath = "./core/images/",
|
var basepath = "./core/images/",
|
||||||
files = fs.readdirSync(basepath).sort();
|
files = fs.readdirSync(basepath).sort();
|
||||||
@ -66,12 +66,14 @@ files.forEach(function(filename) {
|
|||||||
fakeSVG = body.join("\n");
|
fakeSVG = body.join("\n");
|
||||||
// A hack to make the new-journal-button work
|
// A hack to make the new-journal-button work
|
||||||
fakeSVG = fakeSVG.replace("<<now \"DD\">>","<<now "DD">>");
|
fakeSVG = fakeSVG.replace("<<now \"DD\">>","<<now "DD">>");
|
||||||
svgo.optimize(fakeSVG, {path: filepath}).then(function(result) {
|
config.path = filepath;
|
||||||
|
var result = optimize(fakeSVG,config);
|
||||||
|
if(result) {
|
||||||
var newSVG = header.join("\n") + "\n\n" + result.data.replace("<<now "DD">>","<<now \"DD\">>");
|
var newSVG = header.join("\n") + "\n\n" + result.data.replace("<<now "DD">>","<<now \"DD\">>");
|
||||||
fs.writeFileSync(filepath,newSVG);
|
fs.writeFileSync(filepath,newSVG);
|
||||||
},function(err) {
|
} else {
|
||||||
console.log("Error " + err + " with " + filename)
|
console.log("Error " + err + " with " + filename)
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
124
boot/boot.js
124
boot/boot.js
@ -267,8 +267,16 @@ $tw.utils.htmlDecode = function(s) {
|
|||||||
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
|
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
|
||||||
*/
|
*/
|
||||||
$tw.utils.getLocationHash = function() {
|
$tw.utils.getLocationHash = function() {
|
||||||
var parts = window.location.href.split('#');
|
var href = window.location.href;
|
||||||
return "#" + (parts.length > 1 ? parts[1] : "");
|
var idx = href.indexOf('#');
|
||||||
|
if(idx === -1) {
|
||||||
|
return "#";
|
||||||
|
} else if(idx < href.length-1 && href[idx+1] === '#') {
|
||||||
|
// Special case: ignore location hash if it itself starts with a #
|
||||||
|
return "#";
|
||||||
|
} else {
|
||||||
|
return href.substring(idx);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -297,13 +305,21 @@ $tw.utils.stringifyDate = function(value) {
|
|||||||
// Parse a date from a UTC YYYYMMDDHHMMSSmmm format string
|
// Parse a date from a UTC YYYYMMDDHHMMSSmmm format string
|
||||||
$tw.utils.parseDate = function(value) {
|
$tw.utils.parseDate = function(value) {
|
||||||
if(typeof value === "string") {
|
if(typeof value === "string") {
|
||||||
return new Date(Date.UTC(parseInt(value.substr(0,4),10),
|
var negative = 1;
|
||||||
|
if(value.charAt(0) === "-") {
|
||||||
|
negative = -1;
|
||||||
|
value = value.substr(1);
|
||||||
|
}
|
||||||
|
var year = parseInt(value.substr(0,4),10) * negative,
|
||||||
|
d = new Date(Date.UTC(year,
|
||||||
parseInt(value.substr(4,2),10)-1,
|
parseInt(value.substr(4,2),10)-1,
|
||||||
parseInt(value.substr(6,2),10),
|
parseInt(value.substr(6,2),10),
|
||||||
parseInt(value.substr(8,2)||"00",10),
|
parseInt(value.substr(8,2)||"00",10),
|
||||||
parseInt(value.substr(10,2)||"00",10),
|
parseInt(value.substr(10,2)||"00",10),
|
||||||
parseInt(value.substr(12,2)||"00",10),
|
parseInt(value.substr(12,2)||"00",10),
|
||||||
parseInt(value.substr(14,3)||"000",10)));
|
parseInt(value.substr(14,3)||"000",10)));
|
||||||
|
d.setUTCFullYear(year); // See https://stackoverflow.com/a/5870822
|
||||||
|
return d;
|
||||||
} else if($tw.utils.isDate(value)) {
|
} else if($tw.utils.isDate(value)) {
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
@ -876,6 +892,19 @@ $tw.modules.applyMethods = function(moduleType,targetObject) {
|
|||||||
return targetObject;
|
return targetObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return a class created from a modules. The module should export the properties to be added to those of the optional base class
|
||||||
|
*/
|
||||||
|
$tw.modules.createClassFromModule = function(moduleExports,baseClass) {
|
||||||
|
var newClass = function() {};
|
||||||
|
if(baseClass) {
|
||||||
|
newClass.prototype = new baseClass();
|
||||||
|
newClass.prototype.constructor = baseClass;
|
||||||
|
}
|
||||||
|
$tw.utils.extend(newClass.prototype,moduleExports);
|
||||||
|
return newClass;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return an array of classes created from the modules of a specified type. Each module should export the properties to be added to those of the optional base class
|
Return an array of classes created from the modules of a specified type. Each module should export the properties to be added to those of the optional base class
|
||||||
*/
|
*/
|
||||||
@ -883,13 +912,7 @@ $tw.modules.createClassesFromModules = function(moduleType,subType,baseClass) {
|
|||||||
var classes = Object.create(null);
|
var classes = Object.create(null);
|
||||||
$tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) {
|
$tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) {
|
||||||
if(!subType || moduleExports.types[subType]) {
|
if(!subType || moduleExports.types[subType]) {
|
||||||
var newClass = function() {};
|
classes[moduleExports.name] = $tw.modules.createClassFromModule(moduleExports,baseClass);
|
||||||
if(baseClass) {
|
|
||||||
newClass.prototype = new baseClass();
|
|
||||||
newClass.prototype.constructor = baseClass;
|
|
||||||
}
|
|
||||||
$tw.utils.extend(newClass.prototype,moduleExports);
|
|
||||||
classes[moduleExports.name] = newClass;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return classes;
|
return classes;
|
||||||
@ -1878,7 +1901,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
if(isEditableFile) {
|
if(isEditableFile) {
|
||||||
tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, tiddlers: fileTiddlers});
|
tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, isEditableFile: true, tiddlers: fileTiddlers});
|
||||||
} else {
|
} else {
|
||||||
tiddlers.push({tiddlers: fileTiddlers});
|
tiddlers.push({tiddlers: fileTiddlers});
|
||||||
}
|
}
|
||||||
@ -1904,15 +1927,21 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Process directory specifier
|
// Process directory specifier
|
||||||
var dirPath = path.resolve(filepath,dirSpec.path),
|
var dirPath = path.resolve(filepath,dirSpec.path);
|
||||||
files = fs.readdirSync(dirPath),
|
if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
|
||||||
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
|
var files = fs.readdirSync(dirPath),
|
||||||
metaRegExp = /^.*\.meta$/;
|
fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"),
|
||||||
for(var t=0; t<files.length; t++) {
|
metaRegExp = /^.*\.meta$/;
|
||||||
var filename = files[t];
|
for(var t=0; t<files.length; t++) {
|
||||||
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
|
var filename = files[t];
|
||||||
processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
|
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
|
||||||
|
processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Warning: a directory in a tiddlywiki.files file does not exist.");
|
||||||
|
console.log("dirPath: " + dirPath);
|
||||||
|
console.log("tiddlywiki.files location: " + filepath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -2052,6 +2081,11 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
|
|||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// Save the path to the tiddlers folder for the filesystemadaptor
|
||||||
|
var config = wikiInfo.config || {};
|
||||||
|
if($tw.boot.wikiPath == wikiPath) {
|
||||||
|
$tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir);
|
||||||
|
}
|
||||||
// Load any parent wikis
|
// Load any parent wikis
|
||||||
if(wikiInfo.includeWikis) {
|
if(wikiInfo.includeWikis) {
|
||||||
parentPaths = parentPaths.slice(0);
|
parentPaths = parentPaths.slice(0);
|
||||||
@ -2085,27 +2119,31 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
|
|||||||
$tw.boot.files[tiddler.title] = {
|
$tw.boot.files[tiddler.title] = {
|
||||||
filepath: tiddlerFile.filepath,
|
filepath: tiddlerFile.filepath,
|
||||||
type: tiddlerFile.type,
|
type: tiddlerFile.type,
|
||||||
hasMetaFile: tiddlerFile.hasMetaFile
|
hasMetaFile: tiddlerFile.hasMetaFile,
|
||||||
|
isEditableFile: config["retain-original-tiddler-path"] || tiddlerFile.isEditableFile || tiddlerFile.filepath.indexOf($tw.boot.wikiTiddlersPath) !== 0
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
|
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
|
||||||
});
|
});
|
||||||
// Save the original tiddler file locations if requested
|
if ($tw.boot.wikiPath == wikiPath) {
|
||||||
var config = wikiInfo.config || {};
|
// Save the original tiddler file locations if requested
|
||||||
if(config["retain-original-tiddler-path"]) {
|
var output = {}, relativePath, fileInfo;
|
||||||
var output = {}, relativePath;
|
|
||||||
for(var title in $tw.boot.files) {
|
for(var title in $tw.boot.files) {
|
||||||
relativePath = path.relative(resolvedWikiPath,$tw.boot.files[title].filepath);
|
fileInfo = $tw.boot.files[title];
|
||||||
output[title] =
|
if(fileInfo.isEditableFile) {
|
||||||
path.sep === "/" ?
|
relativePath = path.relative($tw.boot.wikiTiddlersPath,fileInfo.filepath);
|
||||||
relativePath :
|
fileInfo.originalpath = relativePath;
|
||||||
relativePath.split(path.sep).join("/");
|
output[title] =
|
||||||
|
path.sep === "/" ?
|
||||||
|
relativePath :
|
||||||
|
relativePath.split(path.sep).join("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Object.keys(output).length > 0){
|
||||||
|
$tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)});
|
||||||
}
|
}
|
||||||
$tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)});
|
|
||||||
}
|
}
|
||||||
// Save the path to the tiddlers folder for the filesystemadaptor
|
|
||||||
$tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir);
|
|
||||||
// Load any plugins within the wiki folder
|
// Load any plugins within the wiki folder
|
||||||
var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir);
|
var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir);
|
||||||
if(fs.existsSync(wikiPluginsPath)) {
|
if(fs.existsSync(wikiPluginsPath)) {
|
||||||
@ -2152,7 +2190,7 @@ $tw.loadTiddlersNode = function() {
|
|||||||
// Load any extra plugins
|
// Load any extra plugins
|
||||||
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
$tw.utils.each($tw.boot.extraPlugins,function(name) {
|
||||||
if(name.charAt(0) === "+") { // Relative path to plugin
|
if(name.charAt(0) === "+") { // Relative path to plugin
|
||||||
var pluginFields = $tw.loadPluginFolder(name.substring(1));;
|
var pluginFields = $tw.loadPluginFolder(name.substring(1));
|
||||||
if(pluginFields) {
|
if(pluginFields) {
|
||||||
$tw.wiki.addTiddler(pluginFields);
|
$tw.wiki.addTiddler(pluginFields);
|
||||||
}
|
}
|
||||||
@ -2271,6 +2309,7 @@ $tw.boot.initStartup = function(options) {
|
|||||||
$tw.utils.registerFileType("image/heic","base64",".heic",{flags:["image"]});
|
$tw.utils.registerFileType("image/heic","base64",".heic",{flags:["image"]});
|
||||||
$tw.utils.registerFileType("image/heif","base64",".heif",{flags:["image"]});
|
$tw.utils.registerFileType("image/heif","base64",".heif",{flags:["image"]});
|
||||||
$tw.utils.registerFileType("image/svg+xml","utf8",".svg",{flags:["image"]});
|
$tw.utils.registerFileType("image/svg+xml","utf8",".svg",{flags:["image"]});
|
||||||
|
$tw.utils.registerFileType("image/vnd.microsoft.icon","base64",".ico",{flags:["image"]});
|
||||||
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
|
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
|
||||||
$tw.utils.registerFileType("application/font-woff","base64",".woff");
|
$tw.utils.registerFileType("application/font-woff","base64",".woff");
|
||||||
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
|
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
|
||||||
@ -2428,16 +2467,29 @@ $tw.boot.executeNextStartupTask = function(callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns true if we are running on one platforms specified in a task modules `platforms` array
|
Returns true if we are running on one of the platforms specified in taskModule's
|
||||||
|
`platforms` array; or if `platforms` property is not defined.
|
||||||
*/
|
*/
|
||||||
$tw.boot.doesTaskMatchPlatform = function(taskModule) {
|
$tw.boot.doesTaskMatchPlatform = function(taskModule) {
|
||||||
var platforms = taskModule.platforms;
|
var platforms = taskModule.platforms;
|
||||||
if(platforms) {
|
if(platforms) {
|
||||||
for(var t=0; t<platforms.length; t++) {
|
for(var t=0; t<platforms.length; t++) {
|
||||||
if((platforms[t] === "browser" && !$tw.browser) || (platforms[t] === "node" && !$tw.node)) {
|
switch (platforms[t]) {
|
||||||
return false;
|
case "browser":
|
||||||
|
if ($tw.browser) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "node":
|
||||||
|
if ($tw.node) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$tw.utils.error("Module " + taskModule.name + ": '" + platforms[t] + "' in export.platforms invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@ type: text/plain
|
|||||||
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
|
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
|
||||||
|
|
||||||
Copyright (c) 2004-2007, Jeremy Ruston
|
Copyright (c) 2004-2007, Jeremy Ruston
|
||||||
Copyright (c) 2007-2020, UnaMesa Association
|
Copyright (c) 2007-2021, UnaMesa Association
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
4
core/images/minus-button.tid
Normal file
4
core/images/minus-button.tid
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
title: $:/core/images/minus-button
|
||||||
|
tags: $:/tags/Image
|
||||||
|
|
||||||
|
<svg width="22pt" height="22pt" class="tc-image-minus-button tc-image-button" viewBox="0 0 128 128"><path d="M64 0c35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64C0 28.654 28.654 0 64 0zm.332 16c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"/><rect width="80" height="16" x="24" y="56" rx="8"/></svg>
|
@ -1,4 +1,4 @@
|
|||||||
title: $:/core/images/plugin-generic-language
|
title: $:/core/images/plugin-generic-language
|
||||||
tags: $:/tags/Image
|
tags: $:/tags/Image
|
||||||
|
|
||||||
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M61.207 68.137c-4.324 2.795-6.999 6.656-6.999 10.921 0 7.906 9.19 14.424 21.042 15.336 2.162 3.902 8.598 6.785 16.318 7.01-5.126-1.125-9.117-3.742-10.62-7.01C92.805 93.487 102 86.967 102 79.059c0-8.53-10.699-15.445-23.896-15.445-6.599 0-12.572 1.729-16.897 4.524zm12.794-14.158c-4.324 2.795-10.298 4.524-16.897 4.524-2.619 0-5.14-.272-7.497-.775-3.312 2.25-8.383 3.69-14.067 3.69l-.255-.002c4.119-.892 7.511-2.747 9.478-5.13-6.925-2.704-11.555-7.617-11.555-13.228 0-8.53 10.699-15.445 23.896-15.445C70.301 27.613 81 34.528 81 43.058c0 4.265-2.675 8.126-6.999 10.921zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>
|
<svg width="22pt" height="22pt" viewBox="0 0 128 128" class="tc-image-plugin-generic-language tc-image-button"><path fill-rule="evenodd" d="M61.207 68.137c-4.324 2.795-6.999 6.656-6.999 10.921 0 7.906 9.19 14.424 21.042 15.336 2.162 3.902 8.598 6.785 16.318 7.01-5.126-1.125-9.117-3.742-10.62-7.01C92.805 93.487 102 86.967 102 79.059c0-8.53-10.699-15.445-23.896-15.445-6.599 0-12.572 1.729-16.897 4.524zm12.794-14.158c-4.324 2.795-10.298 4.524-16.897 4.524-2.619 0-5.14-.272-7.497-.775-3.312 2.25-8.383 3.69-14.067 3.69l-.255-.002c4.119-.892 7.511-2.747 9.478-5.13-6.925-2.704-11.555-7.617-11.555-13.228 0-8.53 10.699-15.445 23.896-15.445C70.301 27.613 81 34.528 81 43.058c0 4.265-2.675 8.126-6.999 10.921zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>
|
@ -1,4 +1,4 @@
|
|||||||
title: $:/core/images/plugin-generic-plugin
|
title: $:/core/images/plugin-generic-plugin
|
||||||
tags: $:/tags/Image
|
tags: $:/tags/Image
|
||||||
|
|
||||||
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M40.397 76.446V95.34h14.12l-.001-.005a6.912 6.912 0 005.364-11.593l.046-.023a6.912 6.912 0 119.979.526l.086.055a6.914 6.914 0 004.408 10.948l-.023.092h21.32V75.568l-.15.038a6.912 6.912 0 00-11.593-5.364l-.022-.046a6.912 6.912 0 11.526-9.979l.055-.086a6.914 6.914 0 0010.948-4.408c.079.018.158.038.236.059v-15.74h-21.32l.023-.094a6.914 6.914 0 01-4.408-10.947 10.23 10.23 0 00-.086-.055 6.912 6.912 0 10-9.979-.526l-.046.023a6.912 6.912 0 01-5.364 11.593l.001.005h-14.12v12.847A6.912 6.912 0 0129.5 59.843l-.054.086a6.912 6.912 0 10-.526 9.979l.023.046a6.912 6.912 0 0111.455 6.492zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>
|
<svg width="22pt" height="22pt" viewBox="0 0 128 128" class="tc-image-plugin-generic-plugin tc-image-button"><path fill-rule="evenodd" d="M40.397 76.446V95.34h14.12l-.001-.005a6.912 6.912 0 005.364-11.593l.046-.023a6.912 6.912 0 119.979.526l.086.055a6.914 6.914 0 004.408 10.948l-.023.092h21.32V75.568l-.15.038a6.912 6.912 0 00-11.593-5.364l-.022-.046a6.912 6.912 0 11.526-9.979l.055-.086a6.914 6.914 0 0010.948-4.408c.079.018.158.038.236.059v-15.74h-21.32l.023-.094a6.914 6.914 0 01-4.408-10.947 10.23 10.23 0 00-.086-.055 6.912 6.912 0 10-9.979-.526l-.046.023a6.912 6.912 0 01-5.364 11.593l.001.005h-14.12v12.847A6.912 6.912 0 0129.5 59.843l-.054.086a6.912 6.912 0 10-.526 9.979l.023.046a6.912 6.912 0 0111.455 6.492zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>
|
@ -1,4 +1,4 @@
|
|||||||
title: $:/core/images/plugin-generic-theme
|
title: $:/core/images/plugin-generic-theme
|
||||||
tags: $:/tags/Image
|
tags: $:/tags/Image
|
||||||
|
|
||||||
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M29.408 91.472L51.469 69.41l-.004-.005a2.22 2.22 0 01.004-3.146c.87-.87 2.281-.872 3.147-.005l9.465 9.464a2.22 2.22 0 01-.005 3.147c-.87.87-2.28.871-3.147.005l-.005-.005-22.061 22.062a6.686 6.686 0 11-9.455-9.455zM60.802 66.38c-2.436-2.704-4.465-5.091-5.817-6.869-6.855-9.014-10.313-4.268-14.226 0-3.913 4.268 1.03 7.726-2.683 10.741-3.713 3.015-3.484 4.06-9.752-1.455-6.267-5.516-6.7-7.034-3.823-10.181 2.877-3.147 5.281 1.808 11.159-3.785 5.877-5.593.94-10.55.94-10.55s12.237-25.014 28.588-23.167c16.351 1.848-6.186-2.392-11.792 17.226-2.4 8.4.447 6.42 4.998 9.968 1.394 1.086 6.03 4.401 11.794 8.685l20.677-20.676 1.615-4.766 7.84-4.689 3.151 3.152-4.688 7.84-4.766 1.615-20.224 20.223c12.663 9.547 28.312 22.146 28.312 26.709 0 7.217-3.071 11.526-9.535 9.164-4.693-1.715-18.768-15.192-28.753-25.897l-2.893 2.893-3.151-3.152 3.029-3.029zM63.953 0l54.56 32v64l-54.56 32-54.56-32V32l54.56-32z"/></svg>
|
<svg width="22pt" height="22pt" viewBox="0 0 128 128" class="tc-image-plugin-generic-theme tc-image-button"><path fill-rule="evenodd" d="M29.408 91.472L51.469 69.41l-.004-.005a2.22 2.22 0 01.004-3.146c.87-.87 2.281-.872 3.147-.005l9.465 9.464a2.22 2.22 0 01-.005 3.147c-.87.87-2.28.871-3.147.005l-.005-.005-22.061 22.062a6.686 6.686 0 11-9.455-9.455zM60.802 66.38c-2.436-2.704-4.465-5.091-5.817-6.869-6.855-9.014-10.313-4.268-14.226 0-3.913 4.268 1.03 7.726-2.683 10.741-3.713 3.015-3.484 4.06-9.752-1.455-6.267-5.516-6.7-7.034-3.823-10.181 2.877-3.147 5.281 1.808 11.159-3.785 5.877-5.593.94-10.55.94-10.55s12.237-25.014 28.588-23.167c16.351 1.848-6.186-2.392-11.792 17.226-2.4 8.4.447 6.42 4.998 9.968 1.394 1.086 6.03 4.401 11.794 8.685l20.677-20.676 1.615-4.766 7.84-4.689 3.151 3.152-4.688 7.84-4.766 1.615-20.224 20.223c12.663 9.547 28.312 22.146 28.312 26.709 0 7.217-3.071 11.526-9.535 9.164-4.693-1.715-18.768-15.192-28.753-25.897l-2.893 2.893-3.151-3.152 3.029-3.029zM63.953 0l54.56 32v64l-54.56 32-54.56-32V32l54.56-32z"/></svg>
|
4
core/images/plus-button.tid
Normal file
4
core/images/plus-button.tid
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
title: $:/core/images/plus-button
|
||||||
|
tags: $:/tags/Image
|
||||||
|
|
||||||
|
<svg width="22pt" height="22pt" class="tc-image-plus-button tc-image-button" viewBox="0 0 128 128"><path d="M64-.333c35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64zM64 16c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"/><rect width="80" height="16" x="24" y="56" rx="8"/><rect width="16" height="80" x="56" y="24" rx="8"/></svg>
|
@ -17,6 +17,8 @@ Basics/NewJournal/Tags/Prompt: Tags for new journal tiddlers
|
|||||||
Basics/NewTiddler/Title/Prompt: Title of new tiddlers
|
Basics/NewTiddler/Title/Prompt: Title of new tiddlers
|
||||||
Basics/NewTiddler/Tags/Prompt: Tags for new tiddlers
|
Basics/NewTiddler/Tags/Prompt: Tags for new tiddlers
|
||||||
Basics/OverriddenShadowTiddlers/Prompt: Number of overridden shadow tiddlers
|
Basics/OverriddenShadowTiddlers/Prompt: Number of overridden shadow tiddlers
|
||||||
|
Basics/RemoveTags: Update to current format
|
||||||
|
Basics/RemoveTags/Hint: Update the tags configuration to the latest format
|
||||||
Basics/ShadowTiddlers/Prompt: Number of shadow tiddlers
|
Basics/ShadowTiddlers/Prompt: Number of shadow tiddlers
|
||||||
Basics/Subtitle/Prompt: Subtitle
|
Basics/Subtitle/Prompt: Subtitle
|
||||||
Basics/SystemTiddlers/Prompt: Number of system tiddlers
|
Basics/SystemTiddlers/Prompt: Number of system tiddlers
|
||||||
@ -44,6 +46,7 @@ KeyboardShortcuts/Platform/Linux: Linux platform only
|
|||||||
KeyboardShortcuts/Platform/NonLinux: Non-Linux platforms only
|
KeyboardShortcuts/Platform/NonLinux: Non-Linux platforms only
|
||||||
KeyboardShortcuts/Platform/Windows: Windows platform only
|
KeyboardShortcuts/Platform/Windows: Windows platform only
|
||||||
KeyboardShortcuts/Platform/NonWindows: Non-Windows platforms only
|
KeyboardShortcuts/Platform/NonWindows: Non-Windows platforms only
|
||||||
|
LayoutSwitcher/Caption: Layout
|
||||||
LoadedModules/Caption: Loaded Modules
|
LoadedModules/Caption: Loaded Modules
|
||||||
LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
|
LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
|
||||||
Palette/Caption: Palette
|
Palette/Caption: Palette
|
||||||
@ -120,11 +123,12 @@ Saving/TiddlySpot/BackupDir: Backup Directory
|
|||||||
Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel
|
Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel
|
||||||
Saving/TiddlySpot/Backups: Backups
|
Saving/TiddlySpot/Backups: Backups
|
||||||
Saving/TiddlySpot/Caption: ~TiddlySpot Saver
|
Saving/TiddlySpot/Caption: ~TiddlySpot Saver
|
||||||
Saving/TiddlySpot/Description: These settings are only used when saving to http://tiddlyspot.com or a compatible remote server
|
Saving/TiddlySpot/Description: These settings are only used when saving to [[TiddlySpot|http://tiddlyspot.com]], [[TiddlyHost|https://tiddlyhost.com]], or a compatible remote server. See [[here|https://github.com/simonbaird/tiddlyhost/wiki/TiddlySpot-Saver-configuration-for-Tiddlyhost-and-Tiddlyspot]] for information on ~TiddlySpot and ~TiddlyHost saving configuration.
|
||||||
Saving/TiddlySpot/Filename: Upload Filename
|
Saving/TiddlySpot/Filename: Upload Filename
|
||||||
Saving/TiddlySpot/Heading: ~TiddlySpot
|
Saving/TiddlySpot/Heading: ~TiddlySpot
|
||||||
Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//
|
Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//
|
||||||
Saving/TiddlySpot/Password: Password
|
Saving/TiddlySpot/Password: Password
|
||||||
|
Saving/TiddlySpot/ReadOnly: Note that [[TiddlySpot|http://tiddlyspot.com]] no longer allows the creation of new sites. For new sites you can use [[TiddlyHost|https://tiddlyhost.com]], a new hosting service which replaces ~TiddlySpot.
|
||||||
Saving/TiddlySpot/ServerURL: Server URL
|
Saving/TiddlySpot/ServerURL: Server URL
|
||||||
Saving/TiddlySpot/UploadDir: Upload Directory
|
Saving/TiddlySpot/UploadDir: Upload Directory
|
||||||
Saving/TiddlySpot/UserName: Wiki Name
|
Saving/TiddlySpot/UserName: Wiki Name
|
||||||
|
@ -23,6 +23,7 @@ tiddlerfield: Defines the behaviour of an individual tiddler field.
|
|||||||
tiddlermethod: Adds methods to the `$tw.Tiddler` prototype.
|
tiddlermethod: Adds methods to the `$tw.Tiddler` prototype.
|
||||||
upgrader: Applies upgrade processing to tiddlers during an upgrade/import.
|
upgrader: Applies upgrade processing to tiddlers during an upgrade/import.
|
||||||
utils: Adds methods to `$tw.utils`.
|
utils: Adds methods to `$tw.utils`.
|
||||||
|
utils-browser: Adds browser-specific methods to `$tw.utils`.
|
||||||
utils-node: Adds Node.js-specific methods to `$tw.utils`.
|
utils-node: Adds Node.js-specific methods to `$tw.utils`.
|
||||||
widget: Widgets encapsulate DOM rendering and refreshing.
|
widget: Widgets encapsulate DOM rendering and refreshing.
|
||||||
wikimethod: Adds methods to `$tw.Wiki`.
|
wikimethod: Adds methods to `$tw.Wiki`.
|
||||||
|
@ -19,6 +19,8 @@ Shadow/OverriddenWarning: This is a modified shadow tiddler. You can revert to t
|
|||||||
Tags/Add/Button: add
|
Tags/Add/Button: add
|
||||||
Tags/Add/Button/Hint: add tag
|
Tags/Add/Button/Hint: add tag
|
||||||
Tags/Add/Placeholder: tag name
|
Tags/Add/Placeholder: tag name
|
||||||
|
Tags/ClearInput/Caption: clear input
|
||||||
|
Tags/ClearInput/Hint: Clear tag input
|
||||||
Tags/Dropdown/Caption: tag list
|
Tags/Dropdown/Caption: tag list
|
||||||
Tags/Dropdown/Hint: Show tag list
|
Tags/Dropdown/Hint: Show tag list
|
||||||
Title/BadCharacterWarning: Warning: avoid using any of the characters <<bad-chars>> in tiddler titles
|
Title/BadCharacterWarning: Warning: avoid using any of the characters <<bad-chars>> in tiddler titles
|
||||||
|
@ -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
|
* ''readers'' - comma separated list of principals allowed to read from this wiki
|
||||||
* ''writers'' - comma separated list of principals allowed to write to 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")
|
* ''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-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-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")
|
* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to "text/html")
|
||||||
|
@ -8,15 +8,15 @@ Optionally, the title of a template tiddler can be specified. In this case, inst
|
|||||||
A name and value for an additional variable may optionally also be specified.
|
A name and value for an additional variable may optionally also be specified.
|
||||||
|
|
||||||
```
|
```
|
||||||
--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [<name>] [<value>]
|
--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [ [<name>] [<value>] ]*
|
||||||
```
|
```
|
||||||
|
|
||||||
* ''tiddler-filter'': A filter identifying the tiddler(s) to be rendered
|
* ''tiddler-filter'': A filter identifying the tiddler(s) to be rendered
|
||||||
* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]addsuffix[.html]]`, which uses the unchanged tiddler title as the filename
|
* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]addsuffix[.html]]`, which uses the unchanged tiddler title as the filename
|
||||||
* ''render-type'': Optional render type: `text/html` (the default) returns the full HTML text and `text/plain` just returns the text content (ie it ignores HTML tags and other unprintable material)
|
* ''render-type'': Optional render type: `text/html` (the default) returns the full HTML text and `text/plain` just returns the text content (ie it ignores HTML tags and other unprintable material)
|
||||||
* ''template'': Optional template through which each tiddler is rendered
|
* ''template'': Optional template through which each tiddler is rendered
|
||||||
* ''name'': Name of optional variable
|
* ''name'': Name of optional variables
|
||||||
* ''value'': Value of optional variable
|
* ''value'': Value of optional variables
|
||||||
|
|
||||||
By default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.
|
By default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ Notes:
|
|||||||
* Any missing directories in the path to the filename are automatically created.
|
* Any missing directories in the path to the filename are automatically created.
|
||||||
* When referring to a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--render "[[Motovun Jack.jpg]]"`
|
* When referring to a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--render "[[Motovun Jack.jpg]]"`
|
||||||
* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being rendered, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`
|
* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being rendered, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`
|
||||||
|
* Multiple ''name''/''value'' pairs can be used to pass more than one variable
|
||||||
* The `--render` command is a more flexible replacement for both the `--rendertiddler` and `--rendertiddlers` commands, which are deprecated
|
* The `--render` command is a more flexible replacement for both the `--rendertiddler` and `--rendertiddlers` commands, which are deprecated
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
@ -13,11 +13,16 @@ Listing/Preview/TextRaw: Text (Raw)
|
|||||||
Listing/Preview/Fields: Fields
|
Listing/Preview/Fields: Fields
|
||||||
Listing/Preview/Diff: Diff
|
Listing/Preview/Diff: Diff
|
||||||
Listing/Preview/DiffFields: Diff (Fields)
|
Listing/Preview/DiffFields: Diff (Fields)
|
||||||
Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugin
|
Listing/Rename/Tooltip: Rename tiddler before importing
|
||||||
Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> being older than existing <<existing>>)
|
Listing/Rename/Prompt: Rename to:
|
||||||
Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>
|
Listing/Rename/ConfirmRename: Rename tiddler
|
||||||
Upgrader/State/Suppressed: Blocked temporary state tiddler
|
Listing/Rename/CancelRename: Cancel
|
||||||
Upgrader/System/Suppressed: Blocked system tiddler
|
Listing/Rename/OverwriteWarning: A tiddler with this title already exists.
|
||||||
Upgrader/System/Warning: Core module tiddler
|
Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugin.
|
||||||
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/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> not being newer than existing <<existing>>).
|
||||||
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>
|
Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>.
|
||||||
|
Upgrader/State/Suppressed: Blocked temporary state tiddler.
|
||||||
|
Upgrader/System/Suppressed: Blocked system tiddler.
|
||||||
|
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>>/>.
|
||||||
|
@ -10,6 +10,7 @@ ConfirmCancelTiddler: Do you wish to discard changes to the tiddler "<$text text
|
|||||||
ConfirmDeleteTiddler: Do you wish to delete the tiddler "<$text text=<<title>>/>"?
|
ConfirmDeleteTiddler: Do you wish to delete the tiddler "<$text text=<<title>>/>"?
|
||||||
ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<<title>>/>"?
|
ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<<title>>/>"?
|
||||||
ConfirmEditShadowTiddler: You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit "<$text text=<<title>>/>"?
|
ConfirmEditShadowTiddler: You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit "<$text text=<<title>>/>"?
|
||||||
|
ConfirmAction: Do you wish to proceed?
|
||||||
Count: count
|
Count: count
|
||||||
DefaultNewTiddlerTitle: New Tiddler
|
DefaultNewTiddlerTitle: New Tiddler
|
||||||
Diffs/CountMessage: <<diff-count>> differences
|
Diffs/CountMessage: <<diff-count>> differences
|
||||||
@ -26,6 +27,7 @@ Error/Caption: Error
|
|||||||
Error/EditConflict: File changed on server
|
Error/EditConflict: File changed on server
|
||||||
Error/Filter: Filter error
|
Error/Filter: Filter error
|
||||||
Error/FilterSyntax: Syntax error in filter expression
|
Error/FilterSyntax: Syntax error in filter expression
|
||||||
|
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
|
||||||
Error/IsFilterOperator: Filter Error: Unknown operand for the 'is' filter operator
|
Error/IsFilterOperator: Filter Error: Unknown operand for the 'is' filter operator
|
||||||
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
|
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
|
||||||
Error/LoadingPluginLibrary: Error loading plugin library
|
Error/LoadingPluginLibrary: Error loading plugin library
|
||||||
@ -38,6 +40,7 @@ Error/XMLHttpRequest: XMLHttpRequest error code
|
|||||||
InternalJavaScriptError/Title: Internal JavaScript Error
|
InternalJavaScriptError/Title: Internal JavaScript Error
|
||||||
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
|
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 (`.`)
|
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>
|
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
|
LoginToTiddlySpace: Login to TiddlySpace
|
||||||
Manager/Controls/FilterByTag/None: (none)
|
Manager/Controls/FilterByTag/None: (none)
|
||||||
@ -61,8 +64,11 @@ MissingTiddler/Hint: Missing tiddler "<$text text=<<currentTiddler>>/>" -- click
|
|||||||
No: No
|
No: No
|
||||||
OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library
|
OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library
|
||||||
OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
||||||
|
PageTemplate/Description: the default ~TiddlyWiki layout
|
||||||
|
PageTemplate/Name: Default ~PageTemplate
|
||||||
PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect
|
PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect
|
||||||
RecentChanges/DateFormat: DDth MMM YYYY
|
RecentChanges/DateFormat: DDth MMM YYYY
|
||||||
|
Shortcuts/Input/AdvancedSearch/Hint: Open the ~AdvancedSearch panel from within the sidebar search field
|
||||||
Shortcuts/Input/Accept/Hint: Accept the selected item
|
Shortcuts/Input/Accept/Hint: Accept the selected item
|
||||||
Shortcuts/Input/AcceptVariant/Hint: Accept the selected item (variant)
|
Shortcuts/Input/AcceptVariant/Hint: Accept the selected item (variant)
|
||||||
Shortcuts/Input/Cancel/Hint: Clear the input field
|
Shortcuts/Input/Cancel/Hint: Clear the input field
|
||||||
@ -70,6 +76,11 @@ Shortcuts/Input/Down/Hint: Select the next item
|
|||||||
Shortcuts/Input/Tab-Left/Hint: Select the previous Tab
|
Shortcuts/Input/Tab-Left/Hint: Select the previous Tab
|
||||||
Shortcuts/Input/Tab-Right/Hint: Select the next Tab
|
Shortcuts/Input/Tab-Right/Hint: Select the next Tab
|
||||||
Shortcuts/Input/Up/Hint: Select the previous item
|
Shortcuts/Input/Up/Hint: Select the previous item
|
||||||
|
Shortcuts/SidebarLayout/Hint: Change the sidebar layout
|
||||||
|
Switcher/Subtitle/theme: Switch Theme
|
||||||
|
Switcher/Subtitle/layout: Switch Layout
|
||||||
|
Switcher/Subtitle/language: Switch Language
|
||||||
|
Switcher/Subtitle/palette: Switch Palette
|
||||||
SystemTiddler/Tooltip: This is a system tiddler
|
SystemTiddler/Tooltip: This is a system tiddler
|
||||||
SystemTiddlers/Include/Prompt: Include system tiddlers
|
SystemTiddlers/Include/Prompt: Include system tiddlers
|
||||||
TagManager/Colour/Heading: Colour
|
TagManager/Colour/Heading: Colour
|
||||||
|
@ -14,7 +14,7 @@ List/Caption: List
|
|||||||
List/Empty: This tiddler does not have a list
|
List/Empty: This tiddler does not have a list
|
||||||
Listed/Caption: Listed
|
Listed/Caption: Listed
|
||||||
Listed/Empty: This tiddler is not listed by any others
|
Listed/Empty: This tiddler is not listed by any others
|
||||||
References/Caption: References
|
References/Caption: Backlinks
|
||||||
References/Empty: No tiddlers link to this one
|
References/Empty: No tiddlers link to this one
|
||||||
Tagging/Caption: Tagging
|
Tagging/Caption: Tagging
|
||||||
Tagging/Empty: No tiddlers are tagged with this one
|
Tagging/Empty: No tiddlers are tagged with this one
|
||||||
|
@ -37,16 +37,16 @@ Command.prototype.execute = function() {
|
|||||||
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
|
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
|
||||||
type = this.params[2] || "text/html",
|
type = this.params[2] || "text/html",
|
||||||
template = this.params[3],
|
template = this.params[3],
|
||||||
varName = this.params[4],
|
variableList = this.params.slice(4),
|
||||||
varValue = this.params[5],
|
tiddlers = wiki.filterTiddlers(tiddlerFilter),
|
||||||
tiddlers = wiki.filterTiddlers(tiddlerFilter);
|
variables = Object.create(null);
|
||||||
$tw.utils.each(tiddlers,function(title) {
|
while(variableList.length >= 2) {
|
||||||
var parser = wiki.parseTiddler(template || title),
|
variables[variableList[0]] = variableList[1];
|
||||||
variables = {currentTiddler: title};
|
variableList = variableList.slice(2);
|
||||||
if(varName) {
|
|
||||||
variables[varName] = varValue || "";
|
|
||||||
}
|
}
|
||||||
var widgetNode = wiki.makeWidget(parser,{variables: variables}),
|
$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");
|
container = $tw.fakeDocument.createElement("div");
|
||||||
widgetNode.render(container,null);
|
widgetNode.render(container,null);
|
||||||
var text = type === "text/html" ? container.innerHTML : container.textContent,
|
var text = type === "text/html" ? container.innerHTML : container.textContent,
|
||||||
|
@ -158,11 +158,25 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
WikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {
|
WikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {
|
||||||
|
var title = tiddler.fields.title, fileInfo, pathFilters, extFilters;
|
||||||
|
if(this.wiki.tiddlerExists("$:/config/FileSystemPaths")) {
|
||||||
|
pathFilters = this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n");
|
||||||
|
}
|
||||||
|
if(this.wiki.tiddlerExists("$:/config/FileSystemExtensions")) {
|
||||||
|
extFilters = this.wiki.getTiddlerText("$:/config/FileSystemExtensions","").split("\n");
|
||||||
|
}
|
||||||
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
|
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
|
||||||
directory: path.resolve(this.wikiFolderPath,directory),
|
directory: path.resolve(this.wikiFolderPath,directory),
|
||||||
wiki: this.wiki
|
pathFilters: pathFilters,
|
||||||
|
extFilters: extFilters,
|
||||||
|
wiki: this.wiki,
|
||||||
|
fileInfo: {}
|
||||||
});
|
});
|
||||||
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
|
try {
|
||||||
|
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("SaveWikiFolder: Error saving file '" + fileInfo.filepath + "', tiddler: '" + tiddler.fields.title);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
WikiFolderMaker.prototype.saveJSONFile = function(filename,json) {
|
WikiFolderMaker.prototype.saveJSONFile = function(filename,json) {
|
||||||
|
@ -42,7 +42,6 @@ function FramedEngine(options) {
|
|||||||
this.iframeNode.style.border = "none";
|
this.iframeNode.style.border = "none";
|
||||||
this.iframeNode.style.padding = "0";
|
this.iframeNode.style.padding = "0";
|
||||||
this.iframeNode.style.resize = "none";
|
this.iframeNode.style.resize = "none";
|
||||||
this.iframeNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
|
|
||||||
this.iframeDoc.body.style.margin = "0";
|
this.iframeDoc.body.style.margin = "0";
|
||||||
this.iframeDoc.body.style.padding = "0";
|
this.iframeDoc.body.style.padding = "0";
|
||||||
this.widget.domNodes.push(this.iframeNode);
|
this.widget.domNodes.push(this.iframeNode);
|
||||||
@ -74,6 +73,12 @@ function FramedEngine(options) {
|
|||||||
if(this.widget.editTabIndex) {
|
if(this.widget.editTabIndex) {
|
||||||
this.iframeNode.setAttribute("tabindex",this.widget.editTabIndex);
|
this.iframeNode.setAttribute("tabindex",this.widget.editTabIndex);
|
||||||
}
|
}
|
||||||
|
if(this.widget.editAutoComplete) {
|
||||||
|
this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete);
|
||||||
|
}
|
||||||
|
if(this.widget.isDisabled === "yes") {
|
||||||
|
this.domNode.setAttribute("disabled",true);
|
||||||
|
}
|
||||||
// Copy the styles from the dummy textarea
|
// Copy the styles from the dummy textarea
|
||||||
this.copyStyles();
|
this.copyStyles();
|
||||||
// Add event listeners
|
// Add event listeners
|
||||||
@ -97,7 +102,6 @@ FramedEngine.prototype.copyStyles = function() {
|
|||||||
this.domNode.style.display = "block";
|
this.domNode.style.display = "block";
|
||||||
this.domNode.style.width = "100%";
|
this.domNode.style.width = "100%";
|
||||||
this.domNode.style.margin = "0";
|
this.domNode.style.margin = "0";
|
||||||
this.domNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
|
|
||||||
// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour
|
// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour
|
||||||
this.domNode.style["-webkit-text-fill-color"] = "currentcolor";
|
this.domNode.style["-webkit-text-fill-color"] = "currentcolor";
|
||||||
};
|
};
|
||||||
|
@ -52,6 +52,12 @@ function SimpleEngine(options) {
|
|||||||
if(this.widget.editTabIndex) {
|
if(this.widget.editTabIndex) {
|
||||||
this.domNode.setAttribute("tabindex",this.widget.editTabIndex);
|
this.domNode.setAttribute("tabindex",this.widget.editTabIndex);
|
||||||
}
|
}
|
||||||
|
if(this.widget.editAutoComplete) {
|
||||||
|
this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete);
|
||||||
|
}
|
||||||
|
if(this.widget.isDisabled === "yes") {
|
||||||
|
this.domNode.setAttribute("disabled",true);
|
||||||
|
}
|
||||||
// Add an input event handler
|
// Add an input event handler
|
||||||
$tw.utils.addEventListeners(this.domNode,[
|
$tw.utils.addEventListeners(this.domNode,[
|
||||||
{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
|
{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
|
||||||
|
@ -103,7 +103,11 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
|||||||
var tiddler = this.wiki.getTiddler(this.editTitle);
|
var tiddler = this.wiki.getTiddler(this.editTitle);
|
||||||
if(tiddler) {
|
if(tiddler) {
|
||||||
// If we've got a tiddler, the value to display is the field string value
|
// If we've got a tiddler, the value to display is the field string value
|
||||||
value = tiddler.getFieldString(this.editField);
|
if(tiddler.hasField(this.editField)) {
|
||||||
|
value = tiddler.getFieldString(this.editField);
|
||||||
|
} else {
|
||||||
|
value = this.editDefault || "";
|
||||||
|
}
|
||||||
if(this.editField === "text") {
|
if(this.editField === "text") {
|
||||||
type = tiddler.fields.type || "text/vnd.tiddlywiki";
|
type = tiddler.fields.type || "text/vnd.tiddlywiki";
|
||||||
}
|
}
|
||||||
@ -180,6 +184,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
|||||||
this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes";
|
this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes";
|
||||||
this.editInputActions = this.getAttribute("inputActions");
|
this.editInputActions = this.getAttribute("inputActions");
|
||||||
this.editRefreshTitle = this.getAttribute("refreshTitle");
|
this.editRefreshTitle = this.getAttribute("refreshTitle");
|
||||||
|
this.editAutoComplete = this.getAttribute("autocomplete");
|
||||||
|
this.isDisabled = this.getAttribute("disabled","no");
|
||||||
// Get the default editor element tag and type
|
// Get the default editor element tag and type
|
||||||
var tag,type;
|
var tag,type;
|
||||||
if(this.editField === "text") {
|
if(this.editField === "text") {
|
||||||
@ -211,7 +217,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
|||||||
EditTextWidget.prototype.refresh = function(changedTiddlers) {
|
EditTextWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
// Completely rerender if any of our attributes have changed
|
// Completely rerender if any of our attributes have changed
|
||||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) {
|
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else if (changedTiddlers[this.editRefreshTitle]) {
|
} else if (changedTiddlers[this.editRefreshTitle]) {
|
||||||
|
25
core/modules/filterrunprefixes/all.js
Normal file
25
core/modules/filterrunprefixes/all.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/all.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
Union of sets without de-duplication.
|
||||||
|
Equivalent to = filter run prefix.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.all = function(operationSubFunction) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
results.push.apply(results, operationSubFunction(source,widget));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
28
core/modules/filterrunprefixes/and.js
Normal file
28
core/modules/filterrunprefixes/and.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/and.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
Intersection of sets.
|
||||||
|
Equivalent to + filter run prefix.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.and = function(operationSubFunction,options) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved
|
||||||
|
source = options.wiki.makeTiddlerIterator(results.toArray());
|
||||||
|
results.clear();
|
||||||
|
results.pushTop(operationSubFunction(source,widget));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
27
core/modules/filterrunprefixes/else.js
Normal file
27
core/modules/filterrunprefixes/else.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/else.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
Equivalent to ~ filter run prefix.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.else = function(operationSubFunction) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
if(results.length === 0) {
|
||||||
|
// Main result so far is empty
|
||||||
|
results.pushTop(operationSubFunction(source,widget));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
25
core/modules/filterrunprefixes/except.js
Normal file
25
core/modules/filterrunprefixes/except.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/except.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
Difference of sets.
|
||||||
|
Equivalent to - filter run prefix.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.except = function(operationSubFunction) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
results.remove(operationSubFunction(source,widget));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
31
core/modules/filterrunprefixes/filter.js
Normal file
31
core/modules/filterrunprefixes/filter.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/filter.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter function
|
||||||
|
*/
|
||||||
|
exports.filter = function(operationSubFunction,options) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
if(results.length > 0) {
|
||||||
|
var resultsToRemove = [];
|
||||||
|
results.each(function(result) {
|
||||||
|
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([result]),widget);
|
||||||
|
if(filtered.length === 0) {
|
||||||
|
resultsToRemove.push(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
results.remove(resultsToRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
31
core/modules/filterrunprefixes/intersection.js
Normal file
31
core/modules/filterrunprefixes/intersection.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/intersection.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.intersection = function(operationSubFunction) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
if(results.length !== 0) {
|
||||||
|
var secondRunResults = operationSubFunction(source,widget);
|
||||||
|
var firstRunResults = results.toArray();
|
||||||
|
results.clear();
|
||||||
|
$tw.utils.each(firstRunResults,function(title) {
|
||||||
|
if(secondRunResults.indexOf(title) !== -1) {
|
||||||
|
results.push(title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
24
core/modules/filterrunprefixes/or.js
Normal file
24
core/modules/filterrunprefixes/or.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/or.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
Equivalent to a filter run with no prefix.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.or = function(operationSubFunction) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
results.pushTop(operationSubFunction(source,widget));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
50
core/modules/filterrunprefixes/reduce.js
Normal file
50
core/modules/filterrunprefixes/reduce.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/reduce.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.reduce = function(operationSubFunction,options) {
|
||||||
|
return function(results,source,widget) {
|
||||||
|
if(results.length > 0) {
|
||||||
|
var accumulator = "";
|
||||||
|
var index = 0;
|
||||||
|
results.each(function(title) {
|
||||||
|
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
|
||||||
|
getVariable: function(name) {
|
||||||
|
switch(name) {
|
||||||
|
case "currentTiddler":
|
||||||
|
return "" + title;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(list.length > 0) {
|
||||||
|
accumulator = "" + list[0];
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
});
|
||||||
|
results.clear();
|
||||||
|
results.push(accumulator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
@ -62,43 +62,61 @@ function parseFilterOperation(operators,filterString,p) {
|
|||||||
else if(operator.operator === "") {
|
else if(operator.operator === "") {
|
||||||
operator.operator = "title";
|
operator.operator = "title";
|
||||||
}
|
}
|
||||||
|
operator.operands = [];
|
||||||
|
var parseOperand = function(bracketType) {
|
||||||
|
var operand = {};
|
||||||
|
switch (bracketType) {
|
||||||
|
case "{": // Curly brackets
|
||||||
|
operand.indirect = true;
|
||||||
|
nextBracketPos = filterString.indexOf("}",p);
|
||||||
|
break;
|
||||||
|
case "[": // Square brackets
|
||||||
|
nextBracketPos = filterString.indexOf("]",p);
|
||||||
|
break;
|
||||||
|
case "<": // Angle brackets
|
||||||
|
operand.variable = true;
|
||||||
|
nextBracketPos = filterString.indexOf(">",p);
|
||||||
|
break;
|
||||||
|
case "/": // regexp brackets
|
||||||
|
var rex = /^((?:[^\\\/]|\\.)*)\/(?:\(([mygi]+)\))?/g,
|
||||||
|
rexMatch = rex.exec(filterString.substring(p));
|
||||||
|
if(rexMatch) {
|
||||||
|
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
|
||||||
|
// DEPRECATION WARNING
|
||||||
|
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
|
||||||
|
nextBracketPos = p + rex.lastIndex - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Unterminated regular expression in filter expression";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nextBracketPos === -1) {
|
||||||
|
throw "Missing closing bracket in filter expression";
|
||||||
|
}
|
||||||
|
if(!operator.regexp) {
|
||||||
|
operand.text = filterString.substring(p,nextBracketPos);
|
||||||
|
operator.operands.push(operand);
|
||||||
|
}
|
||||||
|
p = nextBracketPos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
p = nextBracketPos + 1;
|
p = nextBracketPos + 1;
|
||||||
switch (bracket) {
|
parseOperand(bracket);
|
||||||
case "{": // Curly brackets
|
|
||||||
operator.indirect = true;
|
// Check for multiple operands
|
||||||
nextBracketPos = filterString.indexOf("}",p);
|
while(filterString.charAt(p) === ",") {
|
||||||
break;
|
p++;
|
||||||
case "[": // Square brackets
|
if(/^[\[\{<\/]/.test(filterString.substring(p))) {
|
||||||
nextBracketPos = filterString.indexOf("]",p);
|
nextBracketPos = p;
|
||||||
break;
|
p++;
|
||||||
case "<": // Angle brackets
|
parseOperand(filterString.charAt(nextBracketPos));
|
||||||
operator.variable = true;
|
} else {
|
||||||
nextBracketPos = filterString.indexOf(">",p);
|
throw "Missing [ in filter expression";
|
||||||
break;
|
}
|
||||||
case "/": // regexp brackets
|
|
||||||
var rex = /^((?:[^\\\/]*|\\.)*)\/(?:\(([mygi]+)\))?/g,
|
|
||||||
rexMatch = rex.exec(filterString.substring(p));
|
|
||||||
if(rexMatch) {
|
|
||||||
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
|
|
||||||
// DEPRECATION WARNING
|
|
||||||
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
|
|
||||||
nextBracketPos = p + rex.lastIndex - 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "Unterminated regular expression in filter expression";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nextBracketPos === -1) {
|
|
||||||
throw "Missing closing bracket in filter expression";
|
|
||||||
}
|
|
||||||
if(!operator.regexp) {
|
|
||||||
operator.operand = filterString.substring(p,nextBracketPos);
|
|
||||||
}
|
|
||||||
p = nextBracketPos + 1;
|
|
||||||
|
|
||||||
// Push this operator
|
// Push this operator
|
||||||
operators.push(operator);
|
operators.push(operator);
|
||||||
} while(filterString.charAt(p) !== "]");
|
} while(filterString.charAt(p) !== "]");
|
||||||
@ -119,7 +137,7 @@ exports.parseFilter = function(filterString) {
|
|||||||
p = 0, // Current position in the filter string
|
p = 0, // Current position in the filter string
|
||||||
match;
|
match;
|
||||||
var whitespaceRegExp = /(\s+)/mg,
|
var whitespaceRegExp = /(\s+)/mg,
|
||||||
operandRegExp = /((?:\+|\-|~|=)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
operandRegExp = /((?:\+|\-|~|=|\:(\w+))?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
||||||
while(p < filterString.length) {
|
while(p < filterString.length) {
|
||||||
// Skip any whitespace
|
// Skip any whitespace
|
||||||
whitespaceRegExp.lastIndex = p;
|
whitespaceRegExp.lastIndex = p;
|
||||||
@ -140,16 +158,19 @@ exports.parseFilter = function(filterString) {
|
|||||||
};
|
};
|
||||||
if(match[1]) {
|
if(match[1]) {
|
||||||
operation.prefix = match[1];
|
operation.prefix = match[1];
|
||||||
p++;
|
p = p + operation.prefix.length;
|
||||||
|
if(match[2]) {
|
||||||
|
operation.namedPrefix = match[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(match[2]) { // Opening square bracket
|
if(match[3]) { // Opening square bracket
|
||||||
p = parseFilterOperation(operation.operators,filterString,p);
|
p = parseFilterOperation(operation.operators,filterString,p);
|
||||||
} else {
|
} else {
|
||||||
p = match.index + match[0].length;
|
p = match.index + match[0].length;
|
||||||
}
|
}
|
||||||
if(match[3] || match[4] || match[5]) { // Double quoted string, single quoted string or unquoted title
|
if(match[4] || match[5] || match[6]) { // Double quoted string, single quoted string or unquoted title
|
||||||
operation.operators.push(
|
operation.operators.push(
|
||||||
{operator: "title", operand: match[3] || match[4] || match[5]}
|
{operator: "title", operands: [{text: match[4] || match[5] || match[6]}]}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
results.push(operation);
|
results.push(operation);
|
||||||
@ -166,6 +187,14 @@ exports.getFilterOperators = function() {
|
|||||||
return this.filterOperators;
|
return this.filterOperators;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getFilterRunPrefixes = function() {
|
||||||
|
if(!this.filterRunPrefixes) {
|
||||||
|
$tw.Wiki.prototype.filterRunPrefixes = {};
|
||||||
|
$tw.modules.applyMethods("filterrunprefix",this.filterRunPrefixes);
|
||||||
|
}
|
||||||
|
return this.filterRunPrefixes;
|
||||||
|
}
|
||||||
|
|
||||||
exports.filterTiddlers = function(filterString,widget,source) {
|
exports.filterTiddlers = function(filterString,widget,source) {
|
||||||
var fn = this.compileFilter(filterString);
|
var fn = this.compileFilter(filterString);
|
||||||
return fn.call(this,source,widget);
|
return fn.call(this,source,widget);
|
||||||
@ -198,7 +227,7 @@ exports.compileFilter = function(filterString) {
|
|||||||
results = [],
|
results = [],
|
||||||
currTiddlerTitle = widget && widget.getVariable("currentTiddler");
|
currTiddlerTitle = widget && widget.getVariable("currentTiddler");
|
||||||
$tw.utils.each(operation.operators,function(operator) {
|
$tw.utils.each(operation.operators,function(operator) {
|
||||||
var operand = operator.operand,
|
var operands = [],
|
||||||
operatorFunction;
|
operatorFunction;
|
||||||
if(!operator.operator) {
|
if(!operator.operator) {
|
||||||
operatorFunction = filterOperators.title;
|
operatorFunction = filterOperators.title;
|
||||||
@ -207,16 +236,23 @@ exports.compileFilter = function(filterString) {
|
|||||||
} else {
|
} else {
|
||||||
operatorFunction = filterOperators[operator.operator];
|
operatorFunction = filterOperators[operator.operator];
|
||||||
}
|
}
|
||||||
if(operator.indirect) {
|
|
||||||
operand = self.getTextReference(operator.operand,"",currTiddlerTitle);
|
$tw.utils.each(operator.operands,function(operand) {
|
||||||
}
|
if(operand.indirect) {
|
||||||
if(operator.variable) {
|
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
|
||||||
operand = widget.getVariable(operator.operand,{defaultValue: ""});
|
} else if(operand.variable) {
|
||||||
}
|
operand.value = widget.getVariable(operand.text,{defaultValue: ""});
|
||||||
|
} else {
|
||||||
|
operand.value = operand.text;
|
||||||
|
}
|
||||||
|
operands.push(operand.value);
|
||||||
|
});
|
||||||
|
|
||||||
// Invoke the appropriate filteroperator module
|
// Invoke the appropriate filteroperator module
|
||||||
results = operatorFunction(accumulator,{
|
results = operatorFunction(accumulator,{
|
||||||
operator: operator.operator,
|
operator: operator.operator,
|
||||||
operand: operand,
|
operand: operands.length > 0 ? operands[0] : undefined,
|
||||||
|
operands: operands,
|
||||||
prefix: operator.prefix,
|
prefix: operator.prefix,
|
||||||
suffix: operator.suffix,
|
suffix: operator.suffix,
|
||||||
suffixes: operator.suffixes,
|
suffixes: operator.suffixes,
|
||||||
@ -241,35 +277,30 @@ exports.compileFilter = function(filterString) {
|
|||||||
return resultArray;
|
return resultArray;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
var filterRunPrefixes = self.getFilterRunPrefixes();
|
||||||
// Wrap the operator functions in a wrapper function that depends on the prefix
|
// Wrap the operator functions in a wrapper function that depends on the prefix
|
||||||
operationFunctions.push((function() {
|
operationFunctions.push((function() {
|
||||||
|
var options = {wiki: self};
|
||||||
switch(operation.prefix || "") {
|
switch(operation.prefix || "") {
|
||||||
case "": // No prefix means that the operation is unioned into the result
|
case "": // No prefix means that the operation is unioned into the result
|
||||||
return function(results,source,widget) {
|
return filterRunPrefixes["or"](operationSubFunction, options);
|
||||||
$tw.utils.pushTop(results,operationSubFunction(source,widget));
|
|
||||||
};
|
|
||||||
case "=": // The results of the operation are pushed into the result without deduplication
|
case "=": // The results of the operation are pushed into the result without deduplication
|
||||||
return function(results,source,widget) {
|
return filterRunPrefixes["all"](operationSubFunction, options);
|
||||||
Array.prototype.push.apply(results,operationSubFunction(source,widget));
|
|
||||||
};
|
|
||||||
case "-": // The results of this operation are removed from the main result
|
case "-": // The results of this operation are removed from the main result
|
||||||
return function(results,source,widget) {
|
return filterRunPrefixes["except"](operationSubFunction, options);
|
||||||
$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));
|
|
||||||
};
|
|
||||||
case "+": // This operation is applied to the main results so far
|
case "+": // This operation is applied to the main results so far
|
||||||
return function(results,source,widget) {
|
return filterRunPrefixes["and"](operationSubFunction, options);
|
||||||
// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved
|
|
||||||
source = self.makeTiddlerIterator(results);
|
|
||||||
results.splice(0,results.length);
|
|
||||||
$tw.utils.pushTop(results,operationSubFunction(source,widget));
|
|
||||||
};
|
|
||||||
case "~": // This operation is unioned into the result only if the main result so far is empty
|
case "~": // This operation is unioned into the result only if the main result so far is empty
|
||||||
return function(results,source,widget) {
|
return filterRunPrefixes["else"](operationSubFunction, options);
|
||||||
if(results.length === 0) {
|
default:
|
||||||
// Main result so far is empty
|
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
|
||||||
$tw.utils.pushTop(results,operationSubFunction(source,widget));
|
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
|
||||||
}
|
} else {
|
||||||
};
|
return function(results,source,widget) {
|
||||||
|
results.clear();
|
||||||
|
results.push($tw.language.getString("Error/FilterRunPrefix"));
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})());
|
})());
|
||||||
});
|
});
|
||||||
@ -280,11 +311,11 @@ exports.compileFilter = function(filterString) {
|
|||||||
} else if(typeof source === "object") { // Array or hashmap
|
} else if(typeof source === "object") { // Array or hashmap
|
||||||
source = self.makeTiddlerIterator(source);
|
source = self.makeTiddlerIterator(source);
|
||||||
}
|
}
|
||||||
var results = [];
|
var results = new $tw.utils.LinkedList();
|
||||||
$tw.utils.each(operationFunctions,function(operationFunction) {
|
$tw.utils.each(operationFunctions,function(operationFunction) {
|
||||||
operationFunction(results,source,widget);
|
operationFunction(results,source,widget);
|
||||||
});
|
});
|
||||||
return results;
|
return results.toArray();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ exports.all = function(source,operator,options) {
|
|||||||
// Get our suboperators
|
// Get our suboperators
|
||||||
var allFilterOperators = getAllFilterOperators();
|
var allFilterOperators = getAllFilterOperators();
|
||||||
// Cycle through the suboperators accumulating their results
|
// Cycle through the suboperators accumulating their results
|
||||||
var results = [],
|
var results = new $tw.utils.LinkedList(),
|
||||||
subops = operator.operand.split("+");
|
subops = operator.operand.split("+");
|
||||||
// Check for common optimisations
|
// Check for common optimisations
|
||||||
if(subops.length === 1 && subops[0] === "") {
|
if(subops.length === 1 && subops[0] === "") {
|
||||||
@ -49,10 +49,10 @@ exports.all = function(source,operator,options) {
|
|||||||
for(var t=0; t<subops.length; t++) {
|
for(var t=0; t<subops.length; t++) {
|
||||||
var subop = allFilterOperators[subops[t]];
|
var subop = allFilterOperators[subops[t]];
|
||||||
if(subop) {
|
if(subop) {
|
||||||
$tw.utils.pushTop(results,subop(source,operator.prefix,options));
|
results.pushTop(subop(source,operator.prefix,options));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results.toArray();
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -16,14 +16,16 @@ Filter operator for returning the descriptions of the specified edition names
|
|||||||
Export our filter function
|
Export our filter function
|
||||||
*/
|
*/
|
||||||
exports.editiondescription = function(source,operator,options) {
|
exports.editiondescription = function(source,operator,options) {
|
||||||
var results = [],
|
var results = [];
|
||||||
editionInfo = $tw.utils.getEditionInfo();
|
if($tw.node) {
|
||||||
if(editionInfo) {
|
var editionInfo = $tw.utils.getEditionInfo();
|
||||||
source(function(tiddler,title) {
|
if(editionInfo) {
|
||||||
if($tw.utils.hop(editionInfo,title)) {
|
source(function(tiddler,title) {
|
||||||
results.push(editionInfo[title].description || "");
|
if($tw.utils.hop(editionInfo,title)) {
|
||||||
}
|
results.push(editionInfo[title].description || "");
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
@ -16,14 +16,16 @@ Filter operator for returning the names of the available editions in this wiki
|
|||||||
Export our filter function
|
Export our filter function
|
||||||
*/
|
*/
|
||||||
exports.editions = function(source,operator,options) {
|
exports.editions = function(source,operator,options) {
|
||||||
var results = [],
|
var results = [];
|
||||||
editionInfo = $tw.utils.getEditionInfo();
|
if($tw.node) {
|
||||||
if(editionInfo) {
|
var editionInfo = $tw.utils.getEditionInfo();
|
||||||
$tw.utils.each(editionInfo,function(info,name) {
|
if(editionInfo) {
|
||||||
results.push(name);
|
$tw.utils.each(editionInfo,function(info,name) {
|
||||||
});
|
results.push(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
results.sort();
|
||||||
}
|
}
|
||||||
results.sort();
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ exports.encodehtml = function(source,operator,options) {
|
|||||||
exports.stringify = function(source,operator,options) {
|
exports.stringify = function(source,operator,options) {
|
||||||
var results = [];
|
var results = [];
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
results.push($tw.utils.stringify(title));
|
results.push($tw.utils.stringify(title,(operator.suffix === "rawunicode")));
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
@ -85,7 +85,7 @@ exports.stringify = function(source,operator,options) {
|
|||||||
exports.jsonstringify = function(source,operator,options) {
|
exports.jsonstringify = function(source,operator,options) {
|
||||||
var results = [];
|
var results = [];
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
results.push($tw.utils.jsonStringify(title));
|
results.push($tw.utils.jsonStringify(title,(operator.suffix === "rawunicode")));
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
@ -102,7 +102,7 @@ exports.escapecss = function(source,operator,options) {
|
|||||||
var results = [];
|
var results = [];
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
// escape any character with a special meaning in CSS using CSS.escape()
|
// escape any character with a special meaning in CSS using CSS.escape()
|
||||||
results.push(CSS.escape(title));
|
results.push($tw.utils.escapeCSS(title));
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
36
core/modules/filters/is/draft.js
Normal file
36
core/modules/filters/is/draft.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filters/is/draft.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: isfilteroperator
|
||||||
|
|
||||||
|
Filter function for [is[draft]] analagous to [has[draft.of]]
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter function
|
||||||
|
*/
|
||||||
|
exports.draft = function(source,prefix,options) {
|
||||||
|
var results = [];
|
||||||
|
if(prefix === "!") {
|
||||||
|
source(function(tiddler,title) {
|
||||||
|
if(!tiddler || !$tw.utils.hop(tiddler.fields,"draft.of")) {
|
||||||
|
results.push(title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
source(function(tiddler,title) {
|
||||||
|
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.of") && (tiddler.fields["draft.of"].length !== 0)) {
|
||||||
|
results.push(title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
@ -16,11 +16,11 @@ Filter operator for returning all the links from a tiddler
|
|||||||
Export our filter function
|
Export our filter function
|
||||||
*/
|
*/
|
||||||
exports.links = function(source,operator,options) {
|
exports.links = function(source,operator,options) {
|
||||||
var results = [];
|
var results = new $tw.utils.LinkedList();
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
$tw.utils.pushTop(results,options.wiki.getTiddlerLinks(title));
|
results.pushTop(options.wiki.getTiddlerLinks(title));
|
||||||
});
|
});
|
||||||
return results;
|
return results.toArray();
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -22,7 +22,7 @@ Export our filter function
|
|||||||
exports.lookup = function(source,operator,options) {
|
exports.lookup = function(source,operator,options) {
|
||||||
var results = [];
|
var results = [];
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
results.push(options.wiki.getTiddlerText(operator.operand + title) || options.wiki.getTiddlerText(operator.operand + operator.suffix));
|
results.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix || '');
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
@ -91,6 +91,20 @@ exports.exponential = makeNumericBinaryOperator(
|
|||||||
function(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}
|
function(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
exports.power = makeNumericBinaryOperator(
|
||||||
|
function(a,b) {return Math.pow(a,b);}
|
||||||
|
);
|
||||||
|
|
||||||
|
exports.log = makeNumericBinaryOperator(
|
||||||
|
function(a,b) {
|
||||||
|
if(b) {
|
||||||
|
return Math.log(a)/Math.log(b);
|
||||||
|
} else {
|
||||||
|
return Math.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
exports.sum = makeNumericReducingOperator(
|
exports.sum = makeNumericReducingOperator(
|
||||||
function(accumulator,value) {return accumulator + value},
|
function(accumulator,value) {return accumulator + value},
|
||||||
0 // Initial value
|
0 // Initial value
|
||||||
|
@ -23,7 +23,7 @@ exports.reduce = function(source,operator,options) {
|
|||||||
});
|
});
|
||||||
// Run the filter over each item
|
// Run the filter over each item
|
||||||
var filterFn = options.wiki.compileFilter(operator.operand),
|
var filterFn = options.wiki.compileFilter(operator.operand),
|
||||||
accumulator = operator.suffix || "";
|
accumulator = operator.operands[1] || "";
|
||||||
for(var index=0; index<results.length; index++) {
|
for(var index=0; index<results.length; index++) {
|
||||||
var title = results[index],
|
var title = results[index],
|
||||||
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
|
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
|
||||||
@ -48,7 +48,11 @@ exports.reduce = function(source,operator,options) {
|
|||||||
accumulator = "" + list[0];
|
accumulator = "" + list[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [accumulator];
|
if(results.length > 0) {
|
||||||
|
return [accumulator];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -56,14 +56,14 @@ exports.trim = function(source,operator,options) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// makeStringBinaryOperator(
|
|
||||||
// function(a) {return [$tw.utils.trim(a)];}
|
|
||||||
// );
|
|
||||||
|
|
||||||
exports.split = makeStringBinaryOperator(
|
exports.split = makeStringBinaryOperator(
|
||||||
function(a,b) {return ("" + a).split(b);}
|
function(a,b) {return ("" + a).split(b);}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
exports["enlist-input"] = makeStringBinaryOperator(
|
||||||
|
function(a,o,s) {return $tw.utils.parseStringArray("" + a,(s === "raw"));}
|
||||||
|
);
|
||||||
|
|
||||||
exports.join = makeStringReducingOperator(
|
exports.join = makeStringReducingOperator(
|
||||||
function(accumulator,value,operand) {
|
function(accumulator,value,operand) {
|
||||||
if(accumulator === null) {
|
if(accumulator === null) {
|
||||||
@ -78,7 +78,7 @@ function makeStringBinaryOperator(fnCalc) {
|
|||||||
return function(source,operator,options) {
|
return function(source,operator,options) {
|
||||||
var result = [];
|
var result = [];
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
Array.prototype.push.apply(result,fnCalc(title,operator.operand || ""));
|
Array.prototype.push.apply(result,fnCalc(title,operator.operand || "",operator.suffix || ""));
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@ -115,4 +115,61 @@ exports.splitregexp = function(source,operator,options) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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" : ""),
|
||||||
|
isRegExp = (suffixes[1] && suffixes[1][0] === "regexp") ? true : false,
|
||||||
|
searchTerm,
|
||||||
|
regExp;
|
||||||
|
|
||||||
|
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,operator.operands[1])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
results.push(title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.pad = function(source,operator,options) {
|
||||||
|
var results = [],
|
||||||
|
targetLength = operator.operand ? parseInt(operator.operand) : 0,
|
||||||
|
fill = operator.operands[1] || "0";
|
||||||
|
|
||||||
|
source(function(tiddler,title) {
|
||||||
|
if(title && title.length) {
|
||||||
|
if(title.length >= targetLength) {
|
||||||
|
results.push(title);
|
||||||
|
} else {
|
||||||
|
var padString = "",
|
||||||
|
padStringLength = targetLength - title.length;
|
||||||
|
while (padStringLength > padString.length) {
|
||||||
|
padString += fill;
|
||||||
|
}
|
||||||
|
//make sure we do not exceed the specified length
|
||||||
|
padString = padString.slice(0,padStringLength);
|
||||||
|
if(operator.suffix && (operator.suffix === "suffix")) {
|
||||||
|
title = title + padString;
|
||||||
|
} else {
|
||||||
|
title = padString + title;
|
||||||
|
}
|
||||||
|
results.push(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -8,183 +8,228 @@ Extended filter operators to manipulate the current list.
|
|||||||
\*/
|
\*/
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
/*jslint node: true, browser: true */
|
/*jslint node: true, browser: true */
|
||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Fetch titles from the current list
|
Fetch titles from the current list
|
||||||
*/
|
*/
|
||||||
var prepare_results = function (source) {
|
var prepare_results = function (source) {
|
||||||
var results = [];
|
var results = [];
|
||||||
source(function (tiddler, title) {
|
source(function (tiddler, title) {
|
||||||
results.push(title);
|
results.push(title);
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moves a number of items from the tail of the current list before the item named in the operand
|
Moves a number of items from the tail of the current list before the item named in the operand
|
||||||
*/
|
*/
|
||||||
exports.putbefore = function (source, operator) {
|
exports.putbefore = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
index = results.indexOf(operator.operand),
|
index = results.indexOf(operator.operand),
|
||||||
count = $tw.utils.getInt(operator.suffix,1);
|
count = $tw.utils.getInt(operator.suffix,1);
|
||||||
return (index === -1) ?
|
return (index === -1) ?
|
||||||
results.slice(0, -1) :
|
results.slice(0, -1) :
|
||||||
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));
|
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index, -count));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moves a number of items from the tail of the current list after the item named in the operand
|
Moves a number of items from the tail of the current list after the item named in the operand
|
||||||
*/
|
*/
|
||||||
exports.putafter = function (source, operator) {
|
exports.putafter = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
index = results.indexOf(operator.operand),
|
index = results.indexOf(operator.operand),
|
||||||
count = $tw.utils.getInt(operator.suffix,1);
|
count = $tw.utils.getInt(operator.suffix,1);
|
||||||
return (index === -1) ?
|
return (index === -1) ?
|
||||||
results.slice(0, -1) :
|
results.slice(0, -1) :
|
||||||
results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
|
results.slice(0, index + 1).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Replaces the item named in the operand with a number of items from the tail of the current list
|
Replaces the item named in the operand with a number of items from the tail of the current list
|
||||||
*/
|
*/
|
||||||
exports.replace = function (source, operator) {
|
exports.replace = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
index = results.indexOf(operator.operand),
|
index = results.indexOf(operator.operand),
|
||||||
count = $tw.utils.getInt(operator.suffix,1);
|
count = $tw.utils.getInt(operator.suffix,1);
|
||||||
return (index === -1) ?
|
return (index === -1) ?
|
||||||
results.slice(0, -count) :
|
results.slice(0, -count) :
|
||||||
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
|
results.slice(0, index).concat(results.slice(-count)).concat(results.slice(index + 1, -count));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moves a number of items from the tail of the current list to the head of the list
|
Moves a number of items from the tail of the current list to the head of the list
|
||||||
*/
|
*/
|
||||||
exports.putfirst = function (source, operator) {
|
exports.putfirst = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
count = $tw.utils.getInt(operator.suffix,1);
|
count = $tw.utils.getInt(operator.suffix,1);
|
||||||
return results.slice(-count).concat(results.slice(0, -count));
|
return results.slice(-count).concat(results.slice(0, -count));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moves a number of items from the head of the current list to the tail of the list
|
Moves a number of items from the head of the current list to the tail of the list
|
||||||
*/
|
*/
|
||||||
exports.putlast = function (source, operator) {
|
exports.putlast = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
count = $tw.utils.getInt(operator.suffix,1);
|
count = $tw.utils.getInt(operator.suffix,1);
|
||||||
return results.slice(count).concat(results.slice(0, count));
|
return results.slice(count).concat(results.slice(0, count));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moves the item named in the operand a number of places forward or backward in the list
|
Moves the item named in the operand a number of places forward or backward in the list
|
||||||
*/
|
*/
|
||||||
exports.move = function (source, operator) {
|
exports.move = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
index = results.indexOf(operator.operand),
|
index = results.indexOf(operator.operand),
|
||||||
count = $tw.utils.getInt(operator.suffix,1),
|
count = $tw.utils.getInt(operator.suffix,1),
|
||||||
marker = results.splice(index, 1),
|
marker = results.splice(index, 1),
|
||||||
offset = (index + count) > 0 ? index + count : 0;
|
offset = (index + count) > 0 ? index + count : 0;
|
||||||
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
|
return results.slice(0, offset).concat(marker).concat(results.slice(offset));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns the items from the current list that are after the item named in the operand
|
Returns the items from the current list that are after the item named in the operand
|
||||||
*/
|
*/
|
||||||
exports.allafter = function (source, operator) {
|
exports.allafter = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
index = results.indexOf(operator.operand);
|
index = results.indexOf(operator.operand);
|
||||||
return (index === -1) ? [] :
|
return (index === -1) ? [] :
|
||||||
(operator.suffix) ? results.slice(index) :
|
(operator.suffix) ? results.slice(index) :
|
||||||
results.slice(index + 1);
|
results.slice(index + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns the items from the current list that are before the item named in the operand
|
Returns the items from the current list that are before the item named in the operand
|
||||||
*/
|
*/
|
||||||
exports.allbefore = function (source, operator) {
|
exports.allbefore = function (source, operator) {
|
||||||
var results = prepare_results(source),
|
var results = prepare_results(source),
|
||||||
index = results.indexOf(operator.operand);
|
index = results.indexOf(operator.operand);
|
||||||
return (index === -1) ? [] :
|
return (index === -1) ? [] :
|
||||||
(operator.suffix) ? results.slice(0, index + 1) :
|
(operator.suffix) ? results.slice(0, index + 1) :
|
||||||
results.slice(0, index);
|
results.slice(0, index);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Appends the items listed in the operand array to the tail of the current list
|
Appends the items listed in the operand array to the tail of the current list
|
||||||
*/
|
*/
|
||||||
exports.append = function (source, operator) {
|
exports.append = function (source, operator) {
|
||||||
var append = $tw.utils.parseStringArray(operator.operand, "true"),
|
var append = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||||
results = prepare_results(source),
|
results = prepare_results(source),
|
||||||
count = parseInt(operator.suffix) || append.length;
|
count = parseInt(operator.suffix) || append.length;
|
||||||
return (append.length === 0) ? results :
|
return (append.length === 0) ? results :
|
||||||
(operator.prefix) ? results.concat(append.slice(-count)) :
|
(operator.prefix) ? results.concat(append.slice(-count)) :
|
||||||
results.concat(append.slice(0, count));
|
results.concat(append.slice(0, count));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prepends the items listed in the operand array to the head of the current list
|
Prepends the items listed in the operand array to the head of the current list
|
||||||
*/
|
*/
|
||||||
exports.prepend = function (source, operator) {
|
exports.prepend = function (source, operator) {
|
||||||
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
|
var prepend = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||||
results = prepare_results(source),
|
results = prepare_results(source),
|
||||||
count = $tw.utils.getInt(operator.suffix,prepend.length);
|
count = $tw.utils.getInt(operator.suffix,prepend.length);
|
||||||
return (prepend.length === 0) ? results :
|
return (prepend.length === 0) ? results :
|
||||||
(operator.prefix) ? prepend.slice(-count).concat(results) :
|
(operator.prefix) ? prepend.slice(-count).concat(results) :
|
||||||
prepend.slice(0, count).concat(results);
|
prepend.slice(0, count).concat(results);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns all items from the current list except the items listed in the operand array
|
Returns all items from the current list except the items listed in the operand array
|
||||||
*/
|
*/
|
||||||
exports.remove = function (source, operator) {
|
exports.remove = function (source, operator) {
|
||||||
var array = $tw.utils.parseStringArray(operator.operand, "true"),
|
var array = $tw.utils.parseStringArray(operator.operand, "true"),
|
||||||
results = prepare_results(source),
|
results = prepare_results(source),
|
||||||
count = parseInt(operator.suffix) || array.length,
|
count = parseInt(operator.suffix) || array.length,
|
||||||
p,
|
p,
|
||||||
len,
|
len,
|
||||||
index;
|
index;
|
||||||
len = array.length - 1;
|
len = array.length - 1;
|
||||||
for (p = 0; p < count; ++p) {
|
for (p = 0; p < count; ++p) {
|
||||||
if (operator.prefix) {
|
if (operator.prefix) {
|
||||||
index = results.indexOf(array[len - p]);
|
index = results.indexOf(array[len - p]);
|
||||||
} else {
|
} else {
|
||||||
index = results.indexOf(array[p]);
|
index = results.indexOf(array[p]);
|
||||||
}
|
}
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
results.splice(index, 1);
|
results.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns all items from the current list sorted in the order of the items in the operand array
|
Returns all items from the current list sorted in the order of the items in the operand array
|
||||||
*/
|
*/
|
||||||
exports.sortby = function (source, operator) {
|
exports.sortby = function (source, operator) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
if (!results || results.length < 2) {
|
if (!results || results.length < 2) {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
|
var lookup = $tw.utils.parseStringArray(operator.operand, "true");
|
||||||
results.sort(function (a, b) {
|
results.sort(function (a, b) {
|
||||||
return lookup.indexOf(a) - lookup.indexOf(b);
|
return lookup.indexOf(a) - lookup.indexOf(b);
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Removes all duplicate items from the current list
|
Removes all duplicate items from the current list
|
||||||
*/
|
*/
|
||||||
exports.unique = function (source, operator) {
|
exports.unique = function (source, operator) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
var set = results.reduce(function (a, b) {
|
var set = results.reduce(function (a, b) {
|
||||||
if (a.indexOf(b) < 0) {
|
if (a.indexOf(b) < 0) {
|
||||||
a.push(b);
|
a.push(b);
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
return set;
|
return set;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var cycleValueInArray = function(results,operands,stepSize) {
|
||||||
|
var resultsIndex,
|
||||||
|
step = stepSize || 1,
|
||||||
|
i = 0,
|
||||||
|
opLength = operands.length,
|
||||||
|
nextOperandIndex;
|
||||||
|
for(i; i < opLength; i++) {
|
||||||
|
resultsIndex = results.indexOf(operands[i]);
|
||||||
|
if(resultsIndex !== -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(resultsIndex !== -1) {
|
||||||
|
i = i + step;
|
||||||
|
nextOperandIndex = (i < opLength ? i : i - opLength);
|
||||||
|
if(operands.length > 1) {
|
||||||
|
results.splice(resultsIndex,1,operands[nextOperandIndex]);
|
||||||
|
} else {
|
||||||
|
results.splice(resultsIndex,1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
results.push(operands[0]);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Toggles an item in the current list.
|
||||||
|
*/
|
||||||
|
exports.toggle = function(source,operator) {
|
||||||
|
return cycleValueInArray(prepare_results(source),operator.operands);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.cycle = function(source,operator) {
|
||||||
|
var results = prepare_results(source),
|
||||||
|
operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]),
|
||||||
|
step = $tw.utils.getInt(operator.operands[1]||"",1);
|
||||||
|
if(step < 0) {
|
||||||
|
operands.reverse();
|
||||||
|
step = Math.abs(step);
|
||||||
|
}
|
||||||
|
return cycleValueInArray(results,operands,step);
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -12,7 +12,7 @@ Initialise basic platform $:/info/ tiddlers
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.getInfoTiddlerFields = function() {
|
exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
|
||||||
var mapBoolean = function(value) {return value ? "yes" : "no";},
|
var mapBoolean = function(value) {return value ? "yes" : "no";},
|
||||||
infoTiddlerFields = [];
|
infoTiddlerFields = [];
|
||||||
// Basics
|
// Basics
|
||||||
@ -36,6 +36,13 @@ exports.getInfoTiddlerFields = function() {
|
|||||||
// Screen size
|
// Screen size
|
||||||
infoTiddlerFields.push({title: "$:/info/browser/screen/width", text: window.screen.width.toString()});
|
infoTiddlerFields.push({title: "$:/info/browser/screen/width", text: window.screen.width.toString()});
|
||||||
infoTiddlerFields.push({title: "$:/info/browser/screen/height", text: window.screen.height.toString()});
|
infoTiddlerFields.push({title: "$:/info/browser/screen/height", text: window.screen.height.toString()});
|
||||||
|
// Dark mode through event listener on MediaQueryList
|
||||||
|
var mqList = window.matchMedia("(prefers-color-scheme: dark)"),
|
||||||
|
getDarkModeTiddler = function() {return {title: "$:/info/darkmode", text: mqList.matches ? "yes" : "no"};};
|
||||||
|
infoTiddlerFields.push(getDarkModeTiddler());
|
||||||
|
mqList.addListener(function(event) {
|
||||||
|
updateInfoTiddlersCallback([getDarkModeTiddler()]);
|
||||||
|
});
|
||||||
// Language
|
// Language
|
||||||
infoTiddlerFields.push({title: "$:/info/browser/language", text: navigator.language || ""});
|
infoTiddlerFields.push({title: "$:/info/browser/language", text: navigator.language || ""});
|
||||||
}
|
}
|
||||||
|
@ -285,13 +285,17 @@ KeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
|
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
|
||||||
return event.ctrlKey && !event.shiftKey && !event.altKey ? "ctrl" :
|
return event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey ? "ctrl" :
|
||||||
event.shiftKey && !event.ctrlKey && !event.altKey? "shift" :
|
event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey ? "shift" :
|
||||||
event.ctrlKey && event.shiftKey && !event.altKey ? "ctrl-shift" :
|
event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey ? "ctrl-shift" :
|
||||||
event.altKey && !event.shiftKey && !event.ctrlKey ? "alt" :
|
event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt" :
|
||||||
event.altKey && event.shiftKey && !event.ctrlKey ? "alt-shift" :
|
event.altKey && event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt-shift" :
|
||||||
event.altKey && event.ctrlKey && !event.shiftKey ? "ctrl-alt" :
|
event.altKey && event.ctrlKey && !event.shiftKey && !event.metaKey ? "ctrl-alt" :
|
||||||
event.altKey && event.shiftKey && event.ctrlKey ? "ctrl-alt-shift" : "normal";
|
event.altKey && event.shiftKey && event.ctrlKey && !event.metaKey ? "ctrl-alt-shift" :
|
||||||
|
event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey ? "meta" :
|
||||||
|
event.metaKey && event.ctrlKey && !event.shiftKey && !event.altKey ? "meta-ctrl" :
|
||||||
|
event.metaKey && event.ctrlKey && event.shiftKey && !event.altKey ? "meta-ctrl-shift" :
|
||||||
|
event.metaKey && event.ctrlKey & event.shiftKey && event.altKey ? "meta-ctrl-alt-shift" : "normal";
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyboardManager.prototype.getShortcutTiddlerList = function() {
|
KeyboardManager.prototype.getShortcutTiddlerList = function() {
|
||||||
|
@ -23,10 +23,12 @@ var HtmlParser = function(type,text,options) {
|
|||||||
type: "element",
|
type: "element",
|
||||||
tag: "iframe",
|
tag: "iframe",
|
||||||
attributes: {
|
attributes: {
|
||||||
src: {type: "string", value: src},
|
src: {type: "string", value: src}
|
||||||
sandbox: {type: "string", value: ""}
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
if($tw.wiki.getTiddlerText("$:/config/HtmlParser/DisableSandbox","no") !== "yes") {
|
||||||
|
this.tree[0].attributes.sandbox = {type: "string", value: $tw.wiki.getTiddlerText("$:/config/HtmlParser/SandboxTokens","")};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports["text/html"] = HtmlParser;
|
exports["text/html"] = HtmlParser;
|
||||||
|
@ -39,6 +39,7 @@ exports["image/webp"] = ImageParser;
|
|||||||
exports["image/heic"] = ImageParser;
|
exports["image/heic"] = ImageParser;
|
||||||
exports["image/heif"] = ImageParser;
|
exports["image/heif"] = ImageParser;
|
||||||
exports["image/x-icon"] = ImageParser;
|
exports["image/x-icon"] = ImageParser;
|
||||||
|
exports["image/vnd.microsoft.icon"] = ImageParser;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ exports.parseMacroParameter = function(source,pos) {
|
|||||||
start: pos
|
start: pos
|
||||||
};
|
};
|
||||||
// Define our regexp
|
// Define our regexp
|
||||||
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^\s>"'=]+)))/g;
|
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/g;
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||||
// Look for the parameter
|
// Look for the parameter
|
||||||
|
@ -31,7 +31,7 @@ exports.findNextMatch = function(startPos) {
|
|||||||
this.matchRegExp.lastIndex = startPos;
|
this.matchRegExp.lastIndex = startPos;
|
||||||
this.match = this.matchRegExp.exec(this.parser.source);
|
this.match = this.matchRegExp.exec(this.parser.source);
|
||||||
if(this.match) {
|
if(this.match) {
|
||||||
this.endMatchRegExp.lastIndex = startPos + this.match[0].length;
|
this.endMatchRegExp.lastIndex = this.match.index + this.match[0].length;
|
||||||
this.endMatch = this.endMatchRegExp.exec(this.parser.source);
|
this.endMatch = this.endMatchRegExp.exec(this.parser.source);
|
||||||
if(this.endMatch) {
|
if(this.endMatch) {
|
||||||
return this.match.index;
|
return this.match.index;
|
||||||
|
@ -31,7 +31,7 @@ exports.findNextMatch = function(startPos) {
|
|||||||
this.matchRegExp.lastIndex = startPos;
|
this.matchRegExp.lastIndex = startPos;
|
||||||
this.match = this.matchRegExp.exec(this.parser.source);
|
this.match = this.matchRegExp.exec(this.parser.source);
|
||||||
if(this.match) {
|
if(this.match) {
|
||||||
this.endMatchRegExp.lastIndex = startPos + this.match[0].length;
|
this.endMatchRegExp.lastIndex = this.match.index + this.match[0].length;
|
||||||
this.endMatch = this.endMatchRegExp.exec(this.parser.source);
|
this.endMatch = this.endMatchRegExp.exec(this.parser.source);
|
||||||
if(this.endMatch) {
|
if(this.endMatch) {
|
||||||
return this.match.index;
|
return this.match.index;
|
||||||
|
@ -53,17 +53,12 @@ exports.parse = function() {
|
|||||||
tag.isBlock = this.is.block || hasLineBreak;
|
tag.isBlock = this.is.block || hasLineBreak;
|
||||||
// Parse the body if we need to
|
// Parse the body if we need to
|
||||||
if(!tag.isSelfClosing && $tw.config.htmlVoidElements.indexOf(tag.tag) === -1) {
|
if(!tag.isSelfClosing && $tw.config.htmlVoidElements.indexOf(tag.tag) === -1) {
|
||||||
var reEndString = "</" + $tw.utils.escapeRegExp(tag.tag) + ">",
|
var reEndString = "</" + $tw.utils.escapeRegExp(tag.tag) + ">";
|
||||||
reEnd = new RegExp("(" + reEndString + ")","mg");
|
|
||||||
if(hasLineBreak) {
|
if(hasLineBreak) {
|
||||||
tag.children = this.parser.parseBlocks(reEndString);
|
tag.children = this.parser.parseBlocks(reEndString);
|
||||||
} else {
|
} else {
|
||||||
tag.children = this.parser.parseInlineRun(reEnd);
|
var reEnd = new RegExp("(" + reEndString + ")","mg");
|
||||||
}
|
tag.children = this.parser.parseInlineRun(reEnd,{eatTerminator: true});
|
||||||
reEnd.lastIndex = this.parser.pos;
|
|
||||||
var endMatch = reEnd.exec(this.parser.source);
|
|
||||||
if(endMatch && endMatch.index === this.parser.pos) {
|
|
||||||
this.parser.pos = endMatch.index + endMatch[0].length;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return the tag
|
// Return the tag
|
||||||
|
@ -21,40 +21,36 @@ exports.types = {block: true};
|
|||||||
|
|
||||||
exports.init = function(parser) {
|
exports.init = function(parser) {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
// Regexp to match
|
};
|
||||||
this.matchRegExp = /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*?)>>(?:\r?\n|$)/mg;
|
|
||||||
|
exports.findNextMatch = function(startPos) {
|
||||||
|
var nextStart = startPos;
|
||||||
|
// Try parsing at all possible macrocall openers until we match
|
||||||
|
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
|
||||||
|
var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
|
||||||
|
if(nextCall) {
|
||||||
|
var c = this.parser.source.charAt(nextCall.end);
|
||||||
|
// Ensure EOL after parsed macro
|
||||||
|
// If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym
|
||||||
|
if ((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) {
|
||||||
|
this.nextCall = nextCall;
|
||||||
|
return nextStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextStart += 2;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parse the most recent match
|
Parse the most recent match
|
||||||
*/
|
*/
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Get all the details of the match
|
var call = this.nextCall;
|
||||||
var macroName = this.match[1],
|
call.isBlock = true;
|
||||||
paramString = this.match[2];
|
this.nextCall = null;
|
||||||
// Move past the macro call
|
this.parser.pos = call.end;
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
return [call];
|
||||||
var params = [],
|
|
||||||
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
|
|
||||||
paramMatch = reParam.exec(paramString);
|
|
||||||
while(paramMatch) {
|
|
||||||
// Process this parameter
|
|
||||||
var paramInfo = {
|
|
||||||
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6]
|
|
||||||
};
|
|
||||||
if(paramMatch[1]) {
|
|
||||||
paramInfo.name = paramMatch[1];
|
|
||||||
}
|
|
||||||
params.push(paramInfo);
|
|
||||||
// Find the next match
|
|
||||||
paramMatch = reParam.exec(paramString);
|
|
||||||
}
|
|
||||||
return [{
|
|
||||||
type: "macrocall",
|
|
||||||
name: macroName,
|
|
||||||
params: params,
|
|
||||||
isBlock: true
|
|
||||||
}];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -21,39 +21,29 @@ exports.types = {inline: true};
|
|||||||
|
|
||||||
exports.init = function(parser) {
|
exports.init = function(parser) {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
// Regexp to match
|
};
|
||||||
this.matchRegExp = /<<([^\s>]+)\s*([\s\S]*?)>>/mg;
|
|
||||||
|
exports.findNextMatch = function(startPos) {
|
||||||
|
var nextStart = startPos;
|
||||||
|
// Try parsing at all possible macrocall openers until we match
|
||||||
|
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
|
||||||
|
this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
|
||||||
|
if(this.nextCall) {
|
||||||
|
return nextStart;
|
||||||
|
}
|
||||||
|
nextStart += 2;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parse the most recent match
|
Parse the most recent match
|
||||||
*/
|
*/
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Get all the details of the match
|
var call = this.nextCall;
|
||||||
var macroName = this.match[1],
|
this.nextCall = null;
|
||||||
paramString = this.match[2];
|
this.parser.pos = call.end;
|
||||||
// Move past the macro call
|
return [call];
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
|
||||||
var params = [],
|
|
||||||
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
|
|
||||||
paramMatch = reParam.exec(paramString);
|
|
||||||
while(paramMatch) {
|
|
||||||
// Process this parameter
|
|
||||||
var paramInfo = {
|
|
||||||
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]|| paramMatch[6]
|
|
||||||
};
|
|
||||||
if(paramMatch[1]) {
|
|
||||||
paramInfo.name = paramMatch[1];
|
|
||||||
}
|
|
||||||
params.push(paramInfo);
|
|
||||||
// Find the next match
|
|
||||||
paramMatch = reParam.exec(paramString);
|
|
||||||
}
|
|
||||||
return [{
|
|
||||||
type: "macrocall",
|
|
||||||
name: macroName,
|
|
||||||
params: params
|
|
||||||
}];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -25,6 +25,14 @@ Attributes are stored as hashmaps of the following objects:
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
type: content type of text
|
||||||
|
text: text to be parsed
|
||||||
|
options: see below:
|
||||||
|
parseAsInline: true to parse text as inline instead of block
|
||||||
|
wiki: reference to wiki to use
|
||||||
|
_canonical_uri: optional URI of content if text is missing or empty
|
||||||
|
*/
|
||||||
var WikiParser = function(type,text,options) {
|
var WikiParser = function(type,text,options) {
|
||||||
this.wiki = options.wiki;
|
this.wiki = options.wiki;
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -33,19 +41,6 @@ var WikiParser = function(type,text,options) {
|
|||||||
this.loadRemoteTiddler(options._canonical_uri);
|
this.loadRemoteTiddler(options._canonical_uri);
|
||||||
text = $tw.language.getRawString("LazyLoadingWarning");
|
text = $tw.language.getRawString("LazyLoadingWarning");
|
||||||
}
|
}
|
||||||
// Initialise the classes if we don't have them already
|
|
||||||
if(!this.pragmaRuleClasses) {
|
|
||||||
WikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules("wikirule","pragma",$tw.WikiRuleBase);
|
|
||||||
this.setupRules(WikiParser.prototype.pragmaRuleClasses,"$:/config/WikiParserRules/Pragmas/");
|
|
||||||
}
|
|
||||||
if(!this.blockRuleClasses) {
|
|
||||||
WikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules("wikirule","block",$tw.WikiRuleBase);
|
|
||||||
this.setupRules(WikiParser.prototype.blockRuleClasses,"$:/config/WikiParserRules/Block/");
|
|
||||||
}
|
|
||||||
if(!this.inlineRuleClasses) {
|
|
||||||
WikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules("wikirule","inline",$tw.WikiRuleBase);
|
|
||||||
this.setupRules(WikiParser.prototype.inlineRuleClasses,"$:/config/WikiParserRules/Inline/");
|
|
||||||
}
|
|
||||||
// Save the parse text
|
// Save the parse text
|
||||||
this.type = type || "text/vnd.tiddlywiki";
|
this.type = type || "text/vnd.tiddlywiki";
|
||||||
this.source = text || "";
|
this.source = text || "";
|
||||||
@ -54,13 +49,38 @@ var WikiParser = function(type,text,options) {
|
|||||||
this.configTrimWhiteSpace = false;
|
this.configTrimWhiteSpace = false;
|
||||||
// Set current parse position
|
// Set current parse position
|
||||||
this.pos = 0;
|
this.pos = 0;
|
||||||
// Instantiate the pragma parse rules
|
// Start with empty output
|
||||||
this.pragmaRules = this.instantiateRules(this.pragmaRuleClasses,"pragma",0);
|
|
||||||
// Instantiate the parser block and inline rules
|
|
||||||
this.blockRules = this.instantiateRules(this.blockRuleClasses,"block",0);
|
|
||||||
this.inlineRules = this.instantiateRules(this.inlineRuleClasses,"inline",0);
|
|
||||||
// Parse any pragmas
|
|
||||||
this.tree = [];
|
this.tree = [];
|
||||||
|
// Assemble the rule classes we're going to use
|
||||||
|
var pragmaRuleClasses, blockRuleClasses, inlineRuleClasses;
|
||||||
|
if(options.rules) {
|
||||||
|
pragmaRuleClasses = options.rules.pragma;
|
||||||
|
blockRuleClasses = options.rules.block;
|
||||||
|
inlineRuleClasses = options.rules.inline;
|
||||||
|
} else {
|
||||||
|
// Setup the rule classes if we don't have them already
|
||||||
|
if(!this.pragmaRuleClasses) {
|
||||||
|
WikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules("wikirule","pragma",$tw.WikiRuleBase);
|
||||||
|
this.setupRules(WikiParser.prototype.pragmaRuleClasses,"$:/config/WikiParserRules/Pragmas/");
|
||||||
|
}
|
||||||
|
pragmaRuleClasses = this.pragmaRuleClasses;
|
||||||
|
if(!this.blockRuleClasses) {
|
||||||
|
WikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules("wikirule","block",$tw.WikiRuleBase);
|
||||||
|
this.setupRules(WikiParser.prototype.blockRuleClasses,"$:/config/WikiParserRules/Block/");
|
||||||
|
}
|
||||||
|
blockRuleClasses = this.blockRuleClasses;
|
||||||
|
if(!this.inlineRuleClasses) {
|
||||||
|
WikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules("wikirule","inline",$tw.WikiRuleBase);
|
||||||
|
this.setupRules(WikiParser.prototype.inlineRuleClasses,"$:/config/WikiParserRules/Inline/");
|
||||||
|
}
|
||||||
|
inlineRuleClasses = this.inlineRuleClasses;
|
||||||
|
}
|
||||||
|
// Instantiate the pragma parse rules
|
||||||
|
this.pragmaRules = this.instantiateRules(pragmaRuleClasses,"pragma",0);
|
||||||
|
// Instantiate the parser block and inline rules
|
||||||
|
this.blockRules = this.instantiateRules(blockRuleClasses,"block",0);
|
||||||
|
this.inlineRules = this.instantiateRules(inlineRuleClasses,"inline",0);
|
||||||
|
// Parse any pragmas
|
||||||
var topBranch = this.parsePragmas();
|
var topBranch = this.parsePragmas();
|
||||||
// Parse the text into inline runs or blocks
|
// Parse the text into inline runs or blocks
|
||||||
if(options.parseAsInline) {
|
if(options.parseAsInline) {
|
||||||
@ -405,22 +425,18 @@ Amend the rules used by this instance of the parser
|
|||||||
WikiParser.prototype.amendRules = function(type,names) {
|
WikiParser.prototype.amendRules = function(type,names) {
|
||||||
names = names || [];
|
names = names || [];
|
||||||
// Define the filter function
|
// Define the filter function
|
||||||
var keepFilter;
|
var target;
|
||||||
if(type === "only") {
|
if(type === "only") {
|
||||||
keepFilter = function(name) {
|
target = true;
|
||||||
return names.indexOf(name) !== -1;
|
|
||||||
};
|
|
||||||
} else if(type === "except") {
|
} else if(type === "except") {
|
||||||
keepFilter = function(name) {
|
target = false;
|
||||||
return names.indexOf(name) === -1;
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Define a function to process each of our rule arrays
|
// Define a function to process each of our rule arrays
|
||||||
var processRuleArray = function(ruleArray) {
|
var processRuleArray = function(ruleArray) {
|
||||||
for(var t=ruleArray.length-1; t>=0; t--) {
|
for(var t=ruleArray.length-1; t>=0; t--) {
|
||||||
if(!keepFilter(ruleArray[t].rule.name)) {
|
if((names.indexOf(ruleArray[t].rule.name) === -1) === target) {
|
||||||
ruleArray.splice(t,1);
|
ruleArray.splice(t,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,8 +197,12 @@ SaverHandler.prototype.isDirty = function() {
|
|||||||
Update the document body with the class "tc-dirty" if the wiki has unsaved/unsynced changes
|
Update the document body with the class "tc-dirty" if the wiki has unsaved/unsynced changes
|
||||||
*/
|
*/
|
||||||
SaverHandler.prototype.updateDirtyStatus = function() {
|
SaverHandler.prototype.updateDirtyStatus = function() {
|
||||||
|
var self = this;
|
||||||
if($tw.browser) {
|
if($tw.browser) {
|
||||||
$tw.utils.toggleClass(document.body,"tc-dirty",this.isDirty());
|
$tw.utils.toggleClass(document.body,"tc-dirty",this.isDirty());
|
||||||
|
$tw.utils.each($tw.windows,function(win) {
|
||||||
|
$tw.utils.toggleClass(win.document.body,"tc-dirty",self.isDirty());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
60
core/modules/savers/custom.js
Normal file
60
core/modules/savers/custom.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/savers/custom.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: saver
|
||||||
|
|
||||||
|
Looks for `window.$tw.customSaver` first on the current window, then
|
||||||
|
on the parent window (of an iframe). If present, the saver must define
|
||||||
|
save: function(text,method,callback) { ... }
|
||||||
|
and the saver may define
|
||||||
|
priority: number
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var findSaver = function(window) {
|
||||||
|
try {
|
||||||
|
return window && window.$tw && window.$tw.customSaver;
|
||||||
|
} catch (err) {
|
||||||
|
// Catching the exception is the most reliable way to detect cross-origin iframe errors.
|
||||||
|
// For example, instead of saying that `window.parent.$tw` is undefined, Firefox will throw
|
||||||
|
// Uncaught DOMException: Permission denied to access property "$tw" on cross-origin object
|
||||||
|
console.log({ msg: "custom saver is disabled", reason: err });
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var saver = findSaver(window) || findSaver(window.parent) || {};
|
||||||
|
|
||||||
|
var CustomSaver = function(wiki) {
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomSaver.prototype.save = function(text,method,callback) {
|
||||||
|
return saver.save(text, method, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Information about this saver
|
||||||
|
*/
|
||||||
|
CustomSaver.prototype.info = {
|
||||||
|
name: "custom",
|
||||||
|
priority: saver.priority || 4000,
|
||||||
|
capabilities: ["save","autosave"]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Static method that returns true if this saver is capable of working
|
||||||
|
*/
|
||||||
|
exports.canSave = function(wiki) {
|
||||||
|
return !!(saver.save);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create an instance of this saver
|
||||||
|
*/
|
||||||
|
exports.create = function(wiki) {
|
||||||
|
return new CustomSaver(wiki);
|
||||||
|
};
|
||||||
|
})();
|
@ -26,12 +26,13 @@ GitHubSaver.prototype.save = function(text,method,callback) {
|
|||||||
repo = this.wiki.getTiddlerText("$:/GitHub/Repo"),
|
repo = this.wiki.getTiddlerText("$:/GitHub/Repo"),
|
||||||
path = this.wiki.getTiddlerText("$:/GitHub/Path",""),
|
path = this.wiki.getTiddlerText("$:/GitHub/Path",""),
|
||||||
filename = this.wiki.getTiddlerText("$:/GitHub/Filename"),
|
filename = this.wiki.getTiddlerText("$:/GitHub/Filename"),
|
||||||
branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "master",
|
branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "main",
|
||||||
endpoint = this.wiki.getTiddlerText("$:/GitHub/ServerURL") || "https://api.github.com",
|
endpoint = this.wiki.getTiddlerText("$:/GitHub/ServerURL") || "https://api.github.com",
|
||||||
headers = {
|
headers = {
|
||||||
"Accept": "application/vnd.github.v3+json",
|
"Accept": "application/vnd.github.v3+json",
|
||||||
"Content-Type": "application/json;charset=UTF-8",
|
"Content-Type": "application/json;charset=UTF-8",
|
||||||
"Authorization": "Basic " + window.btoa(username + ":" + password)
|
"Authorization": "Basic " + window.btoa(username + ":" + password),
|
||||||
|
"If-None-Match": ""
|
||||||
};
|
};
|
||||||
// Bail if we don't have everything we need
|
// Bail if we don't have everything we need
|
||||||
if(!username || !password || !repo || !filename) {
|
if(!username || !password || !repo || !filename) {
|
||||||
|
@ -28,10 +28,22 @@ UploadSaver.prototype.save = function(text,method,callback) {
|
|||||||
password = $tw.utils.getPassword("upload"),
|
password = $tw.utils.getPassword("upload"),
|
||||||
uploadDir = this.wiki.getTextReference("$:/UploadDir") || ".",
|
uploadDir = this.wiki.getTextReference("$:/UploadDir") || ".",
|
||||||
uploadFilename = this.wiki.getTextReference("$:/UploadFilename") || "index.html",
|
uploadFilename = this.wiki.getTextReference("$:/UploadFilename") || "index.html",
|
||||||
|
uploadWithUrlOnly = this.wiki.getTextReference("$:/UploadWithUrlOnly") || "no",
|
||||||
url = this.wiki.getTextReference("$:/UploadURL");
|
url = this.wiki.getTextReference("$:/UploadURL");
|
||||||
// Bail out if we don't have the bits we need
|
// Bail out if we don't have the bits we need
|
||||||
if(!username || username.toString().trim() === "" || !password || password.toString().trim() === "") {
|
if (uploadWithUrlOnly === "yes") {
|
||||||
return false;
|
// The url is good enough. No need for a username and password.
|
||||||
|
// Assume the server uses some other kind of auth mechanism.
|
||||||
|
if(!url || url.toString().trim() === "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Require username and password to be present.
|
||||||
|
// Assume the server uses the standard UploadPlugin username/password.
|
||||||
|
if(!username || username.toString().trim() === "" || !password || password.toString().trim() === "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Construct the url if not provided
|
// Construct the url if not provided
|
||||||
if(!url) {
|
if(!url) {
|
||||||
|
@ -25,8 +25,9 @@ exports.handler = function(request,response,state) {
|
|||||||
response.end();
|
response.end();
|
||||||
} else {
|
} else {
|
||||||
// Redirect to the root wiki if login worked
|
// Redirect to the root wiki if login worked
|
||||||
|
var location = ($tw.syncadaptor && $tw.syncadaptor.host)? $tw.syncadaptor.host: "/";
|
||||||
response.writeHead(302,{
|
response.writeHead(302,{
|
||||||
Location: "/"
|
Location: location
|
||||||
});
|
});
|
||||||
response.end();
|
response.end();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ exports.handler = function(request,response,state) {
|
|||||||
username: state.authenticatedUsername || state.server.get("anon-username") || "",
|
username: state.authenticatedUsername || state.server.get("anon-username") || "",
|
||||||
anonymous: !state.authenticatedUsername,
|
anonymous: !state.authenticatedUsername,
|
||||||
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
|
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
|
||||||
|
sse_enabled: state.server.get("sse-enabled") === "yes",
|
||||||
space: {
|
space: {
|
||||||
recipe: "default"
|
recipe: "default"
|
||||||
},
|
},
|
||||||
|
@ -28,6 +28,9 @@ exports.handler = function(request,response,state) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(state.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "no") {
|
||||||
|
filter += "+[!is[system]]";
|
||||||
|
}
|
||||||
var excludeFields = (state.queryParameters.exclude || "text").split(","),
|
var excludeFields = (state.queryParameters.exclude || "text").split(","),
|
||||||
titles = state.wiki.filterTiddlers(filter);
|
titles = state.wiki.filterTiddlers(filter);
|
||||||
response.writeHead(200, {"Content-Type": "application/json"});
|
response.writeHead(200, {"Content-Type": "application/json"});
|
||||||
|
70
core/modules/server/server-sent-events.js
Normal file
70
core/modules/server/server-sent-events.js
Normal 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;
|
||||||
|
|
||||||
|
})();
|
@ -21,29 +21,37 @@ exports.synchronous = true;
|
|||||||
var TITLE_INFO_PLUGIN = "$:/temp/info-plugin";
|
var TITLE_INFO_PLUGIN = "$:/temp/info-plugin";
|
||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
|
// Function to bake the info plugin with new tiddlers
|
||||||
|
var updateInfoPlugin = function(tiddlerFieldsArray) {
|
||||||
|
// Get the existing tiddlers
|
||||||
|
var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}});
|
||||||
|
// Add the new ones
|
||||||
|
$tw.utils.each(tiddlerFieldsArray,function(fields) {
|
||||||
|
if(fields && fields.title) {
|
||||||
|
json.tiddlers[fields.title] = fields;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Bake the info tiddlers into a plugin. We use the non-standard plugin-type "info" because ordinary plugins are only registered asynchronously after being loaded dynamically
|
||||||
|
var fields = {
|
||||||
|
title: TITLE_INFO_PLUGIN,
|
||||||
|
type: "application/json",
|
||||||
|
"plugin-type": "info",
|
||||||
|
text: JSON.stringify(json,null,$tw.config.preferences.jsonSpaces)
|
||||||
|
};
|
||||||
|
$tw.wiki.addTiddler(new $tw.Tiddler(fields));
|
||||||
|
|
||||||
|
};
|
||||||
// Collect up the info tiddlers
|
// Collect up the info tiddlers
|
||||||
var infoTiddlerFields = {};
|
var tiddlerFieldsArray = [];
|
||||||
// Give each info module a chance to fill in as many info tiddlers as they want
|
// Give each info module a chance to provide as many info tiddlers as they want as an array, and give them a callback for dynamically updating them
|
||||||
$tw.modules.forEachModuleOfType("info",function(title,moduleExports) {
|
$tw.modules.forEachModuleOfType("info",function(title,moduleExports) {
|
||||||
if(moduleExports && moduleExports.getInfoTiddlerFields) {
|
if(moduleExports && moduleExports.getInfoTiddlerFields) {
|
||||||
var tiddlerFieldsArray = moduleExports.getInfoTiddlerFields(infoTiddlerFields);
|
Array.prototype.push.apply(tiddlerFieldsArray,moduleExports.getInfoTiddlerFields(updateInfoPlugin));
|
||||||
$tw.utils.each(tiddlerFieldsArray,function(fields) {
|
|
||||||
if(fields) {
|
|
||||||
infoTiddlerFields[fields.title] = fields;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Bake the info tiddlers into a plugin. We use the non-standard plugin-type "info" because ordinary plugins are only registered asynchronously after being loaded dynamically
|
updateInfoPlugin(tiddlerFieldsArray);
|
||||||
var fields = {
|
var changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
||||||
title: TITLE_INFO_PLUGIN,
|
$tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]);
|
||||||
type: "application/json",
|
|
||||||
"plugin-type": "info",
|
|
||||||
text: JSON.stringify({tiddlers: infoTiddlerFields},null,$tw.config.preferences.jsonSpaces)
|
|
||||||
};
|
|
||||||
$tw.wiki.addTiddler(new $tw.Tiddler(fields));
|
|
||||||
$tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]);
|
|
||||||
$tw.wiki.registerPluginTiddlers("info");
|
|
||||||
$tw.wiki.unpackPluginTiddlers();
|
$tw.wiki.unpackPluginTiddlers();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@ exports.startup = function() {
|
|||||||
if($tw.node) {
|
if($tw.node) {
|
||||||
$tw.modules.applyMethods("utils-node",$tw.utils);
|
$tw.modules.applyMethods("utils-node",$tw.utils);
|
||||||
}
|
}
|
||||||
|
if($tw.browser) {
|
||||||
|
$tw.modules.applyMethods("utils-browser",$tw.utils);
|
||||||
|
}
|
||||||
$tw.modules.applyMethods("global",$tw);
|
$tw.modules.applyMethods("global",$tw);
|
||||||
$tw.modules.applyMethods("config",$tw.config);
|
$tw.modules.applyMethods("config",$tw.config);
|
||||||
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
|
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
|
||||||
|
@ -24,6 +24,7 @@ var PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = "$:/config/RegisterPluginType/";
|
|||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "no"});
|
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "no"});
|
||||||
$tw.wiki.addEventListener("change",function(changes) {
|
$tw.wiki.addEventListener("change",function(changes) {
|
||||||
|
// Work out which of the changed tiddlers are plugins that we need to reregister
|
||||||
var changesToProcess = [],
|
var changesToProcess = [],
|
||||||
requireReloadDueToPluginChange = false;
|
requireReloadDueToPluginChange = false;
|
||||||
$tw.utils.each(Object.keys(changes),function(title) {
|
$tw.utils.each(Object.keys(changes),function(title) {
|
||||||
@ -38,6 +39,7 @@ exports.startup = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Issue warning if any of the tiddlers require a reload
|
||||||
if(requireReloadDueToPluginChange) {
|
if(requireReloadDueToPluginChange) {
|
||||||
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "yes"});
|
$tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "yes"});
|
||||||
}
|
}
|
||||||
@ -45,12 +47,35 @@ exports.startup = function() {
|
|||||||
if(changesToProcess.length > 0) {
|
if(changesToProcess.length > 0) {
|
||||||
var changes = $tw.wiki.readPluginInfo(changesToProcess);
|
var changes = $tw.wiki.readPluginInfo(changesToProcess);
|
||||||
if(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) {
|
if(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) {
|
||||||
|
var changedShadowTiddlers = {};
|
||||||
|
// Collect the shadow tiddlers of any deleted plugins
|
||||||
|
$tw.utils.each(changes.deletedPlugins,function(pluginTitle) {
|
||||||
|
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
|
||||||
|
if(pluginInfo) {
|
||||||
|
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
|
||||||
|
changedShadowTiddlers[title] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Collect the shadow tiddlers of any modified plugins
|
||||||
|
$tw.utils.each(changes.modifiedPlugins,function(pluginTitle) {
|
||||||
|
var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle);
|
||||||
|
if(pluginInfo) {
|
||||||
|
$tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) {
|
||||||
|
changedShadowTiddlers[title] = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
// (Re-)register any modified plugins
|
// (Re-)register any modified plugins
|
||||||
$tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins);
|
$tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins);
|
||||||
// Unregister any deleted plugins
|
// Unregister any deleted plugins
|
||||||
$tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins);
|
$tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins);
|
||||||
// Unpack the shadow tiddlers
|
// Unpack the shadow tiddlers
|
||||||
$tw.wiki.unpackPluginTiddlers();
|
$tw.wiki.unpackPluginTiddlers();
|
||||||
|
// Queue change events for the changed shadow tiddlers
|
||||||
|
$tw.utils.each(Object.keys(changedShadowTiddlers),function(title) {
|
||||||
|
$tw.wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -21,7 +21,7 @@ exports.synchronous = true;
|
|||||||
// Default story and history lists
|
// Default story and history lists
|
||||||
var PAGE_TITLE_TITLE = "$:/core/wiki/title";
|
var PAGE_TITLE_TITLE = "$:/core/wiki/title";
|
||||||
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
|
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
|
||||||
var PAGE_TEMPLATE_TITLE = "$:/core/ui/PageTemplate";
|
var PAGE_TEMPLATE_TITLE = "$:/core/ui/RootTemplate";
|
||||||
|
|
||||||
// Time (in ms) that we defer refreshing changes to draft tiddlers
|
// Time (in ms) that we defer refreshing changes to draft tiddlers
|
||||||
var DRAFT_TIDDLER_TIMEOUT_TITLE = "$:/config/Drafts/TypingTimeout";
|
var DRAFT_TIDDLER_TIMEOUT_TITLE = "$:/config/Drafts/TypingTimeout";
|
||||||
@ -52,7 +52,7 @@ exports.startup = function() {
|
|||||||
}));
|
}));
|
||||||
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
|
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
|
||||||
$tw.perf.report("mainRender",function() {
|
$tw.perf.report("mainRender",function() {
|
||||||
$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget});
|
$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget, recursionMarker: "no"});
|
||||||
$tw.pageContainer = document.createElement("div");
|
$tw.pageContainer = document.createElement("div");
|
||||||
$tw.utils.addClass($tw.pageContainer,"tc-page-container-wrapper");
|
$tw.utils.addClass($tw.pageContainer,"tc-page-container-wrapper");
|
||||||
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
|
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
|
||||||
@ -107,7 +107,7 @@ exports.startup = function() {
|
|||||||
$tw.rootWidget.domNodes = [$tw.pageContainer];
|
$tw.rootWidget.domNodes = [$tw.pageContainer];
|
||||||
$tw.rootWidget.children = [$tw.pageWidgetNode];
|
$tw.rootWidget.children = [$tw.pageWidgetNode];
|
||||||
// Run any post-render startup actions
|
// Run any post-render startup actions
|
||||||
$tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction/PostRender");
|
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/PostRender");
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -25,6 +25,9 @@ exports.startup = function() {
|
|||||||
$tw.rootWidget.addEventListener("tm-modal",function(event) {
|
$tw.rootWidget.addEventListener("tm-modal",function(event) {
|
||||||
$tw.modal.display(event.param,{variables: event.paramObject, event: event});
|
$tw.modal.display(event.param,{variables: event.paramObject, event: event});
|
||||||
});
|
});
|
||||||
|
$tw.rootWidget.addEventListener("tm-show-switcher",function(event) {
|
||||||
|
$tw.modal.display("$:/core/ui/SwitcherModal",{variables: event.paramObject, event: event});
|
||||||
|
});
|
||||||
// Install the notification mechanism
|
// Install the notification mechanism
|
||||||
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
|
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
|
||||||
$tw.rootWidget.addEventListener("tm-notify",function(event) {
|
$tw.rootWidget.addEventListener("tm-notify",function(event) {
|
||||||
|
@ -23,7 +23,6 @@ var PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE = "$:/config/Performance/Instrument
|
|||||||
var widget = require("$:/core/modules/widgets/widget.js");
|
var widget = require("$:/core/modules/widgets/widget.js");
|
||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
var modules,n,m,f;
|
|
||||||
// Minimal browser detection
|
// Minimal browser detection
|
||||||
if($tw.browser) {
|
if($tw.browser) {
|
||||||
$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));
|
$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));
|
||||||
@ -64,12 +63,12 @@ exports.startup = function() {
|
|||||||
document: $tw.browser ? document : $tw.fakeDocument
|
document: $tw.browser ? document : $tw.fakeDocument
|
||||||
});
|
});
|
||||||
// Execute any startup actions
|
// Execute any startup actions
|
||||||
$tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction");
|
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction");
|
||||||
if($tw.browser) {
|
if($tw.browser) {
|
||||||
$tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction/Browser");
|
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Browser");
|
||||||
}
|
}
|
||||||
if($tw.node) {
|
if($tw.node) {
|
||||||
$tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction/Node");
|
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Node");
|
||||||
}
|
}
|
||||||
// Kick off the language manager and switcher
|
// Kick off the language manager and switcher
|
||||||
$tw.language = new $tw.Language();
|
$tw.language = new $tw.Language();
|
||||||
|
@ -150,6 +150,11 @@ function openStartupTiddlers(options) {
|
|||||||
// Save the story list
|
// Save the story list
|
||||||
$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: "", list: storyList},$tw.wiki.getModificationFields());
|
$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: "", list: storyList},$tw.wiki.getModificationFields());
|
||||||
// Update history
|
// Update history
|
||||||
|
var story = new $tw.Story({
|
||||||
|
wiki: $tw.wiki,
|
||||||
|
storyTitle: DEFAULT_STORY_TITLE,
|
||||||
|
historyTitle: DEFAULT_HISTORY_TITLE
|
||||||
|
});
|
||||||
if(!options.disableHistory) {
|
if(!options.disableHistory) {
|
||||||
// If a target tiddler was specified add it to the history stack
|
// If a target tiddler was specified add it to the history stack
|
||||||
if(target && target !== "") {
|
if(target && target !== "") {
|
||||||
@ -157,9 +162,9 @@ function openStartupTiddlers(options) {
|
|||||||
if(target.indexOf("[[") === 0 && target.substr(-2) === "]]") {
|
if(target.indexOf("[[") === 0 && target.substr(-2) === "]]") {
|
||||||
target = target.substr(2,target.length - 4);
|
target = target.substr(2,target.length - 4);
|
||||||
}
|
}
|
||||||
$tw.wiki.addToHistory(target);
|
story.addToHistory(target);
|
||||||
} else if(storyList.length > 0) {
|
} else if(storyList.length > 0) {
|
||||||
$tw.wiki.addToHistory(storyList[0]);
|
story.addToHistory(storyList[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ exports.after = ["startup"];
|
|||||||
exports.synchronous = true;
|
exports.synchronous = true;
|
||||||
|
|
||||||
// Global to keep track of open windows (hashmap by title)
|
// Global to keep track of open windows (hashmap by title)
|
||||||
var windows = {};
|
$tw.windows = {};
|
||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
// Handle open window message
|
// Handle open window message
|
||||||
@ -44,7 +44,7 @@ exports.startup = function() {
|
|||||||
catch(e) {
|
catch(e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
windows[title] = srcWindow;
|
$tw.windows[title] = srcWindow;
|
||||||
// Check for reopening the same window
|
// Check for reopening the same window
|
||||||
if(srcWindow.haveInitialisedWindow) {
|
if(srcWindow.haveInitialisedWindow) {
|
||||||
return;
|
return;
|
||||||
@ -54,7 +54,7 @@ exports.startup = function() {
|
|||||||
srcDocument.close();
|
srcDocument.close();
|
||||||
srcDocument.title = windowTitle;
|
srcDocument.title = windowTitle;
|
||||||
srcWindow.addEventListener("beforeunload",function(event) {
|
srcWindow.addEventListener("beforeunload",function(event) {
|
||||||
delete windows[title];
|
delete $tw.windows[title];
|
||||||
$tw.wiki.removeEventListener("change",refreshHandler);
|
$tw.wiki.removeEventListener("change",refreshHandler);
|
||||||
},false);
|
},false);
|
||||||
// Set up the styles
|
// Set up the styles
|
||||||
@ -84,16 +84,13 @@ exports.startup = function() {
|
|||||||
name: "keydown",
|
name: "keydown",
|
||||||
handlerObject: $tw.keyboardManager,
|
handlerObject: $tw.keyboardManager,
|
||||||
handlerMethod: "handleKeydownEvent"
|
handlerMethod: "handleKeydownEvent"
|
||||||
},{
|
|
||||||
name: "click",
|
|
||||||
handlerObject: $tw.popup,
|
|
||||||
handlerMethod: "handleEvent"
|
|
||||||
}]);
|
}]);
|
||||||
|
srcWindow.document.documentElement.addEventListener("click",$tw.popup,true);
|
||||||
srcWindow.haveInitialisedWindow = true;
|
srcWindow.haveInitialisedWindow = true;
|
||||||
});
|
});
|
||||||
// Close open windows when unloading main window
|
// Close open windows when unloading main window
|
||||||
$tw.addUnloadTask(function() {
|
$tw.addUnloadTask(function() {
|
||||||
$tw.utils.each(windows,function(win) {
|
$tw.utils.each($tw.windows,function(win) {
|
||||||
win.close();
|
win.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,6 +20,7 @@ Syncer.prototype.titleIsAnonymous = "$:/status/IsAnonymous";
|
|||||||
Syncer.prototype.titleIsReadOnly = "$:/status/IsReadOnly";
|
Syncer.prototype.titleIsReadOnly = "$:/status/IsReadOnly";
|
||||||
Syncer.prototype.titleUserName = "$:/status/UserName";
|
Syncer.prototype.titleUserName = "$:/status/UserName";
|
||||||
Syncer.prototype.titleSyncFilter = "$:/config/SyncFilter";
|
Syncer.prototype.titleSyncFilter = "$:/config/SyncFilter";
|
||||||
|
Syncer.prototype.titleSyncDisablePolling = "$:/config/SyncDisablePolling";
|
||||||
Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval";
|
Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval";
|
||||||
Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading";
|
Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading";
|
||||||
Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done";
|
Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done";
|
||||||
@ -89,7 +90,7 @@ function Syncer(options) {
|
|||||||
if(filteredChanges.length > 0) {
|
if(filteredChanges.length > 0) {
|
||||||
self.processTaskQueue();
|
self.processTaskQueue();
|
||||||
} else {
|
} else {
|
||||||
// Look for deletions of tiddlers we're already syncing
|
// Look for deletions of tiddlers we're already syncing
|
||||||
var outstandingDeletion = false
|
var outstandingDeletion = false
|
||||||
$tw.utils.each(changes,function(change,title,object) {
|
$tw.utils.each(changes,function(change,title,object) {
|
||||||
if(change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) {
|
if(change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) {
|
||||||
@ -121,7 +122,7 @@ function Syncer(options) {
|
|||||||
self.login(username,password,function() {});
|
self.login(username,password,function() {});
|
||||||
} else {
|
} else {
|
||||||
// No username and password, so we display a prompt
|
// No username and password, so we display a prompt
|
||||||
self.handleLoginEvent();
|
self.handleLoginEvent();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$tw.rootWidget.addEventListener("tm-logout",function() {
|
$tw.rootWidget.addEventListener("tm-logout",function() {
|
||||||
@ -138,7 +139,7 @@ function Syncer(options) {
|
|||||||
if(!this.disableUI && this.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== "yes") {
|
if(!this.disableUI && this.wiki.getTiddlerText(this.titleSyncDisableLazyLoading) !== "yes") {
|
||||||
this.wiki.addEventListener("lazyLoad",function(title) {
|
this.wiki.addEventListener("lazyLoad",function(title) {
|
||||||
self.handleLazyLoadEvent(title);
|
self.handleLazyLoadEvent(title);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Get the login status
|
// Get the login status
|
||||||
this.getStatus(function(err,isLoggedIn) {
|
this.getStatus(function(err,isLoggedIn) {
|
||||||
@ -173,8 +174,8 @@ Syncer.prototype.getTiddlerRevision = function(title) {
|
|||||||
if(this.syncadaptor && this.syncadaptor.getTiddlerRevision) {
|
if(this.syncadaptor && this.syncadaptor.getTiddlerRevision) {
|
||||||
return this.syncadaptor.getTiddlerRevision(title);
|
return this.syncadaptor.getTiddlerRevision(title);
|
||||||
} else {
|
} else {
|
||||||
return this.wiki.getTiddler(title).fields.revision;
|
return this.wiki.getTiddler(title).fields.revision;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -267,7 +268,7 @@ Syncer.prototype.getStatus = function(callback) {
|
|||||||
// Mark us as not logged in
|
// Mark us as not logged in
|
||||||
this.wiki.addTiddler({title: this.titleIsLoggedIn,text: "no"});
|
this.wiki.addTiddler({title: this.titleIsLoggedIn,text: "no"});
|
||||||
// Get login status
|
// Get login status
|
||||||
this.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous) {
|
this.syncadaptor.getStatus(function(err,isLoggedIn,username,isReadOnly,isAnonymous,isPollingDisabled) {
|
||||||
if(err) {
|
if(err) {
|
||||||
self.logger.alert(err);
|
self.logger.alert(err);
|
||||||
} else {
|
} else {
|
||||||
@ -278,6 +279,9 @@ Syncer.prototype.getStatus = function(callback) {
|
|||||||
if(isLoggedIn) {
|
if(isLoggedIn) {
|
||||||
self.wiki.addTiddler({title: self.titleUserName,text: username || ""});
|
self.wiki.addTiddler({title: self.titleUserName,text: username || ""});
|
||||||
}
|
}
|
||||||
|
if(isPollingDisabled) {
|
||||||
|
self.wiki.addTiddler({title: self.titleSyncDisablePolling, text: "yes"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Invoke the callback
|
// Invoke the callback
|
||||||
if(callback) {
|
if(callback) {
|
||||||
@ -301,11 +305,15 @@ Syncer.prototype.syncFromServer = function() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
triggerNextSync = function() {
|
triggerNextSync = function() {
|
||||||
self.pollTimerId = setTimeout(function() {
|
if(pollingEnabled) {
|
||||||
self.pollTimerId = null;
|
self.pollTimerId = setTimeout(function() {
|
||||||
self.syncFromServer.call(self);
|
self.pollTimerId = null;
|
||||||
},self.pollTimerInterval);
|
self.syncFromServer.call(self);
|
||||||
};
|
},self.pollTimerInterval);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes"),
|
||||||
|
pollingEnabled = (self.wiki.getTiddlerText(self.titleSyncDisablePolling) !== "yes");
|
||||||
if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {
|
if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) {
|
||||||
this.logger.log("Retrieving updated tiddler list");
|
this.logger.log("Retrieving updated tiddler list");
|
||||||
cancelNextSync();
|
cancelNextSync();
|
||||||
@ -320,13 +328,15 @@ Syncer.prototype.syncFromServer = function() {
|
|||||||
self.titlesToBeLoaded[title] = true;
|
self.titlesToBeLoaded[title] = true;
|
||||||
});
|
});
|
||||||
$tw.utils.each(updates.deletions,function(title) {
|
$tw.utils.each(updates.deletions,function(title) {
|
||||||
delete self.tiddlerInfo[title];
|
if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) {
|
||||||
self.logger.log("Deleting tiddler missing from server:",title);
|
delete self.tiddlerInfo[title];
|
||||||
self.wiki.deleteTiddler(title);
|
self.logger.log("Deleting tiddler missing from server:",title);
|
||||||
|
self.wiki.deleteTiddler(title);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if(updates.modifications.length > 0 || updates.deletions.length > 0) {
|
if(updates.modifications.length > 0 || updates.deletions.length > 0) {
|
||||||
self.processTaskQueue();
|
self.processTaskQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {
|
} else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) {
|
||||||
@ -365,9 +375,11 @@ Syncer.prototype.syncFromServer = function() {
|
|||||||
}
|
}
|
||||||
// Delete any tiddlers that were previously reported but missing this time
|
// Delete any tiddlers that were previously reported but missing this time
|
||||||
$tw.utils.each(previousTitles,function(title) {
|
$tw.utils.each(previousTitles,function(title) {
|
||||||
delete self.tiddlerInfo[title];
|
if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) {
|
||||||
self.logger.log("Deleting tiddler missing from server:",title);
|
delete self.tiddlerInfo[title];
|
||||||
self.wiki.deleteTiddler(title);
|
self.logger.log("Deleting tiddler missing from server:",title);
|
||||||
|
self.wiki.deleteTiddler(title);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
self.processTaskQueue();
|
self.processTaskQueue();
|
||||||
});
|
});
|
||||||
@ -504,7 +516,7 @@ Syncer.prototype.processTaskQueue = function() {
|
|||||||
} else {
|
} else {
|
||||||
self.updateDirtyStatus();
|
self.updateDirtyStatus();
|
||||||
// Process the next task
|
// Process the next task
|
||||||
self.processTaskQueue.call(self);
|
self.processTaskQueue.call(self);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -512,11 +524,11 @@ Syncer.prototype.processTaskQueue = function() {
|
|||||||
this.updateDirtyStatus();
|
this.updateDirtyStatus();
|
||||||
// And trigger a timeout if there is a pending task
|
// And trigger a timeout if there is a pending task
|
||||||
if(task === true) {
|
if(task === true) {
|
||||||
this.triggerTimeout();
|
this.triggerTimeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.updateDirtyStatus();
|
this.updateDirtyStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -550,7 +562,7 @@ Syncer.prototype.chooseNextTask = function() {
|
|||||||
isReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;
|
isReadyToSave = !tiddlerInfo || !tiddlerInfo.timestampLastSaved || tiddlerInfo.timestampLastSaved < thresholdLastSaved;
|
||||||
if(hasChanged) {
|
if(hasChanged) {
|
||||||
if(isReadyToSave) {
|
if(isReadyToSave) {
|
||||||
return new SaveTiddlerTask(this,title);
|
return new SaveTiddlerTask(this,title);
|
||||||
} else {
|
} else {
|
||||||
havePending = true;
|
havePending = true;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ exports.upgrade = function(wiki,titles,tiddlers) {
|
|||||||
// Reject the incoming plugin by blanking all its fields
|
// Reject the incoming plugin by blanking all its fields
|
||||||
if($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) {
|
if($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) {
|
||||||
tiddlers[title] = Object.create(null);
|
tiddlers[title] = Object.create(null);
|
||||||
messages[title] = requiresReload + $tw.language.getString("Import/Upgrader/Plugins/Suppressed/Version",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});
|
messages[title] = $tw.language.getString("Import/Upgrader/Plugins/Suppressed/Version",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ Modal message mechanism
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var widget = require("$:/core/modules/widgets/widget.js");
|
var widget = require("$:/core/modules/widgets/widget.js");
|
||||||
|
var navigator = require("$:/core/modules/widgets/navigator.js");
|
||||||
|
|
||||||
var Modal = function(wiki) {
|
var Modal = function(wiki) {
|
||||||
this.wiki = wiki;
|
this.wiki = wiki;
|
||||||
@ -30,7 +31,7 @@ Modal.prototype.display = function(title,options) {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
this.srcDocument = options.variables && (options.variables.rootwindow === "true" ||
|
this.srcDocument = options.variables && (options.variables.rootwindow === "true" ||
|
||||||
options.variables.rootwindow === "yes") ? document :
|
options.variables.rootwindow === "yes") ? document :
|
||||||
(options.event.event && options.event.event.target ? options.event.event.target.ownerDocument : document);
|
(options.event && options.event.event && options.event.event.target ? options.event.event.target.ownerDocument : document);
|
||||||
this.srcWindow = this.srcDocument.defaultView;
|
this.srcWindow = this.srcDocument.defaultView;
|
||||||
var self = this,
|
var self = this,
|
||||||
refreshHandler,
|
refreshHandler,
|
||||||
@ -41,7 +42,12 @@ Modal.prototype.display = function(title,options) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Create the variables
|
// Create the variables
|
||||||
var variables = $tw.utils.extend({currentTiddler: title},options.variables);
|
var variables = $tw.utils.extend({
|
||||||
|
currentTiddler: title,
|
||||||
|
"tv-story-list": (options.event && options.event.widget ? options.event.widget.getVariable("tv-story-list") : ""),
|
||||||
|
"tv-history-list": (options.event && options.event.widget ? options.event.widget.getVariable("tv-history-list") : "")
|
||||||
|
},options.variables);
|
||||||
|
|
||||||
// Create the wrapper divs
|
// Create the wrapper divs
|
||||||
var wrapper = this.srcDocument.createElement("div"),
|
var wrapper = this.srcDocument.createElement("div"),
|
||||||
modalBackdrop = this.srcDocument.createElement("div"),
|
modalBackdrop = this.srcDocument.createElement("div"),
|
||||||
@ -75,6 +81,31 @@ Modal.prototype.display = function(title,options) {
|
|||||||
modalFooter.appendChild(modalFooterHelp);
|
modalFooter.appendChild(modalFooterHelp);
|
||||||
modalFooter.appendChild(modalFooterButtons);
|
modalFooter.appendChild(modalFooterButtons);
|
||||||
modalWrapper.appendChild(modalFooter);
|
modalWrapper.appendChild(modalFooter);
|
||||||
|
var navigatorTree = {
|
||||||
|
"type": "navigator",
|
||||||
|
"attributes": {
|
||||||
|
"story": {
|
||||||
|
"name": "story",
|
||||||
|
"type": "string",
|
||||||
|
"value": variables["tv-story-list"]
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"name": "history",
|
||||||
|
"type": "string",
|
||||||
|
"value": variables["tv-history-list"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tag": "$navigator",
|
||||||
|
"isBlock": true,
|
||||||
|
"children": []
|
||||||
|
};
|
||||||
|
var navigatorWidgetNode = new navigator.navigator(navigatorTree, {
|
||||||
|
wiki: this.wiki,
|
||||||
|
document : this.srcDocument,
|
||||||
|
parentWidget: $tw.rootWidget
|
||||||
|
});
|
||||||
|
navigatorWidgetNode.render(modalBody,null);
|
||||||
|
|
||||||
// Render the title of the message
|
// Render the title of the message
|
||||||
var headerWidgetNode = this.wiki.makeTranscludeWidget(title,{
|
var headerWidgetNode = this.wiki.makeTranscludeWidget(title,{
|
||||||
field: "subtitle",
|
field: "subtitle",
|
||||||
@ -86,7 +117,7 @@ Modal.prototype.display = function(title,options) {
|
|||||||
type: "string",
|
type: "string",
|
||||||
value: title
|
value: title
|
||||||
}}}],
|
}}}],
|
||||||
parentWidget: $tw.rootWidget,
|
parentWidget: navigatorWidgetNode,
|
||||||
document: this.srcDocument,
|
document: this.srcDocument,
|
||||||
variables: variables,
|
variables: variables,
|
||||||
importPageMacros: true
|
importPageMacros: true
|
||||||
@ -94,11 +125,12 @@ Modal.prototype.display = function(title,options) {
|
|||||||
headerWidgetNode.render(headerTitle,null);
|
headerWidgetNode.render(headerTitle,null);
|
||||||
// Render the body of the message
|
// Render the body of the message
|
||||||
var bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{
|
var bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{
|
||||||
parentWidget: $tw.rootWidget,
|
parentWidget: navigatorWidgetNode,
|
||||||
document: this.srcDocument,
|
document: this.srcDocument,
|
||||||
variables: variables,
|
variables: variables,
|
||||||
importPageMacros: true
|
importPageMacros: true
|
||||||
});
|
});
|
||||||
|
|
||||||
bodyWidgetNode.render(modalBody,null);
|
bodyWidgetNode.render(modalBody,null);
|
||||||
// Setup the link if present
|
// Setup the link if present
|
||||||
if(options.downloadLink) {
|
if(options.downloadLink) {
|
||||||
@ -135,7 +167,7 @@ Modal.prototype.display = function(title,options) {
|
|||||||
value: $tw.language.getString("Buttons/Close/Caption")
|
value: $tw.language.getString("Buttons/Close/Caption")
|
||||||
}}}
|
}}}
|
||||||
]}],
|
]}],
|
||||||
parentWidget: $tw.rootWidget,
|
parentWidget: navigatorWidgetNode,
|
||||||
document: this.srcDocument,
|
document: this.srcDocument,
|
||||||
variables: variables,
|
variables: variables,
|
||||||
importPageMacros: true
|
importPageMacros: true
|
||||||
|
@ -1,33 +1,28 @@
|
|||||||
/*\
|
/*\
|
||||||
title: $:/core/modules/startup/CSSescape.js
|
title: $:/core/modules/utils/escapecss.js
|
||||||
type: application/javascript
|
type: application/javascript
|
||||||
module-type: startup
|
module-type: utils
|
||||||
|
|
||||||
Polyfill for CSS.escape()
|
Provides CSS.escape() functionality.
|
||||||
|
|
||||||
\*/
|
\*/
|
||||||
(function(root,factory){
|
(function(){
|
||||||
|
|
||||||
/*jslint node: true, browser: true */
|
/*jslint node: true, browser: true */
|
||||||
/*global $tw: false */
|
/*global $tw: false, window: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Export name and synchronous status
|
exports.escapeCSS = (function() {
|
||||||
exports.name = "css-escape";
|
// use browser's native CSS.escape() function if available
|
||||||
exports.platforms = ["browser"];
|
if ($tw.browser && window.CSS && window.CSS.escape) {
|
||||||
exports.after = ["startup"];
|
return window.CSS.escape;
|
||||||
exports.synchronous = true;
|
|
||||||
|
|
||||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
|
||||||
// https://github.com/umdjs/umd/blob/master/returnExports.js
|
|
||||||
exports.startup = factory(root);
|
|
||||||
}(typeof global != 'undefined' ? global : this, function(root) {
|
|
||||||
|
|
||||||
if (root.CSS && root.CSS.escape) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom/#serialize-an-identifier
|
// otherwise, a utility method is provided
|
||||||
var cssEscape = function(value) {
|
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||||
|
|
||||||
|
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||||
|
return function(value) {
|
||||||
if (arguments.length == 0) {
|
if (arguments.length == 0) {
|
||||||
throw new TypeError('`CSS.escape` requires an argument.');
|
throw new TypeError('`CSS.escape` requires an argument.');
|
||||||
}
|
}
|
||||||
@ -104,11 +99,6 @@ exports.startup = factory(root);
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
if (!root.CSS) {
|
})();
|
||||||
root.CSS = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
root.CSS.escape = cssEscape;
|
|
||||||
|
|
||||||
}));
|
|
@ -204,15 +204,23 @@ exports.deleteEmptyDirs = function(dirpath,callback) {
|
|||||||
/*
|
/*
|
||||||
Create a fileInfo object for saving a tiddler:
|
Create a fileInfo object for saving a tiddler:
|
||||||
filepath: the absolute path to the file containing the tiddler
|
filepath: the absolute path to the file containing the tiddler
|
||||||
type: the type of the tiddler file (NOT the type of the tiddler)
|
type: the type of the tiddler file on disk (NOT the type of the tiddler)
|
||||||
hasMetaFile: true if the file also has a companion .meta file
|
hasMetaFile: true if the file also has a companion .meta file
|
||||||
|
isEditableFile: true if the tiddler was loaded via non-standard options & marked editable
|
||||||
Options include:
|
Options include:
|
||||||
directory: absolute path of root directory to which we are saving
|
directory: absolute path of root directory to which we are saving
|
||||||
pathFilters: optional array of filters to be used to generate the base path
|
pathFilters: optional array of filters to be used to generate the base path
|
||||||
wiki: optional wiki for evaluating the pathFilters
|
extFilters: optional array of filters to be used to generate the base path
|
||||||
|
wiki: optional wiki for evaluating the pathFilters,
|
||||||
|
fileInfo: an existing fileInfo to check against
|
||||||
*/
|
*/
|
||||||
exports.generateTiddlerFileInfo = function(tiddler,options) {
|
exports.generateTiddlerFileInfo = function(tiddler,options) {
|
||||||
var fileInfo = {};
|
var fileInfo = {}, metaExt;
|
||||||
|
// Propagate the isEditableFile flag
|
||||||
|
if(options.fileInfo && !!options.fileInfo.isEditableFile) {
|
||||||
|
fileInfo.isEditableFile = true;
|
||||||
|
fileInfo.originalpath = options.fileInfo.originalpath;
|
||||||
|
}
|
||||||
// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace
|
// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace
|
||||||
var hasUnsafeFields = false;
|
var hasUnsafeFields = false;
|
||||||
$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {
|
$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {
|
||||||
@ -238,19 +246,67 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
|
|||||||
fileInfo.type = tiddlerType;
|
fileInfo.type = tiddlerType;
|
||||||
fileInfo.hasMetaFile = true;
|
fileInfo.hasMetaFile = true;
|
||||||
}
|
}
|
||||||
|
if(options.extFilters) {
|
||||||
|
// Check for extension overrides
|
||||||
|
metaExt = $tw.utils.generateTiddlerExtension(tiddler.fields.title,{
|
||||||
|
extFilters: options.extFilters,
|
||||||
|
wiki: options.wiki
|
||||||
|
});
|
||||||
|
if(metaExt) {
|
||||||
|
if(metaExt === ".tid") {
|
||||||
|
// Overriding to the .tid extension needs special handling
|
||||||
|
fileInfo.type = "application/x-tiddler";
|
||||||
|
fileInfo.hasMetaFile = false;
|
||||||
|
} else if (metaExt === ".json") {
|
||||||
|
// Overriding to the .json extension needs special handling
|
||||||
|
fileInfo.type = "application/json";
|
||||||
|
fileInfo.hasMetaFile = false;
|
||||||
|
} else {
|
||||||
|
//If the new type matches a known extention, use that MIME type's encoding
|
||||||
|
var extInfo = $tw.utils.getFileExtensionInfo(metaExt);
|
||||||
|
fileInfo.type = extInfo ? extInfo.type : null;
|
||||||
|
fileInfo.encoding = $tw.utils.getTypeEncoding(metaExt);
|
||||||
|
fileInfo.hasMetaFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Take the file extension from the tiddler content type
|
// Take the file extension from the tiddler content type or metaExt
|
||||||
var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""};
|
var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""};
|
||||||
// Generate the filepath
|
// Generate the filepath
|
||||||
fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{
|
fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{
|
||||||
extension: contentTypeInfo.extension,
|
extension: metaExt || contentTypeInfo.extension,
|
||||||
directory: options.directory,
|
directory: options.directory,
|
||||||
pathFilters: options.pathFilters,
|
pathFilters: options.pathFilters,
|
||||||
wiki: options.wiki
|
wiki: options.wiki,
|
||||||
|
fileInfo: options.fileInfo
|
||||||
});
|
});
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate the file extension for saving a tiddler
|
||||||
|
Options include:
|
||||||
|
extFilters: optional array of filters to be used to generate the extention
|
||||||
|
wiki: optional wiki for evaluating the extFilters
|
||||||
|
*/
|
||||||
|
exports.generateTiddlerExtension = function(title,options) {
|
||||||
|
var extension;
|
||||||
|
// Check if any of the extFilters applies
|
||||||
|
if(options.extFilters && options.wiki) {
|
||||||
|
$tw.utils.each(options.extFilters,function(filter) {
|
||||||
|
if(!extension) {
|
||||||
|
var source = options.wiki.makeTiddlerIterator([title]),
|
||||||
|
result = options.wiki.filterTiddlers(filter,null,source);
|
||||||
|
if(result.length > 0) {
|
||||||
|
extension = result[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return extension;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generate the filepath for saving a tiddler
|
Generate the filepath for saving a tiddler
|
||||||
Options include:
|
Options include:
|
||||||
@ -258,11 +314,12 @@ Options include:
|
|||||||
directory: absolute path of root directory to which we are saving
|
directory: absolute path of root directory to which we are saving
|
||||||
pathFilters: optional array of filters to be used to generate the base path
|
pathFilters: optional array of filters to be used to generate the base path
|
||||||
wiki: optional wiki for evaluating the pathFilters
|
wiki: optional wiki for evaluating the pathFilters
|
||||||
|
fileInfo: an existing fileInfo object to check against
|
||||||
*/
|
*/
|
||||||
exports.generateTiddlerFilepath = function(title,options) {
|
exports.generateTiddlerFilepath = function(title,options) {
|
||||||
var self = this,
|
var directory = options.directory || "",
|
||||||
directory = options.directory || "",
|
|
||||||
extension = options.extension || "",
|
extension = options.extension || "",
|
||||||
|
originalpath = (options.fileInfo && options.fileInfo.originalpath) ? options.fileInfo.originalpath : "",
|
||||||
filepath;
|
filepath;
|
||||||
// Check if any of the pathFilters applies
|
// Check if any of the pathFilters applies
|
||||||
if(options.pathFilters && options.wiki) {
|
if(options.pathFilters && options.wiki) {
|
||||||
@ -276,26 +333,44 @@ exports.generateTiddlerFilepath = function(title,options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// If not, generate a base pathname
|
if(!filepath && !!originalpath) {
|
||||||
if(!filepath) {
|
//Use the originalpath without the extension
|
||||||
|
var ext = path.extname(originalpath);
|
||||||
|
filepath = originalpath.substring(0,originalpath.length - ext.length);
|
||||||
|
} else if(!filepath) {
|
||||||
filepath = title;
|
filepath = title;
|
||||||
// If the filepath already ends in the extension then remove it
|
|
||||||
if(filepath.substring(filepath.length - extension.length) === extension) {
|
|
||||||
filepath = filepath.substring(0,filepath.length - extension.length);
|
|
||||||
}
|
|
||||||
// Remove any forward or backward slashes so we don't create directories
|
// Remove any forward or backward slashes so we don't create directories
|
||||||
filepath = filepath.replace(/\/|\\/g,"_");
|
filepath = filepath.replace(/\/|\\/g,"_");
|
||||||
}
|
}
|
||||||
// Don't let the filename start with a dot because such files are invisible on *nix
|
// Replace any Windows control codes
|
||||||
filepath = filepath.replace(/^\./g,"_");
|
filepath = filepath.replace(/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i,"_$1_");
|
||||||
// Remove any characters that can't be used in cross-platform filenames
|
// Replace any leading spaces with the same number of underscores
|
||||||
filepath = $tw.utils.transliterate(filepath.replace(/<|>|\:|\"|\||\?|\*|\^/g,"_"));
|
filepath = filepath.replace(/^ +/,function (u) { return u.replace(/ /g, "_")});
|
||||||
|
//If the path does not start with "." or ".." && a path seperator, then
|
||||||
|
if(!/^\.{1,2}[/\\]/g.test(filepath)) {
|
||||||
|
// Don't let the filename start with any dots because such files are invisible on *nix
|
||||||
|
filepath = filepath.replace(/^\.+/g,function (u) { return u.replace(/\./g, "_")});
|
||||||
|
}
|
||||||
|
// Replace any Unicode control codes
|
||||||
|
filepath = filepath.replace(/[\x00-\x1f\x80-\x9f]/g,"_");
|
||||||
|
// Replace any characters that can't be used in cross-platform filenames
|
||||||
|
filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_"));
|
||||||
|
// Replace any dots or spaces at the end of the extension with the same number of underscores
|
||||||
|
extension = extension.replace(/[\. ]+$/, function (u) { return u.replace(/[\. ]/g, "_")});
|
||||||
|
// Truncate the extension if it is too long
|
||||||
|
if(extension.length > 32) {
|
||||||
|
extension = extension.substr(0,32);
|
||||||
|
}
|
||||||
|
// If the filepath already ends in the extension then remove it
|
||||||
|
if(filepath.substring(filepath.length - extension.length) === extension) {
|
||||||
|
filepath = filepath.substring(0,filepath.length - extension.length);
|
||||||
|
}
|
||||||
// Truncate the filename if it is too long
|
// Truncate the filename if it is too long
|
||||||
if(filepath.length > 200) {
|
if(filepath.length > 200) {
|
||||||
filepath = filepath.substr(0,200);
|
filepath = filepath.substr(0,200);
|
||||||
}
|
}
|
||||||
// If the resulting filename is blank (eg because the title is just punctuation characters)
|
// If the resulting filename is blank (eg because the title is just punctuation)
|
||||||
if(!filepath) {
|
if(!filepath || /^_+$/g.test(filepath)) {
|
||||||
// ...then just use the character codes of the title
|
// ...then just use the character codes of the title
|
||||||
filepath = "";
|
filepath = "";
|
||||||
$tw.utils.each(title.split(""),function(char) {
|
$tw.utils.each(title.split(""),function(char) {
|
||||||
@ -306,14 +381,31 @@ exports.generateTiddlerFilepath = function(title,options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Add a uniquifier if the file already exists
|
// Add a uniquifier if the file already exists
|
||||||
var fullPath,
|
var fullPath, oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
|
||||||
count = 0;
|
count = 0;
|
||||||
do {
|
do {
|
||||||
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
||||||
|
if(oldPath && oldPath == fullPath) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
count++;
|
count++;
|
||||||
} while(fs.existsSync(fullPath));
|
} while(fs.existsSync(fullPath));
|
||||||
|
// If the last write failed with an error, or if path does not start with:
|
||||||
|
// the resolved options.directory, the resolved wikiPath directory, the wikiTiddlersPath directory,
|
||||||
|
// or the 'originalpath' directory, then encodeURIComponent() and resolve to tiddler directory.
|
||||||
|
var writePath = $tw.hooks.invokeHook("th-make-tiddler-path",fullPath,fullPath),
|
||||||
|
encode = (options.fileInfo || {writeError: false}).writeError == true;
|
||||||
|
if(!encode) {
|
||||||
|
encode = !(writePath.indexOf($tw.boot.wikiTiddlersPath) == 0 ||
|
||||||
|
writePath.indexOf(path.resolve(directory)) == 0 ||
|
||||||
|
writePath.indexOf(path.resolve($tw.boot.wikiPath)) == 0 ||
|
||||||
|
writePath.indexOf(path.resolve($tw.boot.wikiTiddlersPath,originalpath)) == 0 );
|
||||||
|
}
|
||||||
|
if(encode) {
|
||||||
|
writePath = path.resolve(directory,encodeURIComponent(fullPath));
|
||||||
|
}
|
||||||
// Return the full path to the file
|
// Return the full path to the file
|
||||||
return fullPath;
|
return writePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -327,18 +419,33 @@ exports.saveTiddlerToFile = function(tiddler,fileInfo,callback) {
|
|||||||
if(fileInfo.hasMetaFile) {
|
if(fileInfo.hasMetaFile) {
|
||||||
// Save the tiddler as a separate body and meta file
|
// Save the tiddler as a separate body and meta file
|
||||||
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
|
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
|
||||||
fs.writeFile(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding,function(err) {
|
fs.writeFile(fileInfo.filepath,tiddler.fields.text || "",typeInfo.encoding,function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
fs.writeFile(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8",callback);
|
fs.writeFile(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8",function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null,fileInfo);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Save the tiddler as a self contained templated file
|
// Save the tiddler as a self contained templated file
|
||||||
if(fileInfo.type === "application/x-tiddler") {
|
if(fileInfo.type === "application/x-tiddler") {
|
||||||
fs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8",callback);
|
fs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8",function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null,fileInfo);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
fs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8",callback);
|
fs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8",function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null,fileInfo);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -354,7 +461,7 @@ exports.saveTiddlerToFileSync = function(tiddler,fileInfo) {
|
|||||||
if(fileInfo.hasMetaFile) {
|
if(fileInfo.hasMetaFile) {
|
||||||
// Save the tiddler as a separate body and meta file
|
// Save the tiddler as a separate body and meta file
|
||||||
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
|
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
|
||||||
fs.writeFileSync(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding);
|
fs.writeFileSync(fileInfo.filepath,tiddler.fields.text || "",typeInfo.encoding);
|
||||||
fs.writeFileSync(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8");
|
fs.writeFileSync(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8");
|
||||||
} else {
|
} else {
|
||||||
// Save the tiddler as a self contained templated file
|
// Save the tiddler as a self contained templated file
|
||||||
@ -364,6 +471,73 @@ exports.saveTiddlerToFileSync = function(tiddler,fileInfo) {
|
|||||||
fs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8");
|
fs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return fileInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete a file described by the fileInfo if it exits
|
||||||
|
*/
|
||||||
|
exports.deleteTiddlerFile = function(fileInfo,callback) {
|
||||||
|
//Only attempt to delete files that exist on disk
|
||||||
|
if(!fileInfo.filepath || !fs.existsSync(fileInfo.filepath)) {
|
||||||
|
//For some reason, the tiddler is only in memory or we can't modify the file at this path
|
||||||
|
$tw.syncer.displayError("Server deleteTiddlerFile task failed for filepath: "+fileInfo.filepath);
|
||||||
|
return callback(null,fileInfo);
|
||||||
|
}
|
||||||
|
// Delete the file
|
||||||
|
fs.unlink(fileInfo.filepath,function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
// Delete the metafile if present
|
||||||
|
if(fileInfo.hasMetaFile && fs.existsSync(fileInfo.filepath + ".meta")) {
|
||||||
|
fs.unlink(fileInfo.filepath + ".meta",function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null,fileInfo);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),function(err) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null,fileInfo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cleanup old files on disk, by comparing the options values:
|
||||||
|
adaptorInfo from $tw.syncer.tiddlerInfo
|
||||||
|
bootInfo from $tw.boot.files
|
||||||
|
*/
|
||||||
|
exports.cleanupTiddlerFiles = function(options,callback) {
|
||||||
|
var adaptorInfo = options.adaptorInfo || {},
|
||||||
|
bootInfo = options.bootInfo || {},
|
||||||
|
title = options.title || "undefined";
|
||||||
|
if(adaptorInfo.filepath && bootInfo.filepath && adaptorInfo.filepath !== bootInfo.filepath) {
|
||||||
|
$tw.utils.deleteTiddlerFile(adaptorInfo,function(err) {
|
||||||
|
if(err) {
|
||||||
|
if ((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") {
|
||||||
|
// Error deleting the previous file on disk, should fail gracefully
|
||||||
|
$tw.syncer.displayError("Server desynchronized. Error cleaning up previous file for tiddler: \""+title+"\"",err);
|
||||||
|
return callback(null,bootInfo);
|
||||||
|
} else {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback(null,bootInfo);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return callback(null,bootInfo);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
195
core/modules/utils/linked-list.js
Normal file
195
core/modules/utils/linked-list.js
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/*\
|
||||||
|
module-type: utils
|
||||||
|
title: $:/core/modules/utils/linkedlist.js
|
||||||
|
type: application/javascript
|
||||||
|
|
||||||
|
This is a doubly-linked indexed list intended for manipulation, particularly
|
||||||
|
pushTop, which it does with significantly better performance than an array.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
function LinkedList() {
|
||||||
|
this.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkedList.prototype.clear = function() {
|
||||||
|
// LinkedList performs the duty of both the head and tail node
|
||||||
|
this.next = Object.create(null);
|
||||||
|
this.prev = Object.create(null);
|
||||||
|
this.first = undefined;
|
||||||
|
this.last = undefined;
|
||||||
|
this.length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkedList.prototype.remove = function(value) {
|
||||||
|
if($tw.utils.isArray(value)) {
|
||||||
|
for(var t=0; t<value.length; t++) {
|
||||||
|
_assertString(value[t]);
|
||||||
|
}
|
||||||
|
for(var t=0; t<value.length; t++) {
|
||||||
|
_removeOne(this,value[t]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_assertString(value);
|
||||||
|
_removeOne(this,value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Push behaves like array.push and accepts multiple string arguments. But it also
|
||||||
|
accepts a single array argument too, to be consistent with its other methods.
|
||||||
|
*/
|
||||||
|
LinkedList.prototype.push = function(/* values */) {
|
||||||
|
var values = arguments;
|
||||||
|
if($tw.utils.isArray(values[0])) {
|
||||||
|
values = values[0];
|
||||||
|
}
|
||||||
|
for(var i = 0; i < values.length; i++) {
|
||||||
|
_assertString(values[i]);
|
||||||
|
}
|
||||||
|
for(var i = 0; i < values.length; i++) {
|
||||||
|
_linkToEnd(this,values[i]);
|
||||||
|
}
|
||||||
|
return this.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkedList.prototype.pushTop = function(value) {
|
||||||
|
if($tw.utils.isArray(value)) {
|
||||||
|
for (var t=0; t<value.length; t++) {
|
||||||
|
_assertString(value[t]);
|
||||||
|
}
|
||||||
|
for(var t=0; t<value.length; t++) {
|
||||||
|
_removeOne(this,value[t]);
|
||||||
|
}
|
||||||
|
for(var t=0; t<value.length; t++) {
|
||||||
|
_linkToEnd(this,value[t]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_assertString(value);
|
||||||
|
_removeOne(this,value);
|
||||||
|
_linkToEnd(this,value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkedList.prototype.each = function(callback) {
|
||||||
|
var visits = Object.create(null),
|
||||||
|
value = this.first;
|
||||||
|
while(value !== undefined) {
|
||||||
|
callback(value);
|
||||||
|
var next = this.next[value];
|
||||||
|
if(typeof next === "object") {
|
||||||
|
var i = visits[value] || 0;
|
||||||
|
visits[value] = i+1;
|
||||||
|
value = next[i];
|
||||||
|
} else {
|
||||||
|
value = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkedList.prototype.toArray = function() {
|
||||||
|
var output = new Array(this.length),
|
||||||
|
index = 0;
|
||||||
|
this.each(function(value) { output[index++] = value; });
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
function _removeOne(list,value) {
|
||||||
|
var prevEntry = list.prev[value],
|
||||||
|
nextEntry = list.next[value],
|
||||||
|
prev = prevEntry,
|
||||||
|
next = nextEntry;
|
||||||
|
if(typeof nextEntry === "object") {
|
||||||
|
next = nextEntry[0];
|
||||||
|
prev = prevEntry[0];
|
||||||
|
}
|
||||||
|
// Relink preceding element.
|
||||||
|
if(list.first === value) {
|
||||||
|
list.first = next
|
||||||
|
} else if(prev !== undefined) {
|
||||||
|
if(typeof list.next[prev] === "object") {
|
||||||
|
if(next === undefined) {
|
||||||
|
// Must have been last, and 'i' would be last element.
|
||||||
|
list.next[prev].pop();
|
||||||
|
} else {
|
||||||
|
var i = list.next[prev].indexOf(value);
|
||||||
|
list.next[prev][i] = next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.next[prev] = next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Now relink following element
|
||||||
|
// Check "next !== undefined" rather than "list.last === value" because
|
||||||
|
// we need to know if the FIRST value is the last in the list, not the last.
|
||||||
|
if(next !== undefined) {
|
||||||
|
if(typeof list.prev[next] === "object") {
|
||||||
|
if(prev === undefined) {
|
||||||
|
// Must have been first, and 'i' would be 0.
|
||||||
|
list.prev[next].shift();
|
||||||
|
} else {
|
||||||
|
var i = list.prev[next].indexOf(value);
|
||||||
|
list.prev[next][i] = prev;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.prev[next] = prev;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.last = prev;
|
||||||
|
}
|
||||||
|
// Delink actual value. If it uses arrays, just remove first entries.
|
||||||
|
if(typeof nextEntry === "object") {
|
||||||
|
nextEntry.shift();
|
||||||
|
prevEntry.shift();
|
||||||
|
} else {
|
||||||
|
list.next[value] = undefined;
|
||||||
|
list.prev[value] = undefined;
|
||||||
|
}
|
||||||
|
list.length -= 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sticks the given node onto the end of the list.
|
||||||
|
function _linkToEnd(list,value) {
|
||||||
|
if(list.first === undefined) {
|
||||||
|
list.first = value;
|
||||||
|
} else {
|
||||||
|
// Does it already exists?
|
||||||
|
if(list.first === value || list.prev[value] !== undefined) {
|
||||||
|
if(typeof list.next[value] === "string") {
|
||||||
|
list.next[value] = [list.next[value]];
|
||||||
|
list.prev[value] = [list.prev[value]];
|
||||||
|
} else if(typeof list.next[value] === "undefined") {
|
||||||
|
// list.next[value] must be undefined.
|
||||||
|
// Special case. List already has 1 value. It's at the end.
|
||||||
|
list.next[value] = [];
|
||||||
|
list.prev[value] = [list.prev[value]];
|
||||||
|
}
|
||||||
|
list.prev[value].push(list.last);
|
||||||
|
// We do NOT append a new value onto "next" list. Iteration will
|
||||||
|
// figure out it must point to End-of-List on its own.
|
||||||
|
} else {
|
||||||
|
list.prev[value] = list.last;
|
||||||
|
}
|
||||||
|
// Make the old last point to this new one.
|
||||||
|
if(typeof list.next[list.last] === "object") {
|
||||||
|
list.next[list.last].push(value);
|
||||||
|
} else {
|
||||||
|
list.next[list.last] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.last = value;
|
||||||
|
list.length += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
function _assertString(value) {
|
||||||
|
if(typeof value !== "string") {
|
||||||
|
throw "Linked List only accepts string values, not " + value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.LinkedList = LinkedList;
|
||||||
|
|
||||||
|
})();
|
@ -53,6 +53,19 @@ exports.warning = function(text) {
|
|||||||
exports.log(text,"brown/orange");
|
exports.log(text,"brown/orange");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Log a table of name: value pairs
|
||||||
|
*/
|
||||||
|
exports.logTable = function(data) {
|
||||||
|
if(console.table) {
|
||||||
|
console.table(data);
|
||||||
|
} else {
|
||||||
|
$tw.utils.each(data,function(value,name) {
|
||||||
|
console.log(name + ": " + value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return the integer represented by the str (string).
|
Return the integer represented by the str (string).
|
||||||
Return the dflt (default) parameter if str is not a base-10 number.
|
Return the dflt (default) parameter if str is not a base-10 number.
|
||||||
@ -289,7 +302,7 @@ exports.formatDateString = function(date,template) {
|
|||||||
return $tw.utils.pad($tw.utils.getHours12(date));
|
return $tw.utils.pad($tw.utils.getHours12(date));
|
||||||
}],
|
}],
|
||||||
[/^wYYYY/, function() {
|
[/^wYYYY/, function() {
|
||||||
return $tw.utils.getYearForWeekNo(date);
|
return $tw.utils.pad($tw.utils.getYearForWeekNo(date),4);
|
||||||
}],
|
}],
|
||||||
[/^hh12/, function() {
|
[/^hh12/, function() {
|
||||||
return $tw.utils.getHours12(date);
|
return $tw.utils.getHours12(date);
|
||||||
@ -298,7 +311,14 @@ exports.formatDateString = function(date,template) {
|
|||||||
return date.getDate() + $tw.utils.getDaySuffix(date);
|
return date.getDate() + $tw.utils.getDaySuffix(date);
|
||||||
}],
|
}],
|
||||||
[/^YYYY/, function() {
|
[/^YYYY/, function() {
|
||||||
return date.getFullYear();
|
return $tw.utils.pad(date.getFullYear(),4);
|
||||||
|
}],
|
||||||
|
[/^aYYYY/, function() {
|
||||||
|
return $tw.utils.pad(Math.abs(date.getFullYear()),4);
|
||||||
|
}],
|
||||||
|
[/^\{era:([^,\|}]*)\|([^}\|]*)\|([^}]*)\}/, function(match) {
|
||||||
|
var year = date.getFullYear();
|
||||||
|
return year === 0 ? match[2] : (year < 0 ? match[1] : match[3]);
|
||||||
}],
|
}],
|
||||||
[/^0hh/, function() {
|
[/^0hh/, function() {
|
||||||
return $tw.utils.pad(date.getHours());
|
return $tw.utils.pad(date.getHours());
|
||||||
@ -387,7 +407,7 @@ exports.formatDateString = function(date,template) {
|
|||||||
$tw.utils.each(matches, function(m) {
|
$tw.utils.each(matches, function(m) {
|
||||||
var match = m[0].exec(t);
|
var match = m[0].exec(t);
|
||||||
if(match) {
|
if(match) {
|
||||||
matchString = m[1].call();
|
matchString = m[1].call(null,match);
|
||||||
t = t.substr(match[0].length);
|
t = t.substr(match[0].length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -495,6 +515,15 @@ exports.htmlEncode = function(s) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Converts like htmlEncode, but forgets the double quote for brevity
|
||||||
|
exports.htmlTextEncode = function(s) {
|
||||||
|
if(s) {
|
||||||
|
return s.toString().replace(/&/mg,"&").replace(/</mg,"<").replace(/>/mg,">");
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Converts all HTML entities to their character equivalents
|
// Converts all HTML entities to their character equivalents
|
||||||
exports.entityDecode = function(s) {
|
exports.entityDecode = function(s) {
|
||||||
var converter = String.fromCodePoint || String.fromCharCode,
|
var converter = String.fromCodePoint || String.fromCharCode,
|
||||||
@ -544,7 +573,7 @@ exports.escape = function(ch) {
|
|||||||
|
|
||||||
// Turns a string into a legal JavaScript string
|
// Turns a string into a legal JavaScript string
|
||||||
// Copied from peg.js, thanks to David Majda
|
// Copied from peg.js, thanks to David Majda
|
||||||
exports.stringify = function(s) {
|
exports.stringify = function(s, rawUnicode) {
|
||||||
/*
|
/*
|
||||||
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
|
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
|
||||||
* literal except for the closing quote character, backslash, carriage return,
|
* literal except for the closing quote character, backslash, carriage return,
|
||||||
@ -553,19 +582,21 @@ exports.stringify = function(s) {
|
|||||||
*
|
*
|
||||||
* For portability, we also escape all non-ASCII characters.
|
* For portability, we also escape all non-ASCII characters.
|
||||||
*/
|
*/
|
||||||
|
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
|
||||||
return (s || "")
|
return (s || "")
|
||||||
.replace(/\\/g, '\\\\') // backslash
|
.replace(/\\/g, '\\\\') // backslash
|
||||||
.replace(/"/g, '\\"') // double quote character
|
.replace(/"/g, '\\"') // double quote character
|
||||||
.replace(/'/g, "\\'") // single quote character
|
.replace(/'/g, "\\'") // single quote character
|
||||||
.replace(/\r/g, '\\r') // carriage return
|
.replace(/\r/g, '\\r') // carriage return
|
||||||
.replace(/\n/g, '\\n') // line feed
|
.replace(/\n/g, '\\n') // line feed
|
||||||
.replace(/[\x00-\x1f\x80-\uFFFF]/g, exports.escape); // non-ASCII characters
|
.replace(regex, exports.escape); // non-ASCII characters
|
||||||
};
|
};
|
||||||
|
|
||||||
// Turns a string into a legal JSON string
|
// Turns a string into a legal JSON string
|
||||||
// Derived from peg.js, thanks to David Majda
|
// Derived from peg.js, thanks to David Majda
|
||||||
exports.jsonStringify = function(s) {
|
exports.jsonStringify = function(s, rawUnicode) {
|
||||||
// See http://www.json.org/
|
// See http://www.json.org/
|
||||||
|
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
|
||||||
return (s || "")
|
return (s || "")
|
||||||
.replace(/\\/g, '\\\\') // backslash
|
.replace(/\\/g, '\\\\') // backslash
|
||||||
.replace(/"/g, '\\"') // double quote character
|
.replace(/"/g, '\\"') // double quote character
|
||||||
@ -574,7 +605,7 @@ exports.jsonStringify = function(s) {
|
|||||||
.replace(/\x08/g, '\\b') // backspace
|
.replace(/\x08/g, '\\b') // backspace
|
||||||
.replace(/\x0c/g, '\\f') // formfeed
|
.replace(/\x0c/g, '\\f') // formfeed
|
||||||
.replace(/\t/g, '\\t') // tab
|
.replace(/\t/g, '\\t') // tab
|
||||||
.replace(/[\x00-\x1f\x80-\uFFFF]/g,function(s) {
|
.replace(regex,function(s) {
|
||||||
return '\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
|
return '\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
|
||||||
}); // non-ASCII characters
|
}); // non-ASCII characters
|
||||||
};
|
};
|
||||||
@ -596,7 +627,7 @@ exports.nextTick = function(fn) {
|
|||||||
/*global window: false */
|
/*global window: false */
|
||||||
if(typeof process === "undefined") {
|
if(typeof process === "undefined") {
|
||||||
// Apparently it would be faster to use postMessage - http://dbaron.org/log/20100309-faster-timeouts
|
// Apparently it would be faster to use postMessage - http://dbaron.org/log/20100309-faster-timeouts
|
||||||
window.setTimeout(fn,4);
|
window.setTimeout(fn,0);
|
||||||
} else {
|
} else {
|
||||||
process.nextTick(fn);
|
process.nextTick(fn);
|
||||||
}
|
}
|
||||||
|
77
core/modules/widgets/action-confirm.js
Normal file
77
core/modules/widgets/action-confirm.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*\
|
||||||
|
|
||||||
|
title: $:/core/modules/widgets/action-confirm.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var ConfirmWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
ConfirmWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
ConfirmWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.computeAttributes();
|
||||||
|
this.execute();
|
||||||
|
this.parentDomNode = parent;
|
||||||
|
this.renderChildren(parent,nextSibling);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compute the internal state of the widget
|
||||||
|
*/
|
||||||
|
ConfirmWidget.prototype.execute = function() {
|
||||||
|
this.message = this.getAttribute("$message",$tw.language.getString("ConfirmAction"));
|
||||||
|
this.prompt = (this.getAttribute("$prompt","yes") == "no" ? false : true);
|
||||||
|
this.makeChildWidgets();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Refresh the widget by ensuring our attributes are up to date
|
||||||
|
*/
|
||||||
|
ConfirmWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
var changedAttributes = this.computeAttributes();
|
||||||
|
if(changedAttributes["$message"] || changedAttributes["$prompt"]) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.refreshChildren(changedTiddlers);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Invoke the action associated with this widget
|
||||||
|
*/
|
||||||
|
ConfirmWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||||
|
var invokeActions = true,
|
||||||
|
handled = true;
|
||||||
|
if(this.prompt) {
|
||||||
|
invokeActions = confirm(this.message);
|
||||||
|
}
|
||||||
|
if(invokeActions) {
|
||||||
|
handled = this.invokeActions(triggeringWidget,event);
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
};
|
||||||
|
|
||||||
|
ConfirmWidget.prototype.allowActionPropagation = function() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["action-confirm"] = ConfirmWidget;
|
||||||
|
|
||||||
|
})();
|
93
core/modules/widgets/action-log.js
Normal file
93
core/modules/widgets/action-log.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/action-log.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Action widget to log debug messages
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var LogWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
LogWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
LogWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.computeAttributes();
|
||||||
|
this.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
LogWidget.prototype.execute = function(){
|
||||||
|
this.message = this.getAttribute("$$message","debug");
|
||||||
|
this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false;
|
||||||
|
this.filter = this.getAttribute("$$filter");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Refresh the widget by ensuring our attributes are up to date
|
||||||
|
*/
|
||||||
|
LogWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Invoke the action associated with this widget
|
||||||
|
*/
|
||||||
|
LogWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||||
|
this.log();
|
||||||
|
return true; // Action was invoked
|
||||||
|
};
|
||||||
|
|
||||||
|
LogWidget.prototype.log = function() {
|
||||||
|
var data = {},
|
||||||
|
dataCount,
|
||||||
|
allVars = {},
|
||||||
|
filteredVars;
|
||||||
|
|
||||||
|
$tw.utils.each(this.attributes,function(attribute,name) {
|
||||||
|
if(name.substring(0,2) !== "$$") {
|
||||||
|
data[name] = attribute;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for(var v in this.variables) {
|
||||||
|
allVars[v] = this.getVariable(v,{defaultValue:""});
|
||||||
|
}
|
||||||
|
if(this.filter) {
|
||||||
|
filteredVars = this.wiki.compileFilter(this.filter).call(this.wiki,this.wiki.makeTiddlerIterator(allVars));
|
||||||
|
$tw.utils.each(filteredVars,function(name) {
|
||||||
|
data[name] = allVars[name];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dataCount = $tw.utils.count(data);
|
||||||
|
|
||||||
|
console.group(this.message);
|
||||||
|
if(dataCount > 0) {
|
||||||
|
$tw.utils.logTable(data);
|
||||||
|
}
|
||||||
|
if(this.logAll || !dataCount) {
|
||||||
|
console.groupCollapsed("All variables");
|
||||||
|
$tw.utils.logTable(allVars);
|
||||||
|
console.groupEnd();
|
||||||
|
}
|
||||||
|
console.groupEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports["action-log"] = LogWidget;
|
||||||
|
|
||||||
|
})();
|
@ -27,18 +27,20 @@ ButtonWidget.prototype = new Widget();
|
|||||||
Render this widget into the DOM
|
Render this widget into the DOM
|
||||||
*/
|
*/
|
||||||
ButtonWidget.prototype.render = function(parent,nextSibling) {
|
ButtonWidget.prototype.render = function(parent,nextSibling) {
|
||||||
var self = this;
|
var self = this,
|
||||||
|
tag = "button",
|
||||||
|
domNode;
|
||||||
// Remember parent
|
// Remember parent
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
// Compute attributes and execute state
|
// Compute attributes and execute state
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
// Create element
|
// Create element
|
||||||
var tag = "button";
|
|
||||||
if(this.buttonTag && $tw.config.htmlUnsafeElements.indexOf(this.buttonTag) === -1) {
|
if(this.buttonTag && $tw.config.htmlUnsafeElements.indexOf(this.buttonTag) === -1) {
|
||||||
tag = this.buttonTag;
|
tag = this.buttonTag;
|
||||||
}
|
}
|
||||||
var domNode = this.document.createElement(tag);
|
domNode = this.document.createElement(tag);
|
||||||
|
this.domNode = domNode;
|
||||||
// Assign classes
|
// Assign classes
|
||||||
var classes = this["class"].split(" ") || [],
|
var classes = this["class"].split(" ") || [],
|
||||||
isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();
|
isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();
|
||||||
@ -64,10 +66,16 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
if(this["aria-label"]) {
|
if(this["aria-label"]) {
|
||||||
domNode.setAttribute("aria-label",this["aria-label"]);
|
domNode.setAttribute("aria-label",this["aria-label"]);
|
||||||
}
|
}
|
||||||
|
if(this.popup || this.popupTitle) {
|
||||||
|
domNode.setAttribute("aria-expanded",isPoppedUp ? "true" : "false");
|
||||||
|
}
|
||||||
// Set the tabindex
|
// Set the tabindex
|
||||||
if(this.tabIndex) {
|
if(this.tabIndex) {
|
||||||
domNode.setAttribute("tabindex",this.tabIndex);
|
domNode.setAttribute("tabindex",this.tabIndex);
|
||||||
}
|
}
|
||||||
|
if(this.isDisabled === "yes") {
|
||||||
|
domNode.setAttribute("disabled",true);
|
||||||
|
}
|
||||||
// Add a click event handler
|
// Add a click event handler
|
||||||
domNode.addEventListener("click",function (event) {
|
domNode.addEventListener("click",function (event) {
|
||||||
var handled = false;
|
var handled = false;
|
||||||
@ -197,10 +205,10 @@ ButtonWidget.prototype.execute = function() {
|
|||||||
this.setTo = this.getAttribute("setTo");
|
this.setTo = this.getAttribute("setTo");
|
||||||
this.popup = this.getAttribute("popup");
|
this.popup = this.getAttribute("popup");
|
||||||
this.hover = this.getAttribute("hover");
|
this.hover = this.getAttribute("hover");
|
||||||
this["class"] = this.getAttribute("class","");
|
|
||||||
this["aria-label"] = this.getAttribute("aria-label");
|
this["aria-label"] = this.getAttribute("aria-label");
|
||||||
this.tooltip = this.getAttribute("tooltip");
|
this.tooltip = this.getAttribute("tooltip");
|
||||||
this.style = this.getAttribute("style");
|
this.style = this.getAttribute("style");
|
||||||
|
this["class"] = this.getAttribute("class","");
|
||||||
this.selectedClass = this.getAttribute("selectedClass");
|
this.selectedClass = this.getAttribute("selectedClass");
|
||||||
this.defaultSetValue = this.getAttribute("default","");
|
this.defaultSetValue = this.getAttribute("default","");
|
||||||
this.buttonTag = this.getAttribute("tag");
|
this.buttonTag = this.getAttribute("tag");
|
||||||
@ -211,18 +219,39 @@ ButtonWidget.prototype.execute = function() {
|
|||||||
this.setIndex = this.getAttribute("setIndex");
|
this.setIndex = this.getAttribute("setIndex");
|
||||||
this.popupTitle = this.getAttribute("popupTitle");
|
this.popupTitle = this.getAttribute("popupTitle");
|
||||||
this.tabIndex = this.getAttribute("tabindex");
|
this.tabIndex = this.getAttribute("tabindex");
|
||||||
|
this.isDisabled = this.getAttribute("disabled","no");
|
||||||
// Make child widgets
|
// Make child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ButtonWidget.prototype.updateDomNodeClasses = function() {
|
||||||
|
var domNodeClasses = this.domNode.className.split(" "),
|
||||||
|
oldClasses = this.class.split(" "),
|
||||||
|
newClasses;
|
||||||
|
this["class"] = this.getAttribute("class","");
|
||||||
|
newClasses = this.class.split(" ");
|
||||||
|
//Remove classes assigned from the old value of class attribute
|
||||||
|
$tw.utils.each(oldClasses,function(oldClass){
|
||||||
|
var i = domNodeClasses.indexOf(oldClass);
|
||||||
|
if(i !== -1) {
|
||||||
|
domNodeClasses.splice(i,1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//Add new classes from updated class attribute.
|
||||||
|
$tw.utils.pushTop(domNodeClasses,newClasses);
|
||||||
|
this.domNode.className = domNodeClasses.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
*/
|
*/
|
||||||
ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes["class"] || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle) {
|
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
|
} else if(changedAttributes["class"]) {
|
||||||
|
this.updateDomNodeClasses();
|
||||||
}
|
}
|
||||||
return this.refreshChildren(changedTiddlers);
|
return this.refreshChildren(changedTiddlers);
|
||||||
};
|
};
|
||||||
|
@ -41,6 +41,9 @@ CheckboxWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
if(this.getValue()) {
|
if(this.getValue()) {
|
||||||
this.inputDomNode.setAttribute("checked","true");
|
this.inputDomNode.setAttribute("checked","true");
|
||||||
}
|
}
|
||||||
|
if(this.isDisabled === "yes") {
|
||||||
|
this.inputDomNode.setAttribute("disabled",true);
|
||||||
|
}
|
||||||
this.labelDomNode.appendChild(this.inputDomNode);
|
this.labelDomNode.appendChild(this.inputDomNode);
|
||||||
this.spanDomNode = this.document.createElement("span");
|
this.spanDomNode = this.document.createElement("span");
|
||||||
this.labelDomNode.appendChild(this.spanDomNode);
|
this.labelDomNode.appendChild(this.spanDomNode);
|
||||||
@ -181,6 +184,7 @@ CheckboxWidget.prototype.execute = function() {
|
|||||||
this.checkboxDefault = this.getAttribute("default");
|
this.checkboxDefault = this.getAttribute("default");
|
||||||
this.checkboxClass = this.getAttribute("class","");
|
this.checkboxClass = this.getAttribute("class","");
|
||||||
this.checkboxInvertTag = this.getAttribute("invertTag","");
|
this.checkboxInvertTag = this.getAttribute("invertTag","");
|
||||||
|
this.isDisabled = this.getAttribute("disabled","no");
|
||||||
// Make the child widgets
|
// Make the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
@ -190,7 +194,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
*/
|
*/
|
||||||
CheckboxWidget.prototype.refresh = function(changedTiddlers) {
|
CheckboxWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.tiddler || changedAttributes.tag || changedAttributes.invertTag || changedAttributes.field || changedAttributes.index || changedAttributes.checked || changedAttributes.unchecked || changedAttributes["default"] || changedAttributes["class"]) {
|
if(changedAttributes.tiddler || changedAttributes.tag || changedAttributes.invertTag || changedAttributes.field || changedAttributes.index || changedAttributes.checked || changedAttributes.unchecked || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.disabled) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,21 +27,21 @@ DroppableWidget.prototype = new Widget();
|
|||||||
Render this widget into the DOM
|
Render this widget into the DOM
|
||||||
*/
|
*/
|
||||||
DroppableWidget.prototype.render = function(parent,nextSibling) {
|
DroppableWidget.prototype.render = function(parent,nextSibling) {
|
||||||
var self = this;
|
var self = this,
|
||||||
|
tag = this.parseTreeNode.isBlock ? "div" : "span",
|
||||||
|
domNode;
|
||||||
// Remember parent
|
// Remember parent
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
// Compute attributes and execute state
|
// Compute attributes and execute state
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
var tag = this.parseTreeNode.isBlock ? "div" : "span";
|
|
||||||
if(this.droppableTag && $tw.config.htmlUnsafeElements.indexOf(this.droppableTag) === -1) {
|
if(this.droppableTag && $tw.config.htmlUnsafeElements.indexOf(this.droppableTag) === -1) {
|
||||||
tag = this.droppableTag;
|
tag = this.droppableTag;
|
||||||
}
|
}
|
||||||
// Create element and assign classes
|
// Create element and assign classes
|
||||||
var domNode = this.document.createElement(tag),
|
domNode = this.document.createElement(tag);
|
||||||
classes = (this.droppableClass || "").split(" ");
|
this.domNode = domNode;
|
||||||
classes.push("tc-droppable");
|
this.assignDomNodeClasses();
|
||||||
domNode.className = classes.join(" ");
|
|
||||||
// Add event handlers
|
// Add event handlers
|
||||||
if(this.droppableEnable) {
|
if(this.droppableEnable) {
|
||||||
$tw.utils.addEventListeners(domNode,[
|
$tw.utils.addEventListeners(domNode,[
|
||||||
@ -50,6 +50,8 @@ DroppableWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
{name: "dragleave", handlerObject: this, handlerMethod: "handleDragLeaveEvent"},
|
{name: "dragleave", handlerObject: this, handlerMethod: "handleDragLeaveEvent"},
|
||||||
{name: "drop", handlerObject: this, handlerMethod: "handleDropEvent"}
|
{name: "drop", handlerObject: this, handlerMethod: "handleDropEvent"}
|
||||||
]);
|
]);
|
||||||
|
} else {
|
||||||
|
$tw.utils.addClass(this.domNode,this.disabledClass);
|
||||||
}
|
}
|
||||||
// Insert element
|
// Insert element
|
||||||
parent.insertBefore(domNode,nextSibling);
|
parent.insertBefore(domNode,nextSibling);
|
||||||
@ -144,24 +146,32 @@ DroppableWidget.prototype.execute = function() {
|
|||||||
this.droppableActions = this.getAttribute("actions");
|
this.droppableActions = this.getAttribute("actions");
|
||||||
this.droppableEffect = this.getAttribute("effect","copy");
|
this.droppableEffect = this.getAttribute("effect","copy");
|
||||||
this.droppableTag = this.getAttribute("tag");
|
this.droppableTag = this.getAttribute("tag");
|
||||||
this.droppableClass = this.getAttribute("class");
|
|
||||||
this.droppableEnable = (this.getAttribute("enable") || "yes") === "yes";
|
this.droppableEnable = (this.getAttribute("enable") || "yes") === "yes";
|
||||||
|
this.disabledClass = this.getAttribute("disabledClass","");
|
||||||
// Make child widgets
|
// Make child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DroppableWidget.prototype.assignDomNodeClasses = function() {
|
||||||
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
|
classes.push("tc-droppable");
|
||||||
|
this.domNode.className = classes.join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
*/
|
*/
|
||||||
DroppableWidget.prototype.refresh = function(changedTiddlers) {
|
DroppableWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes["class"] || changedAttributes.tag || changedAttributes.enable) {
|
if(changedAttributes.tag || changedAttributes.enable || changedAttributes.disabledClass || changedAttributes.actions || changedAttributes.effect) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
|
} else if(changedAttributes["class"]) {
|
||||||
|
this.assignDomNodeClasses();
|
||||||
}
|
}
|
||||||
return this.refreshChildren(changedTiddlers);
|
return this.refreshChildren(changedTiddlers);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.droppable = DroppableWidget;
|
exports.droppable = DroppableWidget;
|
||||||
|
|
||||||
})();
|
})();
|
@ -12,6 +12,8 @@ Dropzone widget
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var IMPORT_TITLE = "$:/Import";
|
||||||
|
|
||||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
var DropZoneWidget = function(parseTreeNode,options) {
|
var DropZoneWidget = function(parseTreeNode,options) {
|
||||||
@ -110,10 +112,38 @@ DropZoneWidget.prototype.handleDragEndEvent = function(event) {
|
|||||||
$tw.utils.removeClass(this.domNodes[0],"tc-dragover");
|
$tw.utils.removeClass(this.domNodes[0],"tc-dragover");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DropZoneWidget.prototype.filterByContentTypes = function(tiddlerFieldsArray) {
|
||||||
|
var filteredTypes,
|
||||||
|
filtered = [],
|
||||||
|
types = [];
|
||||||
|
$tw.utils.each(tiddlerFieldsArray,function(tiddlerFields) {
|
||||||
|
types.push(tiddlerFields.type);
|
||||||
|
});
|
||||||
|
filteredTypes = this.wiki.filterTiddlers(this.contentTypesFilter,this,this.wiki.makeTiddlerIterator(types));
|
||||||
|
$tw.utils.each(tiddlerFieldsArray,function(tiddlerFields) {
|
||||||
|
if(filteredTypes.indexOf(tiddlerFields.type) !== -1) {
|
||||||
|
filtered.push(tiddlerFields);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filtered;
|
||||||
|
};
|
||||||
|
|
||||||
|
DropZoneWidget.prototype.readFileCallback = function(tiddlerFieldsArray) {
|
||||||
|
if(this.contentTypesFilter) {
|
||||||
|
tiddlerFieldsArray = this.filterByContentTypes(tiddlerFieldsArray);
|
||||||
|
}
|
||||||
|
if(tiddlerFieldsArray.length) {
|
||||||
|
this.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray), autoOpenOnImport: this.autoOpenOnImport, importTitle: this.importTitle});
|
||||||
|
if(this.actions) {
|
||||||
|
this.invokeActionString(this.actions,this,event,{importTitle: this.importTitle});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
DropZoneWidget.prototype.handleDropEvent = function(event) {
|
DropZoneWidget.prototype.handleDropEvent = function(event) {
|
||||||
var self = this,
|
var self = this,
|
||||||
readFileCallback = function(tiddlerFieldsArray) {
|
readFileCallback = function(tiddlerFieldsArray) {
|
||||||
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray), autoOpenOnImport: self.autoOpenOnImport, importTitle: self.importTitle});
|
self.readFileCallback(tiddlerFieldsArray);
|
||||||
};
|
};
|
||||||
this.leaveDrag(event);
|
this.leaveDrag(event);
|
||||||
// Check for being over a TEXTAREA or INPUT
|
// Check for being over a TEXTAREA or INPUT
|
||||||
@ -149,7 +179,7 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
|
|||||||
DropZoneWidget.prototype.handlePasteEvent = function(event) {
|
DropZoneWidget.prototype.handlePasteEvent = function(event) {
|
||||||
var self = this,
|
var self = this,
|
||||||
readFileCallback = function(tiddlerFieldsArray) {
|
readFileCallback = function(tiddlerFieldsArray) {
|
||||||
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray), autoOpenOnImport: self.autoOpenOnImport, importTitle: self.importTitle});
|
self.readFileCallback(tiddlerFieldsArray);
|
||||||
};
|
};
|
||||||
// Let the browser handle it if we're in a textarea or input box
|
// Let the browser handle it if we're in a textarea or input box
|
||||||
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) {
|
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) {
|
||||||
@ -176,7 +206,7 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) {
|
|||||||
if($tw.log.IMPORT) {
|
if($tw.log.IMPORT) {
|
||||||
console.log("Importing string '" + str + "', type: '" + type + "'");
|
console.log("Importing string '" + str + "', type: '" + type + "'");
|
||||||
}
|
}
|
||||||
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify([tiddlerFields]), autoOpenOnImport: self.autoOpenOnImport, importTitle: self.importTitle});
|
readFileCallback([tiddlerFields]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,7 +224,9 @@ DropZoneWidget.prototype.execute = function() {
|
|||||||
this.dropzoneDeserializer = this.getAttribute("deserializer");
|
this.dropzoneDeserializer = this.getAttribute("deserializer");
|
||||||
this.dropzoneEnable = (this.getAttribute("enable") || "yes") === "yes";
|
this.dropzoneEnable = (this.getAttribute("enable") || "yes") === "yes";
|
||||||
this.autoOpenOnImport = this.getAttribute("autoOpenOnImport");
|
this.autoOpenOnImport = this.getAttribute("autoOpenOnImport");
|
||||||
this.importTitle = this.getAttribute("importTitle");
|
this.importTitle = this.getAttribute("importTitle",IMPORT_TITLE);
|
||||||
|
this.actions = this.getAttribute("actions");
|
||||||
|
this.contentTypesFilter = this.getAttribute("contentTypesFilter");
|
||||||
// Make child widgets
|
// Make child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
@ -204,7 +236,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
*/
|
*/
|
||||||
DropZoneWidget.prototype.refresh = function(changedTiddlers) {
|
DropZoneWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.enable || changedAttributes.autoOpenOnImport || changedAttributes.importTitle || changedAttributes.deserializer || changedAttributes.class) {
|
if($tw.utils.count(changedAttributes) > 0) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,6 @@ var LINE_WIDTH_TITLE = "$:/config/BitmapEditor/LineWidth",
|
|||||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
var EditBitmapWidget = function(parseTreeNode,options) {
|
var EditBitmapWidget = function(parseTreeNode,options) {
|
||||||
// Initialise the editor operations if they've not been done already
|
|
||||||
if(!this.editorOperations) {
|
|
||||||
EditBitmapWidget.prototype.editorOperations = {};
|
|
||||||
$tw.modules.applyMethods("bitmapeditoroperation",this.editorOperations);
|
|
||||||
}
|
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +38,11 @@ Render this widget into the DOM
|
|||||||
*/
|
*/
|
||||||
EditBitmapWidget.prototype.render = function(parent,nextSibling) {
|
EditBitmapWidget.prototype.render = function(parent,nextSibling) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
// Initialise the editor operations if they've not been done already
|
||||||
|
if(!this.editorOperations) {
|
||||||
|
EditBitmapWidget.prototype.editorOperations = {};
|
||||||
|
$tw.modules.applyMethods("bitmapeditoroperation",this.editorOperations);
|
||||||
|
}
|
||||||
// Save the parent dom node
|
// Save the parent dom node
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
// Compute our attributes
|
// Compute our attributes
|
||||||
|
@ -51,6 +51,7 @@ EditWidget.prototype.execute = function() {
|
|||||||
this.editCancelPopups = this.getAttribute("cancelPopups","");
|
this.editCancelPopups = this.getAttribute("cancelPopups","");
|
||||||
this.editInputActions = this.getAttribute("inputActions");
|
this.editInputActions = this.getAttribute("inputActions");
|
||||||
this.editRefreshTitle = this.getAttribute("refreshTitle");
|
this.editRefreshTitle = this.getAttribute("refreshTitle");
|
||||||
|
this.editAutoComplete = this.getAttribute("autocomplete");
|
||||||
// Choose the appropriate edit widget
|
// Choose the appropriate edit widget
|
||||||
this.editorType = this.getEditorType();
|
this.editorType = this.getEditorType();
|
||||||
// Make the child widgets
|
// Make the child widgets
|
||||||
@ -89,7 +90,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
EditWidget.prototype.refresh = function(changedTiddlers) {
|
EditWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
// Refresh if an attribute has changed, or the type associated with the target tiddler has changed
|
// Refresh if an attribute has changed, or the type associated with the target tiddler has changed
|
||||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {
|
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
156
core/modules/widgets/eventcatcher.js
Normal file
156
core/modules/widgets/eventcatcher.js
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/eventcatcher.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Event handler widget
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var EventWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
EventWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
EventWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
var self = this;
|
||||||
|
// Remember parent
|
||||||
|
this.parentDomNode = parent;
|
||||||
|
// Compute attributes and execute state
|
||||||
|
this.computeAttributes();
|
||||||
|
this.execute();
|
||||||
|
// Create element
|
||||||
|
var tag = this.parseTreeNode.isBlock ? "div" : "span";
|
||||||
|
if(this.elementTag && $tw.config.htmlUnsafeElements.indexOf(this.elementTag) === -1) {
|
||||||
|
tag = this.elementTag;
|
||||||
|
}
|
||||||
|
var domNode = this.document.createElement(tag);
|
||||||
|
this.domNode = domNode;
|
||||||
|
// Assign classes
|
||||||
|
this.assignDomNodeClasses();
|
||||||
|
// Add our event handler
|
||||||
|
$tw.utils.each(this.types,function(type) {
|
||||||
|
domNode.addEventListener(type,function(event) {
|
||||||
|
var selector = self.getAttribute("selector"),
|
||||||
|
actions = self.getAttribute("actions-"+type),
|
||||||
|
selectedNode = event.target,
|
||||||
|
selectedNodeRect,
|
||||||
|
catcherNodeRect,
|
||||||
|
variables = {};
|
||||||
|
if(selector) {
|
||||||
|
// Search ancestors for a node that matches the selector
|
||||||
|
while(!selectedNode.matches(selector) && selectedNode !== domNode) {
|
||||||
|
selectedNode = selectedNode.parentNode;
|
||||||
|
}
|
||||||
|
// If we found one, copy the attributes as variables, otherwise exit
|
||||||
|
if(selectedNode.matches(selector)) {
|
||||||
|
$tw.utils.each(selectedNode.attributes,function(attribute) {
|
||||||
|
variables["dom-" + attribute.name] = attribute.value.toString();
|
||||||
|
});
|
||||||
|
//Add a variable with a popup coordinate string for the selected node
|
||||||
|
variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")";
|
||||||
|
|
||||||
|
//Add variables for offset of selected node
|
||||||
|
variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString();
|
||||||
|
variables["tv-selectednode-posy"] = selectedNode.offsetTop.toString();
|
||||||
|
variables["tv-selectednode-width"] = selectedNode.offsetWidth.toString();
|
||||||
|
variables["tv-selectednode-height"] = selectedNode.offsetHeight.toString();
|
||||||
|
|
||||||
|
//Add variables for event X and Y position relative to selected node
|
||||||
|
selectedNodeRect = selectedNode.getBoundingClientRect();
|
||||||
|
variables["event-fromselected-posx"] = (event.clientX - selectedNodeRect.left).toString();
|
||||||
|
variables["event-fromselected-posy"] = (event.clientY - selectedNodeRect.top).toString();
|
||||||
|
|
||||||
|
//Add variables for event X and Y position relative to event catcher node
|
||||||
|
catcherNodeRect = self.domNode.getBoundingClientRect();
|
||||||
|
variables["event-fromcatcher-posx"] = (event.clientX - catcherNodeRect.left).toString();
|
||||||
|
variables["event-fromcatcher-posy"] = (event.clientY - catcherNodeRect.top).toString();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Execute our actions with the variables
|
||||||
|
if(actions) {
|
||||||
|
// Add a variable for the modifier key
|
||||||
|
variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);
|
||||||
|
// Add a variable for the mouse button
|
||||||
|
if("button" in event) {
|
||||||
|
if(event.button === 0) {
|
||||||
|
variables["event-mousebutton"] = "left";
|
||||||
|
} else if(event.button === 1) {
|
||||||
|
variables["event-mousebutton"] = "middle";
|
||||||
|
} else if(event.button === 2) {
|
||||||
|
variables["event-mousebutton"] = "right";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
variables["event-type"] = event.type.toString();
|
||||||
|
if(typeof event.detail === "object" && !!event.detail) {
|
||||||
|
$tw.utils.each(event.detail,function(detailValue,detail) {
|
||||||
|
variables["event-detail-" + detail] = detailValue.toString();
|
||||||
|
});
|
||||||
|
} else if(!!event.detail) {
|
||||||
|
variables["event-detail"] = event.detail.toString();
|
||||||
|
}
|
||||||
|
self.invokeActionString(actions,self,event,variables);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},false);
|
||||||
|
});
|
||||||
|
// Insert element
|
||||||
|
parent.insertBefore(domNode,nextSibling);
|
||||||
|
this.renderChildren(domNode,null);
|
||||||
|
this.domNodes.push(domNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compute the internal state of the widget
|
||||||
|
*/
|
||||||
|
EventWidget.prototype.execute = function() {
|
||||||
|
var self = this;
|
||||||
|
// Get attributes that require a refresh on change
|
||||||
|
this.types = this.getAttribute("events","").split(" ");
|
||||||
|
this.elementTag = this.getAttribute("tag");
|
||||||
|
// Make child widgets
|
||||||
|
this.makeChildWidgets();
|
||||||
|
};
|
||||||
|
|
||||||
|
EventWidget.prototype.assignDomNodeClasses = function() {
|
||||||
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
|
classes.push("tc-eventcatcher");
|
||||||
|
this.domNode.className = classes.join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
|
*/
|
||||||
|
EventWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
var changedAttributes = this.computeAttributes();
|
||||||
|
if(changedAttributes["events"] || changedAttributes["tag"]) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
} else if(changedAttributes["class"]) {
|
||||||
|
this.assignDomNodeClasses();
|
||||||
|
}
|
||||||
|
return this.refreshChildren(changedTiddlers);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.eventcatcher = EventWidget;
|
||||||
|
|
||||||
|
})();
|
@ -16,12 +16,6 @@ var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
|||||||
|
|
||||||
var FieldManglerWidget = function(parseTreeNode,options) {
|
var FieldManglerWidget = function(parseTreeNode,options) {
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
this.addEventListeners([
|
|
||||||
{type: "tm-remove-field", handler: "handleRemoveFieldEvent"},
|
|
||||||
{type: "tm-add-field", handler: "handleAddFieldEvent"},
|
|
||||||
{type: "tm-remove-tag", handler: "handleRemoveTagEvent"},
|
|
||||||
{type: "tm-add-tag", handler: "handleAddTagEvent"}
|
|
||||||
]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -33,6 +27,12 @@ FieldManglerWidget.prototype = new Widget();
|
|||||||
Render this widget into the DOM
|
Render this widget into the DOM
|
||||||
*/
|
*/
|
||||||
FieldManglerWidget.prototype.render = function(parent,nextSibling) {
|
FieldManglerWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.addEventListeners([
|
||||||
|
{type: "tm-remove-field", handler: "handleRemoveFieldEvent"},
|
||||||
|
{type: "tm-add-field", handler: "handleAddFieldEvent"},
|
||||||
|
{type: "tm-remove-tag", handler: "handleRemoveTagEvent"},
|
||||||
|
{type: "tm-add-tag", handler: "handleAddTagEvent"}
|
||||||
|
]);
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
@ -67,7 +67,7 @@ FieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {
|
|||||||
deletion = {};
|
deletion = {};
|
||||||
deletion[event.param] = undefined;
|
deletion[event.param] = undefined;
|
||||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,deletion));
|
this.wiki.addTiddler(new $tw.Tiddler(tiddler,deletion));
|
||||||
return true;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
|
FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
|
||||||
@ -105,7 +105,7 @@ FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
|
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
|
||||||
return true;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {
|
FieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {
|
||||||
@ -122,7 +122,7 @@ FieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {
|
|||||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));
|
this.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
FieldManglerWidget.prototype.handleAddTagEvent = function(event) {
|
FieldManglerWidget.prototype.handleAddTagEvent = function(event) {
|
||||||
@ -140,7 +140,7 @@ FieldManglerWidget.prototype.handleAddTagEvent = function(event) {
|
|||||||
tag.push(event.param.trim());
|
tag.push(event.param.trim());
|
||||||
this.wiki.addTiddler(new $tw.Tiddler({title: this.mangleTitle, tags: tag},modification));
|
this.wiki.addTiddler(new $tw.Tiddler({title: this.mangleTitle, tags: tag},modification));
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.fieldmangler = FieldManglerWidget;
|
exports.fieldmangler = FieldManglerWidget;
|
||||||
|
@ -46,13 +46,15 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
// Add a keyboard event handler
|
// Add a keyboard event handler
|
||||||
domNode.addEventListener("keydown",function (event) {
|
domNode.addEventListener("keydown",function (event) {
|
||||||
if($tw.keyboardManager.checkKeyDescriptors(event,self.keyInfoArray)) {
|
if($tw.keyboardManager.checkKeyDescriptors(event,self.keyInfoArray)) {
|
||||||
self.invokeActions(self,event);
|
var handled = self.invokeActions(self,event);
|
||||||
if(self.actions) {
|
if(self.actions) {
|
||||||
self.invokeActionString(self.actions,self,event);
|
self.invokeActionString(self.actions,self,event);
|
||||||
}
|
}
|
||||||
self.dispatchMessage(event);
|
self.dispatchMessage(event);
|
||||||
event.preventDefault();
|
if(handled || self.actions || self.message) {
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -16,9 +16,6 @@ var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
|||||||
|
|
||||||
var LinkCatcherWidget = function(parseTreeNode,options) {
|
var LinkCatcherWidget = function(parseTreeNode,options) {
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
this.addEventListeners([
|
|
||||||
{type: "tm-navigate", handler: "handleNavigateEvent"}
|
|
||||||
]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -30,6 +27,9 @@ LinkCatcherWidget.prototype = new Widget();
|
|||||||
Render this widget into the DOM
|
Render this widget into the DOM
|
||||||
*/
|
*/
|
||||||
LinkCatcherWidget.prototype.render = function(parent,nextSibling) {
|
LinkCatcherWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.addEventListeners([
|
||||||
|
{type: "tm-navigate", handler: "handleNavigateEvent"}
|
||||||
|
]);
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
|
@ -19,11 +19,6 @@ The list widget creates list element sub-widgets that reach back into the list w
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var ListWidget = function(parseTreeNode,options) {
|
var ListWidget = function(parseTreeNode,options) {
|
||||||
// Initialise the storyviews if they've not been done already
|
|
||||||
if(!this.storyViews) {
|
|
||||||
ListWidget.prototype.storyViews = {};
|
|
||||||
$tw.modules.applyMethods("storyview",this.storyViews);
|
|
||||||
}
|
|
||||||
// Main initialisation inherited from widget.js
|
// Main initialisation inherited from widget.js
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
};
|
};
|
||||||
@ -37,6 +32,11 @@ ListWidget.prototype = new Widget();
|
|||||||
Render this widget into the DOM
|
Render this widget into the DOM
|
||||||
*/
|
*/
|
||||||
ListWidget.prototype.render = function(parent,nextSibling) {
|
ListWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
// Initialise the storyviews if they've not been done already
|
||||||
|
if(!this.storyViews) {
|
||||||
|
ListWidget.prototype.storyViews = {};
|
||||||
|
$tw.modules.applyMethods("storyview",this.storyViews);
|
||||||
|
}
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
@ -61,6 +61,7 @@ ListWidget.prototype.execute = function() {
|
|||||||
this.template = this.getAttribute("template");
|
this.template = this.getAttribute("template");
|
||||||
this.editTemplate = this.getAttribute("editTemplate");
|
this.editTemplate = this.getAttribute("editTemplate");
|
||||||
this.variableName = this.getAttribute("variable","currentTiddler");
|
this.variableName = this.getAttribute("variable","currentTiddler");
|
||||||
|
this.indexName = this.getAttribute("index");
|
||||||
this.storyViewName = this.getAttribute("storyview");
|
this.storyViewName = this.getAttribute("storyview");
|
||||||
this.historyTitle = this.getAttribute("history");
|
this.historyTitle = this.getAttribute("history");
|
||||||
// Compose the list elements
|
// Compose the list elements
|
||||||
@ -72,7 +73,7 @@ ListWidget.prototype.execute = function() {
|
|||||||
members = this.getEmptyMessage();
|
members = this.getEmptyMessage();
|
||||||
} else {
|
} else {
|
||||||
$tw.utils.each(this.list,function(title,index) {
|
$tw.utils.each(this.list,function(title,index) {
|
||||||
members.push(self.makeItemTemplate(title));
|
members.push(self.makeItemTemplate(title,index));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Construct the child widgets
|
// Construct the child widgets
|
||||||
@ -87,8 +88,14 @@ ListWidget.prototype.getTiddlerList = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ListWidget.prototype.getEmptyMessage = function() {
|
ListWidget.prototype.getEmptyMessage = function() {
|
||||||
var emptyMessage = this.getAttribute("emptyMessage",""),
|
var parser,
|
||||||
parser = this.wiki.parseText("text/vnd.tiddlywiki",emptyMessage,{parseAsInline: true});
|
emptyMessage = this.getAttribute("emptyMessage","");
|
||||||
|
// this.wiki.parseText() calls
|
||||||
|
// new Parser(..), which should only be done, if needed, because it's heavy!
|
||||||
|
if (emptyMessage === "") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
parser = this.wiki.parseText("text/vnd.tiddlywiki",emptyMessage,{parseAsInline: true});
|
||||||
if(parser) {
|
if(parser) {
|
||||||
return parser.tree;
|
return parser.tree;
|
||||||
} else {
|
} else {
|
||||||
@ -99,7 +106,7 @@ ListWidget.prototype.getEmptyMessage = function() {
|
|||||||
/*
|
/*
|
||||||
Compose the template for a list item
|
Compose the template for a list item
|
||||||
*/
|
*/
|
||||||
ListWidget.prototype.makeItemTemplate = function(title) {
|
ListWidget.prototype.makeItemTemplate = function(title,index) {
|
||||||
// Check if the tiddler is a draft
|
// Check if the tiddler is a draft
|
||||||
var tiddler = this.wiki.getTiddler(title),
|
var tiddler = this.wiki.getTiddler(title),
|
||||||
isDraft = tiddler && tiddler.hasField("draft.of"),
|
isDraft = tiddler && tiddler.hasField("draft.of"),
|
||||||
@ -122,7 +129,14 @@ ListWidget.prototype.makeItemTemplate = function(title) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return the list item
|
// Return the list item
|
||||||
return {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree};
|
var parseTreeNode = {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree};
|
||||||
|
if(this.indexName) {
|
||||||
|
parseTreeNode.index = index.toString();
|
||||||
|
parseTreeNode.indexName = this.indexName;
|
||||||
|
parseTreeNode.isFirst = index === 0;
|
||||||
|
parseTreeNode.isLast = index === this.list.length - 1;
|
||||||
|
}
|
||||||
|
return parseTreeNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -136,7 +150,7 @@ ListWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
this.storyview.refreshStart(changedTiddlers,changedAttributes);
|
this.storyview.refreshStart(changedTiddlers,changedAttributes);
|
||||||
}
|
}
|
||||||
// Completely refresh if any of our attributes have changed
|
// Completely refresh if any of our attributes have changed
|
||||||
if(changedAttributes.filter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) {
|
if(changedAttributes.filter || changedAttributes.variable || changedAttributes.index || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
result = true;
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
@ -205,23 +219,41 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) {
|
|||||||
this.removeChildDomNodes();
|
this.removeChildDomNodes();
|
||||||
this.children = [];
|
this.children = [];
|
||||||
}
|
}
|
||||||
// Cycle through the list, inserting and removing list items as needed
|
// If we are providing an index variable then we must refresh the items, otherwise we can rearrange them
|
||||||
var hasRefreshed = false;
|
var hasRefreshed = false,t;
|
||||||
for(var t=0; t<this.list.length; t++) {
|
if(this.indexName) {
|
||||||
var index = this.findListItem(t,this.list[t]);
|
// Cycle through the list and remove and re-insert the first item that has changed, and all the remaining items
|
||||||
if(index === undefined) {
|
for(t=0; t<this.list.length; t++) {
|
||||||
// The list item must be inserted
|
if(hasRefreshed || !this.children[t] || this.children[t].parseTreeNode.itemTitle !== this.list[t]) {
|
||||||
this.insertListItem(t,this.list[t]);
|
if(this.children[t]) {
|
||||||
hasRefreshed = true;
|
this.removeListItem(t);
|
||||||
} else {
|
}
|
||||||
// There are intervening list items that must be removed
|
this.insertListItem(t,this.list[t]);
|
||||||
for(var n=index-1; n>=t; n--) {
|
|
||||||
this.removeListItem(n);
|
|
||||||
hasRefreshed = true;
|
hasRefreshed = true;
|
||||||
|
} else {
|
||||||
|
// Refresh the item we're reusing
|
||||||
|
var refreshed = this.children[t].refresh(changedTiddlers);
|
||||||
|
hasRefreshed = hasRefreshed || refreshed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Cycle through the list, inserting and removing list items as needed
|
||||||
|
for(t=0; t<this.list.length; t++) {
|
||||||
|
var index = this.findListItem(t,this.list[t]);
|
||||||
|
if(index === undefined) {
|
||||||
|
// The list item must be inserted
|
||||||
|
this.insertListItem(t,this.list[t]);
|
||||||
|
hasRefreshed = true;
|
||||||
|
} else {
|
||||||
|
// There are intervening list items that must be removed
|
||||||
|
for(var n=index-1; n>=t; n--) {
|
||||||
|
this.removeListItem(n);
|
||||||
|
hasRefreshed = true;
|
||||||
|
}
|
||||||
|
// Refresh the item we're reusing
|
||||||
|
var refreshed = this.children[t].refresh(changedTiddlers);
|
||||||
|
hasRefreshed = hasRefreshed || refreshed;
|
||||||
}
|
}
|
||||||
// Refresh the item we're reusing
|
|
||||||
var refreshed = this.children[t].refresh(changedTiddlers);
|
|
||||||
hasRefreshed = hasRefreshed || refreshed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove any left over items
|
// Remove any left over items
|
||||||
@ -251,7 +283,7 @@ Insert a new list item at the specified index
|
|||||||
*/
|
*/
|
||||||
ListWidget.prototype.insertListItem = function(index,title) {
|
ListWidget.prototype.insertListItem = function(index,title) {
|
||||||
// Create, insert and render the new child widgets
|
// Create, insert and render the new child widgets
|
||||||
var widget = this.makeChildWidget(this.makeItemTemplate(title));
|
var widget = this.makeChildWidget(this.makeItemTemplate(title,index));
|
||||||
widget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work
|
widget.parentDomNode = this.parentDomNode; // Hack to enable findNextSiblingDomNode() to work
|
||||||
this.children.splice(index,0,widget);
|
this.children.splice(index,0,widget);
|
||||||
var nextSibling = widget.findNextSiblingDomNode();
|
var nextSibling = widget.findNextSiblingDomNode();
|
||||||
@ -305,6 +337,11 @@ Compute the internal state of the widget
|
|||||||
ListItemWidget.prototype.execute = function() {
|
ListItemWidget.prototype.execute = function() {
|
||||||
// Set the current list item title
|
// Set the current list item title
|
||||||
this.setVariable(this.parseTreeNode.variableName,this.parseTreeNode.itemTitle);
|
this.setVariable(this.parseTreeNode.variableName,this.parseTreeNode.itemTitle);
|
||||||
|
if(this.parseTreeNode.indexName) {
|
||||||
|
this.setVariable(this.parseTreeNode.indexName,this.parseTreeNode.index);
|
||||||
|
this.setVariable(this.parseTreeNode.indexName + "-first",this.parseTreeNode.isFirst ? "yes" : "no");
|
||||||
|
this.setVariable(this.parseTreeNode.indexName + "-last",this.parseTreeNode.isLast ? "yes" : "no");
|
||||||
|
}
|
||||||
// Construct the child widgets
|
// Construct the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
@ -318,4 +355,4 @@ ListItemWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
|
|
||||||
exports.listitem = ListItemWidget;
|
exports.listitem = ListItemWidget;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
30
core/modules/widgets/log.js
Normal file
30
core/modules/widgets/log.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/log.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget-subclass
|
||||||
|
|
||||||
|
Widget to log debug messages
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.baseClass = "action-log";
|
||||||
|
|
||||||
|
exports.name = "log";
|
||||||
|
|
||||||
|
exports.constructor = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.prototype = {};
|
||||||
|
|
||||||
|
exports.prototype.render = function(event) {
|
||||||
|
Object.getPrototypeOf(Object.getPrototypeOf(this)).render.call(this,event);
|
||||||
|
Object.getPrototypeOf(Object.getPrototypeOf(this)).log.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
@ -55,9 +55,19 @@ MacroCallWidget.prototype.execute = function() {
|
|||||||
// Are we rendering to HTML?
|
// Are we rendering to HTML?
|
||||||
if(this.renderOutput === "text/html") {
|
if(this.renderOutput === "text/html") {
|
||||||
// If so we'll return the parsed macro
|
// If so we'll return the parsed macro
|
||||||
var parser = this.wiki.parseText(this.parseType,text,
|
// Check if we've already cached parsing this macro
|
||||||
{parseAsInline: !this.parseTreeNode.isBlock});
|
var mode = this.parseTreeNode.isBlock ? "blockParser" : "inlineParser",
|
||||||
parseTreeNodes = parser ? parser.tree : [];
|
parser;
|
||||||
|
if(variableInfo.srcVariable && variableInfo.srcVariable[mode]) {
|
||||||
|
parser = variableInfo.srcVariable[mode];
|
||||||
|
} else {
|
||||||
|
parser = this.wiki.parseText(this.parseType,text,
|
||||||
|
{parseAsInline: !this.parseTreeNode.isBlock});
|
||||||
|
if(variableInfo.isCacheable && variableInfo.srcVariable) {
|
||||||
|
variableInfo.srcVariable[mode] = parser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var parseTreeNodes = parser ? parser.tree : [];
|
||||||
// Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
|
// Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
|
||||||
var attributes = {};
|
var attributes = {};
|
||||||
$tw.utils.each(variableInfo.params,function(param) {
|
$tw.utils.each(variableInfo.params,function(param) {
|
||||||
|
100
core/modules/widgets/messagecatcher.js
Normal file
100
core/modules/widgets/messagecatcher.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/messagecatcher.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Message catcher widget
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var MessageCatcherWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
MessageCatcherWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
var self = this;
|
||||||
|
// Remember parent
|
||||||
|
this.parentDomNode = parent;
|
||||||
|
// Compute attributes and execute state
|
||||||
|
this.computeAttributes();
|
||||||
|
this.execute();
|
||||||
|
// Add our message handler
|
||||||
|
if(this.messageType) {
|
||||||
|
this.addEventListeners([
|
||||||
|
{type: this.messageType, handler: "handleEvent"}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
// Render children
|
||||||
|
this.renderChildren(parent,null);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compute the internal state of the widget
|
||||||
|
*/
|
||||||
|
MessageCatcherWidget.prototype.execute = function() {
|
||||||
|
var self = this;
|
||||||
|
// Get attributes that require a refresh on change
|
||||||
|
this.messageType = this.getAttribute("type");
|
||||||
|
this.messageActions = this.getAttribute("actions");
|
||||||
|
// Make child widgets
|
||||||
|
this.makeChildWidgets();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle an event
|
||||||
|
*/
|
||||||
|
MessageCatcherWidget.prototype.handleEvent = function(event) {
|
||||||
|
if(this.messageActions) {
|
||||||
|
// Collect all the event properties into variables
|
||||||
|
var collectProps = function(obj,prefix) {
|
||||||
|
prefix = prefix || "";
|
||||||
|
var props = {};
|
||||||
|
$tw.utils.each(obj,function(value,name) {
|
||||||
|
if(["string","boolean","number"].indexOf(typeof value) !== -1) {
|
||||||
|
props[prefix + name] = value.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return props;
|
||||||
|
};
|
||||||
|
var variables = $tw.utils.extend(
|
||||||
|
{},
|
||||||
|
collectProps(event.paramObject,"event-paramObject-"),
|
||||||
|
collectProps(event,"event-"),
|
||||||
|
{
|
||||||
|
modifier: $tw.keyboardManager.getEventModifierKeyDescriptor(event)
|
||||||
|
});
|
||||||
|
this.invokeActionString(this.messageActions,this,event,variables);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
|
*/
|
||||||
|
MessageCatcherWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
var changedAttributes = this.computeAttributes();
|
||||||
|
if(changedAttributes["type"]) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.refreshChildren(changedTiddlers);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.messagecatcher = MessageCatcherWidget;
|
||||||
|
|
||||||
|
})();
|
@ -18,6 +18,17 @@ var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
|||||||
|
|
||||||
var NavigatorWidget = function(parseTreeNode,options) {
|
var NavigatorWidget = function(parseTreeNode,options) {
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
NavigatorWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
NavigatorWidget.prototype.render = function(parent,nextSibling) {
|
||||||
this.addEventListeners([
|
this.addEventListeners([
|
||||||
{type: "tm-navigate", handler: "handleNavigateEvent"},
|
{type: "tm-navigate", handler: "handleNavigateEvent"},
|
||||||
{type: "tm-edit-tiddler", handler: "handleEditTiddlerEvent"},
|
{type: "tm-edit-tiddler", handler: "handleEditTiddlerEvent"},
|
||||||
@ -36,17 +47,6 @@ var NavigatorWidget = function(parseTreeNode,options) {
|
|||||||
{type: "tm-unfold-all-tiddlers", handler: "handleUnfoldAllTiddlersEvent"},
|
{type: "tm-unfold-all-tiddlers", handler: "handleUnfoldAllTiddlersEvent"},
|
||||||
{type: "tm-rename-tiddler", handler: "handleRenameTiddlerEvent"}
|
{type: "tm-rename-tiddler", handler: "handleRenameTiddlerEvent"}
|
||||||
]);
|
]);
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Inherit from the base widget class
|
|
||||||
*/
|
|
||||||
NavigatorWidget.prototype = new Widget();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Render this widget into the DOM
|
|
||||||
*/
|
|
||||||
NavigatorWidget.prototype.render = function(parent,nextSibling) {
|
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
@ -62,6 +62,11 @@ NavigatorWidget.prototype.execute = function() {
|
|||||||
this.historyTitle = this.getAttribute("history");
|
this.historyTitle = this.getAttribute("history");
|
||||||
this.setVariable("tv-story-list",this.storyTitle);
|
this.setVariable("tv-story-list",this.storyTitle);
|
||||||
this.setVariable("tv-history-list",this.historyTitle);
|
this.setVariable("tv-history-list",this.historyTitle);
|
||||||
|
this.story = new $tw.Story({
|
||||||
|
wiki: this.wiki,
|
||||||
|
storyTitle: this.storyTitle,
|
||||||
|
historyTitle: this.historyTitle
|
||||||
|
});
|
||||||
// Construct the child widgets
|
// Construct the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
@ -123,7 +128,7 @@ NavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle
|
|||||||
|
|
||||||
NavigatorWidget.prototype.addToStory = function(title,fromTitle) {
|
NavigatorWidget.prototype.addToStory = function(title,fromTitle) {
|
||||||
if(this.storyTitle) {
|
if(this.storyTitle) {
|
||||||
this.wiki.addToStory(title,fromTitle,this.storyTitle,{
|
this.story.addToStory(title,fromTitle,{
|
||||||
openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"),
|
openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"),
|
||||||
openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top")
|
openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top")
|
||||||
});
|
});
|
||||||
@ -136,7 +141,7 @@ title: a title string or an array of title strings
|
|||||||
fromPageRect: page coordinates of the origin of the navigation
|
fromPageRect: page coordinates of the origin of the navigation
|
||||||
*/
|
*/
|
||||||
NavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {
|
NavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {
|
||||||
this.wiki.addToHistory(title,fromPageRect,this.historyTitle);
|
this.story.addToHistory(title,fromPageRect,this.historyTitle);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -524,6 +529,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
|
|||||||
$tw.utils.each(importData.tiddlers,function(tiddler,title) {
|
$tw.utils.each(importData.tiddlers,function(tiddler,title) {
|
||||||
if($tw.utils.count(tiddler) === 0) {
|
if($tw.utils.count(tiddler) === 0) {
|
||||||
newFields["selection-" + title] = "unchecked";
|
newFields["selection-" + title] = "unchecked";
|
||||||
|
newFields["suppressed-" + title] = "yes";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Save the $:/Import tiddler
|
// Save the $:/Import tiddler
|
||||||
@ -558,10 +564,14 @@ NavigatorWidget.prototype.handlePerformImportEvent = function(event) {
|
|||||||
$tw.utils.each(importData.tiddlers,function(tiddlerFields) {
|
$tw.utils.each(importData.tiddlers,function(tiddlerFields) {
|
||||||
var title = tiddlerFields.title;
|
var title = tiddlerFields.title;
|
||||||
if(title && importTiddler && importTiddler.fields["selection-" + title] !== "unchecked") {
|
if(title && importTiddler && importTiddler.fields["selection-" + title] !== "unchecked") {
|
||||||
var tiddler = new $tw.Tiddler(tiddlerFields);
|
if($tw.utils.hop(importTiddler.fields,["rename-" + title])) {
|
||||||
|
var tiddler = new $tw.Tiddler(tiddlerFields,{title : importTiddler.fields["rename-" + title]});
|
||||||
|
} else {
|
||||||
|
var tiddler = new $tw.Tiddler(tiddlerFields);
|
||||||
|
}
|
||||||
tiddler = $tw.hooks.invokeHook("th-importing-tiddler",tiddler);
|
tiddler = $tw.hooks.invokeHook("th-importing-tiddler",tiddler);
|
||||||
self.wiki.addTiddler(tiddler);
|
self.wiki.addTiddler(tiddler);
|
||||||
importReport.push("# [[" + tiddlerFields.title + "]]");
|
importReport.push("# [[" + tiddler.fields.title + "]]");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Replace the $:/Import tiddler with an import report
|
// Replace the $:/Import tiddler with an import report
|
||||||
|
@ -13,7 +13,6 @@ Set a field or index at a given tiddler via radio buttons
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
var RadioWidget = function(parseTreeNode,options) {
|
var RadioWidget = function(parseTreeNode,options) {
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
};
|
};
|
||||||
@ -37,12 +36,15 @@ RadioWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
// Create our elements
|
// Create our elements
|
||||||
this.labelDomNode = this.document.createElement("label");
|
this.labelDomNode = this.document.createElement("label");
|
||||||
this.labelDomNode.setAttribute("class",
|
this.labelDomNode.setAttribute("class",
|
||||||
"tc-radio " + this.radioClass + (isChecked ? " tc-radio-selected" : "")
|
"tc-radio " + this.radioClass + (isChecked ? " tc-radio-selected" : "")
|
||||||
);
|
);
|
||||||
this.inputDomNode = this.document.createElement("input");
|
this.inputDomNode = this.document.createElement("input");
|
||||||
this.inputDomNode.setAttribute("type","radio");
|
this.inputDomNode.setAttribute("type","radio");
|
||||||
if(isChecked) {
|
if(isChecked) {
|
||||||
this.inputDomNode.setAttribute("checked","true");
|
this.inputDomNode.checked = true;
|
||||||
|
}
|
||||||
|
if(this.isDisabled === "yes") {
|
||||||
|
this.inputDomNode.setAttribute("disabled",true);
|
||||||
}
|
}
|
||||||
this.labelDomNode.appendChild(this.inputDomNode);
|
this.labelDomNode.appendChild(this.inputDomNode);
|
||||||
this.spanDomNode = this.document.createElement("span");
|
this.spanDomNode = this.document.createElement("span");
|
||||||
@ -60,10 +62,14 @@ RadioWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
RadioWidget.prototype.getValue = function() {
|
RadioWidget.prototype.getValue = function() {
|
||||||
var value,
|
var value,
|
||||||
tiddler = this.wiki.getTiddler(this.radioTitle);
|
tiddler = this.wiki.getTiddler(this.radioTitle);
|
||||||
if (this.radioIndex) {
|
if(tiddler) {
|
||||||
value = this.wiki.extractTiddlerDataItem(this.radioTitle,this.radioIndex);
|
if(this.radioIndex) {
|
||||||
|
value = this.wiki.extractTiddlerDataItem(this.radioTitle,this.radioIndex);
|
||||||
|
} else {
|
||||||
|
value = tiddler.getFieldString(this.radioField);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
value = tiddler && tiddler.getFieldString(this.radioField);
|
value = this.radioDefault;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -83,6 +89,10 @@ RadioWidget.prototype.handleChangeEvent = function(event) {
|
|||||||
if(this.inputDomNode.checked) {
|
if(this.inputDomNode.checked) {
|
||||||
this.setValue();
|
this.setValue();
|
||||||
}
|
}
|
||||||
|
// Trigger actions
|
||||||
|
if(this.radioActions) {
|
||||||
|
this.invokeActionString(this.radioActions,this,event,{"actionValue": this.radioValue});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -95,6 +105,9 @@ RadioWidget.prototype.execute = function() {
|
|||||||
this.radioIndex = this.getAttribute("index");
|
this.radioIndex = this.getAttribute("index");
|
||||||
this.radioValue = this.getAttribute("value");
|
this.radioValue = this.getAttribute("value");
|
||||||
this.radioClass = this.getAttribute("class","");
|
this.radioClass = this.getAttribute("class","");
|
||||||
|
this.radioDefault = this.getAttribute("default");
|
||||||
|
this.isDisabled = this.getAttribute("disabled","no");
|
||||||
|
this.radioActions = this.getAttribute("actions","");
|
||||||
// Make the child widgets
|
// Make the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
@ -104,16 +117,14 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
*/
|
*/
|
||||||
RadioWidget.prototype.refresh = function(changedTiddlers) {
|
RadioWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.value || changedAttributes["class"]) {
|
if(($tw.utils.count(changedAttributes) > 0)) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
|
} else if(changedTiddlers[this.radioTitle]) {
|
||||||
|
this.inputDomNode.checked = this.getValue() === this.radioValue;
|
||||||
|
return this.refreshChildren(changedTiddlers);
|
||||||
} else {
|
} else {
|
||||||
var refreshed = false;
|
return this.refreshChildren(changedTiddlers);
|
||||||
if(changedTiddlers[this.radioTitle]) {
|
|
||||||
this.inputDomNode.checked = this.getValue() === this.radioValue;
|
|
||||||
refreshed = true;
|
|
||||||
}
|
|
||||||
return this.refreshChildren(changedTiddlers) || refreshed;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,11 +46,16 @@ RangeWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
if(this.increment){
|
if(this.increment){
|
||||||
this.inputDomNode.setAttribute("step", this.increment);
|
this.inputDomNode.setAttribute("step", this.increment);
|
||||||
}
|
}
|
||||||
|
if(this.isDisabled === "yes") {
|
||||||
|
this.inputDomNode.setAttribute("disabled",true);
|
||||||
|
}
|
||||||
this.inputDomNode.value = this.getValue();
|
this.inputDomNode.value = this.getValue();
|
||||||
// Add a click event handler
|
// Add a click event handler
|
||||||
$tw.utils.addEventListeners(this.inputDomNode,[
|
$tw.utils.addEventListeners(this.inputDomNode,[
|
||||||
{name: "input", handlerObject: this, handlerMethod: "handleInputEvent"},
|
{name:"mousedown", handlerObject:this, handlerMethod:"handleMouseDownEvent"},
|
||||||
{name: "change", handlerObject: this, handlerMethod: "handleInputEvent"}
|
{name:"mouseup", handlerObject:this, handlerMethod:"handleMouseUpEvent"},
|
||||||
|
{name:"change", handlerObject:this, handlerMethod:"handleChangeEvent"},
|
||||||
|
{name:"input", handlerObject:this, handlerMethod:"handleInputEvent"},
|
||||||
]);
|
]);
|
||||||
// Insert the label into the DOM and render any children
|
// Insert the label into the DOM and render any children
|
||||||
parent.insertBefore(this.inputDomNode,nextSibling);
|
parent.insertBefore(this.inputDomNode,nextSibling);
|
||||||
@ -59,23 +64,77 @@ RangeWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
|
|
||||||
RangeWidget.prototype.getValue = function() {
|
RangeWidget.prototype.getValue = function() {
|
||||||
var tiddler = this.wiki.getTiddler(this.tiddlerTitle),
|
var tiddler = this.wiki.getTiddler(this.tiddlerTitle),
|
||||||
fieldName = this.tiddlerField || "text",
|
fieldName = this.tiddlerField,
|
||||||
value = this.defaultValue;
|
value = this.defaultValue;
|
||||||
if(tiddler) {
|
if(tiddler) {
|
||||||
if(this.tiddlerIndex) {
|
if(this.tiddlerIndex) {
|
||||||
value = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue || "");
|
value = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue);
|
||||||
} else {
|
} else {
|
||||||
if($tw.utils.hop(tiddler.fields,fieldName)) {
|
if($tw.utils.hop(tiddler.fields,fieldName)) {
|
||||||
value = tiddler.fields[fieldName] || "";
|
value = tiddler.fields[fieldName] || "";
|
||||||
} else {
|
} else {
|
||||||
value = this.defaultValue || "";
|
value = this.defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RangeWidget.prototype.getActionVariables = function(options) {
|
||||||
|
options = options || {};
|
||||||
|
var hasChanged = (this.startValue !== this.inputDomNode.value) ? "yes" : "no";
|
||||||
|
// Trigger actions. Use variables = {key:value, key:value ...}
|
||||||
|
// the "value" is needed.
|
||||||
|
return $tw.utils.extend({"actionValue": this.inputDomNode.value, "actionValueHasChanged": hasChanged}, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// actionsStart
|
||||||
|
RangeWidget.prototype.handleMouseDownEvent = function(event) {
|
||||||
|
this.mouseDown = true; // TODO remove once IE is gone.
|
||||||
|
this.startValue = this.inputDomNode.value; // TODO remove this line once IE is gone!
|
||||||
|
this.handleEvent(event);
|
||||||
|
// Trigger actions
|
||||||
|
if(this.actionsMouseDown) {
|
||||||
|
var variables = this.getActionVariables() // TODO this line will go into the function call below.
|
||||||
|
this.invokeActionString(this.actionsMouseDown,this,event,variables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// actionsStop
|
||||||
|
RangeWidget.prototype.handleMouseUpEvent = function(event) {
|
||||||
|
this.mouseDown = false; // TODO remove once IE is gone.
|
||||||
|
this.handleEvent(event);
|
||||||
|
// Trigger actions
|
||||||
|
if(this.actionsMouseUp) {
|
||||||
|
var variables = this.getActionVariables()
|
||||||
|
this.invokeActionString(this.actionsMouseUp,this,event,variables);
|
||||||
|
}
|
||||||
|
// TODO remove the following if() once IE is gone!
|
||||||
|
if ($tw.browser.isIE) {
|
||||||
|
if (this.startValue !== this.inputDomNode.value) {
|
||||||
|
this.handleChangeEvent(event);
|
||||||
|
this.startValue = this.inputDomNode.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeWidget.prototype.handleChangeEvent = function(event) {
|
||||||
|
if (this.mouseDown) { // TODO refactor this function once IE is gone.
|
||||||
|
this.handleInputEvent(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
RangeWidget.prototype.handleInputEvent = function(event) {
|
RangeWidget.prototype.handleInputEvent = function(event) {
|
||||||
|
this.handleEvent(event);
|
||||||
|
// Trigger actions
|
||||||
|
if(this.actionsInput) {
|
||||||
|
// "tiddler" parameter may be missing. See .execute() below
|
||||||
|
var variables = this.getActionVariables({"actionValueHasChanged": "yes"}) // TODO this line will go into the function call below.
|
||||||
|
this.invokeActionString(this.actionsInput,this,event,variables);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RangeWidget.prototype.handleEvent = function(event) {
|
||||||
if(this.getValue() !== this.inputDomNode.value) {
|
if(this.getValue() !== this.inputDomNode.value) {
|
||||||
if(this.tiddlerIndex) {
|
if(this.tiddlerIndex) {
|
||||||
this.wiki.setText(this.tiddlerTitle,"",this.tiddlerIndex,this.inputDomNode.value);
|
this.wiki.setText(this.tiddlerTitle,"",this.tiddlerIndex,this.inputDomNode.value);
|
||||||
@ -89,15 +148,24 @@ RangeWidget.prototype.handleInputEvent = function(event) {
|
|||||||
Compute the internal state of the widget
|
Compute the internal state of the widget
|
||||||
*/
|
*/
|
||||||
RangeWidget.prototype.execute = function() {
|
RangeWidget.prototype.execute = function() {
|
||||||
|
// TODO remove the next 1 lines once IE is gone!
|
||||||
|
this.mouseUp = true; // Needed for IE10
|
||||||
// Get the parameters from the attributes
|
// Get the parameters from the attributes
|
||||||
this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
||||||
this.tiddlerField = this.getAttribute("field");
|
this.tiddlerField = this.getAttribute("field","text");
|
||||||
this.tiddlerIndex = this.getAttribute("index");
|
this.tiddlerIndex = this.getAttribute("index");
|
||||||
this.minValue = this.getAttribute("min");
|
this.minValue = this.getAttribute("min");
|
||||||
this.maxValue = this.getAttribute("max");
|
this.maxValue = this.getAttribute("max");
|
||||||
this.increment = this.getAttribute("increment");
|
this.increment = this.getAttribute("increment");
|
||||||
this.defaultValue = this.getAttribute("default");
|
this.defaultValue = this.getAttribute("default","");
|
||||||
this.elementClass = this.getAttribute("class","");
|
this.elementClass = this.getAttribute("class","");
|
||||||
|
this.isDisabled = this.getAttribute("disabled","no");
|
||||||
|
// Actions since 5.1.23
|
||||||
|
// Next 2 only fire once!
|
||||||
|
this.actionsMouseDown = this.getAttribute("actionsStart","");
|
||||||
|
this.actionsMouseUp = this.getAttribute("actionsStop","");
|
||||||
|
// Input fires very often!
|
||||||
|
this.actionsInput = this.getAttribute("actions","");
|
||||||
// Make the child widgets
|
// Make the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
@ -107,7 +175,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
*/
|
*/
|
||||||
RangeWidget.prototype.refresh = function(changedTiddlers) {
|
RangeWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes['min'] || changedAttributes['max'] || changedAttributes['increment'] || changedAttributes["default"] || changedAttributes["class"]) {
|
if($tw.utils.count(changedAttributes) > 0) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -115,7 +183,7 @@ RangeWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
if(changedTiddlers[this.tiddlerTitle]) {
|
if(changedTiddlers[this.tiddlerTitle]) {
|
||||||
var value = this.getValue();
|
var value = this.getValue();
|
||||||
if(this.inputDomNode.value !== value) {
|
if(this.inputDomNode.value !== value) {
|
||||||
this.inputDomNode.value = value;
|
this.inputDomNode.value = value;
|
||||||
}
|
}
|
||||||
refreshed = true;
|
refreshed = true;
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,8 @@ RevealWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
tag = this.revealTag;
|
tag = this.revealTag;
|
||||||
}
|
}
|
||||||
var domNode = this.document.createElement(tag);
|
var domNode = this.document.createElement(tag);
|
||||||
var classes = this["class"].split(" ") || [];
|
this.domNode = domNode;
|
||||||
classes.push("tc-reveal");
|
this.assignDomNodeClasses();
|
||||||
domNode.className = classes.join(" ");
|
|
||||||
if(this.style) {
|
if(this.style) {
|
||||||
domNode.setAttribute("style",this.style);
|
domNode.setAttribute("style",this.style);
|
||||||
}
|
}
|
||||||
@ -70,6 +69,10 @@ RevealWidget.prototype.positionPopup = function(domNode) {
|
|||||||
left = this.popup.left + this.popup.width;
|
left = this.popup.left + this.popup.width;
|
||||||
top = this.popup.top + this.popup.height - domNode.offsetHeight;
|
top = this.popup.top + this.popup.height - domNode.offsetHeight;
|
||||||
break;
|
break;
|
||||||
|
case "belowright":
|
||||||
|
left = this.popup.left + this.popup.width;
|
||||||
|
top = this.popup.top + this.popup.height;
|
||||||
|
break;
|
||||||
case "right":
|
case "right":
|
||||||
left = this.popup.left + this.popup.width;
|
left = this.popup.left + this.popup.width;
|
||||||
top = this.popup.top;
|
top = this.popup.top;
|
||||||
@ -78,6 +81,10 @@ RevealWidget.prototype.positionPopup = function(domNode) {
|
|||||||
left = this.popup.left + this.popup.width - domNode.offsetWidth;
|
left = this.popup.left + this.popup.width - domNode.offsetWidth;
|
||||||
top = this.popup.top + this.popup.height;
|
top = this.popup.top + this.popup.height;
|
||||||
break;
|
break;
|
||||||
|
case "aboveleft":
|
||||||
|
left = this.popup.left - domNode.offsetWidth;
|
||||||
|
top = this.popup.top - domNode.offsetHeight;
|
||||||
|
break;
|
||||||
default: // Below
|
default: // Below
|
||||||
left = this.popup.left;
|
left = this.popup.left;
|
||||||
top = this.popup.top + this.popup.height;
|
top = this.popup.top + this.popup.height;
|
||||||
@ -102,13 +109,14 @@ RevealWidget.prototype.execute = function() {
|
|||||||
this.text = this.getAttribute("text");
|
this.text = this.getAttribute("text");
|
||||||
this.position = this.getAttribute("position");
|
this.position = this.getAttribute("position");
|
||||||
this.positionAllowNegative = this.getAttribute("positionAllowNegative") === "yes";
|
this.positionAllowNegative = this.getAttribute("positionAllowNegative") === "yes";
|
||||||
this["class"] = this.getAttribute("class","");
|
// class attribute handled in assignDomNodeClasses()
|
||||||
this.style = this.getAttribute("style","");
|
this.style = this.getAttribute("style","");
|
||||||
this["default"] = this.getAttribute("default","");
|
this["default"] = this.getAttribute("default","");
|
||||||
this.animate = this.getAttribute("animate","no");
|
this.animate = this.getAttribute("animate","no");
|
||||||
this.retain = this.getAttribute("retain","no");
|
this.retain = this.getAttribute("retain","no");
|
||||||
this.openAnimation = this.animate === "no" ? undefined : "open";
|
this.openAnimation = this.animate === "no" ? undefined : "open";
|
||||||
this.closeAnimation = this.animate === "no" ? undefined : "close";
|
this.closeAnimation = this.animate === "no" ? undefined : "close";
|
||||||
|
this.updatePopupPosition = this.getAttribute("updatePopupPosition","no") === "yes";
|
||||||
// Compute the title of the state tiddler and read it
|
// Compute the title of the state tiddler and read it
|
||||||
this.stateTiddlerTitle = this.state;
|
this.stateTiddlerTitle = this.state;
|
||||||
this.stateTitle = this.getAttribute("stateTitle");
|
this.stateTitle = this.getAttribute("stateTitle");
|
||||||
@ -194,6 +202,12 @@ RevealWidget.prototype.readPopupState = function(state) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RevealWidget.prototype.assignDomNodeClasses = function() {
|
||||||
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
|
classes.push("tc-reveal");
|
||||||
|
this.domNode.className = classes.join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
*/
|
*/
|
||||||
@ -212,7 +226,15 @@ RevealWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if(this.type === "popup" && this.updatePopupPosition && (changedTiddlers[this.state] || changedTiddlers[this.stateTitle])) {
|
||||||
|
this.positionPopup(this.domNode);
|
||||||
}
|
}
|
||||||
|
if(changedAttributes.style) {
|
||||||
|
this.domNode.style = this.getAttribute("style","");
|
||||||
|
}
|
||||||
|
if(changedAttributes["class"]) {
|
||||||
|
this.assignDomNodeClasses();
|
||||||
|
}
|
||||||
return this.refreshChildren(changedTiddlers);
|
return this.refreshChildren(changedTiddlers);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -16,26 +16,6 @@ var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
|||||||
|
|
||||||
var ScrollableWidget = function(parseTreeNode,options) {
|
var ScrollableWidget = function(parseTreeNode,options) {
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
this.scaleFactor = 1;
|
|
||||||
this.addEventListeners([
|
|
||||||
{type: "tm-scroll", handler: "handleScrollEvent"}
|
|
||||||
]);
|
|
||||||
if($tw.browser) {
|
|
||||||
this.requestAnimationFrame = window.requestAnimationFrame ||
|
|
||||||
window.webkitRequestAnimationFrame ||
|
|
||||||
window.mozRequestAnimationFrame ||
|
|
||||||
function(callback) {
|
|
||||||
return window.setTimeout(callback, 1000/60);
|
|
||||||
};
|
|
||||||
this.cancelAnimationFrame = window.cancelAnimationFrame ||
|
|
||||||
window.webkitCancelAnimationFrame ||
|
|
||||||
window.webkitCancelRequestAnimationFrame ||
|
|
||||||
window.mozCancelAnimationFrame ||
|
|
||||||
window.mozCancelRequestAnimationFrame ||
|
|
||||||
function(id) {
|
|
||||||
window.clearTimeout(id);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -147,6 +127,26 @@ Render this widget into the DOM
|
|||||||
*/
|
*/
|
||||||
ScrollableWidget.prototype.render = function(parent,nextSibling) {
|
ScrollableWidget.prototype.render = function(parent,nextSibling) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
this.scaleFactor = 1;
|
||||||
|
this.addEventListeners([
|
||||||
|
{type: "tm-scroll", handler: "handleScrollEvent"}
|
||||||
|
]);
|
||||||
|
if($tw.browser) {
|
||||||
|
this.requestAnimationFrame = window.requestAnimationFrame ||
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
function(callback) {
|
||||||
|
return window.setTimeout(callback, 1000/60);
|
||||||
|
};
|
||||||
|
this.cancelAnimationFrame = window.cancelAnimationFrame ||
|
||||||
|
window.webkitCancelAnimationFrame ||
|
||||||
|
window.webkitCancelRequestAnimationFrame ||
|
||||||
|
window.mozCancelAnimationFrame ||
|
||||||
|
window.mozCancelRequestAnimationFrame ||
|
||||||
|
function(id) {
|
||||||
|
window.clearTimeout(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
// Remember parent
|
// Remember parent
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
// Compute attributes and execute state
|
// Compute attributes and execute state
|
||||||
|
@ -43,6 +43,7 @@ TranscludeWidget.prototype.execute = function() {
|
|||||||
this.transcludeField = this.getAttribute("field");
|
this.transcludeField = this.getAttribute("field");
|
||||||
this.transcludeIndex = this.getAttribute("index");
|
this.transcludeIndex = this.getAttribute("index");
|
||||||
this.transcludeMode = this.getAttribute("mode");
|
this.transcludeMode = this.getAttribute("mode");
|
||||||
|
this.recursionMarker = this.getAttribute("recursionMarker","yes");
|
||||||
// Parse the text reference
|
// Parse the text reference
|
||||||
var parseAsInline = !this.parseTreeNode.isBlock;
|
var parseAsInline = !this.parseTreeNode.isBlock;
|
||||||
if(this.transcludeMode === "inline") {
|
if(this.transcludeMode === "inline") {
|
||||||
@ -61,7 +62,9 @@ TranscludeWidget.prototype.execute = function() {
|
|||||||
parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;
|
parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;
|
||||||
// Set context variables for recursion detection
|
// Set context variables for recursion detection
|
||||||
var recursionMarker = this.makeRecursionMarker();
|
var recursionMarker = this.makeRecursionMarker();
|
||||||
this.setVariable("transclusion",recursionMarker);
|
if(this.recursionMarker === "yes") {
|
||||||
|
this.setVariable("transclusion",recursionMarker);
|
||||||
|
}
|
||||||
// Check for recursion
|
// Check for recursion
|
||||||
if(parser) {
|
if(parser) {
|
||||||
if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) {
|
if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user