mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-23 03:14:40 +00:00
Compare commits
1 Commits
publishing
...
word-games
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e26d0175eb |
@@ -5,7 +5,7 @@
|
||||
# Default to the current version number for building the plugin library
|
||||
|
||||
if [ -z "$TW5_BUILD_VERSION" ]; then
|
||||
TW5_BUILD_VERSION=v5.2.0
|
||||
TW5_BUILD_VERSION=v5.1.24
|
||||
fi
|
||||
|
||||
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
||||
|
||||
60
boot/boot.js
60
boot/boot.js
@@ -757,12 +757,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
|
||||
tiddler = $tw.wiki.getTiddler(name),
|
||||
_exports = {},
|
||||
sandbox = {
|
||||
module: {
|
||||
exports: _exports,
|
||||
setStringHandler: function(handler) {
|
||||
moduleInfo.stringHandler = handler;
|
||||
}
|
||||
},
|
||||
module: {exports: _exports},
|
||||
//moduleInfo: moduleInfo,
|
||||
exports: _exports,
|
||||
console: console,
|
||||
@@ -826,7 +821,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
|
||||
moduleInfo.definition(moduleInfo,moduleInfo.exports,sandbox.require);
|
||||
} else if(typeof moduleInfo.definition === "string") { // String
|
||||
moduleInfo.exports = _exports;
|
||||
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,name);
|
||||
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title);
|
||||
if(sandbox.module.exports) {
|
||||
moduleInfo.exports = sandbox.module.exports; //more codemirror workaround
|
||||
}
|
||||
@@ -923,20 +918,6 @@ $tw.modules.createClassesFromModules = function(moduleType,subType,baseClass) {
|
||||
return classes;
|
||||
};
|
||||
|
||||
/*
|
||||
Return a specified module string for a module, null if the module or string is missing
|
||||
*/
|
||||
$tw.modules.getModuleString = function(moduleName,stringName,language) {
|
||||
if(moduleName in $tw.modules.titles) {
|
||||
$tw.modules.execute(moduleName);
|
||||
var stringHandler = $tw.modules.titles[moduleName].stringHandler;
|
||||
if(stringHandler) {
|
||||
return stringHandler(stringName,language);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/////////////////////////// Barebones tiddler object
|
||||
|
||||
/*
|
||||
@@ -1743,20 +1724,13 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
|
||||
},
|
||||
t,result = [];
|
||||
if(node) {
|
||||
var type = (node.getAttribute && node.getAttribute("type")) || null;
|
||||
if(type) {
|
||||
// A new-style container with an explicit deserialization type
|
||||
result = $tw.wiki.deserializeTiddlers(type,node.textContent);
|
||||
} else {
|
||||
// An old-style container of classic DIV-based tiddlers
|
||||
for(t = 0; t < node.childNodes.length; t++) {
|
||||
for(t = 0; t < node.childNodes.length; t++) {
|
||||
var childNode = node.childNodes[t],
|
||||
tiddlers = extractTextTiddlers(childNode);
|
||||
tiddlers = tiddlers || extractModuleTiddlers(childNode);
|
||||
if(tiddlers) {
|
||||
result.push.apply(result,tiddlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1765,23 +1739,17 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
|
||||
|
||||
$tw.loadTiddlersBrowser = function() {
|
||||
// In the browser, we load tiddlers from certain elements
|
||||
var containerSelectors = [
|
||||
// IDs for old-style v5.1.x tiddler stores
|
||||
"#libraryModules",
|
||||
"#modules",
|
||||
"#bootKernelPrefix",
|
||||
"#bootKernel",
|
||||
"#styleArea",
|
||||
"#storeArea",
|
||||
"#systemArea",
|
||||
// Classes for new-style v5.2.x JSON tiddler stores
|
||||
"script.tiddlywiki-tiddler-store"
|
||||
var containerIds = [
|
||||
"libraryModules",
|
||||
"modules",
|
||||
"bootKernelPrefix",
|
||||
"bootKernel",
|
||||
"styleArea",
|
||||
"storeArea",
|
||||
"systemArea"
|
||||
];
|
||||
for(var t=0; t<containerSelectors.length; t++) {
|
||||
var nodes = document.querySelectorAll(containerSelectors[t]);
|
||||
for(var n=0; n<nodes.length; n++) {
|
||||
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",nodes[n]));
|
||||
}
|
||||
for(var t=0; t<containerIds.length; t++) {
|
||||
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",document.getElementById(containerIds[t])));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2017,7 +1985,7 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
|
||||
pluginInfo.dependents = pluginInfo.dependents || [];
|
||||
pluginInfo.type = "application/json";
|
||||
// Set plugin text
|
||||
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
|
||||
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers},null,4);
|
||||
delete pluginInfo.tiddlers;
|
||||
// Deserialise array fields (currently required for the dependents field)
|
||||
for(var field in pluginInfo) {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
title: $:/core/images/publish
|
||||
tags: $:/tags/Image
|
||||
|
||||
<svg width="22pt" height="22pt" class="tc-image-publish tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd">
|
||||
<path d="M64.0434107,46.2358498 C65.8048912,45.8955184 67.6195684,46.7809274 68.4102078,48.4458716 L68.4937877,48.6340507 L98.8972485,122.034498 C99.7426494,124.075476 98.7734424,126.415349 96.7324641,127.26075 C94.7552664,128.079732 92.4975633,127.195747 91.5897922,125.284145 L91.5062123,125.095966 L88.403,117.605598 L79.5048497,126.50485 C78.775871,127.233828 77.8355254,127.622617 76.8810886,127.671216 L76.6764226,127.676423 C75.6527333,127.676423 74.6290441,127.285898 73.8479955,126.50485 L63.999,116.656598 L54.1520045,126.50485 C53.4230259,127.233828 52.4826802,127.622617 51.5282434,127.671216 L51.3235774,127.676423 C50.2998881,127.676423 49.2761989,127.285898 48.4951503,126.50485 L39.596,117.605598 L36.4937877,125.095966 C35.6483868,127.136944 33.3085142,128.106151 31.2675359,127.26075 C29.2265576,126.415349 28.2573506,124.075476 29.1027515,122.034498 L59.5062123,48.6340507 C60.2518688,46.8338766 62.1601511,45.867488 64.0005148,46.2445933 L64.0434107,46.2358498 Z M77.679,102.976598 L69.656,110.999598 L76.676,118.018598 L84.699,109.996598 L77.679,102.976598 Z M50.326,102.983598 L43.307,110.002598 L51.323,118.018598 L58.342,110.999598 L50.326,102.983598 Z M64.006,89.3035977 L55.983,97.3265977 L63.999,105.342598 L72.022,97.3195977 L64.006,89.3035977 Z M55.035,80.3325977 L50.348,91.6475977 L58.349,83.6465977 L55.035,80.3325977 Z M72.968,80.3415977 L69.663,83.6465977 L77.642,91.6255977 L72.968,80.3415977 Z M64,58.6895977 L58.3344072,72.3699713 C58.4295481,72.4423583 58.5221874,72.5195778 58.6119911,72.6016299 L58.7445283,72.7283325 L64.006,77.9895977 L69.2684411,72.7283325 C69.3957231,72.6010505 69.5294489,72.4841397 69.6685683,72.3775999 L64,58.6895977 Z M38.5026635,2.59571369 C40.7118025,2.59571369 42.5026635,4.38657469 42.5026635,6.59571369 C42.5026635,7.7643162 42.0015346,8.8158738 41.2024517,9.54721162 L41.372583,9.372583 C35.581722,15.163444 32,23.163444 32,32 C32,40.8370609 35.5821314,48.8374703 41.3735757,54.6284097 C42.0884306,55.3520538 42.531226,56.3471171 42.531226,57.4456008 C42.531226,59.6547398 40.740365,61.4456008 38.531226,61.4456008 C37.4327422,61.4456008 36.4376789,61.0028055 35.7147885,60.2859673 L35.7048234,60.2963403 C28.472656,53.0586276 24,43.0631255 24,32.0229786 C24,21.1046577 28.3744907,11.2080539 35.4664167,3.99022262 C36.2004724,3.13678606 37.2883808,2.59571369 38.5026635,2.59571369 Z M89.3688013,2.48959773 C90.5097745,2.48959773 91.5391719,2.96731026 92.2678917,3.73363348 L92.2733617,3.72780197 C99.5183488,10.9672382 104,20.9717355 104,32.0229786 C104,42.8488024 99.6993143,52.6701472 92.7132398,59.8717162 C91.9816831,60.8152368 90.8371876,61.4223982 89.5508819,61.4223982 C87.3417429,61.4223982 85.5508819,59.6315372 85.5508819,57.4223982 C85.5508819,56.3502862 85.9726717,55.3766885 86.6593633,54.6584932 L86.627417,54.627417 C92.418278,48.836556 96,40.836556 96,32 C96,23.2702193 92.5043135,15.3568999 86.8363661,9.5834674 C85.9399594,8.85136737 85.3688013,7.73718311 85.3688013,6.48959773 C85.3688013,4.28045873 87.1596623,2.48959773 89.3688013,2.48959773 Z M50.0871028,13.6297119 C52.2962418,13.6297119 54.0871028,15.4205729 54.0871028,17.6297119 C54.0871028,18.8506134 53.5401157,19.9437593 52.6778337,20.6774573 L52.6862915,20.6862915 C49.790861,23.581722 48,27.581722 48,32 C48,36.4187838 49.791271,40.4191937 52.6872859,43.3147028 L52.6777105,43.3251493 C53.4423082,44.0537041 53.918794,45.0819221 53.918794,46.2214294 C53.918794,48.4305684 52.127933,50.2214294 49.918794,50.2214294 C48.6900999,50.2214294 47.5907975,49.6674376 46.8570439,48.7956109 L47.0304281,48.9715536 C42.6867001,44.6283295 40,38.627921 40,32 C40,25.372583 42.6862915,19.372583 47.0294373,15.0294373 L47.0395567,15.0387468 C47.7732533,14.1766 48.8663118,13.6297119 50.0871028,13.6297119 Z M77.9823819,13.700452 C79.1679628,13.700452 80.2330731,14.2162483 80.9655529,15.0356811 L80.9715536,15.0304281 C85.314117,19.3734956 88,25.373087 88,32 C88,38.4619387 85.4461804,44.3274009 81.2927766,48.6421512 L80.9933974,48.9476975 C80.2638884,49.7186971 79.2309977,50.2000547 78.08568,50.2000547 C75.876541,50.2000547 74.08568,48.4091937 74.08568,46.2000547 C74.08568,45.0665777 74.557136,44.0432152 75.314649,43.3153662 L75.3137085,43.3137085 C78.209139,40.418278 80,36.418278 80,32 C80,27.5822253 78.209547,23.5826334 75.314698,20.6872811 C74.4981782,19.9511432 73.9823819,18.8860329 73.9823819,17.700452 C73.9823819,15.491313 75.7732429,13.700452 77.9823819,13.700452 Z M64,24 C68.418278,24 72,27.581722 72,32 C72,36.418278 68.418278,40 64,40 C59.581722,40 56,36.418278 56,32 C56,27.581722 59.581722,24 64,24 Z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
@@ -32,8 +32,6 @@ ExportTiddler/Caption: export tiddler
|
||||
ExportTiddler/Hint: Export tiddler
|
||||
ExportTiddlers/Caption: export tiddlers
|
||||
ExportTiddlers/Hint: Export tiddlers
|
||||
ExportTiddlyWikiCore/Caption: export TiddlyWiki core
|
||||
ExportTiddlyWikiCore/Hint: Export the ~TiddlyWiki core code for running with external ~JavaScript
|
||||
SidebarSearch/Hint: Select the sidebar search field
|
||||
Fold/Caption: fold tiddler
|
||||
Fold/Hint: Fold the body of this tiddler
|
||||
@@ -85,8 +83,6 @@ Permaview/Caption: permaview
|
||||
Permaview/Hint: Set browser address bar to a direct link to all the tiddlers in this story
|
||||
Print/Caption: print page
|
||||
Print/Hint: Print the current page
|
||||
Publish/Caption: publish
|
||||
Publish/Hint: Publish from the wiki
|
||||
Refresh/Caption: refresh
|
||||
Refresh/Hint: Perform a full refresh of the wiki
|
||||
Save/Caption: ok
|
||||
|
||||
@@ -96,8 +96,6 @@ Plugins/Updates/Caption: Updates
|
||||
Plugins/Updates/Hint: Available updates to installed plugins
|
||||
Plugins/Updates/UpdateAll/Caption: Update <<update-count>> plugins
|
||||
Plugins/SubPluginPrompt: With <<count>> sub-plugins available
|
||||
Publishing/Caption: Publishing
|
||||
Publishing/Hint: Settings used for publishing extracts from this TiddlyWiki as separate files through a "publisher" module
|
||||
Saving/Caption: Saving
|
||||
Saving/DownloadSaver/AutoSave/Description: Permit automatic saving for the download saver
|
||||
Saving/DownloadSaver/AutoSave/Hint: Enable Autosave for Download Saver
|
||||
|
||||
@@ -23,7 +23,6 @@ All parameters are optional with safe defaults, and can be specified in any orde
|
||||
* ''writers'' - comma-separated list of principals allowed to write to this wiki
|
||||
* ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no")
|
||||
* ''sse-enabled'' - set to "yes" to enable Server-sent events (defaults to "no")
|
||||
* ''sitemap'' - optional sitemap describing how the tiddlers will be served. See [[Publishing]] for more details
|
||||
* ''root-tiddler'' - the tiddler to serve at the root (defaults to "$:/core/save/all")
|
||||
* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to "text/plain")
|
||||
* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to "text/html")
|
||||
|
||||
@@ -3,7 +3,6 @@ title: $:/language/Import/
|
||||
Editor/Import/Heading: Import images and insert them into the editor.
|
||||
Imported/Hint: The following tiddlers were imported:
|
||||
Listing/Cancel/Caption: Cancel
|
||||
Listing/Cancel/Warning: Do you wish to cancel the import?
|
||||
Listing/Hint: These tiddlers are ready to import:
|
||||
Listing/Import/Caption: Import
|
||||
Listing/Select/Caption: Select
|
||||
|
||||
@@ -41,6 +41,7 @@ Error/WhileSaving: Error while saving
|
||||
Error/XMLHttpRequest: XMLHttpRequest error code
|
||||
InternalJavaScriptError/Title: Internal JavaScript Error
|
||||
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
|
||||
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)
|
||||
LayoutSwitcher/Description: Open the layout switcher
|
||||
LazyLoadingWarning: <p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p>
|
||||
LoginToTiddlySpace: Login to TiddlySpace
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
title: $:/language/Publishing/Modal
|
||||
subtitle: Publishing: ''<$transclude field="caption"><$view field="title"/></$transclude>''
|
||||
footer: <$button message="tm-close-tiddler">Cancel</$button>
|
||||
|
||||
Publishing <$text text=<<totalFiles>>/> files via the "{{!!publisher}}" publisher.
|
||||
@@ -1,46 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/publish.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Publish static files
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "publish",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
if(this.params.length < 1) {
|
||||
return "Missing filename filter";
|
||||
}
|
||||
var self = this,
|
||||
wiki = this.commander.wiki,
|
||||
jobTiddler = this.params[0],
|
||||
variableList = this.params.slice(1),
|
||||
variables = Object.create(null);
|
||||
while(variableList.length >= 2) {
|
||||
variables[variableList[0]] = variableList[1];
|
||||
variableList = variableList.slice(2);
|
||||
}
|
||||
$tw.publisherHandler.publish(jobTiddler,this.callback,{commander: this.commander,variables: variables});
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
|
||||
@@ -40,10 +40,10 @@ Command.prototype.execute = function() {
|
||||
variableList = this.params.slice(4),
|
||||
tiddlers = wiki.filterTiddlers(tiddlerFilter),
|
||||
variables = Object.create(null);
|
||||
while(variableList.length >= 2) {
|
||||
variables[variableList[0]] = variableList[1];
|
||||
variableList = variableList.slice(2);
|
||||
}
|
||||
while(variableList.length >= 2) {
|
||||
variables[variableList[0]] = variableList[1];
|
||||
variableList = variableList.slice(2);
|
||||
}
|
||||
$tw.utils.each(tiddlers,function(title) {
|
||||
var parser = wiki.parseTiddler(template || title);
|
||||
var widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title})}),
|
||||
|
||||
@@ -12,8 +12,63 @@ Functions to deserialise tiddlers from a block of text
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Utility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:
|
||||
|
||||
<div title="Title" creator="JoeBloggs" modifier="JoeBloggs" created="201102111106" modified="201102111310" tags="myTag [[my long tag]]">
|
||||
<pre>The text of the tiddler (without the expected HTML encoding).
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
Note that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.
|
||||
|
||||
When these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.
|
||||
*/
|
||||
var parseTiddlerDiv = function(text /* [,fields] */) {
|
||||
// Slot together the default results
|
||||
var result = {};
|
||||
if(arguments.length > 1) {
|
||||
for(var f=1; f<arguments.length; f++) {
|
||||
var fields = arguments[f];
|
||||
for(var t in fields) {
|
||||
result[t] = fields[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parse the DIV body
|
||||
var startRegExp = /^\s*<div\s+([^>]*)>(\s*<pre>)?/gi,
|
||||
endRegExp,
|
||||
match = startRegExp.exec(text);
|
||||
if(match) {
|
||||
// Old-style DIVs don't have the <pre> tag
|
||||
if(match[2]) {
|
||||
endRegExp = /<\/pre>\s*<\/div>\s*$/gi;
|
||||
} else {
|
||||
endRegExp = /<\/div>\s*$/gi;
|
||||
}
|
||||
var endMatch = endRegExp.exec(text);
|
||||
if(endMatch) {
|
||||
// Extract the text
|
||||
result.text = text.substring(match.index + match[0].length,endMatch.index);
|
||||
// Process the attributes
|
||||
var attrRegExp = /\s*([^=\s]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi,
|
||||
attrMatch;
|
||||
do {
|
||||
attrMatch = attrRegExp.exec(match[1]);
|
||||
if(attrMatch) {
|
||||
var name = attrMatch[1];
|
||||
var value = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];
|
||||
result[name] = value;
|
||||
}
|
||||
} while(attrMatch);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
exports["application/x-tiddler-html-div"] = function(text,fields) {
|
||||
return [deserializeTiddlerDiv(text,fields)];
|
||||
return [parseTiddlerDiv(text,fields)];
|
||||
};
|
||||
|
||||
exports["application/json"] = function(text,fields) {
|
||||
@@ -50,34 +105,30 @@ Parse an HTML file into tiddlers. There are three possibilities:
|
||||
# An ordinary HTML file
|
||||
*/
|
||||
exports["text/html"] = function(text,fields) {
|
||||
var results = [];
|
||||
// Check if we've got an old-style store area
|
||||
// Check if we've got a store area
|
||||
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
|
||||
storeAreaMatch = storeAreaMarkerRegExp.exec(text);
|
||||
if(storeAreaMatch) {
|
||||
// If so, we've got tiddlers in classic TiddlyWiki format or unencrypted old-style TW5 format
|
||||
results.push.apply(results,deserializeStoreArea(text,storeAreaMarkerRegExp.lastIndex,!!storeAreaMatch[1],fields));
|
||||
}
|
||||
// Check for new-style store areas
|
||||
var newStoreAreaMarkerRegExp = /<script class="tiddlywiki-tiddler-store" type="([^"]*)">/gi,
|
||||
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text),
|
||||
haveHadNewStoreArea = !!newStoreAreaMatch;
|
||||
while(newStoreAreaMatch) {
|
||||
results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields));
|
||||
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text);
|
||||
}
|
||||
// Return if we had either an old-style or a new-style store area
|
||||
if(storeAreaMatch || haveHadNewStoreArea) {
|
||||
match = storeAreaMarkerRegExp.exec(text);
|
||||
if(match) {
|
||||
// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file
|
||||
// First read the normal tiddlers
|
||||
var results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
|
||||
// Then any system tiddlers
|
||||
var systemAreaMarkerRegExp = /<div id=["']?systemArea['"]?( style=["']?display:none;["']?)?>/gi,
|
||||
sysMatch = systemAreaMarkerRegExp.exec(text);
|
||||
if(sysMatch) {
|
||||
results.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
// Otherwise, check whether we've got an encrypted file
|
||||
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
|
||||
if(encryptedStoreArea) {
|
||||
// If so, attempt to decrypt it using the current password
|
||||
return $tw.utils.decryptStoreArea(encryptedStoreArea);
|
||||
} else {
|
||||
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
|
||||
return deserializeHtmlFile(text,fields);
|
||||
// Check whether we've got an encrypted file
|
||||
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
|
||||
if(encryptedStoreArea) {
|
||||
// If so, attempt to decrypt it using the current password
|
||||
return $tw.utils.decryptStoreArea(encryptedStoreArea);
|
||||
} else {
|
||||
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
|
||||
return deserializeHtmlFile(text,fields);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,19 +142,7 @@ function deserializeHtmlFile(text,fields) {
|
||||
return [result];
|
||||
}
|
||||
|
||||
function deserializeNewStoreArea(text,storeAreaEnd,type,fields) {
|
||||
var endOfScriptRegExp = /<\/script>/gi;
|
||||
endOfScriptRegExp.lastIndex = storeAreaEnd;
|
||||
var match = endOfScriptRegExp.exec(text);
|
||||
if(match) {
|
||||
var scriptContent = text.substring(storeAreaEnd,match.index);
|
||||
return $tw.wiki.deserializeTiddlers(type,scriptContent);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
|
||||
function deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {
|
||||
var results = [],
|
||||
endOfDivRegExp = /(<\/div>\s*)/gi,
|
||||
startPos = storeAreaEnd,
|
||||
@@ -112,7 +151,7 @@ function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
|
||||
var match = endOfDivRegExp.exec(text);
|
||||
while(match) {
|
||||
var endPos = endOfDivRegExp.lastIndex,
|
||||
tiddlerFields = deserializeTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
|
||||
tiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
|
||||
if(!tiddlerFields) {
|
||||
break;
|
||||
}
|
||||
@@ -130,59 +169,4 @@ function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
|
||||
return results;
|
||||
}
|
||||
|
||||
/*
|
||||
Utility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:
|
||||
|
||||
<div title="Title" creator="JoeBloggs" modifier="JoeBloggs" created="201102111106" modified="201102111310" tags="myTag [[my long tag]]">
|
||||
<pre>The text of the tiddler (without the expected HTML encoding).
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
Note that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.
|
||||
|
||||
When these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.
|
||||
*/
|
||||
var deserializeTiddlerDiv = function(text /* [,fields] */) {
|
||||
// Slot together the default results
|
||||
var result = {};
|
||||
if(arguments.length > 1) {
|
||||
for(var f=1; f<arguments.length; f++) {
|
||||
var fields = arguments[f];
|
||||
for(var t in fields) {
|
||||
result[t] = fields[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parse the DIV body
|
||||
var startRegExp = /^\s*<div\s+([^>]*)>(\s*<pre>)?/gi,
|
||||
endRegExp,
|
||||
match = startRegExp.exec(text);
|
||||
if(match) {
|
||||
// Old-style DIVs don't have the <pre> tag
|
||||
if(match[2]) {
|
||||
endRegExp = /<\/pre>\s*<\/div>\s*$/gi;
|
||||
} else {
|
||||
endRegExp = /<\/div>\s*$/gi;
|
||||
}
|
||||
var endMatch = endRegExp.exec(text);
|
||||
if(endMatch) {
|
||||
// Extract the text
|
||||
result.text = text.substring(match.index + match[0].length,endMatch.index);
|
||||
// Process the attributes
|
||||
var attrRegExp = /\s*([^=\s]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi,
|
||||
attrMatch;
|
||||
do {
|
||||
attrMatch = attrRegExp.exec(match[1]);
|
||||
if(attrMatch) {
|
||||
var name = attrMatch[1];
|
||||
var value = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];
|
||||
result[name] = value;
|
||||
}
|
||||
} while(attrMatch);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/filterrunprefixes/map.js
|
||||
type: application/javascript
|
||||
module-type: filterrunprefix
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter prefix function
|
||||
*/
|
||||
exports.map = function(operationSubFunction,options) {
|
||||
return function(results,source,widget) {
|
||||
if(results.length > 0) {
|
||||
var inputTitles = results.toArray();
|
||||
results.clear();
|
||||
$tw.utils.each(inputTitles,function(title) {
|
||||
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
|
||||
getVariable: function(name) {
|
||||
switch(name) {
|
||||
case "currentTiddler":
|
||||
return "" + title;
|
||||
case "..currentTiddler":
|
||||
return widget.getVariable("currentTiddler");
|
||||
default:
|
||||
return widget.getVariable(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
results.push(filtered[0] || "");
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -253,8 +253,7 @@ exports.compileFilter = function(filterString) {
|
||||
if(operand.indirect) {
|
||||
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
|
||||
} else if(operand.variable) {
|
||||
var varTree = $tw.utils.parseFilterVariable(operand.text);
|
||||
operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""});
|
||||
operand.value = widget.getVariable(operand.text,{defaultValue: ""});
|
||||
} else {
|
||||
operand.value = operand.text;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Export our filter function
|
||||
*/
|
||||
exports.contains = function(source,operator,options) {
|
||||
var results = [],
|
||||
fieldname = operator.suffix || "list";
|
||||
fieldname = (operator.suffix || "list").toLowerCase();
|
||||
if(operator.prefix === "!") {
|
||||
source(function(tiddler,title) {
|
||||
if(tiddler) {
|
||||
|
||||
@@ -17,7 +17,7 @@ Export our filter function
|
||||
*/
|
||||
exports.field = function(source,operator,options) {
|
||||
var results = [],indexedResults,
|
||||
fieldname = operator.suffix || operator.operator || "title";
|
||||
fieldname = (operator.suffix || operator.operator || "title").toLowerCase();
|
||||
if(operator.prefix === "!") {
|
||||
if(operator.regexp) {
|
||||
source(function(tiddler,title) {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/moduleproperty.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter [[module-name]moduleproperty[name]] retrieve a module property
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.moduleproperty = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
var value = require(title)[operator.operand || ""];
|
||||
if(value !== undefined) {
|
||||
results.push(value);
|
||||
}
|
||||
});
|
||||
results.sort();
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -17,23 +17,11 @@ Export our filter function
|
||||
*/
|
||||
exports.modules = function(source,operator,options) {
|
||||
var results = [];
|
||||
if(operator.operands.length === 1) {
|
||||
// Return all the module names without filtering
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
|
||||
results.push(moduleName);
|
||||
});
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
|
||||
results.push(moduleName);
|
||||
});
|
||||
} else if(operator.operands.length >= 2) {
|
||||
// Return the modules that have the module property specified in the first operand with the value in the second operand
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
|
||||
if(require(moduleName)[operator.operands[0]] === operator.operands[1]) {
|
||||
results.push(moduleName);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
results.sort();
|
||||
return results;
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/modulestring.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter [[module-name]modulestring[en-gb]] retrieve a module strings in a particular language
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.modulestring = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
var s = $tw.modules.getModuleString(title,operator.operands[0] || "",operator.operands[1] || "");
|
||||
if(s !== null) {
|
||||
results.push(s);
|
||||
}
|
||||
});
|
||||
results.sort();
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -17,7 +17,7 @@ Export our filter function
|
||||
*/
|
||||
exports.regexp = function(source,operator,options) {
|
||||
var results = [],
|
||||
fieldname = operator.suffix || "title",
|
||||
fieldname = (operator.suffix || "title").toLowerCase(),
|
||||
regexpString, regexp, flags = "", match,
|
||||
getFieldString = function(tiddler,title) {
|
||||
if(tiddler) {
|
||||
|
||||
@@ -172,14 +172,4 @@ exports.pad = function(source,operator,options) {
|
||||
return results;
|
||||
}
|
||||
|
||||
exports.charcode = function(source,operator,options) {
|
||||
var chars = [];
|
||||
$tw.utils.each(operator.operands,function(operand) {
|
||||
if(operand !== "") {
|
||||
chars.push(String.fromCharCode($tw.utils.parseInt(operand)));
|
||||
}
|
||||
});
|
||||
return [chars.join("")];
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -179,7 +179,7 @@ Key descriptors have the following format:
|
||||
ctrl+enter
|
||||
ctrl+shift+alt+A
|
||||
*/
|
||||
KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor,options) {
|
||||
KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {
|
||||
var components = keyDescriptor.split(/\+|\-/),
|
||||
info = {
|
||||
keyCode: 0,
|
||||
@@ -206,9 +206,6 @@ KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor,options) {
|
||||
info.keyCode = this.namedKeys[s];
|
||||
}
|
||||
}
|
||||
if(options.keyDescriptor) {
|
||||
info.keyDescriptor = options.keyDescriptor;
|
||||
}
|
||||
if(info.keyCode) {
|
||||
return info;
|
||||
} else {
|
||||
@@ -240,7 +237,6 @@ KeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options)
|
||||
lookupName = function(configName) {
|
||||
var keyDescriptors = wiki.getTiddlerText("$:/config/" + configName + "/" + name);
|
||||
if(keyDescriptors) {
|
||||
options.keyDescriptor = keyDescriptor;
|
||||
result.push.apply(result,self.parseKeyDescriptors(keyDescriptors,options));
|
||||
}
|
||||
};
|
||||
@@ -249,7 +245,7 @@ KeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
result.push(self.parseKeyDescriptor(keyDescriptor,options));
|
||||
result.push(self.parseKeyDescriptor(keyDescriptor));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
@@ -280,16 +276,12 @@ KeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {
|
||||
};
|
||||
|
||||
KeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {
|
||||
return (this.getMatchingKeyDescriptor(event,keyInfoArray) !== null);
|
||||
};
|
||||
|
||||
KeyboardManager.prototype.getMatchingKeyDescriptor = function(event,keyInfoArray) {
|
||||
for(var t=0; t<keyInfoArray.length; t++) {
|
||||
if(this.checkKeyDescriptor(event,keyInfoArray[t])) {
|
||||
return keyInfoArray[t];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return false;
|
||||
};
|
||||
|
||||
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
|
||||
@@ -332,7 +324,7 @@ KeyboardManager.prototype.handleKeydownEvent = function(event) {
|
||||
if(key !== undefined) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$tw.rootWidget.invokeActionString(action,$tw.rootWidget,event);
|
||||
$tw.rootWidget.invokeActionString(action,$tw.rootWidget);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -123,19 +123,6 @@ exports.parseStringLiteral = function(source,pos) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.parseMacroParameters = function(node,source,pos) {
|
||||
// Process parameters
|
||||
var parameter = $tw.utils.parseMacroParameter(source,pos);
|
||||
while(parameter) {
|
||||
node.params.push(parameter);
|
||||
pos = parameter.end;
|
||||
// Get the next parameter
|
||||
parameter = $tw.utils.parseMacroParameter(source,pos);
|
||||
}
|
||||
node.end = pos;
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
|
||||
*/
|
||||
@@ -200,8 +187,14 @@ exports.parseMacroInvocation = function(source,pos) {
|
||||
}
|
||||
node.name = name.match[1];
|
||||
pos = name.end;
|
||||
node = $tw.utils.parseMacroParameters(node,source,pos);
|
||||
pos = node.end;
|
||||
// Process parameters
|
||||
var parameter = $tw.utils.parseMacroParameter(source,pos);
|
||||
while(parameter) {
|
||||
node.params.push(parameter);
|
||||
pos = parameter.end;
|
||||
// Get the next parameter
|
||||
parameter = $tw.utils.parseMacroParameter(source,pos);
|
||||
}
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for a double greater than sign
|
||||
@@ -215,29 +208,6 @@ exports.parseMacroInvocation = function(source,pos) {
|
||||
return node;
|
||||
};
|
||||
|
||||
exports.parseFilterVariable = function(source) {
|
||||
var node = {
|
||||
name: "",
|
||||
params: [],
|
||||
},
|
||||
pos = 0,
|
||||
reName = /([^\s"']+)/g;
|
||||
// If there is no whitespace or it is an empty string then there are no macro parameters
|
||||
if(/^\S*$/.test(source)) {
|
||||
node.name = source;
|
||||
return node;
|
||||
}
|
||||
// Get the variable name
|
||||
var nameMatch = $tw.utils.parseTokenRegExp(source,pos,reName);
|
||||
if(nameMatch) {
|
||||
node.name = nameMatch.match[1];
|
||||
pos = nameMatch.end;
|
||||
node = $tw.utils.parseMacroParameters(node,source,pos);
|
||||
delete node.end;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
/*
|
||||
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
|
||||
*/
|
||||
|
||||
@@ -7,12 +7,6 @@ Wiki text block rule for HTML comments. For example:
|
||||
|
||||
```
|
||||
<!-- This is a comment -->
|
||||
\define macroX()
|
||||
<!-- This is a comment -->
|
||||
xxxx
|
||||
\end
|
||||
<!-- This is a comment -->
|
||||
|
||||
```
|
||||
|
||||
Note that the syntax for comments is simplified to an opening "<!--" sequence and a closing "-->" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)
|
||||
@@ -25,7 +19,7 @@ Note that the syntax for comments is simplified to an opening "<!--" sequence an
|
||||
"use strict";
|
||||
|
||||
exports.name = "commentblock";
|
||||
exports.types = {block:true, pragma:true};
|
||||
exports.types = {block: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/publisherhandler.js
|
||||
type: application/javascript
|
||||
module-type: global
|
||||
|
||||
The publisher manages publishing extracts of wikis as external files
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var PUBLISHING_MODAL_TITLE = "$:/language/Publishing/Modal";
|
||||
|
||||
/*
|
||||
Instantiate the publisher manager with the following options
|
||||
wiki: wiki object to be used
|
||||
commander: commander object to be used for output
|
||||
*/
|
||||
function PublisherHandler(options) {
|
||||
this.wiki = options.wiki;
|
||||
this.commander = options.commander;
|
||||
}
|
||||
|
||||
/*
|
||||
Publish a job
|
||||
|
||||
jobTitle: title of tiddler containing details of the job
|
||||
callback: completion callback invoked callback(err)
|
||||
options: Include:
|
||||
|
||||
commander: commander object associated with publishing under Node.js
|
||||
variables: hashmap of variables to be passed to renderings
|
||||
*/
|
||||
PublisherHandler.prototype.publish = function(jobTitle,callback,options) {
|
||||
if(jobTitle) {
|
||||
var job = new PublishingJob(jobTitle,this,options);
|
||||
job.publish(callback);
|
||||
}
|
||||
};
|
||||
|
||||
function PublishingJob(jobTitle,publisherHandler,options) {
|
||||
options = options || {};
|
||||
// Save params
|
||||
this.jobTitle = jobTitle;
|
||||
this.publisherHandler = publisherHandler;
|
||||
this.commander = options.commander;
|
||||
this.publishVariables = options.variables || Object.create(null);
|
||||
}
|
||||
|
||||
/*
|
||||
Start publishing
|
||||
*/
|
||||
PublishingJob.prototype.publish = function(callback) {
|
||||
var self = this;
|
||||
// Get the job tiddler and check it is enabled
|
||||
this.jobTiddler = this.publisherHandler.wiki.getTiddler(this.jobTitle);
|
||||
if(this.jobTiddler && this.jobTiddler.fields.enabled === "yes") {
|
||||
// Get the list of tiddlers to be exported, defaulting to all non-system tiddlers
|
||||
this.exportList = this.publisherHandler.wiki.filterTiddlers(this.jobTiddler.fields["export-filter"] || "[!is[system]]");
|
||||
// Get publisher
|
||||
this.publisher = this.getPublisher(this.jobTiddler.fields.publisher);
|
||||
if(this.publisher) {
|
||||
// Get the sitemap
|
||||
this.sitemap = new $tw.Sitemap(this.jobTiddler.fields.sitemap,{
|
||||
wiki: this.publisherHandler.wiki,
|
||||
variables: this.publishVariables
|
||||
});
|
||||
this.sitemap.load();
|
||||
// Get the output operations
|
||||
this.operations = this.sitemap.getAllFileDetails(this.exportList);
|
||||
// Display the progress modal
|
||||
if($tw.modal) {
|
||||
this.progressModal = $tw.modal.display(PUBLISHING_MODAL_TITLE,{
|
||||
progress: true,
|
||||
variables: {
|
||||
currentTiddler: this.jobTitle,
|
||||
totalFiles: this.operations.length + ""
|
||||
},
|
||||
onclose: function(event) {
|
||||
if(event !== self) {
|
||||
// The modal was closed other than by us programmatically
|
||||
self.isCancelled = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Send the operations to the publisher
|
||||
this.executeOperations(function(err) {
|
||||
if(self.progressModal) {
|
||||
self.progressModal.closeHandler(self);
|
||||
}
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
return callback("Unrecognised publisher");
|
||||
}
|
||||
} else {
|
||||
return callback("Missing or disabled job tiddler");
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Instantiate the required publisher object
|
||||
*/
|
||||
PublishingJob.prototype.getPublisher = function(publisherName) {
|
||||
var publisher;
|
||||
$tw.modules.forEachModuleOfType("publisher",function(title,module) {
|
||||
if(module.name === publisherName) {
|
||||
publisher = module;
|
||||
}
|
||||
});
|
||||
return publisher && publisher.create(this.jobTiddler.fields,this.publisherHandler,this);
|
||||
};
|
||||
|
||||
/*
|
||||
Execute the operations for this job
|
||||
*/
|
||||
PublishingJob.prototype.executeOperations = function(callback) {
|
||||
var self = this,
|
||||
report = {overwrites: []},
|
||||
nextOperation = 0,
|
||||
performNextOperation = function() {
|
||||
// Check for having been cancelled
|
||||
if(self.isCancelled) {
|
||||
if(self.publisher.publishCancel) {
|
||||
self.publisher.publishCancel();
|
||||
}
|
||||
return callback("CANCELLED");
|
||||
}
|
||||
// Update progress
|
||||
if(self.progressModal) {
|
||||
self.progressModal.setProgress(nextOperation,self.operations.length);
|
||||
}
|
||||
// Check for having finished
|
||||
if(nextOperation >= self.operations.length) {
|
||||
$tw.utils.nextTick(function() {
|
||||
self.publisher.publishEnd(callback);
|
||||
});
|
||||
} else {
|
||||
// Execute this operation
|
||||
var fileDetails = self.operations[nextOperation]();
|
||||
nextOperation += 1;
|
||||
self.publisher.publishFile(fileDetails,function() {
|
||||
$tw.utils.nextTick(performNextOperation);
|
||||
});
|
||||
}
|
||||
};
|
||||
// Tell the publisher to start, and get back an array of the existing paths
|
||||
self.publisher.publishStart(function(existingPaths) {
|
||||
var paths = {};
|
||||
$tw.utils.each(self.operations,function(operation) {
|
||||
if(operation.path in paths) {
|
||||
report.overwrites.push(operation.path);
|
||||
}
|
||||
paths[operation.path] = true;
|
||||
});
|
||||
// Run the operations
|
||||
performNextOperation();
|
||||
});
|
||||
};
|
||||
|
||||
PublishingJob.prototype.saveReport = function(report) {
|
||||
// Create the report tiddler
|
||||
var reportTitle = this.wiki.generateNewTitle("$:/temp/publish-report");
|
||||
$tw.wiki.addTiddler({
|
||||
title: reportTitle,
|
||||
text: "* " + report.overwrites.join("\n* ")
|
||||
});
|
||||
// Add the report tiddler title to the list field of the publisher parameters tiddler
|
||||
var paramsTiddler = $tw.wiki.getTiddler(this.publisherParamsTitle),
|
||||
list = (paramsTiddler.fields.list || []).slice(0);
|
||||
list.unshift(reportTitle);
|
||||
$tw.wiki.addTiddler(new $tw.Tiddler(paramsTiddler,{list: list}));
|
||||
};
|
||||
|
||||
exports.PublisherHandler = PublisherHandler;
|
||||
|
||||
})();
|
||||
@@ -1,52 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/publishers/filesystem.js
|
||||
type: application/javascript
|
||||
module-type: publisher
|
||||
|
||||
Handles publishing to the Node.js filesystem
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.name = "filesystem";
|
||||
|
||||
exports.create = function(params,publisherHandler,publishingJob) {
|
||||
return new FileSystemPublisher(params,publisherHandler,publishingJob);
|
||||
};
|
||||
|
||||
function FileSystemPublisher(params,publisherHandler,publishingJob) {
|
||||
this.params = params;
|
||||
this.publisherHandler = publisherHandler;
|
||||
this.publishingJob = publishingJob;
|
||||
};
|
||||
|
||||
FileSystemPublisher.prototype.publishStart = function(callback) {
|
||||
console.log("publishStart");
|
||||
// Returns a list of the previously published files
|
||||
callback([]);
|
||||
};
|
||||
|
||||
FileSystemPublisher.prototype.publishFile = function(item,callback) {
|
||||
var fs = require("fs"),
|
||||
path = require("path"),
|
||||
filepath = path.resolve(this.publishingJob.commander.outputPath,item.path);
|
||||
$tw.utils.createFileDirectories(filepath);
|
||||
fs.writeFile(filepath,item.text,item.isBase64 ? "base64" : "utf8",function(err) {
|
||||
if(err) {
|
||||
console.log("File writing error",err)
|
||||
}
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
FileSystemPublisher.prototype.publishEnd = function(callback) {
|
||||
console.log("publishEnd");
|
||||
callback(null);
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -157,8 +157,7 @@ SaverHandler.prototype.saveWiki = function(options) {
|
||||
return false;
|
||||
}
|
||||
var variables = options.variables || {},
|
||||
template = (options.template ||
|
||||
this.wiki.getTiddlerText("$:/config/SaveWikiButton/Template","$:/core/save/all")).trim(),
|
||||
template = options.template || "$:/core/save/all",
|
||||
downloadType = options.downloadType || "text/plain",
|
||||
text = this.wiki.renderTiddler(downloadType,template,options),
|
||||
callback = function(err) {
|
||||
|
||||
@@ -14,7 +14,7 @@ GET /
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/index.html$/;
|
||||
exports.path = /^\/$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler")),
|
||||
|
||||
@@ -63,7 +63,10 @@ function Server(options) {
|
||||
self.addAuthenticator(authenticatorDefinition.AuthenticatorClass);
|
||||
});
|
||||
// Load route handlers
|
||||
this.addRouteHandlers();
|
||||
$tw.modules.forEachModuleOfType("route", function(title,routeDefinition) {
|
||||
// console.log("Loading server route " + title);
|
||||
self.addRoute(routeDefinition);
|
||||
});
|
||||
// Initialise the http vs https
|
||||
this.listenOptions = null;
|
||||
this.protocol = "http";
|
||||
@@ -179,43 +182,11 @@ Server.prototype.addAuthenticator = function(AuthenticatorClass) {
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.addRouteHandlers = function() {
|
||||
var self = this;
|
||||
// Load route handlers from sitemap if present, or just load all route modules
|
||||
if(this.variables.sitemap) {
|
||||
this.sitemap = new $tw.Sitemap(this.variables.sitemap,{
|
||||
wiki: this.wiki,
|
||||
variables: {}
|
||||
});
|
||||
this.sitemap.load();
|
||||
$tw.utils.each(this.sitemap.getServerRoutes(),function(routeInfo) {
|
||||
self.addRoute({
|
||||
method: "GET",
|
||||
path: routeInfo.regexp,
|
||||
handler: function(request,response,state) {
|
||||
var fileDetails = routeInfo.handler(state.params);
|
||||
if(fileDetails) {
|
||||
response.writeHead(200, {"Content-Type": fileDetails.type});
|
||||
response.end(fileDetails.text,fileDetails.isBase64 ? "base64" : "utf8");
|
||||
} else {
|
||||
response.writeHead(404);
|
||||
response.end();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$tw.modules.forEachModuleOfType("route",function(title,routeDefinition) {
|
||||
self.addRoute(routeDefinition);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.findMatchingRoute = function(request,state,options) {
|
||||
options = options || {};
|
||||
Server.prototype.findMatchingRoute = function(request,state) {
|
||||
for(var t=0; t<this.routes.length; t++) {
|
||||
var potentialRoute = this.routes[t],
|
||||
pathname = options.pathname || state.urlInfo.pathname,
|
||||
pathRegExp = potentialRoute.path,
|
||||
pathname = state.urlInfo.pathname,
|
||||
match;
|
||||
if(state.pathPrefix) {
|
||||
if(pathname.substr(0,state.pathPrefix.length) === state.pathPrefix) {
|
||||
@@ -292,15 +263,6 @@ Server.prototype.requestHandler = function(request,response,options) {
|
||||
}
|
||||
// Find the route that matches this path
|
||||
var route = self.findMatchingRoute(request,state);
|
||||
if(!route) {
|
||||
// Try with the default document
|
||||
var defaultDocumentPathname = state.urlInfo.pathname;
|
||||
if(defaultDocumentPathname.substr(-1) !== "/") {
|
||||
defaultDocumentPathname = defaultDocumentPathname + "/";
|
||||
}
|
||||
defaultDocumentPathname = defaultDocumentPathname + "index.html";
|
||||
route = self.findMatchingRoute(request,state,{pathname: defaultDocumentPathname});
|
||||
}
|
||||
// Optionally output debug info
|
||||
if(self.get("debug-level") !== "none") {
|
||||
console.log("Request path:",JSON.stringify(state.urlInfo));
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/sitemap.js
|
||||
type: application/javascript
|
||||
module-type: global
|
||||
|
||||
Sitemaps are used for static publishing and web serving
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
function Sitemap(sitemapTitle,options) {
|
||||
options = options || {};
|
||||
this.sitemapTitle = sitemapTitle;
|
||||
this.wiki = options.wiki;
|
||||
this.routes = [];
|
||||
this.variables = $tw.utils.extend({},options.variables);
|
||||
}
|
||||
|
||||
Sitemap.prototype.load = function(sitemapTitle) {
|
||||
var self = this;
|
||||
// Get the sitemap
|
||||
var sitemapTiddler = this.wiki.getTiddler(this.sitemapTitle);
|
||||
if(sitemapTiddler) {
|
||||
// Collect each route
|
||||
$tw.utils.each(sitemapTiddler.fields.list,function(routeTitle) {
|
||||
var routeTiddler = self.wiki.getTiddler(routeTitle);
|
||||
if(routeTiddler) {
|
||||
// Convert the path into a regexp and an array of {field:,function:} for each capture group
|
||||
var regexpurgatedParameterisedPath = self.regexpurgateParameterisedPath(routeTiddler.fields["route-path"]);
|
||||
self.routes.push({
|
||||
title: routeTitle,
|
||||
params: routeTiddler.getFieldStrings({prefix: "route-"}),
|
||||
variables: routeTiddler.getFieldStrings({prefix: "var-"}),
|
||||
regexp: regexpurgatedParameterisedPath.regexp,
|
||||
captureGroups: regexpurgatedParameterisedPath.captureGroups
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Sitemap.prototype.renderRoute = function(title,route) {
|
||||
var tiddler = this.wiki.getTiddler(title);
|
||||
switch(route.params.type) {
|
||||
case "raw":
|
||||
return {
|
||||
path: this.resolveParameterisedPath(route.params.path,title),
|
||||
text: tiddler.fields.text || "",
|
||||
type: tiddler.fields.type || "",
|
||||
isBase64: ($tw.config.contentTypeInfo[tiddler.fields.type] || {}).encoding === "base64"
|
||||
};
|
||||
break;
|
||||
case "render":
|
||||
var parser = {
|
||||
tree: [
|
||||
{
|
||||
"type": "importvariables",
|
||||
"attributes": {
|
||||
"tiddler": {
|
||||
"name": "tiddler",
|
||||
"type": "string",
|
||||
"value": this.sitemapTitle,
|
||||
}
|
||||
},
|
||||
"tag": "$importvariables",
|
||||
"isBlock": false,
|
||||
"children": [
|
||||
{
|
||||
"type": "importvariables",
|
||||
"attributes": {
|
||||
"tiddler": {
|
||||
"name": "tiddler",
|
||||
"type": "string",
|
||||
"value": route.title,
|
||||
}
|
||||
},
|
||||
"tag": "$importvariables",
|
||||
"isBlock": false,
|
||||
"children": this.wiki.parseTiddler(route.params.template,{parseAsInline: true}).tree
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
widgetNode = this.wiki.makeWidget(parser,{
|
||||
variables: $tw.utils.extend({},this.variables,{currentTiddler: title})
|
||||
}),
|
||||
container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
return {
|
||||
path: this.resolveParameterisedPath(route.params.path,title),
|
||||
text: container.textContent,
|
||||
type: route.params["output-type"] || "text/html"
|
||||
};
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Returns an array of functions that return {path:,text:,type:,isBase64:} for each path
|
||||
*/
|
||||
Sitemap.prototype.getAllFileDetails = function(exportTiddlers) {
|
||||
var self = this,
|
||||
output = [];
|
||||
$tw.utils.each(this.routes,function(route) {
|
||||
var routeFilter = route.params["tiddler-filter"] || "DUMMY_RESULT", // If no filter is provided, use a dummy filter that returns a single result
|
||||
routeTiddlers = self.wiki.filterTiddlers(routeFilter,null,self.wiki.makeTiddlerIterator(exportTiddlers));
|
||||
$tw.utils.each(routeTiddlers,function(title) {
|
||||
output.push(self.renderRoute.bind(self,title,route));
|
||||
});
|
||||
});
|
||||
return output;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Returns an array of server routes {regexp:, handler:}
|
||||
*/
|
||||
Sitemap.prototype.getServerRoutes = function() {
|
||||
var self = this,
|
||||
output = [];
|
||||
$tw.utils.each(this.routes,function(route) {
|
||||
output.push({
|
||||
regexp: route.regexp,
|
||||
handler: function(params) {
|
||||
// Locate the tiddler identified by the capture groups, if any
|
||||
var title = null,
|
||||
nextParam = 0;
|
||||
$tw.utils.each(route.captureGroups,function(captureGroup) {
|
||||
var param = params[nextParam++];
|
||||
if(captureGroup.field === "title") {
|
||||
switch(captureGroup.function) {
|
||||
case "slugify":
|
||||
var titles = self.wiki.unslugify(param);
|
||||
if(titles && titles.length > 0) {
|
||||
title = titles[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
// Check that the tiddler passes the route filter
|
||||
if(route.params["tiddler-filter"]) {
|
||||
if(!title) {
|
||||
return null;
|
||||
}
|
||||
var routeTiddlers = self.wiki.filterTiddlers(route.params["tiddler-filter"],null,self.wiki.makeTiddlerIterator([title]));
|
||||
if(routeTiddlers.indexOf(title) === -1) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Return the rendering or raw tiddler
|
||||
return self.renderRoute(title,route);
|
||||
}
|
||||
});
|
||||
});
|
||||
return output;
|
||||
};
|
||||
|
||||
/*
|
||||
Apply a tiddler to a parameterised path to create a usable path
|
||||
*/
|
||||
Sitemap.prototype.resolveParameterisedPath = function(parameterisedPath,title) {
|
||||
var self = this;
|
||||
// Split the path on $*_*$ markers
|
||||
var tiddler = this.wiki.getTiddler(title),
|
||||
output = [];
|
||||
$tw.utils.each(parameterisedPath.split(/(\$[a-z_]+\$)/),function(part) {
|
||||
var match = part.match(/\$([a-z]+)_([a-z]+)\$/);
|
||||
if(match) {
|
||||
var value;
|
||||
// Get the base value
|
||||
switch(match[1]) {
|
||||
case "uri":
|
||||
case "title":
|
||||
value = title;
|
||||
break;
|
||||
case "type":
|
||||
value = tiddler.fields.type || "text/vnd.tiddlywiki";
|
||||
break;
|
||||
}
|
||||
// Apply the encoding function
|
||||
switch(match[2]) {
|
||||
case "encoded":
|
||||
value = encodeURIComponent(value);
|
||||
break;
|
||||
case "doubleencoded":
|
||||
value = encodeURIComponent(encodeURIComponent(value));
|
||||
break;
|
||||
case "slugify":
|
||||
value = self.wiki.slugify(value);
|
||||
break;
|
||||
case "extension":
|
||||
value = ($tw.config.contentTypeInfo[value] || {extension: "."}).extension.slice(1);
|
||||
break;
|
||||
}
|
||||
output.push(value);
|
||||
} else {
|
||||
output.push(part);
|
||||
}
|
||||
});
|
||||
return output.join("");
|
||||
};
|
||||
|
||||
/*
|
||||
// Convert the path into a regexp and an array of {field:,function:} for each capture group
|
||||
*/
|
||||
Sitemap.prototype.regexpurgateParameterisedPath = function(parameterisedPath) {
|
||||
var regexpParts = ["\\/"],
|
||||
captureGroups = [];
|
||||
$tw.utils.each(parameterisedPath.split(/(\$[a-z_]+\$)/),function(part) {
|
||||
var match = part.match(/\$([a-z]+)_([a-z]+)\$/);
|
||||
if(match) {
|
||||
regexpParts.push("(.+)");
|
||||
captureGroups.push({
|
||||
field: match[1],
|
||||
function: match[2]
|
||||
});
|
||||
} else {
|
||||
regexpParts.push($tw.utils.escapeRegExp(part));
|
||||
}
|
||||
});
|
||||
return {
|
||||
regexp: new RegExp("^" + regexpParts.join("") + "$"),
|
||||
captureGroups: captureGroups
|
||||
};
|
||||
};
|
||||
|
||||
exports.Sitemap = Sitemap;
|
||||
|
||||
})();
|
||||
|
||||
@@ -40,10 +40,9 @@ exports.startup = function() {
|
||||
// Install the tm-focus-selector message
|
||||
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
|
||||
var selector = event.param || "",
|
||||
element,
|
||||
doc = event.event && event.event.target ? event.event.target.ownerDocument : document;
|
||||
element;
|
||||
try {
|
||||
element = doc.querySelector(selector);
|
||||
element = document.querySelector(selector);
|
||||
} catch(e) {
|
||||
console.log("Error in selector: ",selector)
|
||||
}
|
||||
@@ -73,12 +72,6 @@ exports.startup = function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
// Hook up events for the publisher handler
|
||||
$tw.rootWidget.addEventListener("tm-publish",function(event) {
|
||||
$tw.publisherHandler.publish(event.paramObject.job,function(err) {
|
||||
console.log("Finished publishing with result:",err);
|
||||
});
|
||||
});
|
||||
// If we're being viewed on a data: URI then give instructions for how to save
|
||||
if(document.location.protocol === "data:") {
|
||||
$tw.rootWidget.dispatchEvent({
|
||||
|
||||
@@ -129,10 +129,6 @@ exports.startup = function() {
|
||||
dirtyTracking: !$tw.syncadaptor,
|
||||
preloadDirty: $tw.boot.preloadDirty || []
|
||||
});
|
||||
// Install the publisher handler
|
||||
$tw.publisherHandler = new $tw.PublisherHandler({
|
||||
wiki: $tw.wiki
|
||||
});
|
||||
// Host-specific startup
|
||||
if($tw.browser) {
|
||||
// Install the popup manager
|
||||
|
||||
@@ -27,7 +27,7 @@ ClassicStoryView.prototype.navigateTo = function(historyInfo) {
|
||||
var listItemWidget = this.listWidget.children[listElementIndex],
|
||||
targetElement = listItemWidget.findFirstDomNode();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
if(duration) {
|
||||
@@ -43,7 +43,7 @@ ClassicStoryView.prototype.insert = function(widget) {
|
||||
if(duration) {
|
||||
var targetElement = widget.findFirstDomNode();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Get the current height of the tiddler
|
||||
@@ -83,7 +83,7 @@ ClassicStoryView.prototype.remove = function(widget) {
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
removeElement();
|
||||
return;
|
||||
}
|
||||
@@ -118,4 +118,4 @@ ClassicStoryView.prototype.remove = function(widget) {
|
||||
|
||||
exports.classic = ClassicStoryView;
|
||||
|
||||
})();
|
||||
})();
|
||||
@@ -24,7 +24,7 @@ PopStoryView.prototype.navigateTo = function(historyInfo) {
|
||||
var listItemWidget = this.listWidget.children[listElementIndex],
|
||||
targetElement = listItemWidget.findFirstDomNode();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Scroll the node into view
|
||||
@@ -35,7 +35,7 @@ PopStoryView.prototype.insert = function(widget) {
|
||||
var targetElement = widget.findFirstDomNode(),
|
||||
duration = $tw.utils.getAnimationDuration();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Reset once the transition is over
|
||||
@@ -77,7 +77,7 @@ PopStoryView.prototype.remove = function(widget) {
|
||||
}
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
removeElement();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ ZoominListView.prototype.navigateTo = function(historyInfo) {
|
||||
var listItemWidget = this.listWidget.children[listElementIndex],
|
||||
targetElement = listItemWidget.findFirstDomNode();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Make the new tiddler be position absolute and visible so that we can measure it
|
||||
@@ -130,7 +130,7 @@ function findTitleDomNode(widget,targetClass) {
|
||||
ZoominListView.prototype.insert = function(widget) {
|
||||
var targetElement = widget.findFirstDomNode();
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
// Make the newly inserted node position absolute and hidden
|
||||
@@ -147,7 +147,7 @@ ZoominListView.prototype.remove = function(widget) {
|
||||
widget.removeChildDomNodes();
|
||||
};
|
||||
// Abandon if the list entry isn't a DOM element (it might be a text node)
|
||||
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
|
||||
if(!(targetElement instanceof Element)) {
|
||||
removeElement();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -601,7 +601,10 @@ SaveTiddlerTask.prototype.run = function(callback) {
|
||||
tiddler = this.syncer.wiki.tiddlerExists(this.title) && this.syncer.wiki.getTiddler(this.title);
|
||||
this.syncer.logger.log("Dispatching 'save' task:",this.title);
|
||||
if(tiddler) {
|
||||
this.syncer.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {
|
||||
this.syncer.syncadaptor.saveTiddler(tiddler,{
|
||||
changeCount: changeCount,
|
||||
tiddlerInfo: self.syncer.tiddlerInfo[self.title]
|
||||
},function(err,adaptorInfo,revision) {
|
||||
// If there's an error, exit without changing any internal state
|
||||
if(err) {
|
||||
return callback(err);
|
||||
@@ -615,8 +618,6 @@ SaveTiddlerTask.prototype.run = function(callback) {
|
||||
};
|
||||
// Invoke the callback
|
||||
callback(null);
|
||||
},{
|
||||
tiddlerInfo: self.syncer.tiddlerInfo[self.title]
|
||||
});
|
||||
} else {
|
||||
this.syncer.logger.log(" Not Dispatching 'save' task:",this.title,"tiddler does not exist");
|
||||
@@ -633,7 +634,9 @@ function DeleteTiddlerTask(syncer,title) {
|
||||
DeleteTiddlerTask.prototype.run = function(callback) {
|
||||
var self = this;
|
||||
this.syncer.logger.log("Dispatching 'delete' task:",this.title);
|
||||
this.syncer.syncadaptor.deleteTiddler(this.title,function(err) {
|
||||
this.syncer.syncadaptor.deleteTiddler(this.title,{
|
||||
tiddlerInfo: self.syncer.tiddlerInfo[this.title]
|
||||
},function(err,adaptorInfo) {
|
||||
// If there's an error, exit without changing any internal state
|
||||
if(err) {
|
||||
return callback(err);
|
||||
@@ -642,8 +645,6 @@ DeleteTiddlerTask.prototype.run = function(callback) {
|
||||
delete self.syncer.tiddlerInfo[self.title];
|
||||
// Invoke the callback
|
||||
callback(null);
|
||||
},{
|
||||
tiddlerInfo: self.syncer.tiddlerInfo[this.title]
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -54,27 +54,15 @@ exports.getFieldList = function(field) {
|
||||
/*
|
||||
Get all the fields as a hashmap of strings. Options:
|
||||
exclude: an array of field names to exclude
|
||||
prefix: an optional field name prefix. Only fields with the prefix are included, and the prefix is stripped from the name
|
||||
*/
|
||||
exports.getFieldStrings = function(options) {
|
||||
options = options || {};
|
||||
var exclude = options.exclude || [],
|
||||
fields = {},
|
||||
field;
|
||||
if(options.prefix) {
|
||||
for(field in this.fields) {
|
||||
if($tw.utils.hop(this.fields,field)) {
|
||||
if(exclude.indexOf(field) === -1 && field.substring(0,options.prefix.length) === options.prefix) {
|
||||
fields[field.substring(options.prefix.length)] = this.getFieldString(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(field in this.fields) {
|
||||
if($tw.utils.hop(this.fields,field)) {
|
||||
if(exclude.indexOf(field) === -1) {
|
||||
fields[field] = this.getFieldString(field);
|
||||
}
|
||||
var exclude = options.exclude || [];
|
||||
var fields = {};
|
||||
for(var field in this.fields) {
|
||||
if($tw.utils.hop(this.fields,field)) {
|
||||
if(exclude.indexOf(field) === -1) {
|
||||
fields[field] = this.getFieldString(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ Modal message mechanism
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var widget = require("$:/core/modules/widgets/widget.js"),
|
||||
navigator = require("$:/core/modules/widgets/navigator.js"),
|
||||
dm = $tw.utils.domMaker;
|
||||
var widget = require("$:/core/modules/widgets/widget.js");
|
||||
var navigator = require("$:/core/modules/widgets/navigator.js");
|
||||
|
||||
var Modal = function(wiki) {
|
||||
this.wiki = wiki;
|
||||
@@ -27,10 +26,6 @@ Display a modal dialogue
|
||||
options: see below
|
||||
Options include:
|
||||
downloadLink: Text of a big download link to include
|
||||
variables: variables to be passed to the modal
|
||||
event: optional DOM event that initiated the modal
|
||||
progress: set to true to add a progress bar
|
||||
onclose: callback for when the modal is closed
|
||||
*/
|
||||
Modal.prototype.display = function(title,options) {
|
||||
options = options || {};
|
||||
@@ -52,6 +47,7 @@ Modal.prototype.display = function(title,options) {
|
||||
"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
|
||||
var wrapper = this.srcDocument.createElement("div"),
|
||||
modalBackdrop = this.srcDocument.createElement("div"),
|
||||
@@ -59,7 +55,6 @@ Modal.prototype.display = function(title,options) {
|
||||
modalHeader = this.srcDocument.createElement("div"),
|
||||
headerTitle = this.srcDocument.createElement("h3"),
|
||||
modalBody = this.srcDocument.createElement("div"),
|
||||
modalProgress = this.srcDocument.createElement("div"),
|
||||
modalLink = this.srcDocument.createElement("a"),
|
||||
modalFooter = this.srcDocument.createElement("div"),
|
||||
modalFooterHelp = this.srcDocument.createElement("span"),
|
||||
@@ -76,7 +71,6 @@ Modal.prototype.display = function(title,options) {
|
||||
$tw.utils.addClass(modalWrapper,"tc-modal");
|
||||
$tw.utils.addClass(modalHeader,"tc-modal-header");
|
||||
$tw.utils.addClass(modalBody,"tc-modal-body");
|
||||
$tw.utils.addClass(modalProgress,"tc-modal-progress");
|
||||
$tw.utils.addClass(modalFooter,"tc-modal-footer");
|
||||
// Join them together
|
||||
wrapper.appendChild(modalBackdrop);
|
||||
@@ -84,15 +78,6 @@ Modal.prototype.display = function(title,options) {
|
||||
modalHeader.appendChild(headerTitle);
|
||||
modalWrapper.appendChild(modalHeader);
|
||||
modalWrapper.appendChild(modalBody);
|
||||
if(options.progress) {
|
||||
var modalProgressBar = this.srcDocument.createElement("div");
|
||||
modalProgressBar.className = "tc-modal-progress-bar";
|
||||
modalProgress.appendChild(modalProgressBar);
|
||||
var modalProgressPercent = this.srcDocument.createElement("div");
|
||||
modalProgressPercent.className = "tc-modal-progress-percent";
|
||||
modalProgress.appendChild(modalProgressPercent);
|
||||
modalWrapper.appendChild(modalProgress);
|
||||
}
|
||||
modalFooter.appendChild(modalFooterHelp);
|
||||
modalFooter.appendChild(modalFooterButtons);
|
||||
modalWrapper.appendChild(modalFooter);
|
||||
@@ -120,6 +105,7 @@ Modal.prototype.display = function(title,options) {
|
||||
parentWidget: $tw.rootWidget
|
||||
});
|
||||
navigatorWidgetNode.render(modalBody,null);
|
||||
|
||||
// Render the title of the message
|
||||
var headerWidgetNode = this.wiki.makeTranscludeWidget(title,{
|
||||
field: "subtitle",
|
||||
@@ -196,10 +182,6 @@ Modal.prototype.display = function(title,options) {
|
||||
this.wiki.addEventListener("change",refreshHandler);
|
||||
// Add the close event handler
|
||||
var closeHandler = function(event) {
|
||||
// Call the onclose handler
|
||||
if(options.onclose) {
|
||||
options.onclose(event);
|
||||
}
|
||||
// Remove our refresh handler
|
||||
self.wiki.removeEventListener("change",refreshHandler);
|
||||
// Decrease the modal count and adjust the body class
|
||||
@@ -254,22 +236,6 @@ Modal.prototype.display = function(title,options) {
|
||||
$tw.utils.setStyle(modalWrapper,[
|
||||
{transform: "translateY(0px)"}
|
||||
]);
|
||||
// Return the wrapper node
|
||||
return {
|
||||
domNode: wrapper,
|
||||
closeHandler: closeHandler,
|
||||
setProgress: function(numerator,denominator) {
|
||||
// Remove old progress
|
||||
while(modalProgressPercent.hasChildNodes()) {
|
||||
modalProgressPercent.removeChild(modalProgressPercent.firstChild);
|
||||
}
|
||||
// Set new text
|
||||
var percent = (numerator * 100 /denominator).toFixed(2) + "%";
|
||||
modalProgressPercent.appendChild(self.srcDocument.createTextNode(percent));
|
||||
// Set bar width
|
||||
modalProgressBar.style.width = percent;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Modal.prototype.adjustPageClass = function() {
|
||||
@@ -277,7 +243,6 @@ Modal.prototype.adjustPageClass = function() {
|
||||
if(windowContainer) {
|
||||
$tw.utils.toggleClass(windowContainer,"tc-modal-displayed",this.modalCount > 0);
|
||||
}
|
||||
$tw.utils.toggleClass(this.srcDocument.body,"tc-modal-prevent-scroll",this.modalCount > 0);
|
||||
};
|
||||
|
||||
exports.Modal = Modal;
|
||||
|
||||
@@ -228,7 +228,6 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
|
||||
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
|
||||
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
|
||||
}
|
||||
hasUnsafeFields = hasUnsafeFields || /:/mg.test(fieldName);
|
||||
});
|
||||
// Check for field values
|
||||
if(hasUnsafeFields) {
|
||||
|
||||
@@ -223,7 +223,6 @@ exports.removeArrayEntries = function(array,value) {
|
||||
array.splice(p,1);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -741,8 +740,9 @@ exports.isValidFieldName = function(name) {
|
||||
if(!name || typeof name !== "string") {
|
||||
return false;
|
||||
}
|
||||
// Since v5.2.x, there are no restrictions on characters in field names
|
||||
return name;
|
||||
name = name.toLowerCase().trim();
|
||||
var fieldValidatorRegEx = /^[a-z0-9\-\._]+$/mg;
|
||||
return fieldValidatorRegEx.test(name);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -58,10 +58,9 @@ Invoke the action associated with this widget
|
||||
*/
|
||||
ConfirmWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
var invokeActions = true,
|
||||
handled = true,
|
||||
win = event.event && event.event.view ? event.event.view : window;
|
||||
handled = true;
|
||||
if(this.prompt) {
|
||||
invokeActions = win.confirm(this.message);
|
||||
invokeActions = confirm(this.message);
|
||||
}
|
||||
if(invokeActions) {
|
||||
handled = this.invokeActions(triggeringWidget,event);
|
||||
@@ -75,4 +74,4 @@ ConfirmWidget.prototype.allowActionPropagation = function() {
|
||||
|
||||
exports["action-confirm"] = ConfirmWidget;
|
||||
|
||||
})();
|
||||
})();
|
||||
@@ -27,11 +27,8 @@ CreateTiddlerWidget.prototype = new Widget();
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
CreateTiddlerWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Render children
|
||||
this.renderChildren(parent,nextSibling);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -47,8 +44,7 @@ CreateTiddlerWidget.prototype.execute = function() {
|
||||
this.actionTemplate = this.getAttribute("$template");
|
||||
this.useTemplate = !!this.actionTemplate;
|
||||
this.actionOverwrite = this.getAttribute("$overwrite","no");
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets();
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -90,21 +86,18 @@ CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
if (!this.hasBase && this.useTemplate) {
|
||||
title = this.wiki.generateNewTitle(this.actionTemplate);
|
||||
} else if (!this.hasBase && !this.useTemplate) {
|
||||
// If no $basetitle and no $template then use initial title
|
||||
// If NO $basetitle AND NO $template use initial title
|
||||
// DON'T overwrite any stuff
|
||||
title = this.wiki.generateNewTitle(title);
|
||||
}
|
||||
var templateTiddler = this.wiki.getTiddler(this.actionTemplate) || {};
|
||||
this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));
|
||||
var draftTitle = this.wiki.generateDraftTitle(title);
|
||||
var tiddler = this.wiki.addTiddler(new $tw.Tiddler(templateTiddler.fields,creationFields,fields,modificationFields,{title: title}));
|
||||
if(this.actionSaveTitle) {
|
||||
this.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable("currentTiddler"));
|
||||
}
|
||||
if(this.actionSaveDraftTitle) {
|
||||
this.wiki.setTextReference(this.actionSaveDraftTitle,draftTitle,this.getVariable("currentTiddler"));
|
||||
this.wiki.setTextReference(this.actionSaveDraftTitle,this.wiki.generateDraftTitle(title),this.getVariable("currentTiddler"));
|
||||
}
|
||||
this.setVariable("createTiddler-title",title);
|
||||
this.setVariable("createTiddler-draftTitle",draftTitle);
|
||||
this.refreshChildren();
|
||||
return true; // Action was invoked
|
||||
};
|
||||
|
||||
|
||||
@@ -70,18 +70,7 @@ NavigateWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
navigateFromNode: triggeringWidget,
|
||||
navigateFromClientRect: bounds && { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height
|
||||
},
|
||||
navigateFromClientTop: bounds && bounds.top,
|
||||
navigateFromClientLeft: bounds && bounds.left,
|
||||
navigateFromClientWidth: bounds && bounds.width,
|
||||
navigateFromClientRight: bounds && bounds.right,
|
||||
navigateFromClientBottom: bounds && bounds.bottom,
|
||||
navigateFromClientHeight: bounds && bounds.height,
|
||||
navigateSuppressNavigation: suppressNavigation,
|
||||
metaKey: event.metaKey,
|
||||
ctrlKey: event.ctrlKey,
|
||||
altKey: event.altKey,
|
||||
shiftKey: event.shiftKey,
|
||||
event: event
|
||||
navigateSuppressNavigation: suppressNavigation
|
||||
});
|
||||
return true; // Action was invoked
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ EventWidget.prototype.render = function(parent,nextSibling) {
|
||||
$tw.utils.each(this.types,function(type) {
|
||||
domNode.addEventListener(type,function(event) {
|
||||
var selector = self.getAttribute("selector"),
|
||||
actions = self.getAttribute("$"+type) || self.getAttribute("actions-"+type),
|
||||
actions = self.getAttribute("actions-"+type),
|
||||
stopPropagation = self.getAttribute("stopPropagation","onaction"),
|
||||
selectedNode = event.target,
|
||||
selectedNodeRect,
|
||||
@@ -135,15 +135,7 @@ Compute the internal state of the widget
|
||||
EventWidget.prototype.execute = function() {
|
||||
var self = this;
|
||||
// Get attributes that require a refresh on change
|
||||
this.types = [];
|
||||
$tw.utils.each(this.attributes,function(value,key) {
|
||||
if(key.charAt(0) === "$") {
|
||||
self.types.push(key.slice(1));
|
||||
}
|
||||
});
|
||||
if(!this.types.length) {
|
||||
this.types = this.getAttribute("events","").split(" ");
|
||||
}
|
||||
this.types = this.getAttribute("events","").split(" ");
|
||||
this.elementTag = this.getAttribute("tag");
|
||||
// Make child widgets
|
||||
this.makeChildWidgets();
|
||||
@@ -159,13 +151,12 @@ EventWidget.prototype.assignDomNodeClasses = function() {
|
||||
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(),
|
||||
changedAttributesCount = $tw.utils.count(changedAttributes);
|
||||
if(changedAttributesCount === 1 && changedAttributes["class"]) {
|
||||
this.assignDomNodeClasses();
|
||||
} else if(changedAttributesCount > 0) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes["events"] || changedAttributes["tag"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else if(changedAttributes["class"]) {
|
||||
this.assignDomNodeClasses();
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
};
|
||||
|
||||
@@ -73,12 +73,26 @@ FieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {
|
||||
FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
|
||||
var tiddler = this.wiki.getTiddler(this.mangleTitle),
|
||||
addition = this.wiki.getModificationFields(),
|
||||
hadInvalidFieldName = false,
|
||||
addField = function(name,value) {
|
||||
var trimmedName = name.trim();
|
||||
if(!value && tiddler) {
|
||||
value = tiddler.fields[trimmedName];
|
||||
var trimmedName = name.toLowerCase().trim();
|
||||
if(!$tw.utils.isValidFieldName(trimmedName)) {
|
||||
if(!hadInvalidFieldName) {
|
||||
alert($tw.language.getString(
|
||||
"InvalidFieldName",
|
||||
{variables:
|
||||
{fieldName: trimmedName}
|
||||
}
|
||||
));
|
||||
hadInvalidFieldName = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(!value && tiddler) {
|
||||
value = tiddler.fields[trimmedName];
|
||||
}
|
||||
addition[trimmedName] = value || "";
|
||||
}
|
||||
addition[trimmedName] = value || "";
|
||||
return;
|
||||
};
|
||||
addition.title = this.mangleTitle;
|
||||
|
||||
@@ -40,8 +40,10 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
||||
var widgetPointer = this;
|
||||
// Got to flush all the accumulated variables
|
||||
this.variables = new this.variablesConstructor();
|
||||
// Get our parameters
|
||||
this.filter = this.getAttribute("filter");
|
||||
// Compute the filter
|
||||
this.tiddlerList = tiddlerList || this.getTiddlerList();
|
||||
this.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this);
|
||||
// Accumulate the <$set> widgets from each tiddler
|
||||
$tw.utils.each(this.tiddlerList,function(title) {
|
||||
var parser = widgetPointer.wiki.parseTiddler(title);
|
||||
@@ -84,6 +86,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (widgetPointer != this) {
|
||||
widgetPointer.parseTreeNode.children = this.parseTreeNode.children;
|
||||
} else {
|
||||
@@ -91,21 +94,13 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
||||
}
|
||||
};
|
||||
|
||||
ImportVariablesWidget.prototype.getTiddlerList = function() {
|
||||
var filter = this.getAttribute("filter"),
|
||||
title = this.getAttribute("tiddler");
|
||||
return (filter && this.wiki.filterTiddlers(filter,this)) || (title && [title]) || [];
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
ImportVariablesWidget.prototype.refresh = function(changedTiddlers) {
|
||||
// Recompute our attributes and the filter list
|
||||
var changedAttributes = this.computeAttributes(),
|
||||
filter = this.getAttribute("filter"),
|
||||
title = this.getAttribute("tiddler"),
|
||||
tiddlerList = this.getTiddlerList();
|
||||
tiddlerList = this.wiki.filterTiddlers(this.getAttribute("filter"),this);
|
||||
// Refresh if the filter has changed, or the list of tiddlers has changed, or any of the tiddlers in the list has changed
|
||||
function haveListedTiddlersChanged() {
|
||||
var changed = false;
|
||||
@@ -116,7 +111,7 @@ ImportVariablesWidget.prototype.refresh = function(changedTiddlers) {
|
||||
});
|
||||
return changed;
|
||||
}
|
||||
if(changedAttributes.filter || changedAttributes.tiddler || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {
|
||||
if(changedAttributes.filter || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {
|
||||
// Compute the filter
|
||||
this.removeChildDomNodes();
|
||||
this.execute(tiddlerList);
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/jsontiddler.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Render a tiddler as JSON text
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var JSONTiddlerWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
JSONTiddlerWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
JSONTiddlerWidget.prototype.render = function(parent,nextSibling) {
|
||||
var self = this;
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Collect the fields from the optional base tiddler
|
||||
var fields = {};
|
||||
if(this.attTiddler) {
|
||||
var tiddler = this.wiki.getTiddler(this.attTiddler);
|
||||
if(tiddler) {
|
||||
fields = tiddler.getFieldStrings({exclude: this.attExclude.split(" ")});
|
||||
}
|
||||
}
|
||||
// Add custom fields specified in attributes starting with $
|
||||
$tw.utils.each(this.attributes,function(attribute,name) {
|
||||
if(name.charAt(0) === "$") {
|
||||
fields[name.slice(1)] = attribute;
|
||||
}
|
||||
});
|
||||
// JSONify
|
||||
var json = JSON.stringify(fields);
|
||||
// Escape unsafe script characters
|
||||
if(this.attEscapeUnsafeScriptChars) {
|
||||
json = json.replace(/</g,"\\u003C");
|
||||
}
|
||||
// Update the DOM
|
||||
var textNode = this.document.createTextNode(json);
|
||||
parent.insertBefore(textNode,nextSibling);
|
||||
this.domNodes.push(textNode);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
JSONTiddlerWidget.prototype.execute = function() {
|
||||
this.attTiddler = this.getAttribute("tiddler");
|
||||
this.attExclude = this.getAttribute("exclude","");
|
||||
this.attEscapeUnsafeScriptChars = this.getAttribute("escapeUnsafeScriptChars","no") === "yes";
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
JSONTiddlerWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if($tw.utils.count(changedAttributes) > 0 || (this.attTiddler && changedTiddlers[this.attTiddler])) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
exports.jsontiddler = JSONTiddlerWidget;
|
||||
|
||||
})();
|
||||
@@ -40,8 +40,9 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Create element
|
||||
var domNode = this.document.createElement(tag);
|
||||
// Assign classes
|
||||
this.domNode = domNode;
|
||||
this.assignDomNodeClasses();
|
||||
var classes = (this["class"] || "").split(" ");
|
||||
classes.push("tc-keyboard");
|
||||
domNode.className = classes.join(" ");
|
||||
// Add a keyboard event handler
|
||||
$tw.utils.addEventListeners(domNode,[
|
||||
{name: "keydown", handlerObject: this, handlerMethod: "handleChangeEvent"}
|
||||
@@ -53,8 +54,7 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
|
||||
};
|
||||
|
||||
KeyboardWidget.prototype.handleChangeEvent = function(event) {
|
||||
var keyInfo = $tw.keyboardManager.getMatchingKeyDescriptor(event,this.keyInfoArray);
|
||||
if(keyInfo) {
|
||||
if($tw.keyboardManager.checkKeyDescriptors(event,this.keyInfoArray)) {
|
||||
var handled = this.invokeActions(this,event);
|
||||
if(this.actions) {
|
||||
var variables = {
|
||||
@@ -62,9 +62,6 @@ KeyboardWidget.prototype.handleChangeEvent = function(event) {
|
||||
"event-code": event.code,
|
||||
"modifier": $tw.keyboardManager.getEventModifierKeyDescriptor(event)
|
||||
};
|
||||
if(keyInfo.keyDescriptor) {
|
||||
variables["event-key-descriptor"] = keyInfo.keyDescriptor;
|
||||
}
|
||||
this.invokeActionString(this.actions,this,event,variables);
|
||||
}
|
||||
this.dispatchMessage(event);
|
||||
@@ -93,6 +90,7 @@ KeyboardWidget.prototype.execute = function() {
|
||||
this.key = this.getAttribute("key","");
|
||||
this.tag = this.getAttribute("tag","");
|
||||
this.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);
|
||||
this["class"] = this.getAttribute("class","");
|
||||
if(this.key.substr(0,2) === "((" && this.key.substr(-2,2) === "))") {
|
||||
this.shortcutTiddlers = [];
|
||||
var name = this.key.substring(2,this.key.length -2);
|
||||
@@ -104,22 +102,14 @@ KeyboardWidget.prototype.execute = function() {
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
KeyboardWidget.prototype.assignDomNodeClasses = function() {
|
||||
var classes = this.getAttribute("class","").split(" ");
|
||||
classes.push("tc-keyboard");
|
||||
this.domNode.className = classes.join(" ");
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
KeyboardWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.message || changedAttributes.param || changedAttributes.key || changedAttributes.tag) {
|
||||
if(changedAttributes.message || changedAttributes.param || changedAttributes.key || changedAttributes["class"] || changedAttributes.tag) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else if(changedAttributes["class"]) {
|
||||
this.assignDomNodeClasses();
|
||||
}
|
||||
// Update the keyInfoArray if one of its shortcut-config-tiddlers has changed
|
||||
if(this.shortcutTiddlers && $tw.utils.hopArray(changedTiddlers,this.shortcutTiddlers)) {
|
||||
|
||||
@@ -98,7 +98,6 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
||||
var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"),
|
||||
wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$";
|
||||
wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",encodeURIComponent(this.to));
|
||||
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$title_slugify$",this.wiki.slugify(this.to));
|
||||
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to)));
|
||||
}
|
||||
// Override with the value of tv-get-export-link if defined
|
||||
@@ -155,12 +154,6 @@ LinkWidget.prototype.handleClickEvent = function(event) {
|
||||
navigateFromNode: this,
|
||||
navigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height
|
||||
},
|
||||
navigateFromClientTop: bounds.top,
|
||||
navigateFromClientLeft: bounds.left,
|
||||
navigateFromClientWidth: bounds.width,
|
||||
navigateFromClientRight: bounds.right,
|
||||
navigateFromClientBottom: bounds.bottom,
|
||||
navigateFromClientHeight: bounds.height,
|
||||
navigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1),
|
||||
metaKey: event.metaKey,
|
||||
ctrlKey: event.ctrlKey,
|
||||
|
||||
@@ -33,44 +33,12 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Compute attributes and execute state
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Helper to add an event handler
|
||||
var addEventHandler = function(type,actions) {
|
||||
if(type && actions) {
|
||||
self.addEventListener(
|
||||
type,
|
||||
function(event) {
|
||||
// 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)
|
||||
});
|
||||
self.invokeActionString(actions,self,event,variables);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
// Add our message handler
|
||||
if(this.messageType) {
|
||||
this.addEventListeners([
|
||||
{type: this.messageType, handler: "handleEvent"}
|
||||
]);
|
||||
}
|
||||
// Add the main event handler
|
||||
addEventHandler(this.getAttribute("type"),this.getAttribute("actions"));
|
||||
// Add any other event handlers
|
||||
$tw.utils.each(this.attributes,function(value,key) {
|
||||
if(key.charAt(0) === "$") {
|
||||
addEventHandler(key.slice(1),value);
|
||||
}
|
||||
});
|
||||
// Render children
|
||||
this.renderChildren(parent,null);
|
||||
};
|
||||
@@ -79,16 +47,48 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
|
||||
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($tw.utils.count(changedAttributes) > 0) {
|
||||
if(changedAttributes["type"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,6 @@ NavigatorWidget.prototype.handleNavigateEvent = function(event) {
|
||||
|
||||
// Close a specified tiddler
|
||||
NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
|
||||
event = $tw.hooks.invokeHook("th-closing-tiddler",event);
|
||||
var title = event.param || event.tiddlerTitle,
|
||||
storyList = this.getStoryList();
|
||||
// Look for tiddlers with this title to close
|
||||
@@ -184,8 +183,7 @@ NavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {
|
||||
|
||||
// Place a tiddler in edit mode
|
||||
NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
|
||||
var editTiddler = $tw.hooks.invokeHook("th-editing-tiddler",event),
|
||||
win = event.event && event.event.view ? event.event.view : window;
|
||||
var editTiddler = $tw.hooks.invokeHook("th-editing-tiddler",event);
|
||||
if(!editTiddler) {
|
||||
return false;
|
||||
}
|
||||
@@ -194,7 +192,7 @@ NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
|
||||
return self.wiki.isShadowTiddler(title) && !self.wiki.tiddlerExists(title);
|
||||
}
|
||||
function confirmEditShadow(title) {
|
||||
return win.confirm($tw.language.getString(
|
||||
return confirm($tw.language.getString(
|
||||
"ConfirmEditShadowTiddler",
|
||||
{variables:
|
||||
{title: title}
|
||||
@@ -227,8 +225,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
|
||||
storyList = this.getStoryList(),
|
||||
originalTitle = tiddler ? tiddler.fields["draft.of"] : "",
|
||||
originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,
|
||||
confirmationTitle,
|
||||
win = event.event && event.event.view ? event.event.view : window;
|
||||
confirmationTitle;
|
||||
if(!tiddler) {
|
||||
return false;
|
||||
}
|
||||
@@ -241,7 +238,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
|
||||
confirmationTitle = title;
|
||||
}
|
||||
// Seek confirmation
|
||||
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !win.confirm($tw.language.getString(
|
||||
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !confirm($tw.language.getString(
|
||||
"ConfirmDeleteTiddler",
|
||||
{variables:
|
||||
{title: confirmationTitle}
|
||||
@@ -307,8 +304,7 @@ NavigatorWidget.prototype.generateDraftTitle = function(title) {
|
||||
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
|
||||
var title = event.param || event.tiddlerTitle,
|
||||
tiddler = this.wiki.getTiddler(title),
|
||||
storyList = this.getStoryList(),
|
||||
win = event.event && event.event.view ? event.event.view : window;
|
||||
storyList = this.getStoryList();
|
||||
// Replace the original tiddler with the draft
|
||||
if(tiddler) {
|
||||
var draftTitle = (tiddler.fields["draft.title"] || "").trim(),
|
||||
@@ -317,7 +313,7 @@ NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
|
||||
var isRename = draftOf !== draftTitle,
|
||||
isConfirmed = true;
|
||||
if(isRename && this.wiki.tiddlerExists(draftTitle)) {
|
||||
isConfirmed = win.confirm($tw.language.getString(
|
||||
isConfirmed = confirm($tw.language.getString(
|
||||
"ConfirmOverwriteTiddler",
|
||||
{variables:
|
||||
{title: draftTitle}
|
||||
@@ -366,7 +362,6 @@ NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
|
||||
// Take a tiddler out of edit mode without saving the changes
|
||||
NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
|
||||
event = $tw.hooks.invokeHook("th-cancelling-tiddler", event);
|
||||
var win = event.event && event.event.view ? event.event.view : window;
|
||||
// Flip the specified tiddler from draft back to the original
|
||||
var draftTitle = event.param || event.tiddlerTitle,
|
||||
draftTiddler = this.wiki.getTiddler(draftTitle),
|
||||
@@ -377,7 +372,7 @@ NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
|
||||
originalTiddler = this.wiki.getTiddler(originalTitle),
|
||||
storyList = this.getStoryList();
|
||||
if(this.wiki.isDraftModified(draftTitle)) {
|
||||
isConfirmed = win.confirm($tw.language.getString(
|
||||
isConfirmed = confirm($tw.language.getString(
|
||||
"ConfirmCancelTiddler",
|
||||
{variables:
|
||||
{title: draftTitle}
|
||||
|
||||
@@ -60,8 +60,6 @@ TranscludeWidget.prototype.execute = function() {
|
||||
subTiddler: this.transcludeSubTiddler
|
||||
}),
|
||||
parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;
|
||||
this.sourceText = parser ? parser.source : null;
|
||||
this.parserType = parser? parser.type : null;
|
||||
// Set context variables for recursion detection
|
||||
var recursionMarker = this.makeRecursionMarker();
|
||||
if(this.recursionMarker === "yes") {
|
||||
@@ -100,17 +98,12 @@ TranscludeWidget.prototype.makeRecursionMarker = function() {
|
||||
return output.join("");
|
||||
};
|
||||
|
||||
TranscludeWidget.prototype.parserNeedsRefresh = function() {
|
||||
var parserInfo = this.wiki.getTextReferenceParserInfo(this.transcludeTitle,this.transcludeField,this.transcludeIndex,{subTiddler:this.transcludeSubTiddler});
|
||||
return (this.sourceText === undefined || parserInfo.sourceText !== this.sourceText || parserInfo.parserType !== this.parserType)
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
TranscludeWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) {
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedTiddlers[this.transcludeTitle]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -568,15 +568,10 @@ Widget.prototype.invokeActions = function(triggeringWidget,event) {
|
||||
var handled = false;
|
||||
// For each child widget
|
||||
for(var t=0; t<this.children.length; t++) {
|
||||
var child = this.children[t],
|
||||
childIsActionWidget = !!child.invokeAction,
|
||||
actionRefreshPolicy = child.getVariable("tv-action-refresh-policy");
|
||||
// Refresh the child if required
|
||||
if(childIsActionWidget || actionRefreshPolicy === "always") {
|
||||
child.refreshSelf();
|
||||
}
|
||||
var child = this.children[t];
|
||||
// Invoke the child if it is an action widget
|
||||
if(childIsActionWidget) {
|
||||
if(child.invokeAction) {
|
||||
child.refreshSelf();
|
||||
if(child.invokeAction(triggeringWidget,event)) {
|
||||
handled = true;
|
||||
}
|
||||
|
||||
@@ -937,57 +937,41 @@ exports.parseTiddler = function(title,options) {
|
||||
};
|
||||
|
||||
exports.parseTextReference = function(title,field,index,options) {
|
||||
var tiddler,
|
||||
text,
|
||||
parserInfo;
|
||||
if(!options.subTiddler) {
|
||||
var tiddler,text;
|
||||
if(options.subTiddler) {
|
||||
tiddler = this.getSubTiddler(title,options.subTiddler);
|
||||
} else {
|
||||
tiddler = this.getTiddler(title);
|
||||
if(field === "text" || (!field && !index)) {
|
||||
this.getTiddlerText(title); // Force the tiddler to be lazily loaded
|
||||
return this.parseTiddler(title,options);
|
||||
}
|
||||
}
|
||||
parserInfo = this.getTextReferenceParserInfo(title,field,index,options);
|
||||
if(parserInfo.sourceText !== null) {
|
||||
return this.parseText(parserInfo.parserType,parserInfo.sourceText,options);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
exports.getTextReferenceParserInfo = function(title,field,index,options) {
|
||||
var tiddler,
|
||||
parserInfo = {
|
||||
sourceText : null,
|
||||
parserType : "text/vnd.tiddlywiki"
|
||||
};
|
||||
if(options.subTiddler) {
|
||||
tiddler = this.getSubTiddler(title,options.subTiddler);
|
||||
} else {
|
||||
tiddler = this.getTiddler(title);
|
||||
}
|
||||
if(field === "text" || (!field && !index)) {
|
||||
if(tiddler && tiddler.fields) {
|
||||
parserInfo.sourceText = tiddler.fields.text || "";
|
||||
if(tiddler.fields.type) {
|
||||
parserInfo.parserType = tiddler.fields.type;
|
||||
}
|
||||
return this.parseText(tiddler.fields.type,tiddler.fields.text,options);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if(field) {
|
||||
if(field === "title") {
|
||||
parserInfo.sourceText = title;
|
||||
} else if(tiddler && tiddler.fields) {
|
||||
parserInfo.sourceText = tiddler.hasField(field) ? tiddler.fields[field].toString() : null;
|
||||
text = title;
|
||||
} else {
|
||||
if(!tiddler || !tiddler.hasField(field)) {
|
||||
return null;
|
||||
}
|
||||
text = tiddler.fields[field];
|
||||
}
|
||||
return this.parseText("text/vnd.tiddlywiki",text.toString(),options);
|
||||
} else if(index) {
|
||||
this.getTiddlerText(title); // Force the tiddler to be lazily loaded
|
||||
parserInfo.sourceText = this.extractTiddlerDataItem(tiddler,index,null);
|
||||
text = this.extractTiddlerDataItem(tiddler,index,undefined);
|
||||
if(text === undefined) {
|
||||
return null;
|
||||
}
|
||||
return this.parseText("text/vnd.tiddlywiki",text,options);
|
||||
}
|
||||
if(parserInfo.sourceText === null) {
|
||||
parserInfo.parserType = null;
|
||||
}
|
||||
return parserInfo;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Make a widget tree for a parse tree
|
||||
@@ -1575,23 +1559,4 @@ exports.slugify = function(title,options) {
|
||||
return slug;
|
||||
};
|
||||
|
||||
/*
|
||||
Return an array of the titles that would generate a specified slug, if any. Options include:
|
||||
*/
|
||||
exports.unslugify = function(slug) {
|
||||
var self = this,
|
||||
slugToTitle = this.getGlobalCache("slugs",function() {
|
||||
var map = {};
|
||||
$tw.utils.each($tw.wiki.allTitles(),function(title) {
|
||||
var slug = self.slugify(title);
|
||||
if(!(slug in map)) {
|
||||
map[slug] = [];
|
||||
}
|
||||
map[slug].push(title);
|
||||
});
|
||||
return map;
|
||||
});
|
||||
return slugToTitle[slug];
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -4,5 +4,4 @@ title: $:/core/save/all-external-js
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define coreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js
|
||||
{{$:/core/templates/tiddlywiki5-external-js.html}}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
title: $:/core/save/offline-external-js
|
||||
|
||||
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define coreURL() tiddlywikicore-$(version)$.js
|
||||
{{$:/core/templates/tiddlywiki5-external-js.html}}
|
||||
@@ -2,8 +2,4 @@ title: $:/core/templates/tiddlywiki5.js/tiddlers
|
||||
|
||||
`
|
||||
$tw.preloadTiddlerArray(`<$text text=<<jsontiddlers "[[$:/core]]">>/>`);
|
||||
$tw.preloadTiddlerArray([{
|
||||
title: "$:/config/SaveWikiButton/Template",
|
||||
text: "$:/core/save/offline-external-js"
|
||||
}]);
|
||||
`
|
||||
|
||||
@@ -2,7 +2,7 @@ title: $:/core/templates/tiddlywiki5-external-js.html
|
||||
|
||||
\rules only filteredtranscludeinline transcludeinline
|
||||
<!doctype html>
|
||||
{{$:/core/templates/MOTW.html}}<html lang="{{{ [{$:/language}get[name]] }}}">
|
||||
{{$:/core/templates/MOTW.html}}<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<!--~~ Raw markup for the top of the head section ~~-->
|
||||
@@ -43,6 +43,5 @@ title: $:/core/templates/tiddlywiki5-external-js.html
|
||||
<!--~~ Raw markup for the bottom of the body section ~~-->
|
||||
{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}
|
||||
</body>
|
||||
<!--~~ Load external JS ~~-->
|
||||
<script src="{{{ [<coreURL>] }}}" onerror="alert('Error: Cannot load {{{ [<coreURL>] }}}');"></script>
|
||||
<script src="%24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js" onerror="alert('Error: Cannot load tiddlywiki.js');"></script>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
title: $:/core/templates/html-json-skinny-tiddler
|
||||
|
||||
<$list filter="[<numTiddlers>compare:number:gteq[1]] ~[<counter>!match[1]]">`,`<$text text=<<newline>>/></$list>
|
||||
<$jsontiddler tiddler=<<currentTiddler>> exclude="text" escapeUnsafeScriptChars="yes"/>
|
||||
@@ -1,3 +0,0 @@
|
||||
title: $:/core/templates/html-json-tiddler
|
||||
|
||||
<$list filter="[<counter>!match[1]]">`,`<$text text=<<newline>>/></$list><$jsontiddler tiddler=<<currentTiddler>> escapeUnsafeScriptChars="yes"/>
|
||||
@@ -1,37 +1,14 @@
|
||||
title: $:/core/templates/store.area.template.html
|
||||
|
||||
\whitespace trim
|
||||
<!-- Unencrypted -->
|
||||
<$list filter="[[$:/isEncrypted]get[text]else[no]match[no]]">
|
||||
<$list filter="[[storeAreaFormat]is[variable]getvariable[]else[json]match[json]]">
|
||||
<!-- New-style JSON store area, with an old-style store area for compatibility with v5.1.x tooling -->
|
||||
`<script class="tiddlywiki-tiddler-store" type="application/json">[`
|
||||
<$vars newline={{{ [charcode[10]] }}}>
|
||||
<$text text=<<newline>>/>
|
||||
<$list filter=<<saveTiddlerFilter>> counter="counter" template="$:/core/templates/html-json-tiddler"/>
|
||||
<$vars numTiddlers={{{ [subfilter<saveTiddlerFilter>count[]] }}}>
|
||||
<$list filter={{{ [<skinnySaveTiddlerFilter>] }}} counter="counter" template="$:/core/templates/html-json-skinny-tiddler"/>
|
||||
</$vars>
|
||||
<$text text=<<newline>>/>
|
||||
</$vars>
|
||||
`]</script>`
|
||||
`<div id="storeArea" style="display:none;">`
|
||||
`</div>`
|
||||
</$list>
|
||||
<$list filter="[[storeAreaFormat]is[variable]getvariable[]else[json]match[div]]">
|
||||
<!-- Old-style DIV/PRE-based store area -->
|
||||
<$reveal type="nomatch" state="$:/isEncrypted" text="yes">
|
||||
`<div id="storeArea" style="display:none;">`
|
||||
<$list filter=<<saveTiddlerFilter>> template="$:/core/templates/html-div-tiddler"/>
|
||||
<$list filter={{{ [<skinnySaveTiddlerFilter>] }}} template="$:/core/templates/html-div-skinny-tiddler"/>
|
||||
`</div>`
|
||||
</$reveal>
|
||||
</$list>
|
||||
</$list>
|
||||
<!-- Encrypted -->
|
||||
<$list filter="[[$:/isEncrypted]get[text]else[no]match[yes]]">
|
||||
`<!--~~ Encrypted tiddlers ~~-->`
|
||||
`<pre id="encryptedStoreArea" type="text/plain" style="display:none;">`
|
||||
<$encrypt filter=<<saveTiddlerFilter>>/>
|
||||
`</pre>`
|
||||
</$list>
|
||||
<$reveal type="nomatch" state="$:/isEncrypted" text="yes">
|
||||
`<div id="storeArea" style="display:none;">`
|
||||
<$list filter=<<saveTiddlerFilter>> template="$:/core/templates/html-div-tiddler"/>
|
||||
<$list filter={{{ [<skinnySaveTiddlerFilter>] }}} template="$:/core/templates/html-div-skinny-tiddler"/>
|
||||
`</div>`
|
||||
</$reveal>
|
||||
<$reveal type="match" state="$:/isEncrypted" text="yes">
|
||||
`<!--~~ Encrypted tiddlers ~~-->`
|
||||
`<pre id="encryptedStoreArea" type="text/plain" style="display:none;">`
|
||||
<$encrypt filter=<<saveTiddlerFilter>>/>
|
||||
`</pre>`
|
||||
</$reveal>
|
||||
@@ -1,81 +0,0 @@
|
||||
title: $:/core/ui/ControlPanel/Publishing
|
||||
tags: $:/tags/ControlPanel
|
||||
caption: {{$:/language/ControlPanel/Publishing/Caption}}
|
||||
|
||||
{{$:/language/ControlPanel/Publishing/Hint}}
|
||||
|
||||
<div class="tc-publishing-job-listing">
|
||||
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/PublishingJob]]" variable="job">
|
||||
|
||||
<div class="tc-publishing-job">
|
||||
|
||||
<h2>Job: <$link to=<<job>>><$transclude tiddler=<<job>> field="caption" mode="inline"/></$link></h2>
|
||||
|
||||
Publisher: <$select tiddler=<<job>> field="publisher">
|
||||
<$list filter="[[publisher]modules[]moduleproperty[name]]">
|
||||
<option value=<<currentTiddler>>><$text text=<<currentTiddler>>/></option>
|
||||
</$list>
|
||||
</$select>
|
||||
|
||||
Base URL: <$edit-text tiddler=<<job>> size="50" field="baseurl"/>
|
||||
|
||||
Logs: <$view tiddler=<<job>> field="list"/>
|
||||
|
||||
<$set name="publisher-name" value={{{ [<job>get[publisher]] }}}>
|
||||
|
||||
<$set name="publisher-module" value={{{ [[publisher]modules[name],<publisher-name>] }}}>
|
||||
|
||||
<div class="tc-publishing-job-publisher">
|
||||
|
||||
<h2>Publisher: <$text text=<<publisher-name>>/></h2>
|
||||
|
||||
<$set name="publisher-ui" value={{{ [<publisher-module>modulestring[ui],{$:/language}] }}}>
|
||||
|
||||
<$tiddler tiddler=<<job>>>
|
||||
|
||||
<<publisher-ui>>
|
||||
|
||||
</$tiddler>
|
||||
|
||||
</$set>
|
||||
|
||||
</div>
|
||||
|
||||
<$vars sitemap={{{ [<job>get[sitemap]] }}}>
|
||||
|
||||
<div class="tc-publishing-sitemap">
|
||||
|
||||
<h2>Sitemap: <$link to=<<sitemap>>><$view tiddler=<<sitemap>> field="caption"><$text text=<<sitemap>>/></$view></$link></h2>
|
||||
|
||||
<$list filter="[<sitemap>get[list]enlist-input[]]" variable="route">
|
||||
|
||||
<div class="tc-publishing-route">
|
||||
|
||||
<h2>Route: <$link to=<<route>>><$view tiddler=<<route>> field="caption"><$text text=<<route>>/></$view></$link></h2>
|
||||
|
||||
route type: <$view tiddler=<<route>> field="route-type"/>
|
||||
|
||||
path: <$edit-text tiddler=<<route>> size="50" field="route-path"/>
|
||||
|
||||
filter: <$edit-text tiddler=<<route>> size="50" field="route-tiddler-filter"/>
|
||||
|
||||
template: <$edit-text tiddler=<<route>> size="50" field="route-template"/>
|
||||
|
||||
</div>
|
||||
|
||||
</$list>
|
||||
|
||||
</div>
|
||||
|
||||
</$vars>
|
||||
|
||||
</$set>
|
||||
|
||||
</$set>
|
||||
|
||||
</div>
|
||||
|
||||
</$list>
|
||||
|
||||
</div>
|
||||
@@ -1,25 +0,0 @@
|
||||
title: $:/core/ui/Buttons/export-tiddlywikicore
|
||||
tags: $:/tags/PageControls
|
||||
caption: {{$:/core/images/star-filled}} {{$:/language/Buttons/ExportTiddlyWikiCore/Caption}}
|
||||
description: {{$:/language/Buttons/ExportTiddlyWikiCore/Hint}}
|
||||
|
||||
\whitespace trim
|
||||
\define jsFileName() tiddlywikicore-$(version)$.js
|
||||
\define noExportMsg()
|
||||
It appears that you have a wiki with an external ~TiddlyWiki core. The export action cannot be performed.
|
||||
<p>You will need to view the page source in your browser. Then go to the very bottom the the source, find the last `<script>`
|
||||
element, and right-click its `src` URI. Save the link as ''$(jsFileName)$''</p>
|
||||
\end
|
||||
|
||||
<$button tooltip={{$:/language/Buttons/ExportTiddlyWikiCore/Hint}} aria-label={{$:/language/Buttons/ExportTiddlyWikiCore/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[[$:/boot/boot.js]is[missing]]" variable="ignore" emptyMessage="""<$action-sendmessage $message="tm-download-file" $param="$:/core/templates/tiddlywiki5.js" filename=<<jsFileName>>/>""" >
|
||||
<$action-setfield $tiddler=<<qualify "$:/temp/alert">> text=<<noExportMsg>> subtitle="Export ~TiddllyWiki Core"/>
|
||||
<$action-sendmessage $message="tm-modal" $param=<<qualify "$:/temp/alert">>/>
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]" variable="listItem">
|
||||
{{$:/core/images/star-filled}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/ExportTiddlyWikiCore/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -1,19 +0,0 @@
|
||||
title: $:/core/ui/Buttons/publish
|
||||
tags: $:/tags/PageControls
|
||||
caption: {{$:/core/images/publish}} {{$:/language/Buttons/Publish/Caption}}
|
||||
description: {{$:/language/Buttons/Publish/Hint}}
|
||||
|
||||
\define publish-actions()
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/PublishingJob]has[enabled]field:enabled[yes]]" variable="job">
|
||||
<$action-sendmessage $message="tm-publish" job=<<job>>/>
|
||||
</$list>
|
||||
\end
|
||||
|
||||
<$button actions=<<publish-actions>> tooltip={{$:/language/Buttons/Publish/Hint}} aria-label={{$:/language/Buttons/Publish/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/publish}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/Publish/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -3,15 +3,8 @@ tags: $:/tags/ViewTemplate
|
||||
|
||||
\define lingo-base() $:/language/Import/
|
||||
|
||||
\define confirmCancel()
|
||||
<$action-confirm $message={{$:/language/Import/Listing/Cancel/Warning}} >
|
||||
<$action-deletetiddler $tiddler=<<currentTiddler>>/>
|
||||
<$action-sendmessage $message="tm-close-tiddler" title=<<currentTiddler>>/>
|
||||
</$action-confirm>
|
||||
\end
|
||||
|
||||
\define buttons()
|
||||
<$button actions=<<confirmCancel>> ><<lingo Listing/Cancel/Caption>></$button>
|
||||
<$button message="tm-delete-tiddler" param=<<currentTiddler>>><<lingo Listing/Cancel/Caption>></$button>
|
||||
<$button message="tm-perform-import" param=<<currentTiddler>>><<lingo Listing/Import/Caption>></$button>
|
||||
<<lingo Listing/Preview>> <$select tiddler="$:/state/importpreviewtype" default="$:/core/ui/ImportPreviews/Text">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ImportPreview]!has[draft.of]]">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/library/v5.2.0/index.html
|
||||
url: https://tiddlywiki.com/library/v5.1.24/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}}
|
||||
|
||||
{{$:/language/OfficialPluginLibrary/Hint}}
|
||||
|
||||
@@ -4,7 +4,6 @@ core/ui/Buttons/advanced-search: hide
|
||||
core/ui/Buttons/close-all: hide
|
||||
core/ui/Buttons/encryption: hide
|
||||
core/ui/Buttons/export-page: hide
|
||||
core/ui/Buttons/export-tiddlywikicore: hide
|
||||
core/ui/Buttons/fold-all: hide
|
||||
core/ui/Buttons/full-screen: hide
|
||||
core/ui/Buttons/home: hide
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
title: $:/config/PublishingJobs/Default
|
||||
tags: $:/tags/PublishingJob
|
||||
caption: Demo static site
|
||||
publisher: filesystem
|
||||
sitemap: $:/core/sitemaps/StaticSite
|
||||
jszip-output-filename: myzipfile.zip
|
||||
baseurl: https://example.com
|
||||
enabled: yes
|
||||
export-filter: [!is[image]!is[system]] [is[image]!is[system]]
|
||||
@@ -1,7 +0,0 @@
|
||||
title: $:/core/routes/StaticSite/HTML
|
||||
caption: Static HTML
|
||||
tags: $:/tags/Route
|
||||
route-type: render
|
||||
route-path: static/$title_slugify$.html
|
||||
route-tiddler-filter: [!is[system]!is[image]]
|
||||
route-template: $:/core/templates/static.tiddler.html
|
||||
@@ -1,6 +0,0 @@
|
||||
title: $:/core/routes/StaticSite/Images
|
||||
caption: Images
|
||||
tags: $:/tags/Route
|
||||
route-type: raw
|
||||
route-path: images/$title_slugify$.$type_extension$
|
||||
route-tiddler-filter: [is[image]]
|
||||
@@ -1,6 +0,0 @@
|
||||
title: $:/core/routes/StaticSite/Index
|
||||
caption: Index
|
||||
tags: $:/tags/Route
|
||||
route-type: render
|
||||
route-path: index.html
|
||||
route-template: $:/core/save/all
|
||||
@@ -1,7 +0,0 @@
|
||||
title: $:/core/routes/StaticSite/Styles
|
||||
caption: Styles
|
||||
tags: $:/tags/Route
|
||||
route-type: render
|
||||
route-path: static/static.css
|
||||
route-template: $:/core/templates/static.template.css
|
||||
route-output-type: text/css
|
||||
@@ -1,9 +0,0 @@
|
||||
title: $:/core/sitemaps/StaticSite
|
||||
caption: Static site map
|
||||
description: The original TiddlyWiki 5 static file layout
|
||||
tags: $:/tags/SiteMap
|
||||
list: $:/core/routes/StaticSite/Index $:/core/routes/StaticSite/HTML $:/core/routes/StaticSite/Images $:/core/routes/StaticSite/Styles
|
||||
|
||||
\define tv-wikilink-template()
|
||||
$title_slugify$.html
|
||||
\end
|
||||
@@ -1,2 +1,2 @@
|
||||
title: $:/tags/PageControls
|
||||
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/export-tiddlywikicore]] [[$:/core/ui/Buttons/more-page-actions]]
|
||||
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]
|
||||
|
||||
@@ -8,7 +8,6 @@ Welcome to the developer documentation for TiddlyWiki (https://tiddlywiki.com/).
|
||||
|
||||
* An assignment by Christian Jurke and Christian Heigele, two students working on their Master's degree in Information Technology at the Gießen University of Applied Sciences (Technische Hochschule Mittelhessen). Their work can be seen in the [[Introduction]] and the tiddlers that link from it.
|
||||
* New developer documentation
|
||||
** [[Data Storage in Single File TiddlyWiki]]
|
||||
** [[Continuous Deployment]]
|
||||
** [[GitHub Branches]]
|
||||
** HookMechanism
|
||||
@@ -30,4 +29,4 @@ Welcome to the developer documentation for TiddlyWiki (https://tiddlywiki.com/).
|
||||
** [[Scripts for building tiddlywiki.com]]
|
||||
** SyncAdaptorModules
|
||||
** WidgetModules
|
||||
** WikiRuleModules
|
||||
** WikiRuleModules
|
||||
@@ -3,4 +3,12 @@ modified: 20140710081051087
|
||||
tags: doc
|
||||
title: Data-Storage
|
||||
|
||||
{{Data Storage}}
|
||||
TW has two approaches to save the user data. These approaches depends on way you use TW. either you use node.js as a server for TW its saves the tiddlers as plain text in different files or you use TW as standalone in a browser it persists the data within the HTML-File in two Div-Areas depending on whether the encryption of the TiddlyWiki is activated or not. If the TiddlyWiki is not encrypted the data is stored in the Div-Area called "~StoreArea". Every created Tiddler is stored in a own Div-area with a few custom values. An example of a saved Tiddler is shown below (\prettyref{lst:data-div}).
|
||||
|
||||
```html
|
||||
<div created="20140611153703343" modified="20140611153734589" tags="testTag" testfield="testvalue" title="TestTiddler" type="text/plain">
|
||||
<pre>testText</pre>
|
||||
</div>
|
||||
```
|
||||
The Div-Area has the same attributes like the standard tillder fields, listed in [[TiddlerFields|https://tiddlywiki.com/#TiddlerFields]], all attributes which are not in this list are parsed as a custom field. The only required attribute is the name attribute, all other attributes are optional.\\
|
||||
With a activated encryption the data is stored in a special Div-Area called "encryptedStoreArea". TiddlyWiki uses the Standford [[JavaScript Crypto Libary|http://bitwiseshiftleft.github.io/sjcl/]]. The encrypted Tiddlers are saved in a JSON string within this Div-Area.
|
||||
|
||||
@@ -69,7 +69,7 @@ Returns a revision ID.
|
||||
Retrieves status information from the server. This method is optional.
|
||||
|
||||
|!Parameter |!Description |
|
||||
|callback |Callback function invoked with parameters `err,isLoggedIn,username,isReadOnly` |
|
||||
|callback |Callback function invoked with parameters `err,isLoggedIn,username,isReadOnly,isAnonymous,isPollingDisabled` |
|
||||
|
||||
!! `login(username,password,callback)`
|
||||
|
||||
@@ -128,33 +128,40 @@ The syncer will use the `getUpdatedTiddlers()` method in preference to the `getS
|
||||
|!Parameter |!Description |
|
||||
|callback |Callback function invoked with parameter `err,tiddlers`, where `tiddlers` is an array of tiddler field objects |
|
||||
|
||||
!! `saveTiddler(tiddler,callback)`
|
||||
!! `saveTiddler(tiddler,options,callback)`
|
||||
|
||||
Saves a tiddler to the server.
|
||||
|
||||
|!Parameter |!Description |
|
||||
|tiddler |Tiddler to be saved |
|
||||
|options |See below |
|
||||
|callback |Callback function invoked with parameter `err,adaptorInfo,revision` |
|
||||
|tiddlerInfo |The tiddlerInfo maintained by the syncer for this tiddler |
|
||||
|
||||
!! `loadTiddler(title,callback)`
|
||||
!! `loadTiddler(title,options,callback)`
|
||||
|
||||
Loads a tiddler from the server.
|
||||
|
||||
|!Parameter |!Description |
|
||||
|title |Title of tiddler to be retrieved |
|
||||
|options |See below |
|
||||
|callback |Callback function invoked with parameter `err,tiddlerFields` |
|
||||
|
||||
!! `deleteTiddler(title,callback,options)`
|
||||
!! `deleteTiddler(title,options,callback)`
|
||||
|
||||
Delete a tiddler from the server.
|
||||
|
||||
|!Parameter |!Description |
|
||||
|title |Title of tiddler to be deleted |
|
||||
|callback |Callback function invoked with parameter `err` |
|
||||
|options |See below |
|
||||
|callback |Callback function invoked with parameter `err` |
|
||||
|
||||
The options parameter contains the following properties:
|
||||
!!! Options
|
||||
|
||||
<<.from-version "5.2.0">> The signature of syncadaptor functions that accept callbacks has been changed so that the callback is always the last argument. A check for the old order of arguments means that this change is backwards compatible. The new order should be prefered when updating or writing new plugins.
|
||||
|
||||
The options parameter may contain the following properties, depending on the method called.
|
||||
|
||||
|!Property |!Description |
|
||||
|changeCount |The //new// changeCount value for this tiddler |
|
||||
|tiddlerInfo |The tiddlerInfo maintained by the syncer for this tiddler |
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
created: 20210525165258247
|
||||
modified: 20210614134705320
|
||||
tags: Data-Storage doc [[Data Storage]]
|
||||
title: Data Storage in Single File TiddlyWiki
|
||||
|
||||
The single file version of ~TiddlyWiki saves the tiddlers within the HTML file.
|
||||
|
||||
Version 5.2.0 of ~TiddlyWiki introduced a new format for how tiddlers are saved within the HTML file.
|
||||
|
||||
|
||||
---
|
||||
|
||||
!! Up to and including ~TiddlyWiki v5.1.23
|
||||
|
||||
Tiddlers are saved within the HTML file in one of two `<div>` tags depending on whether the TiddlyWiki is configured to encrypt its content or not.
|
||||
|
||||
!!! Without encryption
|
||||
If the ~TiddlyWiki is not encrypted the data is stored in a `<div>` tag with an `id` attribute of "storeArea".
|
||||
|
||||
```html
|
||||
<div id="storeArea" style="display:none;">
|
||||
```
|
||||
|
||||
Within the store area `<div>`, each tiddler is stored in its own div.
|
||||
|
||||
//Tiddler DIV//
|
||||
|
||||
Each tiddler `<div>` has an attribute corresponding to each of the tiddler's fields, except the text field which is saved within a `pre` tag within the `<div>`. Note that all attributes and therefore field names must be lowercase letters, digits or the characters `-` (dash), `_` (underscore) and `.` (period). The only attribute that is required is `title`, all other attributes are optional. All attribute values and the text field within the `pre` tag are HTML encoded.
|
||||
|
||||
Example:
|
||||
|
||||
```html
|
||||
<div id="storeArea" style="display:none;">
|
||||
<div created="20140611153703343" modified="20140611153734589" tags="testTag" testfield="testvalue" title="TestTiddler" type="text/plain">
|
||||
<pre>testText</pre>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
|
||||
!!! With encryption
|
||||
|
||||
If the ~TiddlyWiki is configured to encrypt its content, the tiddlers are stored as as an encrypted JSON string in a `<pre>` tag with the `id` attribute "encryptedStoreArea".
|
||||
|
||||
```html
|
||||
<pre id="encryptedStoreArea" type="text/plain" style="display:none;">
|
||||
```
|
||||
|
||||
~TiddlyWiki uses the [[Stanford JavaScript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]].
|
||||
|
||||
---
|
||||
|
||||
!! From ~TiddlyWiki v5.2.0
|
||||
|
||||
From v5.2.0 onwards, ~TiddlyWiki introduces a new JSON based format for the tiddler store area for unencrypted content, while retaining support for the older store area formats described above for backwards compatibility. The store area format remains unchanged for encrypted content.
|
||||
|
||||
|
||||
!!! Without encryption
|
||||
|
||||
By default, all tiddlers are now stored as an array of JSON objects inside a `<script>` tag with the `class` attribute "tiddlywiki-tiddler-store" and the `type` "application/json". For better readability, every tiddler object begins on a new line. There are no longer any restrictions on characters that are allowed in tiddler field names. However, `<script>` tag store areas must encode the `<` character to `\u003c`.
|
||||
|
||||
```html
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[
|
||||
{"title":"XLSX Utilities Edition","created":"20161023202301847","modified":"20161023202301847","tags":"Editions","type":"text/vnd.tiddlywiki","text":"The ''XLSX Utilities'' edition of TiddlyWiki contains tools to work with `.XLSX` spreadsheets generated by applications like Microsoft Excel and Google Sheets. It can be used in the browser or under Node.js.\n\nhttps://tiddlywiki.com/editions/xlsx-utils/\r\n"},
|
||||
{"text":"In accordance with the [[Philosophy of Tiddlers]], documentation tiddlers are typically short and interlinked.\n\nWhen a tiddler seems as if it needs to contain subheadings, this is often a sign that it should in fact be split into several tiddlers. But it is reasonable for a [[reference tiddler|Reference Tiddlers]] to consist of an untitled introductory section followed by a titled section of details.\n\nConsistency of terminology is essential if the reader is not to become confused. Consistent typography and punctuation lend a professional quality to the documentation. Macros can improve the consistency and maintainability of the text.\n\nUse numbered lists for step-by-step instructions, and bullet points for lists whose order is arbitrary. Use a definition list in preference to a bulleted list if each bulleted item would begin with a term and a colon. If at all possible, avoid burdening the reader with a nested list.\n\nUse a table when information naturally falls into three or more columns, and also for lists of parameters, attributes, etc in [[reference tiddlers|Reference Tiddlers]].\n\nAvoid periods at the end of list items, headings and table cell text.\n\nThe documentation describes the current reality of ~TiddlyWiki. Avoid discussing future aspirations.\n","title":"Tiddler Structure","tags":"[[Improving TiddlyWiki Documentation]]","modified":"20210207124737959","created":"20150110183300000"}
|
||||
]</script>
|
||||
```
|
||||
|
||||
To retain compatibility with external tools that might insert tiddlers by directly manipulating the ~TiddlyWiki HTML file, the older format `<div>` store area is still present in the HTML file immediately after the new `<script>` tag store area:
|
||||
|
||||
|
||||
```html
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[
|
||||
{"title":"XLSX Utilities Edition","created":"20161023202301847","modified":"20161023202301847","tags":"Editions","type":"text/vnd.tiddlywiki","text":"The ''XLSX Utilities'' edition of TiddlyWiki contains tools to work with `.XLSX` spreadsheets generated by applications like Microsoft Excel and Google Sheets. It can be used in the browser or under Node.js.\n\nhttps://tiddlywiki.com/editions/xlsx-utils/\r\n"},
|
||||
{"text":"In accordance with the [[Philosophy of Tiddlers]], documentation tiddlers are typically short and interlinked.\n\nWhen a tiddler seems as if it needs to contain subheadings, this is often a sign that it should in fact be split into several tiddlers. But it is reasonable for a [[reference tiddler|Reference Tiddlers]] to consist of an untitled introductory section followed by a titled section of details.\n\nConsistency of terminology is essential if the reader is not to become confused. Consistent typography and punctuation lend a professional quality to the documentation. Macros can improve the consistency and maintainability of the text.\n\nUse numbered lists for step-by-step instructions, and bullet points for lists whose order is arbitrary. Use a definition list in preference to a bulleted list if each bulleted item would begin with a term and a colon. If at all possible, avoid burdening the reader with a nested list.\n\nUse a table when information naturally falls into three or more columns, and also for lists of parameters, attributes, etc in [[reference tiddlers|Reference Tiddlers]].\n\nAvoid periods at the end of list items, headings and table cell text.\n\nThe documentation describes the current reality of ~TiddlyWiki. Avoid discussing future aspirations.\n","title":"Tiddler Structure","tags":"[[Improving TiddlyWiki Documentation]]","modified":"20210207124737959","created":"20150110183300000"}
|
||||
]</script><div id="storeArea" style="display:none;"></div>
|
||||
```
|
||||
|
||||
Any tiddlers in the older format `<div>` store area are also loaded before tiddlers from the new `<script>` store area.
|
||||
|
||||
!!! Multiple store areas and precedence
|
||||
|
||||
Tiddlers from the new `<script>` tag store areas are loaded in the order of their store areas in the HTML file. Therefore if the same tiddler exists in two different `<script>` tag store areas, the tiddler from the later store area takes precedence. Note however that tiddlers from `<script>` tag store areas always take precedence over tiddlers from the older format `<div>` store area. Therefore a tiddler from the older `<div>` store area can never overwrite a tiddler from a `<script>` tag store area.
|
||||
|
||||
Note that all `<script>` tags with the `class` attribute "tiddlywiki-tiddler-store" have their content parsed as JSON and loaded as tiddlers. This allows external tools to easily insert tiddlers into an HTML file by appending additional `<script>` tag(s) at the very end of the HTML file:
|
||||
|
||||
```html
|
||||
</html>
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[
|
||||
{"created":"20210525212411223","text":"This is some test text","tags":"[[test tag]] [[another tag]]","title":"My new tiddler to insert","modified":"20210525212430577"}
|
||||
]</script>
|
||||
```
|
||||
|
||||
Additional topics:
|
||||
|
||||
* [[Extracting tiddlers from a single file TiddlyWiki]]
|
||||
@@ -1,10 +0,0 @@
|
||||
created: 20140708085814626
|
||||
modified: 20210525165526997
|
||||
tags: doc
|
||||
title: Data Storage
|
||||
|
||||
~TiddlyWiki has two approaches to saving the user data (tiddlers) depending on whether you are using the single file version, or are using the node.js server.
|
||||
|
||||
~TiddlyWiki on node.js saves each tiddler in a separate text file. For details on the file formats supported for tiddlers on node.js, see [[Tiddler Files|https://tiddlywiki.com/#TiddlerFiles]].
|
||||
|
||||
The single file version of ~TiddlyWiki saves the tiddlers within the HTML file. See [[Data Storage in Single File TiddlyWiki]]
|
||||
@@ -1,20 +0,0 @@
|
||||
created: 20210623075733310
|
||||
modified: 20210623081959571
|
||||
tags: HookMechanism
|
||||
title: Hook: th-closing-tiddler
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
This hook allows plugins to monitor the closing of a tiddler from the story.
|
||||
|
||||
Hook function parameters:
|
||||
|
||||
* ''event'': Widget message object with the following properties:
|
||||
** ''event'': DOM event object that triggered the widget message
|
||||
** ''tiddlerTitle'': the title of the tiddler being closed
|
||||
** ''widget'': reference to the widget that sent the message.
|
||||
|
||||
Return value:
|
||||
|
||||
* ''event'': Widget message object
|
||||
|
||||
The original event widget message object can be returned unmodified by the hook.
|
||||
@@ -1,8 +1,8 @@
|
||||
caption: 5.2.0
|
||||
created: 20210714091904613
|
||||
modified: 20210714091904613
|
||||
caption: 5.1.24
|
||||
created: 20201229120443187
|
||||
modified: 20201229120443187
|
||||
tags: ReleaseNotes
|
||||
title: Release 5.2.0
|
||||
title: Release 5.1.24
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define contributor(username)
|
||||
@@ -11,104 +11,61 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.1.23...master]]//
|
||||
|
||||
! Unrestricted Fieldnames and the New JSON Store Area
|
||||
|
||||
The major change in this release is that the format used to store tiddlers in TiddlyWiki's HTML file has changed from an HTML DIV-based format to a new JSON-based format. The consequences of this change are far-reaching, and justify the move from v5.1.x to v5.2.x:
|
||||
|
||||
Firstly, the ''characters that can be used in field names are now unrestricted'' (just like tiddler titles), making it possible to use fieldnames like `My^Field` or `☃️`. This became possible because every other part of TiddlyWiki was already capable of dealing with unrestricted field names apart from saving as an HTML file.
|
||||
|
||||
Secondly, external tools that read, write or otherwise process TiddlyWiki HTML files will need modification to understand the new store area format. The details are documented in the [[/dev wiki|https://tiddlywiki.com/prerelease/dev/#Data%20Storage%20in%20Single%20File%20TiddlyWiki]].
|
||||
|
||||
For more details, see ticket [[#5708|https://github.com/Jermolene/TiddlyWiki5/pull/5708]] on GitHub.
|
||||
|
||||
! Performance Improvements
|
||||
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5380">> (and again [[here|https://github.com/Jermolene/TiddlyWiki5/pull/5488]]) the efficiency of the linked list implementation used in filter processing
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5362">> the [[all Operator]] and ([[here|https://github.com/Jermolene/TiddlyWiki5/pull/5369"]]) the [[links Operator]] to use the new linked list implementation
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5436">> [[ETag|https://en.wikipedia.org/wiki/HTTP_ETag]]-based browser-side caching for all resources and GZip or Deflate compression for all responses to GET requests
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5736">> transclude widget to avoid triggering a refresh unless the transcluded field changes (previously it was also triggered for changes to other fields)
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/70e60cd93fe26e9cde1e350e3236578fa5abfe48">> plugin internal formatting to remove unneeded whitespace, saving about 6% on the size of the $:/core plugin
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5380">> (and again [[here|https://github.com/Jermolene/TiddlyWiki5/pull/5488]]) the efficiency of the linked list implementation
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5362">> [[all Operator]] to use new linked list implementation
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5369">> [[links Operator]] to use new linked list implementation
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5383">> unneeded escaping of double quotes in tiddler DIVs inside single file wikis (saving about 10% from the size of empty.html)
|
||||
|
||||
! Usability Improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5699">> (and again [[here|https://github.com/Jermolene/TiddlyWiki5/pull/5705]]) ability to drag and drop images in the editor to import and insert
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5816">> modal mechanism to prevent page from scrolling while modals are displayed
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/a360adbba924d222c5b55709133c18890c04398d">> size of dropzone when story river is empty
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/a360adbba924d222c5b55709133c18890c04398d">> dropzone size when story river is empty
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5326">> fill colour for "remove tag" button
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5370">> page title so that the separating em-dash is only used if the site subtitle is present
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5397">> broken aria-label in $:/PaletteManager
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5451">> macro calls to use the same parser as that used for widget attributes
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/89546b3357b0696a7047e6915bd6cd137b589de6">> a hidden setting to control sandboxing of tiddlers of type `text/html`
|
||||
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/commit/caec6bc3fea9155eb2b0aae64d577c565dd7b088">> SVG optimiser script
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/c325380231a8c592a6e51d4498c1e6c3a241b539">> plus/minus SVG icons: <<.icon $:/core/images/plus-button>> and <<.icon $:/core/images/minus-button>>
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5672">> link to the existing tiddler when the warning "Target tiddler already exists" is displayed in the edit template
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5479">> ability to import previously blocked system tiddlers
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5727">> class to make tag pills in the edit template look like those in the ViewTemplate
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5812">> warning message when cancelling a pending import
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5726">> the HTML comment syntax to enable it to be used before and in between pragmas such as macro definitions
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/1661">> overflow of long field values that do not contain whitespace
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5294">> support for [[dynamic toolbar buttons|How to create dynamic editor toolbar buttons]]
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5612">> [[average Operator]], [[median Operator]], [[variance Operator]] and [[standard-deviation Operator]] for calculating the arithmetic mean of a list of numbers
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/cf56a17f28f1e44dcb62c5e161be4ac29e27c3f2">> unusedtitle macro to use the prefix parameter
|
||||
|
||||
! Filter improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5813">> new [[:map filter run prefix|Filter Expression]]
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5653">> new [[:sort filter run prefix|Sort Filter Run Prefix]]
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5612">> [[average Operator]], [[median Operator]], [[variance Operator]] and [[standard-deviation Operator]] for calculating averages of a list of numbers
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5673">> [[deserializers filter Operator|deserializers Operator]] for obtaining a list of the available deserializers
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5665">> [[format:titlelist operator|format Operator]] for selectively adding double square brackets around titles
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/83ee363cb4c19246ac977f55e46439dd8a1508ba">> [[charcode Operator]] for easily accessing special characters like tab and linefeed
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5252">> support for suffixes to filter run prefixes
|
||||
|
||||
! Hackability Improvements
|
||||
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/3094e062366830bdecfb91e3d852667fa951dc50">> action widget execution to ensure all widgets are refreshed before invocation
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5836">> support for macro parameters within filters (see [[Filter Parameter]])
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5361">> [[unusedtitle Macro]] to add ''separator'' and ''template'' parameters
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5720">> ''color-scheme'' field to all themes to differentiate between light and dark themes
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/9eda02868f21e9dd1733ffe26352bd7ac96285b4">> new MessageCatcherWidget
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/d25e540dd2f0decf61c52fdc665a28a5dfeda93f">> support for `image/vnd.microsoft.icon` content type
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5458">> support for throttling refreshes for changed tiddlers with the title prefix $:/temp/volatile/
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5451">> macro calls to use the same parser as that used for widget attributes
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/89546b3357b0696a7047e6915bd6cd137b589de6">> a hidden setting to control sandboxing of tiddlers of type `text/html`
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5707">> text operation [[insert-text|WidgetMessage: tm-edit-text-operation]]
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/e157d16b724172f752da0ff714847e0c0ca9664d">> ''data-tag-title'' attribute to tag pills
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5294">> support for [[dynamic toolbar buttons|How to create dynamic editor toolbar buttons]]
|
||||
|
||||
! Widget Improvements
|
||||
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/9faaa312998d48c56bd50335820b6b881266af4b">> [[ActionCreateTiddlerWidget]] to make the new title available as a variable
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5611">> (and [[here|https://github.com/Jermolene/TiddlyWiki5/commit/4a99e0cc7d4a6b9e7071c0b2a9a0f63c3c7d2492]]) [[ListWidget]] with optional `counter` attribute specifying a variable to contain the numeric index of each list item
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/9eda02868f21e9dd1733ffe26352bd7ac96285b4">> (and [[here|https://github.com/Jermolene/TiddlyWiki5/commit/f87b3bfcdba79b6ad198af286bd827c61044891f]]) new MessageCatcherWidget to catch arbitrary messages and execute action strings
|
||||
* <<.link-badge-modified "https://github.com/Jermolene/TiddlyWiki5/commit/b9647b2c48152dac069a1099a0822b32375a66cf">> [[FieldManglerWidget]] to ensure it doesn't propogate events that it traps
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5597">> [[DropzoneWidget]] to optionally invoke actions after the `tm-import-tiddlers` message has been sent, and to specify an optional `contentTypesFilter` which determines which content types are accepted by the dropzone.
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5635">> [[SelectWidget]] refreshing
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5644">> [[ActionListopsWidget]] bug by avoiding concatenating fragmnts of filter expressions
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5611">> [[ListWidget]] with `index` attribute and here (and [[here| https://github.com/Jermolene/TiddlyWiki5/commit/4a99e0cc7d4a6b9e7071c0b2a9a0f63c3c7d2492]])
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5635">> [[SelectWidget]] refreshing
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5252">> support for suffixes to filter run prefixes
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5653">> :sort filter run prefix
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5644">> [[ActionListopsWidget]] bug by avoiding stitching together filter expressions for the original list values
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/07caa16e8714afe9a64eb202375e4a2f95da1508">> [[DropzoneWidget]] to also use the specified deserializer for strings either dropped or pasted on to the dropzone
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/44df6fe52f79bee88357afb4fc3d6f4800aa6dde">> issue with widget not being available to filter operator
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/3f986861538a3cc5c3c6da578b45d0d9138a6b2b">> [[ActionPopupWidget]] to create floating popups that must be manually cleared
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5648">> (and [[here|https://github.com/Jermolene/TiddlyWiki5/pull/5782]]) [[KeyboardWidget]] to provide additional information variables
|
||||
|
||||
! Client-server Improvements
|
||||
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/e96a54c7531a2d9e07745e27d2015d8d7d09588f">> crash running in client server configuration when 'ETag' header is missing
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/e96a54c7531a2d9e07745e27d2015d8d7d09588f">> crash running in client server configuration when 'etag' header is missing
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5423">> blank favicon when using lazily loaded images
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/4461">> web server issue with custom path prefix and basic authentication
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5416">> crash on Node.js with ActionSetFieldWidget when type field is given a value upon new tiddler creation
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5329">> issue with saving tiddler files with titles that already end in the required extension
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/5366">> crash on Node.js with ActionSetFieldWidget when type field is given a value upon new tiddler creation
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5329">> issue with tiddler titles that already end in the required extension
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5465">> several consistency issues with the filesystem plugin
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/5483">> issue with encoding of $:/config/OriginalTiddlerPaths outside the wiki folder
|
||||
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/5628">> the TiddlySpot Saver settings form
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5638">> 401 and 403 error messages for PUT saver
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/d8ac00a10856b1b64311b8e0496344d5b0c1b987">> fixed crash if browser doesn't support Server Sent Events
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5570">> the [[external JavaScript template|Using the external JavaScript template]] to be easier to use and work more smoothly when offline
|
||||
|
||||
! Node.js Improvements
|
||||
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/a38dc1730010c6a2b6a011aff4818bbc67c04055">> RenderCommand to allow multiple variables to be passed
|
||||
|
||||
! Plugin Improvements
|
||||
|
||||
!! [[Markdown Plugin]]
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5846">> support for using the [[KaTeX Plugin]] in Markdown
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5848">> extraneous paragraph tags in lists
|
||||
|
||||
!! [[XLSX Utilities Plugin|XLSX Utilities Edition]]
|
||||
!! [[XLSX Utilities Plugin]]
|
||||
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/5400">> crash with the XLSX Utils plugin
|
||||
|
||||
@@ -136,15 +93,10 @@ For more details, see ticket [[#5708|https://github.com/Jermolene/TiddlyWiki5/pu
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/5377">> the Jasmine test suite output
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/9f9ce6595b08032a602981f82940ca113cff8211">> wikitext parser with a subclassing mechanism
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/ef76349c37662e9706acfffc2c2edb51a920183d">> added support for ''utils-browser'' modules
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/5464">> ''th-before-importing'' hook to allow plugins to inspect or modify the `importTiddler` object before any tiddlers are imported
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/3797">> ''th-closing-tiddler'' hook when tiddlers are closed
|
||||
|
||||
! Translation improvements
|
||||
|
||||
* <<.link-badge-improved>> Chinese translations
|
||||
* <<.link-badge-improved>> French translations
|
||||
* <<.link-badge-improved>> German translations
|
||||
* <<.link-badge-improved>> Spanish translations
|
||||
|
||||
|
||||
! Other Bug Fixes
|
||||
@@ -158,21 +110,14 @@ For more details, see ticket [[#5708|https://github.com/Jermolene/TiddlyWiki5/pu
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5455">> upload saver to optionally work without a username or password
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/5e4430dbf9ff66d9a18fbdf3005abcd716efc07d">> RadioWidget to refresh selectively, and to use the ''checked'' attribute correctly
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5542">> "invert" option of `wiki.search()` method
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/7b1a0c6e6a8bd2d3badf8766af0cd3f5f7ac5ec8">> ES5 compatibility issue
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/e157d16b724172f752da0ff714847e0c0ca9664d">> ''data-tag-title'' attribute to tag pills
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/7b1a0c6e6a8bd2d3badf8766af0cd3f5f7ac5ec8">> ES5 compatibility issue
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/a38dc1730010c6a2b6a011aff4818bbc67c04055">> RenderCommand to allow multiple variables to be passed
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/226df2ad7d2978d3d7400d94767a0503e495cf98">> exporting of tiddlers that begin and end with double quotes
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/d56e8764a1f02a214df5da1cc95191be2da2491b">> accessibility of button widget when controlling a popup
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/d6ea369f5ef9d3092a360a4286a99902df37782b">> EditTextWidget to use default text for missing fields
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5552">> css-escape-polyfill to work under Node.js
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/dbd3f835bf8399ed1a3da7cc322ec9b6ab783d53">> crash when sorting by non-string fields
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5711">> (and [[here|https://github.com/Jermolene/TiddlyWiki5/pull/5868]]) some bugs in the [[EventCatcherWidget]], introduced new `stopPorpagation` attribute and new syntax for specifying actions
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5691">> CurrentTiddler variable consistency in subfilters and prefixes
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/485779f5b2136b7bcd739352b56188d94b0eb9e4">> crash when accessing variables in filters that don't have a widget context
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/8fbf52e419e71d726ea32b6c44e3ccfc4245d825">> unnecessary triggering reload warning when javascript tiddlers are not subsequently imported
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5521">> minor issue with import pragma
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5700">> leading and trailing whitespace in themes
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5469">> configuration list of HTML5 block elements
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5692">> shape and color for disabled button to work with `tc-btn-invisible` class
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/5473">> inconsistent spacing of view toolbar items
|
||||
|
||||
|
||||
[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki:
|
||||
|
||||
@@ -185,7 +130,6 @@ For more details, see ticket [[#5708|https://github.com/Jermolene/TiddlyWiki5/pu
|
||||
* <<contributor CodaCodr>>
|
||||
* <<contributor dixonge>>
|
||||
* <<contributor donmor>>
|
||||
* <<contributor felixhayashi>>
|
||||
* <<contributor FlashSystems>>
|
||||
* <<contributor flibbles>>
|
||||
* <<contributor hoelzro>>
|
||||
@@ -200,7 +144,6 @@ For more details, see ticket [[#5708|https://github.com/Jermolene/TiddlyWiki5/pu
|
||||
* <<contributor NicolasPetton>>
|
||||
* <<contributor OdinJorna>>
|
||||
* <<contributor pmario>>
|
||||
* <<contributor rryan>>
|
||||
* <<contributor saqimtiaz>>
|
||||
* <<contributor simonbaird>>
|
||||
* <<contributor slaymaker1907>>
|
||||
@@ -2,5 +2,7 @@ created: 20131127215321439
|
||||
modified: 20140912135951542
|
||||
title: $:/DefaultTiddlers
|
||||
|
||||
Publishing
|
||||
$:/core/ui/ControlPanel/Publishing
|
||||
[[TiddlyWiki Pre-release]]
|
||||
HelloThere
|
||||
GettingStarted
|
||||
Community
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.2.0/index.html
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.1.24/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease)
|
||||
|
||||
The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
||||
|
||||
@@ -11,16 +11,13 @@
|
||||
],
|
||||
"build": {
|
||||
"listen": [
|
||||
"--listen","root-tiddler=$:/core/save/all-external-js","use-browser-cache=yes"],
|
||||
"--listen","root-tiddler=$:/core/save/all-external-js"],
|
||||
"index": [
|
||||
"--rendertiddler","$:/core/save/offline-external-js","index.html","text/plain",
|
||||
"--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]","text/plain"],
|
||||
"--rendertiddler","$:/plugins/tiddlywiki/tiddlyweb/save/offline","index.html","text/plain"],
|
||||
"static": [
|
||||
"--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain",
|
||||
"--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain",
|
||||
"--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain",
|
||||
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"],
|
||||
"tiddlywikicore": [
|
||||
"--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]","text/plain"]
|
||||
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
title: dezerializer test data case 1
|
||||
type: text/html
|
||||
|
||||
<!doctype html>
|
||||
@@ -1,12 +0,0 @@
|
||||
title: dezerializer test data case 2
|
||||
type: text/html
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Data</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +0,0 @@
|
||||
title: dezerializer test data case 3
|
||||
type: text/html
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Data</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--~~ Ordinary tiddlers ~~-->
|
||||
<div id="storeArea" style="display:none;"><div title="Hello "There"" type="text/vnd.tiddlywiki">
|
||||
<pre>Abacus</pre>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
title: dezerializer test data case 4
|
||||
type: text/html
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Data</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--~~ Ordinary tiddlers ~~-->
|
||||
<div id="storeArea" style="display:none;"><div title="Hello "There"" type="text/vnd.tiddlywiki">
|
||||
<pre>Abacus</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[{"title":"Hello \"There\"","text":"Calculator"}]</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,20 +0,0 @@
|
||||
title: dezerializer test data case 5
|
||||
type: text/html
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Data</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--~~ Ordinary tiddlers ~~-->
|
||||
<div id="storeArea" style="display:none;"><div title="Hello "There"" type="text/vnd.tiddlywiki">
|
||||
<pre>Abacus</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[{"title":"Hello \"There\"","text":"Calculator"}]</script>
|
||||
</body>
|
||||
</html>
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[{"title":"Hello \"There\"","text":"Protractor"}]</script>
|
||||
@@ -1,39 +0,0 @@
|
||||
/*\
|
||||
title: test-deserializers.js
|
||||
type: application/javascript
|
||||
tags: [[$:/tags/test-spec]]
|
||||
|
||||
Tests various core deserializers
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/* jslint node: true, browser: true */
|
||||
/* eslint-env node, browser, jasmine */
|
||||
/* eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/
|
||||
/* global $tw, require */
|
||||
"use strict";
|
||||
|
||||
describe("deserializer tests", function() {
|
||||
|
||||
function executeTestCase(title,expectedOutput) {
|
||||
it("test case " + title, function() {
|
||||
var tiddler = $tw.wiki.getTiddler(title);
|
||||
expect($tw.wiki.deserializeTiddlers(tiddler.fields.type,tiddler.fields.text)).toEqual(expectedOutput);
|
||||
});
|
||||
}
|
||||
|
||||
executeTestCase("dezerializer test data case 1",[ { text: '<!doctype html>\n', type: 'text/html' } ]);
|
||||
|
||||
executeTestCase("dezerializer test data case 2",[ { text: '<!doctype html>\n<html lang="en">\n<head>\n\t<meta charset="utf-8">\n\t<title>Test Data</title>\n</head>\n<body>\n</body>\n</html>\n', type: 'text/html' } ]);
|
||||
|
||||
executeTestCase("dezerializer test data case 3",[ { title: 'Hello "There"', text: 'Abacus', type: 'text/vnd.tiddlywiki' } ]);
|
||||
|
||||
executeTestCase("dezerializer test data case 4",[ { title: 'Hello "There"', text: 'Abacus', type: 'text/vnd.tiddlywiki' }, { title: 'Hello "There"', text: 'Calculator'} ]);
|
||||
|
||||
executeTestCase("dezerializer test data case 5",[ { title: 'Hello "There"', text: 'Abacus', type: 'text/vnd.tiddlywiki' }, { title: 'Hello "There"', text: 'Calculator'} , { title: 'Hello "There"', text: 'Protractor'} ]);
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
@@ -818,48 +818,6 @@ function runTests(wiki) {
|
||||
it("should handle the deserializers operator", function() {
|
||||
expect(wiki.filterTiddlers("[deserializers[]]").join(",")).toBe("application/javascript,application/json,application/x-tiddler,application/x-tiddler-html-div,application/x-tiddlers,text/css,text/html,text/plain");
|
||||
});
|
||||
|
||||
it("should handle the charcode operator", function() {
|
||||
expect(wiki.filterTiddlers("[charcode[9]]").join(" ")).toBe(String.fromCharCode(9));
|
||||
expect(wiki.filterTiddlers("[charcode[9],[10]]").join(" ")).toBe(String.fromCharCode(9) + String.fromCharCode(10));
|
||||
expect(wiki.filterTiddlers("[charcode[]]").join(" ")).toBe("");
|
||||
});
|
||||
|
||||
it("should parse filter variable parameters", function(){
|
||||
expect($tw.utils.parseFilterVariable("currentTiddler")).toEqual(
|
||||
{ name: 'currentTiddler', params: [ ] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now DDMM")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', start: 3, value: 'DDMM', end: 8 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now DDMM UTC")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', start: 3, value: 'DDMM', end: 8 }, { type: 'macro-parameter', start: 8, value: 'UTC', end: 12 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now format:DDMM")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', name:'format', start: 3, value: 'DDMM', end: 15 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now format:'DDMM'")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', name:'format', start: 3, value: 'DDMM', end: 17 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("nowformat:'DDMM'")).toEqual(
|
||||
{ name: 'nowformat:\'DDMM\'', params: [] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("nowformat:'DD MM'")).toEqual(
|
||||
{ name: 'nowformat:', params: [{ type: 'macro-parameter', start: 10, value: 'DD MM', end: 17 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now [UTC]YYYY0MM0DD0hh0mm0ssXXX")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', start: 3, value: '[UTC]YYYY0MM0DD0hh0mm0ssXXX', end: 31 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now '[UTC]YYYY0MM0DD0hh0mm0ssXXX'")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', start: 3, value: '[UTC]YYYY0MM0DD0hh0mm0ssXXX', end: 33 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("now format:'[UTC]YYYY0MM0DD0hh0mm0ssXXX'")).toEqual(
|
||||
{ name: 'now', params: [{ type: 'macro-parameter', start: 3, name:'format', value: '[UTC]YYYY0MM0DD0hh0mm0ssXXX', end: 40 }] }
|
||||
);
|
||||
expect($tw.utils.parseFilterVariable("")).toEqual(
|
||||
{ name: '', params: [] }
|
||||
);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/*\
|
||||
title: test-parsetextreference.js
|
||||
type: application/javascript
|
||||
tags: [[$:/tags/test-spec]]
|
||||
|
||||
Tests for source attribute in parser returned from wiki.parseTextReference
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
describe("Wiki.parseTextReference tests", function() {
|
||||
|
||||
// Create a wiki
|
||||
var wiki = new $tw.Wiki();
|
||||
wiki.addTiddler({
|
||||
title: "TiddlerOne",
|
||||
text: "The quick brown fox in $:/TiddlerTwo",
|
||||
tags: ["one"],
|
||||
authors: "Joe Bloggs",
|
||||
modifier: "JoeBloggs",
|
||||
modified: "201304152222"});
|
||||
wiki.addTiddler({
|
||||
title: "$:/TiddlerTwo",
|
||||
tags: ["two"],
|
||||
authors: "[[John Doe]]",
|
||||
modifier: "John",
|
||||
modified: "201304152211"});
|
||||
wiki.addTiddler({
|
||||
title: "Tiddler Three",
|
||||
text: '{"oct":31,"nov":30,"dec":31,"jan":""}',
|
||||
tags: ["one","two"],
|
||||
type: "application/json",
|
||||
modifier: "John",
|
||||
modified: "201304162202"});
|
||||
wiki.addTiddler({
|
||||
title: "TiddlerFour",
|
||||
text: "The quick brown fox in $:/TiddlerTwo",
|
||||
tags: ["one"],
|
||||
type: "text/vnd.tiddlywiki",
|
||||
authors: "",
|
||||
modifier: "JoeBloggs",
|
||||
modified: "201304152222"});
|
||||
// Add a plugin containing some shadow tiddlers
|
||||
var shadowTiddlers = {
|
||||
tiddlers: {
|
||||
"$:/TiddlerFive": {
|
||||
title: "$:/TiddlerFive",
|
||||
text: "Everything in federation",
|
||||
tags: ["two"]
|
||||
},
|
||||
"TiddlerSix": {
|
||||
title: "TiddlerSix",
|
||||
text: "Missing inaction from TiddlerOne",
|
||||
filter: "[[one]] [[a a]] [subfilter{hasList!!list}]",
|
||||
tags: []
|
||||
},
|
||||
"TiddlerSeventh": {
|
||||
title: "TiddlerSeventh",
|
||||
text: "",
|
||||
list: "TiddlerOne [[Tiddler Three]] [[a fourth tiddler]] MissingTiddler",
|
||||
tags: ["one"]
|
||||
},
|
||||
"Tiddler8": {
|
||||
title: "Tiddler8",
|
||||
text: "Tidd",
|
||||
tags: ["one"],
|
||||
"test-field": "JoeBloggs",
|
||||
"myfield":""
|
||||
}
|
||||
}
|
||||
};
|
||||
wiki.addTiddler({
|
||||
title: "$:/ShadowPlugin",
|
||||
text: JSON.stringify(shadowTiddlers),
|
||||
"plugin-type": "plugin",
|
||||
type: "application/json"});
|
||||
wiki.addTiddler({
|
||||
title: "TiddlerNine",
|
||||
text: "this is plain text",
|
||||
type: "text/plain"
|
||||
});
|
||||
|
||||
// Define a parsing shortcut for souce attribute of parser returned by wiki.parseTextReference
|
||||
var parseAndGetSource = function(title,field,index,subTiddler) {
|
||||
var parser = wiki.parseTextReference(title,field,index,{subTiddler: subTiddler});
|
||||
return parser ? parser.source : null;
|
||||
};
|
||||
|
||||
it("should parse text references and return correct source attribute", function(){
|
||||
// Existing tiddler with a text field, no field argument specified
|
||||
expect(parseAndGetSource("TiddlerOne")).toEqual("The quick brown fox in $:/TiddlerTwo");
|
||||
// Existing tiddler with a text field, field argument specified as text
|
||||
expect(parseAndGetSource("TiddlerOne","text")).toEqual("The quick brown fox in $:/TiddlerTwo");
|
||||
// Existing tiddler with no text field
|
||||
expect(parseAndGetSource("$:/TiddlerTwo")).toEqual("");
|
||||
// Existing tiddler, field argument specified as authors
|
||||
expect(parseAndGetSource("TiddlerOne","authors")).toEqual("Joe Bloggs");
|
||||
// Non-existent tiddler, no field argument
|
||||
expect(parseAndGetSource("MissingTiddler")).toEqual(null);
|
||||
// Non-existent tiddler, field argument
|
||||
expect(parseAndGetSource("MissingTiddler","missing-field")).toEqual(null);
|
||||
// Non-existent tiddler, index specified
|
||||
expect(parseAndGetSource("MissingTiddler",null,"missing-index")).toEqual(null);
|
||||
// Existing tiddler with non existent field
|
||||
expect(parseAndGetSource("TiddlerOne","missing-field")).toEqual(null);
|
||||
// Existing tiddler with blank field
|
||||
expect(parseAndGetSource("TiddlerFour","authors")).toEqual("");
|
||||
// Data tiddler with index specified
|
||||
expect(parseAndGetSource("Tiddler Three",null,"oct")).toEqual("31");
|
||||
// Data tiddler with blank index
|
||||
expect(parseAndGetSource("Tiddler Three",null,"jan")).toEqual("");
|
||||
// Data tiddler with non-existent index
|
||||
expect(parseAndGetSource("Tiddler Three",null,"feb")).toEqual(null);
|
||||
// Existing tiddler with a text field, type set to vnd.tiddlywiki
|
||||
expect(parseAndGetSource("TiddlerFour")).toEqual("The quick brown fox in $:/TiddlerTwo");
|
||||
// Existing subtiddler of a plugin
|
||||
expect(parseAndGetSource("$:/ShadowPlugin","text",null,"Tiddler8")).toEqual("Tidd");
|
||||
// Existing blank field of a subtiddler of a plugin
|
||||
expect(parseAndGetSource("$:/ShadowPlugin","myfield",null,"Tiddler8")).toEqual("");
|
||||
// Non-existent subtiddler of a plugin
|
||||
expect(parseAndGetSource("$:/ShadowPlugin","text",null,"MyMissingTiddler")).toEqual(null);
|
||||
// Plain text tiddler
|
||||
expect(parseAndGetSource("TiddlerNine")).toEqual(undefined);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -220,7 +220,6 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
|
||||
wiki.addTiddler({
|
||||
title: "Brownies",
|
||||
text: "//This is a sample shopping list item for the [[Shopping List Example]]//",
|
||||
description: "A square of rich chocolate cake",
|
||||
tags: ["shopping","food"],
|
||||
price: "4.99",
|
||||
quantity: "1"
|
||||
@@ -229,7 +228,6 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
|
||||
title: "Chick Peas",
|
||||
text: "//This is a sample shopping list item for the [[Shopping List Example]]//",
|
||||
tags: ["shopping","food"],
|
||||
description: "a round yellow seed",
|
||||
price: "1.32",
|
||||
quantity: "5"
|
||||
});
|
||||
@@ -244,7 +242,6 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
|
||||
title: "Rice Pudding",
|
||||
price: "2.66",
|
||||
quantity: "4",
|
||||
description: "",
|
||||
tags: ["shopping", "dairy"],
|
||||
text: "//This is a sample shopping list item for the [[Shopping List Example]]//"
|
||||
});
|
||||
@@ -377,14 +374,6 @@ describe("'reduce' and 'intersection' filter prefix tests", function() {
|
||||
expect(wiki.filterTiddlers("[tag[cakes]] :sort:string:casesensitive[{!!title}]").join(",")).toBe("Cheesecake,Chocolate Cake,Persian love cake,Pound cake,cheesecake,chocolate cake");
|
||||
expect(wiki.filterTiddlers("[tag[cakes]] :sort:string:casesensitive,reverse[{!!title}]").join(",")).toBe("chocolate cake,cheesecake,Pound cake,Persian love cake,Chocolate Cake,Cheesecake");
|
||||
});
|
||||
|
||||
it("should handle the :map prefix", function() {
|
||||
expect(wiki.filterTiddlers("[tag[shopping]] :map[get[title]]").join(",")).toBe("Brownies,Chick Peas,Milk,Rice Pudding");
|
||||
expect(wiki.filterTiddlers("[tag[shopping]] :map[get[description]]").join(",")).toBe("A square of rich chocolate cake,a round yellow seed,,");
|
||||
expect(wiki.filterTiddlers("[tag[shopping]] :map[get[description]else{!!title}]").join(",")).toBe("A square of rich chocolate cake,a round yellow seed,Milk,Rice Pudding");
|
||||
// Return the first title from :map if the filter returns more than one result
|
||||
expect(wiki.filterTiddlers("[tag[shopping]] :map[tags[]]").join(",")).toBe("shopping,shopping,shopping,shopping");
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -117,14 +117,7 @@ describe("WikiText parser tests", function() {
|
||||
[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ]
|
||||
|
||||
);
|
||||
});
|
||||
|
||||
it("should parse comment in pragma area. Comment will be INVISIBLE", function() {
|
||||
expect(parse("<!-- comment in pragma area -->\n\\define aMacro()\nnothing\n\\end\n")).toEqual(
|
||||
|
||||
[ { type : 'set', attributes : { name : { type : 'string', value : 'aMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ]
|
||||
|
||||
);
|
||||
});
|
||||
|
||||
it("should parse inline macro calls", function() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
created: 20140912145537860
|
||||
footer: <$button message="tm-close-tiddler">Close</$button>
|
||||
modified: 20210627054504823
|
||||
modified: 20140912145537861
|
||||
subtitle: I'm a modal wizard
|
||||
title: SampleWizard
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20130825150000000
|
||||
modified: 20210714130751701
|
||||
modified: 20190609154450433
|
||||
tags: [[TiddlyWiki on Node.js]]
|
||||
title: TiddlerFiles
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -78,22 +78,11 @@ The ContentType `application/json` is used internally for these files.
|
||||
|
||||
Note that JSON files that do not conform to the tiddler structure will instead be imported as a single tiddler containing the JSON data.
|
||||
|
||||
!! New JSON-based format for TiddlyWiki HTML files
|
||||
!! TiddlyWiki HTML files
|
||||
|
||||
The new format for TiddlyWiki HTML files embeds the tiddlers in JSON format within a script tag:
|
||||
TiddlyWiki HTML files contain a collection of tiddlers encoded in `<DIV>` format.
|
||||
|
||||
```json
|
||||
<script class="tiddlywiki-tiddler-store" type="application/json">[
|
||||
{"title": "A","text": "One"},
|
||||
{"title": "B","text": "Two"}
|
||||
]</script>
|
||||
```
|
||||
|
||||
!! Old DIV-based format for TiddlyWiki HTML files
|
||||
|
||||
TiddlyWiki Classic and TiddlyWiki 5 prior to version v5.2.0 stored tiddlers encoded in `<DIV>` format.
|
||||
|
||||
For TiddlyWiki to import an unencrypted DIV-based HTML file, it requires a `<div id="storeArea">` containing tiddler DIVs as explained above. For example:
|
||||
For TiddlyWiki to import an unencrypted HTML file, it requires a `<div id="storeArea">` containing tiddler DIVs as explained above. For example:
|
||||
|
||||
```
|
||||
<div id="storeArea">
|
||||
|
||||
@@ -8,6 +8,6 @@ tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Oper
|
||||
title: average Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.2.0">> See [[Mathematics Operators]] for an overview.
|
||||
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
|
||||
|
||||
<<.operator-examples "average">>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
caption: charcode
|
||||
created: 20210622214425635
|
||||
modified: 20210622214425635
|
||||
op-input: ignored
|
||||
op-output: a string formed from concatenating the characters specified by the numeric codes given in the operand(s)
|
||||
op-parameter: numeric character code
|
||||
op-parameter-name: C
|
||||
op-purpose: generates string characters from their numeric character codes
|
||||
tags: [[Filter Operators]]
|
||||
title: charcode Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.2.0">>
|
||||
|
||||
This operator returns a string formed from concatenating the characters specified by the numeric codes given in one or more operands. It is useful for generating special characters such as tab (`charcode[9]`) or new line (`charcode[13],[10]`).
|
||||
|
||||
<<.operator-examples "charcode">>
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: deserializers
|
||||
created: 20210506115203172
|
||||
from-version: 5.2.0
|
||||
from-version: 5.1.24
|
||||
modified: 20210506130322593
|
||||
op-input: ignored
|
||||
op-output: the title of each available deserializer
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
created: 20210622214849214
|
||||
modified: 20210622214849214
|
||||
tags: [[charcode Operator]] [[Operator Examples]]
|
||||
title: charcode Operator (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.operator-example 1 "[charcode[65]match[A]]">>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user