Merge branch 'master' into publishing-framework

publishing-framework
jeremy@jermolene.com 2021-07-14 15:48:54 +01:00
commit bbdf9bae89
163 zmienionych plików z 1772 dodań i 500 usunięć

Wyświetl plik

@ -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.1.24
TW5_BUILD_VERSION=v5.2.0
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"

Wyświetl plik

@ -1743,13 +1743,20 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
},
t,result = [];
if(node) {
for(t = 0; t < node.childNodes.length; t++) {
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++) {
var childNode = node.childNodes[t],
tiddlers = extractTextTiddlers(childNode);
tiddlers = tiddlers || extractModuleTiddlers(childNode);
if(tiddlers) {
result.push.apply(result,tiddlers);
}
}
}
}
return result;
@ -1758,17 +1765,23 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
$tw.loadTiddlersBrowser = function() {
// In the browser, we load tiddlers from certain elements
var containerIds = [
"libraryModules",
"modules",
"bootKernelPrefix",
"bootKernel",
"styleArea",
"storeArea",
"systemArea"
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"
];
for(var t=0; t<containerIds.length; t++) {
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",document.getElementById(containerIds[t])));
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]));
}
}
};
@ -2004,7 +2017,7 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
pluginInfo.dependents = pluginInfo.dependents || [];
pluginInfo.type = "application/json";
// Set plugin text
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers},null,4);
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
delete pluginInfo.tiddlers;
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginInfo) {

Wyświetl plik

@ -32,6 +32,8 @@ 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

Wyświetl plik

@ -3,6 +3,7 @@ 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

Wyświetl plik

@ -41,7 +41,6 @@ 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

Wyświetl plik

@ -12,63 +12,8 @@ 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 [parseTiddlerDiv(text,fields)];
return [deserializeTiddlerDiv(text,fields)];
};
exports["application/json"] = function(text,fields) {
@ -105,30 +50,34 @@ Parse an HTML file into tiddlers. There are three possibilities:
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) {
// Check if we've got a store area
var results = [];
// Check if we've got an old-style store area
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
match = storeAreaMarkerRegExp.exec(text);
if(match) {
// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file
// First read the normal tiddlers
var results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
// Then any system tiddlers
var systemAreaMarkerRegExp = /<div id=["']?systemArea['"]?( style=["']?display:none;["']?)?>/gi,
sysMatch = systemAreaMarkerRegExp.exec(text);
if(sysMatch) {
results.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));
}
storeAreaMatch = storeAreaMarkerRegExp.exec(text);
if(storeAreaMatch) {
// If so, we've got tiddlers in classic TiddlyWiki format or unencrypted old-style TW5 format
results.push.apply(results,deserializeStoreArea(text,storeAreaMarkerRegExp.lastIndex,!!storeAreaMatch[1],fields));
}
// Check for new-style store areas
var newStoreAreaMarkerRegExp = /<script class="tiddlywiki-tiddler-store" type="([^"]*)">/gi,
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text),
haveHadNewStoreArea = !!newStoreAreaMatch;
while(newStoreAreaMatch) {
results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields));
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text);
}
// Return if we had either an old-style or a new-style store area
if(storeAreaMatch || haveHadNewStoreArea) {
return results;
}
// Otherwise, check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
return $tw.utils.decryptStoreArea(encryptedStoreArea);
} else {
// 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);
}
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
}
};
@ -142,7 +91,19 @@ function deserializeHtmlFile(text,fields) {
return [result];
}
function deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {
function deserializeNewStoreArea(text,storeAreaEnd,type,fields) {
var endOfScriptRegExp = /<\/script>/gi;
endOfScriptRegExp.lastIndex = storeAreaEnd;
var match = endOfScriptRegExp.exec(text);
if(match) {
var scriptContent = text.substring(storeAreaEnd,match.index);
return $tw.wiki.deserializeTiddlers(type,scriptContent);
} else {
return [];
}
}
function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
var results = [],
endOfDivRegExp = /(<\/div>\s*)/gi,
startPos = storeAreaEnd,
@ -151,7 +112,7 @@ function deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {
var match = endOfDivRegExp.exec(text);
while(match) {
var endPos = endOfDivRegExp.lastIndex,
tiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
tiddlerFields = deserializeTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
if(!tiddlerFields) {
break;
}
@ -169,4 +130,59 @@ function deserializeTiddlyWikiFile(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;
};
})();

Wyświetl plik

@ -0,0 +1,39 @@
/*\
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] || "");
});
}
}
};
})();

Wyświetl plik

@ -253,7 +253,8 @@ exports.compileFilter = function(filterString) {
if(operand.indirect) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
operand.value = widget.getVariable(operand.text,{defaultValue: ""});
var varTree = $tw.utils.parseFilterVariable(operand.text);
operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""});
} else {
operand.value = operand.text;
}

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -172,4 +172,14 @@ 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("")];
};
})();

Wyświetl plik

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

Wyświetl plik

@ -123,6 +123,19 @@ 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:}
*/
@ -187,14 +200,8 @@ exports.parseMacroInvocation = function(source,pos) {
}
node.name = name.match[1];
pos = name.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);
}
node = $tw.utils.parseMacroParameters(node,source,pos);
pos = node.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double greater than sign
@ -208,6 +215,29 @@ 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:,}
*/

Wyświetl plik

@ -7,6 +7,12 @@ 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)
@ -19,7 +25,7 @@ Note that the syntax for comments is simplified to an opening "<!--" sequence an
"use strict";
exports.name = "commentblock";
exports.types = {block: true};
exports.types = {block:true, pragma:true};
exports.init = function(parser) {
this.parser = parser;

Wyświetl plik

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

Wyświetl plik

@ -40,9 +40,10 @@ exports.startup = function() {
// Install the tm-focus-selector message
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
var selector = event.param || "",
element;
element,
doc = event.event && event.event.target ? event.event.target.ownerDocument : document;
try {
element = document.querySelector(selector);
element = doc.querySelector(selector);
} catch(e) {
console.log("Error in selector: ",selector)
}

Wyświetl plik

@ -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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
removeElement();
return;
}
@ -118,4 +118,4 @@ ClassicStoryView.prototype.remove = function(widget) {
exports.classic = ClassicStoryView;
})();
})();

Wyświetl plik

@ -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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
removeElement();
return;
}

Wyświetl plik

@ -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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
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 instanceof Element)) {
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
removeElement();
return;
}

Wyświetl plik

@ -601,10 +601,7 @@ 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,{
changeCount: changeCount,
tiddlerInfo: self.syncer.tiddlerInfo[self.title]
},function(err,adaptorInfo,revision) {
this.syncer.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {
// If there's an error, exit without changing any internal state
if(err) {
return callback(err);
@ -618,6 +615,8 @@ 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");
@ -634,9 +633,7 @@ 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,{
tiddlerInfo: self.syncer.tiddlerInfo[this.title]
},function(err,adaptorInfo) {
this.syncer.syncadaptor.deleteTiddler(this.title,function(err) {
// If there's an error, exit without changing any internal state
if(err) {
return callback(err);
@ -645,6 +642,8 @@ DeleteTiddlerTask.prototype.run = function(callback) {
delete self.syncer.tiddlerInfo[self.title];
// Invoke the callback
callback(null);
},{
tiddlerInfo: self.syncer.tiddlerInfo[this.title]
});
};

Wyświetl plik

@ -277,6 +277,7 @@ 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;

Wyświetl plik

@ -228,6 +228,7 @@ 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) {

Wyświetl plik

@ -223,6 +223,7 @@ exports.removeArrayEntries = function(array,value) {
array.splice(p,1);
}
}
return array;
};
/*
@ -740,9 +741,8 @@ exports.isValidFieldName = function(name) {
if(!name || typeof name !== "string") {
return false;
}
name = name.toLowerCase().trim();
var fieldValidatorRegEx = /^[a-z0-9\-\._]+$/mg;
return fieldValidatorRegEx.test(name);
// Since v5.2.x, there are no restrictions on characters in field names
return name;
};
/*

Wyświetl plik

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

Wyświetl plik

@ -104,6 +104,7 @@ CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
}
this.setVariable("createTiddler-title",title);
this.setVariable("createTiddler-draftTitle",draftTitle);
this.refreshChildren();
return true; // Action was invoked
};

Wyświetl plik

@ -70,7 +70,18 @@ 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
},
navigateSuppressNavigation: suppressNavigation
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
});
return true; // Action was invoked
};

Wyświetl plik

@ -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("actions-"+type),
actions = self.getAttribute("$"+type) || self.getAttribute("actions-"+type),
stopPropagation = self.getAttribute("stopPropagation","onaction"),
selectedNode = event.target,
selectedNodeRect,
@ -135,7 +135,15 @@ Compute the internal state of the widget
EventWidget.prototype.execute = function() {
var self = this;
// Get attributes that require a refresh on change
this.types = this.getAttribute("events","").split(" ");
this.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.elementTag = this.getAttribute("tag");
// Make child widgets
this.makeChildWidgets();
@ -151,12 +159,13 @@ 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();
if(changedAttributes["events"] || changedAttributes["tag"]) {
var changedAttributes = this.computeAttributes(),
changedAttributesCount = $tw.utils.count(changedAttributes);
if(changedAttributesCount === 1 && changedAttributes["class"]) {
this.assignDomNodeClasses();
} else if(changedAttributesCount > 0) {
this.refreshSelf();
return true;
} else if(changedAttributes["class"]) {
this.assignDomNodeClasses();
}
return this.refreshChildren(changedTiddlers);
};

Wyświetl plik

@ -73,26 +73,12 @@ 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.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 || "";
var trimmedName = name.trim();
if(!value && tiddler) {
value = tiddler.fields[trimmedName];
}
addition[trimmedName] = value || "";
return;
};
addition.title = this.mangleTitle;

Wyświetl plik

@ -0,0 +1,84 @@
/*\
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;
})();

Wyświetl plik

@ -40,9 +40,8 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
// Create element
var domNode = this.document.createElement(tag);
// Assign classes
var classes = (this["class"] || "").split(" ");
classes.push("tc-keyboard");
domNode.className = classes.join(" ");
this.domNode = domNode;
this.assignDomNodeClasses();
// Add a keyboard event handler
$tw.utils.addEventListeners(domNode,[
{name: "keydown", handlerObject: this, handlerMethod: "handleChangeEvent"}
@ -54,7 +53,8 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
};
KeyboardWidget.prototype.handleChangeEvent = function(event) {
if($tw.keyboardManager.checkKeyDescriptors(event,this.keyInfoArray)) {
var keyInfo = $tw.keyboardManager.getMatchingKeyDescriptor(event,this.keyInfoArray);
if(keyInfo) {
var handled = this.invokeActions(this,event);
if(this.actions) {
var variables = {
@ -62,6 +62,9 @@ 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);
@ -90,7 +93,6 @@ 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);
@ -102,14 +104,22 @@ 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["class"] || changedAttributes.tag) {
if(changedAttributes.message || changedAttributes.param || changedAttributes.key || 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)) {

Wyświetl plik

@ -155,6 +155,12 @@ 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,

Wyświetl plik

@ -33,12 +33,44 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
// Compute attributes and execute state
this.computeAttributes();
this.execute();
// Add our message handler
if(this.messageType) {
this.addEventListeners([
{type: this.messageType, handler: "handleEvent"}
]);
// 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 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);
};
@ -47,48 +79,16 @@ 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(changedAttributes["type"]) {
if($tw.utils.count(changedAttributes) > 0) {
this.refreshSelf();
return true;
}

Wyświetl plik

@ -160,6 +160,7 @@ 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
@ -183,7 +184,8 @@ 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);
var editTiddler = $tw.hooks.invokeHook("th-editing-tiddler",event),
win = event.event && event.event.view ? event.event.view : window;
if(!editTiddler) {
return false;
}
@ -192,7 +194,7 @@ NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
return self.wiki.isShadowTiddler(title) && !self.wiki.tiddlerExists(title);
}
function confirmEditShadow(title) {
return confirm($tw.language.getString(
return win.confirm($tw.language.getString(
"ConfirmEditShadowTiddler",
{variables:
{title: title}
@ -225,7 +227,8 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
storyList = this.getStoryList(),
originalTitle = tiddler ? tiddler.fields["draft.of"] : "",
originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,
confirmationTitle;
confirmationTitle,
win = event.event && event.event.view ? event.event.view : window;
if(!tiddler) {
return false;
}
@ -238,7 +241,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
confirmationTitle = title;
}
// Seek confirmation
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !confirm($tw.language.getString(
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !win.confirm($tw.language.getString(
"ConfirmDeleteTiddler",
{variables:
{title: confirmationTitle}
@ -304,7 +307,8 @@ NavigatorWidget.prototype.generateDraftTitle = function(title) {
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
var title = event.param || event.tiddlerTitle,
tiddler = this.wiki.getTiddler(title),
storyList = this.getStoryList();
storyList = this.getStoryList(),
win = event.event && event.event.view ? event.event.view : window;
// Replace the original tiddler with the draft
if(tiddler) {
var draftTitle = (tiddler.fields["draft.title"] || "").trim(),
@ -313,7 +317,7 @@ NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
var isRename = draftOf !== draftTitle,
isConfirmed = true;
if(isRename && this.wiki.tiddlerExists(draftTitle)) {
isConfirmed = confirm($tw.language.getString(
isConfirmed = win.confirm($tw.language.getString(
"ConfirmOverwriteTiddler",
{variables:
{title: draftTitle}
@ -362,6 +366,7 @@ 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),
@ -372,7 +377,7 @@ NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
originalTiddler = this.wiki.getTiddler(originalTitle),
storyList = this.getStoryList();
if(this.wiki.isDraftModified(draftTitle)) {
isConfirmed = confirm($tw.language.getString(
isConfirmed = win.confirm($tw.language.getString(
"ConfirmCancelTiddler",
{variables:
{title: draftTitle}

Wyświetl plik

@ -60,6 +60,8 @@ 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") {
@ -98,12 +100,17 @@ 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(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedTiddlers[this.transcludeTitle]) {
if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) {
this.refreshSelf();
return true;
} else {

Wyświetl plik

@ -568,11 +568,15 @@ 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];
// Rerender the child to ensure the attribute values are up to date
child.refreshSelf();
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();
}
// Invoke the child if it is an action widget
if(child.invokeAction) {
if(childIsActionWidget) {
if(child.invokeAction(triggeringWidget,event)) {
handled = true;
}

Wyświetl plik

@ -937,41 +937,57 @@ exports.parseTiddler = function(title,options) {
};
exports.parseTextReference = function(title,field,index,options) {
var tiddler,text;
if(options.subTiddler) {
tiddler = this.getSubTiddler(title,options.subTiddler);
} else {
var tiddler,
text,
parserInfo;
if(!options.subTiddler) {
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) {
return this.parseText(tiddler.fields.type,tiddler.fields.text,options);
} else {
return null;
parserInfo.sourceText = tiddler.fields.text || "";
if(tiddler.fields.type) {
parserInfo.parserType = tiddler.fields.type;
}
}
} else if(field) {
if(field === "title") {
text = title;
} else {
if(!tiddler || !tiddler.hasField(field)) {
return null;
}
text = tiddler.fields[field];
parserInfo.sourceText = title;
} else if(tiddler && tiddler.fields) {
parserInfo.sourceText = tiddler.hasField(field) ? tiddler.fields[field].toString() : null;
}
return this.parseText("text/vnd.tiddlywiki",text.toString(),options);
} else if(index) {
this.getTiddlerText(title); // Force the tiddler to be lazily loaded
text = this.extractTiddlerDataItem(tiddler,index,undefined);
if(text === undefined) {
return null;
}
return this.parseText("text/vnd.tiddlywiki",text,options);
parserInfo.sourceText = this.extractTiddlerDataItem(tiddler,index,null);
}
};
if(parserInfo.sourceText === null) {
parserInfo.parserType = null;
}
return parserInfo;
}
/*
Make a widget tree for a parse tree

Wyświetl plik

@ -4,4 +4,5 @@ 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}}

Wyświetl plik

@ -0,0 +1,8 @@
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}}

Wyświetl plik

@ -2,4 +2,8 @@ title: $:/core/templates/tiddlywiki5.js/tiddlers
`
$tw.preloadTiddlerArray(`<$text text=<<jsontiddlers "[[$:/core]]">>/>`);
$tw.preloadTiddlerArray([{
title: "$:/config/SaveWikiButton/Template",
text: "$:/core/save/offline-external-js"
}]);
`

Wyświetl plik

@ -2,7 +2,7 @@ title: $:/core/templates/tiddlywiki5-external-js.html
\rules only filteredtranscludeinline transcludeinline
<!doctype html>
{{$:/core/templates/MOTW.html}}<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
{{$:/core/templates/MOTW.html}}<html lang="{{{ [{$:/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,5 +43,6 @@ 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>
<script src="%24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js" onerror="alert('Error: Cannot load tiddlywiki.js');"></script>
<!--~~ Load external JS ~~-->
<script src="{{{ [<coreURL>] }}}" onerror="alert('Error: Cannot load {{{ [<coreURL>] }}}');"></script>
</html>

Wyświetl plik

@ -0,0 +1,4 @@
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"/>

Wyświetl plik

@ -0,0 +1,3 @@
title: $:/core/templates/html-json-tiddler
<$list filter="[<counter>!match[1]]">`,`<$text text=<<newline>>/></$list><$jsontiddler tiddler=<<currentTiddler>> escapeUnsafeScriptChars="yes"/>

Wyświetl plik

@ -1,14 +1,37 @@
title: $:/core/templates/store.area.template.html
<$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>
\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>

Wyświetl plik

@ -0,0 +1,25 @@
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>

Wyświetl plik

@ -3,8 +3,15 @@ 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 message="tm-delete-tiddler" param=<<currentTiddler>>><<lingo Listing/Cancel/Caption>></$button>
<$button actions=<<confirmCancel>> ><<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]]">

Wyświetl plik

@ -1,6 +1,6 @@
title: $:/config/OfficialPluginLibrary
tags: $:/tags/PluginLibrary
url: https://tiddlywiki.com/library/v5.1.24/index.html
url: https://tiddlywiki.com/library/v5.2.0/index.html
caption: {{$:/language/OfficialPluginLibrary}}
{{$:/language/OfficialPluginLibrary/Hint}}

Wyświetl plik

@ -4,6 +4,7 @@ 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

Wyświetl plik

@ -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/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/export-tiddlywikicore]] [[$:/core/ui/Buttons/more-page-actions]]

Wyświetl plik

@ -8,6 +8,7 @@ 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
@ -29,4 +30,4 @@ Welcome to the developer documentation for TiddlyWiki (https://tiddlywiki.com/).
** [[Scripts for building tiddlywiki.com]]
** SyncAdaptorModules
** WidgetModules
** WikiRuleModules
** WikiRuleModules

Wyświetl plik

@ -3,12 +3,4 @@ modified: 20140710081051087
tags: doc
title: 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.
{{Data Storage}}

Wyświetl plik

@ -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,isAnonymous,isPollingDisabled` |
|callback |Callback function invoked with parameters `err,isLoggedIn,username,isReadOnly` |
!! `login(username,password,callback)`
@ -128,40 +128,33 @@ 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,options,callback)`
!! `saveTiddler(tiddler,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,options,callback)`
!! `loadTiddler(title,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,options,callback)`
!! `deleteTiddler(title,callback,options)`
Delete a tiddler from the server.
|!Parameter |!Description |
|title |Title of tiddler to be deleted |
|options |See below |
|callback |Callback function invoked with parameter `err` |
|options |See below |
!!! 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.
The options parameter contains the following properties:
|!Property |!Description |
|changeCount |The //new// changeCount value for this tiddler |
|tiddlerInfo |The tiddlerInfo maintained by the syncer for this tiddler |

Wyświetl plik

@ -0,0 +1,97 @@
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]]

Wyświetl plik

@ -0,0 +1,10 @@
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]]

Wyświetl plik

@ -0,0 +1,20 @@
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.

Wyświetl plik

@ -1,8 +1,8 @@
caption: 5.1.24
created: 20201229120443187
modified: 20201229120443187
caption: 5.2.0
created: 20210714091904613
modified: 20210714091904613
tags: ReleaseNotes
title: Release 5.1.24
title: Release 5.2.0
type: text/vnd.tiddlywiki
\define contributor(username)
@ -11,61 +11,104 @@ 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
* <<.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)
* <<.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
! Usability Improvements
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/a360adbba924d222c5b55709133c18890c04398d">> dropzone size when story river is empty
* <<.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/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/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
* <<.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
! 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-added "https://github.com/Jermolene/TiddlyWiki5/commit/9eda02868f21e9dd1733ffe26352bd7ac96285b4">> new MessageCatcherWidget
* <<.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/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-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-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/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/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/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/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
!! [[XLSX Utilities Plugin]]
!! [[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]]
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/5400">> crash with the XLSX Utils plugin
@ -93,10 +136,15 @@ type: text/vnd.tiddlywiki
* <<.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
@ -110,14 +158,21 @@ type: text/vnd.tiddlywiki
* <<.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-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/7b1a0c6e6a8bd2d3badf8766af0cd3f5f7ac5ec8">> ES5 compatibility issue
* <<.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:
@ -130,6 +185,7 @@ type: text/vnd.tiddlywiki
* <<contributor CodaCodr>>
* <<contributor dixonge>>
* <<contributor donmor>>
* <<contributor felixhayashi>>
* <<contributor FlashSystems>>
* <<contributor flibbles>>
* <<contributor hoelzro>>
@ -144,6 +200,7 @@ type: text/vnd.tiddlywiki
* <<contributor NicolasPetton>>
* <<contributor OdinJorna>>
* <<contributor pmario>>
* <<contributor rryan>>
* <<contributor saqimtiaz>>
* <<contributor simonbaird>>
* <<contributor slaymaker1907>>

Wyświetl plik

@ -1,6 +1,6 @@
title: $:/config/OfficialPluginLibrary
tags: $:/tags/PluginLibrary
url: https://tiddlywiki.com/prerelease/library/v5.1.24/index.html
url: https://tiddlywiki.com/prerelease/library/v5.2.0/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.

Wyświetl plik

@ -11,13 +11,16 @@
],
"build": {
"listen": [
"--listen","root-tiddler=$:/core/save/all-external-js"],
"--listen","root-tiddler=$:/core/save/all-external-js","use-browser-cache=yes"],
"index": [
"--rendertiddler","$:/plugins/tiddlywiki/tiddlyweb/save/offline","index.html","text/plain"],
"--rendertiddler","$:/core/save/offline-external-js","index.html","text/plain",
"--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]","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"]
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"],
"tiddlywikicore": [
"--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]","text/plain"]
}
}
}

Wyświetl plik

@ -0,0 +1,4 @@
title: dezerializer test data case 1
type: text/html
<!doctype html>

Wyświetl plik

@ -0,0 +1,12 @@
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>

Wyświetl plik

@ -0,0 +1,18 @@
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 &quot;There&quot;" type="text/vnd.tiddlywiki">
<pre>Abacus</pre>
</div>
</div>
</body>
</html>

Wyświetl plik

@ -0,0 +1,19 @@
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 &quot;There&quot;" 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>

Wyświetl plik

@ -0,0 +1,20 @@
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 &quot;There&quot;" 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>

Wyświetl plik

@ -0,0 +1,39 @@
/*\
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'} ]);
});
})();

Wyświetl plik

@ -818,6 +818,48 @@ 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: [] }
);
});
}

Wyświetl plik

@ -0,0 +1,132 @@
/*\
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);
});
});
})();

Wyświetl plik

@ -220,6 +220,7 @@ 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"
@ -228,6 +229,7 @@ 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"
});
@ -242,6 +244,7 @@ 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]]//"
});
@ -374,6 +377,14 @@ 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");
});
});
})();

Wyświetl plik

@ -117,7 +117,14 @@ 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() {

Wyświetl plik

@ -1,6 +1,6 @@
created: 20140912145537860
footer: <$button message="tm-close-tiddler">Close</$button>
modified: 20140912145537861
modified: 20210627054504823
subtitle: I'm a modal wizard
title: SampleWizard
type: text/vnd.tiddlywiki

Wyświetl plik

@ -1,5 +1,5 @@
created: 20130825150000000
modified: 20190609154450433
modified: 20210714130751701
tags: [[TiddlyWiki on Node.js]]
title: TiddlerFiles
type: text/vnd.tiddlywiki
@ -78,11 +78,22 @@ 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.
!! TiddlyWiki HTML files
!! New JSON-based format for TiddlyWiki HTML files
TiddlyWiki HTML files contain a collection of tiddlers encoded in `<DIV>` format.
The new format for TiddlyWiki HTML files embeds the tiddlers in JSON format within a script tag:
For TiddlyWiki to import an unencrypted HTML file, it requires a `<div id="storeArea">` containing tiddler DIVs as explained above. For example:
```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:
```
<div id="storeArea">

Wyświetl plik

@ -8,6 +8,6 @@ tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Oper
title: average Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
<<.from-version "5.2.0">> See [[Mathematics Operators]] for an overview.
<<.operator-examples "average">>

Wyświetl plik

@ -0,0 +1,17 @@
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">>

Wyświetl plik

@ -1,6 +1,6 @@
caption: deserializers
created: 20210506115203172
from-version: 5.1.24
from-version: 5.2.0
modified: 20210506130322593
op-input: ignored
op-output: the title of each available deserializer

Wyświetl plik

@ -0,0 +1,7 @@
created: 20210622214849214
modified: 20210622214849214
tags: [[charcode Operator]] [[Operator Examples]]
title: charcode Operator (Examples)
type: text/vnd.tiddlywiki
<<.operator-example 1 "[charcode[65]match[A]]">>

Wyświetl plik

@ -28,7 +28,7 @@ Simple filter operations can be concatenated together directly (eg `[tag[HelloTh
</$vars>
```
Note that within the subfilter, the "currentTiddler" variable is set to the title of the tiddler being processed. The value of currentTiddler outside the subfilter is available in the variable "..currentTiddler". <<.from-version "5.1.24">>
Note that within the subfilter, the "currentTiddler" variable is set to the title of the tiddler being processed. The value of currentTiddler outside the subfilter is available in the variable "..currentTiddler". <<.from-version "5.2.0">>
<<.tip "Compare with the similar [[subfilter|subfilter Operator]] operator which runs a subfilter and directly returns the results">>

Wyświetl plik

@ -8,6 +8,6 @@ tags: [[Filter Operators]] [[Mathematics Operators]]
title: median Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
<<.from-version "5.2.0">> See [[Mathematics Operators]] for an overview.
<<.operator-examples "median">>

Wyświetl plik

@ -18,7 +18,7 @@ The following variables are available within the subfilter:
* ''accumulator'' - the result of the previous subfilter run
* ''currentTiddler'' - the input title
* ''..currentTiddler'' - the value of the variable `currentTiddler` outside the subfilter. <<.from-version "5.1.24">>
* ''..currentTiddler'' - the value of the variable `currentTiddler` outside the subfilter. <<.from-version "5.2.0">>
* ''index'' - the numeric index of the current list item (with zero being the first item in the list)
* ''revIndex'' - the reverse numeric index of the current list item (with zero being the last item in the list)
* ''length'' - the total length of the input list

Wyświetl plik

@ -17,7 +17,7 @@ Each item in the list of input titles is passed to the subfilter in turn. The su
Note that within the subfilter, the "currentTiddler" variable is set to the title of the tiddler being processed. This permits subfilters like `[{!!value}divide{!!cost}]` to be used for computation.
The value of currentTiddler outside the subfilter is available in the variable "..currentTiddler". <<.from-version "5.1.24">>
The value of currentTiddler outside the subfilter is available in the variable "..currentTiddler". <<.from-version "5.2.0">>
The suffix <<.place T>> determines how the items are compared and can be:
@ -26,7 +26,7 @@ The suffix <<.place T>> determines how the items are compared and can be:
* "integer" - invalid integers are interpreted as zero
* "date" - invalid dates are interpreted as 1st January 1970
* "version" - invalid versions are interpreted as "v0.0.0"
* "alphanumeric" - treat items as alphanumerics <<.from-version "5.1.24">>
* "alphanumeric" - treat items as alphanumerics <<.from-version "5.2.0">>
Note that subfilters should return the same number of items that they are passed. Any missing entries will be treated as zero or the empty string. In particular, when retrieving the value of a field with the [[get Operator]] it is helpful to guard against a missing field value using the [[else Operator]]. For example `[get[myfield]else[default-value]...`.

Wyświetl plik

@ -8,7 +8,7 @@ tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Oper
title: standard-deviation Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
<<.from-version "5.2.0">> See [[Mathematics Operators]] for an overview.
<<.tip """ The `standard-deviation` operator treats the input as a complete population and not a sample""">>

Wyświetl plik

@ -1,5 +1,5 @@
created: 20150124182421000
modified: 20210522162642994
modified: 20210618153333369
tags: [[Filter Syntax]]
title: Filter Expression
type: text/vnd.tiddlywiki
@ -26,14 +26,17 @@ If a run has:
* named prefix `:intersection` replaces all filter output so far with titles that are present in the output of this run, as well as the output from previous runs. Forms the input for the next run. <<.from-version "5.1.23">>
* named prefix `:reduce` replaces all filter output so far with a single item by repeatedly applying a formula to each input title. A typical use is to add up the values in a given field of each input title. <<.from-version "5.1.23">>
** [[Examples|Filter Run Prefix (Examples)]]
* named prefix `:sort` sorts all filter output so far by applying this run to each input title and sorting according to that output. <<.from-version "5.1.24">>
* named prefix `:sort` sorts all filter output so far by applying this run to each input title and sorting according to that output. <<.from-version "5.2.0">>
** See [[Sort Filter Run Prefix]].
* named prefix `:map` transforms all filter output so far by applying this run to each input title and replacing the input title with the output of this run for that title.
** See [[Map Filter Run Prefix]]. <<.from-version "5.2.0">>
<<.tip "Compare named filter run prefix `:filter` with [[filter Operator]] which applies a subfilter to every input title, removing the titles that return an empty result from the subfilter">>
<<.tip "Compare named filter run prefix `:reduce` with [[reduce Operator]] which is used to used to flatten a list of items down to a single item by repeatedly applying a subfilter.">>
<<.tip """Within the filter runs prefixed with `:reduce`, `:sort` and `:filter`, the "currentTiddler" variable is set to the title of the tiddler being processed. The value of currentTiddler outside the subfilter is available in the variable "..currentTiddler".<<.from-version "5.1.24">>""" >>
<<.tip """Within the filter runs prefixed with `:reduce`, `:sort`, `:map` and `:filter`, the "currentTiddler" variable is set to the title of the tiddler being processed. The value of currentTiddler outside the subfilter is available in the variable "..currentTiddler".<<.from-version "5.2.0">>""" >>
In technical / logical terms:

Wyświetl plik

@ -1,5 +1,5 @@
created: 20150220152540000
modified: 20201103110920722
modified: 20210629215024053
tags: [[Filter Syntax]]
title: Filter Parameter
type: text/vnd.tiddlywiki
@ -24,7 +24,8 @@ The parameter to a [[filter operator|Filter Operators]] can be:
:: The parameter is the text indicated by the [[text reference|TextReference]] whose name appears between the curly brackets, i.e. a [[field|TiddlerFields]] of a specified tiddler, or the value of a property of a specified [[data tiddler|DataTiddlers]].
: <<.def variable>>
:: `<like this>`
:: The parameter is the current value of the [[variable|Variables]] whose name appears between the angle brackets. Macro parameters are <<.em not>> supported.
:: The parameter is the current value of the [[variable|Variables]] whose name appears between the angle brackets. Macro parameters are <<.em not>> supported up to and including ~TiddlyWiki v5.1.23.
::<<.from-version "5.2.0">> Literal macro parameters are supported. For example: `[<now [UTC]YYYY0MM0DD0hh0mm0ssXXX>]`.
<<.from-version "5.1.23">> Filter operators support multiple parameters which are separated by a ` , ` character.

Wyświetl plik

@ -0,0 +1,16 @@
created: 20210618134753828
modified: 20210618140945870
tags: [[Filter Syntax]] [[Filter Run Prefix Examples]] [[Map Filter Run Prefix]]
title: Map Filter Run Prefix (Examples)
type: text/vnd.tiddlywiki
Replace the input titles with the caption field if it exists, otherwise preserve the input title:
<<.operator-example 1 "[tag[Widgets]] :map[get[caption]else{!!title}]">>
<<.tip "The above example is equivalent to `[tag[Widgets]] :map[get[{!!caption}!is[blank]else{!!title}]`. Note that referencing a field as a text reference such as `{!!caption}` returns an empty string for a non-existent or empty caption field. Therefore a check for `is[blank]` is needed before the `else` operator">>
For each title in a shopping list, calculate the total cost of purchasing each item:
<<.operator-example 2 "[tag[shopping]] :map[get[quantity]else[0]multiply{!!price}]">>

Wyświetl plik

@ -0,0 +1,19 @@
created: 20210618133745003
modified: 20210618134747652
tags: [[Filter Syntax]] [[Filter Run Prefix]]
title: Map Filter Run Prefix
type: text/vnd.tiddlywiki
<<.from-version "5.2.0">>
|''purpose'' |modify input titles by the result of evaluating this filter run for each item |
|''input'' |all titles from previous filter runs |
|''output''|the input titles as modified by the result of this filter run |
Each input title from previous runs is passed to this run in turn. The filter run transforms the input titles and the output of this run replaces the input title. For example, the filter run `[get[caption]else{!!title}]` replaces each input title with its caption field, unless the field does not exist in which case the title is preserved.
Note that within the filter run, the "currentTiddler" variable is set to the title of the tiddler being processed. This permits filter runs like `:map[{!!price}multiply{!!cost}]` to be used for computation. The value of currentTiddler outside the run is available in the variable "..currentTiddler".
Filter runs used with the `:map` prefix should return the same number of items that they are passed. Any missing entries will be treated as an empty string. In particular, when retrieving the value of a field with the [[get Operator]] it is helpful to guard against a missing field value using the [[else Operator]]. For example `[get[myfield]else[default-value]...`.
[[Examples|Map Filter Run Prefix (Examples)]]

Wyświetl plik

@ -4,7 +4,7 @@ tags: [[Filter Syntax]] [[Filter Run Prefix]]
title: Sort Filter Run Prefix
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">>
<<.from-version "5.2.0">>
|''purpose'' |sort the input titles by the result of evaluating this filter run for each item |
|''input'' |all titles from previous filter runs |

Wyświetl plik

@ -8,7 +8,7 @@ tags: [[Reducing Mathematics Operators]] [[Filter Operators]] [[Mathematics Oper
title: variance Operator
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> See [[Mathematics Operators]] for an overview.
<<.from-version "5.2.0">> See [[Mathematics Operators]] for an overview.
<<.tip """ The `standard-deviation` operator treats the input as a complete population and not a sample""">>

Wyświetl plik

@ -4,7 +4,7 @@ tags: [[Hidden Settings]]
title: Hidden Setting: HTML Parser Sandbox
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">> By default, tiddlers with the type `text/html` are displayed in an iframe with the [[sandbox attribute|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox]] set to the empty string. This causes all security restrictions to be applied, disabling many features such as JavaScript, downloads and external file references. This is the safest setting.
<<.from-version "5.2.0">> By default, tiddlers with the type `text/html` are displayed in an iframe with the [[sandbox attribute|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox]] set to the empty string. This causes all security restrictions to be applied, disabling many features such as JavaScript, downloads and external file references. This is the safest setting.
To globally disable the sandbox, set the tiddler $:/config/HtmlParser/DisableSandbox to `yes`. This will mean that the code in the iframe has full access to TiddlyWiki's internals, which means that a malicious HTML page could exfiltrate data from a private wiki.

Wyświetl plik

@ -4,7 +4,7 @@ tags: [[Hidden Settings]]
title: Hidden Setting: Enable File Import in Editor
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">>
<<.from-version "5.2.0">>
$:/config/Editor/EnableImportFilter

Wyświetl plik

@ -4,7 +4,7 @@ tags: [[Hidden Settings]]
title: Hidden Settings: Import Content Types for Editor
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">>
<<.from-version "5.2.0">>
$:/config/Editor/ImportContentTypesFilter

Wyświetl plik

@ -1,6 +1,6 @@
caption: now
created: 20141008141616791
modified: 20170630223406157
modified: 20210629215024061
tags: Macros [[Core Macros]]
title: now Macro
type: text/vnd.tiddlywiki
@ -16,5 +16,7 @@ The value doesn't update automatically, like a ticking clock. It updates wheneve
''Note'': The format string `[UTC]YYYY0MM0DD0hh0mm0ssXXX` will return a date string representing the UTC time-stamp as it is used in the ~TiddlyWiki `created` and `modified` time-stamp fields.
<<.from-version 5.2.0>><<.tip "You can now pass literal parameters to the `now` macro in filters. For example, this filter will return all tiddlers created today: `[all[tiddlers]] :filter[get[created]format:date[YYYY0MM0DD]match<now YYYY0MM0DD>]`">>
<<.macro-examples "now">>

Wyświetl plik

@ -15,10 +15,10 @@ It uses the same method as the create new tiddler button, a number is appended t
: A string specifying the desired base name, defaulting to `New Tiddler`. <br>The default setting can be adjusted in the $:/ControlPanel '': Info : Basics - tab.''
; separator
: <<.from-version "5.1.24">> An ''optional'' string specifying the separator between baseName and the unique number. eg: `separator:"-"`. Defaults to a space: `" "`. If you need an empty separator use the ''template''!
: <<.from-version "5.2.0">> An ''optional'' string specifying the separator between baseName and the unique number. eg: `separator:"-"`. Defaults to a space: `" "`. If you need an empty separator use the ''template''!
; template
: <<.from-version "5.1.24">> A ''optional'' template string can be used to allow you maximum flexibility. If the template string is used, there will always be a counter value.
: <<.from-version "5.2.0">> A ''optional'' template string can be used to allow you maximum flexibility. If the template string is used, there will always be a counter value.
!! Template String

Wyświetl plik

@ -1,5 +1,5 @@
created: 20140226085215941
modified: 20140226085454346
modified: 20210705094948968
tags: Messages
title: WidgetMessage: tm-navigate
type: text/vnd.tiddlywiki
@ -13,6 +13,12 @@ The navigate message requires the following properties on the `event` object:
|navigateTo |Title of the tiddler that is being navigated |
|navigateFromTitle |Title of the tiddler from which the navigation was initiated |
|navigateFromClientRect |Bounding rectangle in client page coordinates of the element initiating the navigation |
|navigateFromClientTop |<<<<.from-version "5.2.0">> Y coordinate of top edge of bounding client rectangle |
|navigateFromClientLeft |<<<<.from-version "5.2.0">> X coordinate of left edge of bounding client rectangle |
|navigateFromClientWidth |<<<<.from-version "5.2.0">> Width of bounding client rectangle |
|navigateFromClientRight |<<<<.from-version "5.2.0">> X coordinate of right edge of bounding client rectangle |
|navigateFromClientBottom |<<<<.from-version "5.2.0">> Y coordinate of bottom edge of bounding client rectangle |
|navigateFromClientHeight |<<<<.from-version "5.2.0">> Height of bounding client rectangle |
|navigateSuppressNavigation |''true'' causes the new tiddler to only be added to the story, and not the history stack. This suppresses the scrolling associated with navigating to a tiddler |
The navigate message can be generated by the LinkWidget, the ActionNavigateWidget and the ButtonWidget, and is handled by the NavigatorWidget.

Wyświetl plik

@ -1,23 +1,95 @@
created: 20180905075846391
modified: 20200814110131083
modified: 20210611055708739
tags: [[WebServer Guides]]
title: Using the external JavaScript template
type: text/vnd.tiddlywiki
Setting the [[root-tiddler|WebServer Parameter: root-tiddler]] parameter to `$:/core/save/all-external-js` switches to a special template that externalises TiddlyWiki's core ~JavaScript into a separate file. For example:
You can use a special template to externalise TiddlyWiki's core code into a separate file. This configuration allows the browser to cache the core for improved efficiency.
```
tiddlywiki editions/tw5.com-server/ --listen host=0.0.0.0 "root-tiddler=$:/core/save/all-external-js"
```
To ensure that the "save changes" button saves a full, standalone wiki, it is also necessary to set the tiddler $:/config/SaveWikiButton/Template to contain `$:/core/save/all-external-js`.
The provided edition `server-external-js` contains all the configuration necessary to use the external ~JavaScript template.
!! Background
! Background
TiddlyWiki in the single file configuration ordinarily packs everything into a single file: your data, and the ~JavaScript, CSS and HTML comprising TiddlyWiki itself. This lack of dependencies is usually very convenient: it means that it is impossible for the parts of a TiddlyWiki to become separated, and enormously improves the chances of it still functioning in the future.
However, there is some inefficiency in this arrangement because the core code is repeatedly loaded and saved every time the content of the wiki is saved. This inefficiency is partially ameliorated when working in the client server configuration because once the wiki is loaded by the browser the synchronisation process only transmits individual tiddlers back and forth to the server.
The remaining inefficiency when working in the client server configuration is that the single page wiki that is initially loaded will contain a copy of the entire core code of TiddlyWiki, making it impossible for the browser to cache it.
The remaining inefficiency when working in the client server configuration is that the single page wiki that is initially loaded will contain a copy of the entire core code of TiddlyWiki, making it impossible for the browser to cache it.
! A quickstart
The mechanism will be activated by setting the [[root-tiddler|WebServer Parameter: root-tiddler]] parameter to `$:/core/save/all-external-js`. This template externalises TiddlyWiki's core JavaScript into a separate file. For example, the following command will start your server with caching enabled. It will transfer the wiki with two GET requests, and the core can be cached by the browser.
```
tiddlywiki YOUR_WIKI_FOLDER --listen 'root-tiddler=$:/core/save/all-external-js' use-browser-cache=yes
```
<<.tip """You can activate your browser's ''Developer Tools: Network'' tab and reload the page to see how it works.""">>
<<.tip """On Windows, Command Prompt (CMD) users need to replace single quotes `'` with double quotation marks `"`.""">>
! Initializing a new wiki
The provided edition `server-external-js` contains all the configuration necessary to use the external ~JavaScript template. Here is an example:
```
tiddlywiki ./myNewWiki --init server-external-js
tiddlywiki ./myNewWiki --build listen
```
The above commands perform the following:
* Create a new wiki with external-js customization included.
* Start the server with external-js enabled. The server listens on port 8080. Visit http://localhost:8080 in your browser.
To customize your `--build listen` command, see [[tiddlywiki.info Files]] and [[ListenCommand]].
! Standalone wiki with the external-js template
You can use the "external-js" template with your standalone wiki, but this requires that you have ~TiddlyWiki's core ~JavaScript saved alongside your html file. You may prefer this configuration, for example, if you have several wikis on a ~WebDav server. (See: [[Saving via WebDAV]])
<<.warning "Since working with several files, that belong together, will open up all kinds of synchronisation challenges, this functionality is intended for advanced users.">>
!! Saving your snapshots
If you start your ~TiddlyWiki server in the "external-js" configuration, snapshots you saved from the wiki will also have the external-js configuration:
* Click on the "cloud" button and choose <<.icon $:/core/images/download-button>> ''Save snapshot for offline use''. The html wiki you saved will have a reduced file size compared to a regular snapshot because the ~TiddlyWiki core code has been externalized. However, to be able to use this wiki, you ''must'' also own a copy of ~TiddlyWiki's core ~JavaScript.
* Click on the "cloud" button and choose <<.icon $:/core/images/download-button>> ''Save ~TiddlyWiki core for offline use'' to download the core ~JavaScript from the server. Save this file in the same folder as your html wiki. <<.from-version "5.2.0">>
The "server-external-js" edition lets you save the snapshot from the command line:
```
tiddlywiki YOUR_WIKI_FOLDER --build index
```
Files "index.html" and "tiddlywikicore-5.x.x.js" will be saved in your wiki folder's `output` directory.
!! Obtaining the ~TiddlyWiki core with tiddlywiki command
You can also run the following command to obtain the core ~JavaScript. The file "tiddlywikicore-5.x.x.js" will be saved in the`output` directory of your wiki folder:
```
tiddlywiki YOUR_WIKI_FOLDER \
--render '$:/core/templates/tiddlywiki5.js' \
'[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]' \
'text/plain'
```
The "server-external-js" edition has the shortcut set up for you. Just run:
```
tiddlywiki YOUR_WIKI_FOLDER --build tiddlywikicore
```
! Upgrading your standalone wiki <span style="font-size:0.65em">(experimental)</span>
Before you proceed, backup your wiki first! Follow the steps below to upgrade a single-file wiki with the external-js template:
# Proceed with the [[Upgrade Process for Standalone TiddlyWikis|Upgrading]]. Your wiki will be converted to a full standalone HTML.
# Open your upgraded wiki in the browser. If you'd like to revert to using the regular template, restore the original shadow tiddler `$:/config/SaveWikiButton/Template` by deleting any custom copy. Save your wiki and you are done.
# Otherwise, from your wiki, select the ''Tools'' tab from the sidebar and click on the <<.icon $:/core/images/star-filled>> ''export tiddlywiki core'' button to obtain the core from your wiki.
# Verify that `$:/config/SaveWikiButton/Template` still contains `$:/core/save/offline-external-js`. Modify if necessary.
# Save your wiki again. Your wiki is now converted to using the external core.

Wyświetl plik

@ -18,18 +18,18 @@ There are several differences from the [[tm-new-tiddler message|WidgetMessage: t
The ''action-createtiddler'' widget is invisible.
<<.from-version "5.1.24">> The action widgets contained within the ''action-createtiddler'' widget are executed after the new tiddler has been created with the title of the tiddler in the variable `createTiddler-title` and `createTiddler-draftTitle`.
<<.from-version "5.2.0">> The action widgets contained within the ''action-createtiddler'' widget are executed after the new tiddler has been created with the title of the tiddler in the variable `createTiddler-title` and `createTiddler-draftTitle`.
|!Attribute |!Description |
|$basetitle |The initial title that will be attempted. If a tiddler with that title already exists, then a numerical counter is added to the title and incremented until it is unique|
|$savetitle |//(deprecated – see below))// A text reference identifying a field or index into which the title of the newly created tiddler will be stored after it is created |
|$savedrafttitle |//(deprecated – see below))// <<.from-version "5.1.20">> A text reference identifying a field or index into which the draft title associated with the newly created tiddler will be stored after it is created. This is useful when using a sequence of action widgets to create a new tiddler, put it into edit mode, and position it within the list of its parent tag |
|$savetitle |//(deprecated – see below)// A text reference identifying a field or index into which the title of the newly created tiddler will be stored after it is created |
|$savedrafttitle |//(deprecated – see below)// <<.from-version "5.1.20">> A text reference identifying a field or index into which the draft title associated with the newly created tiddler will be stored after it is created. This is useful when using a sequence of action widgets to create a new tiddler, put it into edit mode, and position it within the list of its parent tag |
|$timestamp |Specifies whether the timestamp(s) of the target tiddler will be updated (''modified'' and ''modifier'', plus ''created'' and ''creator'' for newly created tiddlers). Can be "yes" (the default) or "no" |
|$template |<<.from-version "5.1.22">> The title of a template tiddler, that will be used to create a new tiddler |
|$overwrite |<<.from-version "5.1.22">> If set to "yes", it will overwrite existing tiddlers. ''Be careful!'' |
|//{any attributes not starting with $}// |Each attribute name specifies a field to be created in the new tiddler |
<<.from-version "5.1.24">> Note that the attributes `$savetitle` and `$savedrafttitle` are no longer needed. Instead, any action widgets that need to use the title of the newly created tiddler should be contained within the ''action-createtiddler'' widget, and reference the variables `createTiddler-title` and `createTiddler-draftTitle` to obtain the title.
<<.from-version "5.2.0">> Note that the attributes `$savetitle` and `$savedrafttitle` are no longer needed. Instead, any action widgets that need to use the title of the newly created tiddler should be contained within the ''action-createtiddler'' widget, and reference the variables `createTiddler-title` and `createTiddler-draftTitle` to obtain the title.
! Examples

Wyświetl plik

@ -16,7 +16,7 @@ The ''action-popup'' widget is invisible. Any content within it is ignored.
|!Attribute |!Description |
|$state |The title of the state tiddler for the popup |
|$coords |Optional coordinates for the handle to which popup is positioned (in the format `(x,y,w,h)`) |
|$floating |<<.from-version "5.1.24">> Optional. Defaults to `no`. Set to `yes` to create a popup that must be closed explicitly. |
|$floating |<<.from-version "5.2.0">> Optional. Defaults to `no`. Set to `yes` to create a popup that must be closed explicitly. |
<<.from-version "5.1.23">> If the ''$coords'' attribute is missing or empty then all popups are cancelled.

Wyświetl plik

@ -1,5 +1,5 @@
created: 20141008134425548
modified: 20160429165240169
modified: 20210630163127249
tags: Widgets
title: ActionWidgets
type: text/vnd.tiddlywiki
@ -12,10 +12,10 @@ The following action widgets are provided:
There are two ways to use action widgets:
* Using the `actions` attribute of the triggering widget (this is the preferred way)
* Placing them within an action string attribute (typically called `actions`) on the triggering widget (this is the preferred way)
* Embedding the actions within the triggering widget (an older technique that is now deprecated)
!! Assigning action widgets with the `actions` attribute
!! Using action string attributes
The action widgets are passed as a string to the `actions` attribute of the triggering widget. Usually, it is more convenient to use a macro to assign the action widgets to a variable. For example, here is a button that triggers two actions of sending different messages:
@ -30,7 +30,7 @@ Click me!
</$button>
```
!! Assigning action widgets by embedding
!! Directly embedding action widgets
The action widgets need not be immediate children of their triggering widget, but they must be descendents of it. The actions are performed in sequence. Here is the above example rewritten to use embedding:
@ -42,3 +42,49 @@ Click me!
</$button>
```
! Action Execution Modes
<<.from-version "5.2.0">> The default behaviour of action widgets has some peculiarities that often cause confusion. There is now an improved mode that simplifies how things work, but due to BackwardsCompatibility constraints, it must be explicitly engaged in order to take advantage of it.
The peculiarities relate to the way that the results of previous action widgets are available to subsequent action widgets. By default, action widgets are refreshed before each execution which ensure that they reflect the results of previous actions. However, ordinary widgets are not updated in the same way.
In the following contrived example, a button triggers a series of actions that should result in the string `foo` being assigned to the ''text'' field of the tiddler ActionTestTiddler. However, it fails to produce the expected result because the `<$set>` widget is not refreshed with the new value of ActionTestTiddler after the execution of the first `<$action-setfield>` widget.
<$macrocall $name='wikitext-example-without-html'
src='\define actions()
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value="FOO"/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
</$set>
\end
Current value of ActionTestTiddler: {{ActionTestTiddler}}
<$button actions=<<actions>>>
Click me
</$button>'/>
The new behaviour avoids these problems by refreshing all widgets before execution, not just action widgets. It is engaged by running the actions in a scopr that includes the variable `tv-action-refresh-policy` set to the value `always`.
This can be done within an action string, or via a local variable declaration containing the widget triggering the action.
<<.warning "Do not attempt to set `tv-action-refresh-policy` globally; the core will only work correctly with the default setting">>
The example above works as expected with the addition of `tv-action-refresh-policy`:
<$macrocall $name='wikitext-example-without-html'
src='\define tv-action-refresh-policy() always
\define actions()
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value="FOO"/>
<$set name="newvalue" value={{{ [{ActionTestTiddler}lowercase[]] }}}>
<$action-setfield $tiddler="ActionTestTiddler" $field="text" $value=<<newvalue>>/>
</$set>
\end
Current value of ActionTestTiddler: {{ActionTestTiddler}}
<$button actions=<<actions>>>
Click me
</$button>'/>

Wyświetl plik

@ -19,9 +19,9 @@ It sends a [[WidgetMessage: tm-import-tiddlers]] carrying a JSON representation
|class |<<.from-version "5.1.22">> Optional CSS class to be assigned to the DOM node created by the dropzone (defaults to "tc-dropzone") |
|autoOpenOnImport |<<.from-version "5.1.23">> Optional value "no" or "yes" that can override tv-auto-open-on-import |
|importTitle|<<.from-version "5.1.23">> Optional tiddler title to use for import process instead of ~$:/Import |
|actions|<<.from-version "5.1.24">> Optional actions string to be invoked after the `tm-import-tiddlers` message has been sent. The variable `importTitle` provides the title of the tiddler used for the import process. |
|contentTypesFilter |<<.from-version "5.1.24">> Optional filter that specifies the [[content types|ContentType]] accepted by the dropzone. |
|filesOnly|<<.from-version "5.1.24">> Optional. When set to "yes", the dropzone only accepts files and not string data. Defaults to "no" |
|actions|<<.from-version "5.2.0">> Optional actions string to be invoked after the `tm-import-tiddlers` message has been sent. The variable `importTitle` provides the title of the tiddler used for the import process. |
|contentTypesFilter |<<.from-version "5.2.0">> Optional filter that specifies the [[content types|ContentType]] accepted by the dropzone. |
|filesOnly|<<.from-version "5.2.0">> Optional. When set to "yes", the dropzone only accepts files and not string data. Defaults to "no" |
<<.tip """Use the `prefix` filter operator to easily accept multiple related content types. For example this filter will accept all image content types: `[prefix[image/]]`""">>

Wyświetl plik

@ -36,7 +36,7 @@ The content of the `<$edit-text>` widget is ignored.
|inputActions |<<.from-version 5.1.23>> Optional actions that are triggered every time an input event occurs within the input field or textarea |
|refreshTitle |<<.from-version 5.1.23>> An optional tiddler title that makes the input field update whenever the specified tiddler changes |
|disabled|<<.from-version "5.1.23">> Optional, disables the text input if set to "yes". Defaults to "no"|
|fileDrop|<<.from-version "5.1.24">> Optional. When set to "yes" allows dropping or pasting images into the editor to import them. Defaults to "no"|
|fileDrop|<<.from-version "5.2.0">> Optional. When set to "yes" allows dropping or pasting images into the editor to import them. Defaults to "no"|
! Notes

Wyświetl plik

@ -1,5 +1,5 @@
created: 20201123113532200
modified: 20210520162813234
modified: 20210711165425543
tags: Widgets
title: EventCatcherWidget
type: text/vnd.tiddlywiki
@ -25,12 +25,16 @@ Use of the event catcher widget is beneficial when using large numbers of other
The content of the `<$eventcatcher>` widget is displayed normally.
|!Attribute |!Description |
|events |Space separated list of JavaScript events to be trapped, for example "click" or "click dblclick" |
|selector |A CSS selector. Only events originating inside a DOM node with this selector will be trapped |
|actions-* |Action strings to be invoked when a matching event is trapped. Each event is mapped to an action attribute name of the form <code>actions-<em>event</em></code> where <code><em>event</em></code> represents the type of the event. For example: `actions-click` or `actions-dblclick` |
|//{any attributes starting with $}// |<<.from-version "5.2.0">> Each attribute name (excluding the $) specifies the name of an event, and the value specifies the action string to be invoked. For example: `$click=<<clickActions>>` |
|tag |Optional. The HTML element the widget creates to capture the events, defaults to:<br>» `span` when parsed in inline-mode<br>» `div` when parsed in block-mode |
|class |Optional. A CSS class name (or names) to be assigned to the widget HTML element |
|stopPropagation |<<.from-version "5.1.24">> Optional. Set to "always" to always stop event propagation even if there are no corresponding actions to invoke, "never" to never stop event propagation, or the default value "onaction" with which event propagation is only stopped if there are corresponding actions that are invoked. |
|stopPropagation |<<.from-version "5.2.0">> Optional. Set to "always" to always stop event propagation even if there are no corresponding actions to invoke, "never" to never stop event propagation, or the default value "onaction" with which event propagation is only stopped if there are corresponding actions that are invoked. |
|events |//(deprecated – see below)// Space separated list of JavaScript events to be trapped, for example "click" or "click dblclick" |
|actions-* |//(deprecated – see below)// Action strings to be invoked when a matching event is trapped. Each event is mapped to an action attribute name of the form <code>actions-<em>event</em></code> where <code><em>event</em></code> represents the type of the event. For example: `actions-click` or `actions-dblclick` |
<<.from-version "5.2.0">> Note that the attributes `events` and `actions-*` are no longer needed. Instead you can use attributes starting with $ where the attribute name (excluding the $) specifies the name of the event and the value specifies the action string to be invoked. If any attributes with the prefix $ are present then the `types` attribute is ignored.
! Variables
@ -65,7 +69,7 @@ This example uses the ActionLogWidget and will log the `data-item-id` attribute
<$action-log item=<<dom-data-item-id>> event=<<event-type>>/>
\end
<$eventcatcher events="click contextmenu" selector=".item" actions-click=<<clickactions>> actions-contextmenu=<<contextmenu-actions>> tag="div">
<$eventcatcher selector=".item" $click=<<clickactions>> $contextmenu=<<contextmenu-actions>> tag="div">
<div class="item" data-item-id="item1">
Click events here will be trapped
@ -85,4 +89,3 @@ And here
</$eventcatcher>
```

Wyświetl plik

@ -0,0 +1,22 @@
title: JSONTiddlerWidget
created: 20210630100923398
modified: 20210630100923398
tags: Widgets
caption: jsontiddler
! Introduction
The jsontiddler widget renders the fields of a tiddler to display as a JSON object. The fields of the tiddler can be customised or excluded.
The jsontiddler widget is used in system templates to generate JSON representations of tiddlers for saving.
! Content and Attributes
The content of the `<$jsontiddler>` widget is ignored.
|!Attribute |!Description |
|tiddler |Optional title of the tiddler from which the fields are to be displayed |
|exclude |Optional space separated list of fields to be excluded |
|escapeUnsafeScriptChars |If set to "yes" then the `<` character will be escaped to the equivalent `\u003C` encoding |
|//{any attributes starting with $}// |Each attribute name (without the leading `$`) specifies a field to be modified with the attribute value providing the value to assign to the field |

Wyświetl plik

@ -1,7 +1,7 @@
caption: keyboard
created: 20140302192136805
list: [[Keyboard Codes]] [[Key Codes (Example)]] [[Key Codes (Example 1)]] [[Possible Keys (Example 2)]]
modified: 20210525102143381
modified: 20210612101618855
tags: Widgets
title: KeyboardWidget
type: text/vnd.tiddlywiki
@ -26,10 +26,10 @@ The content of the `<$keyboard>` widget is rendered normally. The keyboard short
<<.from-version "5.2.0">> The following variables are made available to the actions:
|column-1-20 |k
|!Variables |!Description |
|`event-key` |The <<.var event-key>> variable contains the character, if possible. eg: `1`. You can experiment with some settings at: [[Key Codes (Example)]] |
|`event-code` |The <<.var event-code>> variable contains a character description. eg: `Digit1` instead of `1`. Or `Space` instead of an empty string ` `, which is hard to see|
|`event-key-descriptor` |The <<.var event-key-descriptor>> variable is available if the keyboard event captured was configured using a [[keyboard shortcut descriptor|Keyboard Shortcut Descriptor]] of the form `((my-shortcut))` which references a configuration tiddler. |
|`modifier` |The [[modifier Variable]] contains the Modifier Key held during the event (can be <kbd>normal</kbd>, <kbd>ctrl</kbd>, <kbd>shift</kbd>, <kbd>alt</kbd> or combinations thereof) |
! Key Strings

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