mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-23 03:14:40 +00:00
Compare commits
38 Commits
tm-http-re
...
plugin-sta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08cc320d34 | ||
|
|
5837570196 | ||
|
|
f2f6b72056 | ||
|
|
ece8b0ee01 | ||
|
|
f1299120a6 | ||
|
|
0b475628de | ||
|
|
24dceb1bce | ||
|
|
21b02e8ba5 | ||
|
|
404015c455 | ||
|
|
25b1900849 | ||
|
|
29373c3359 | ||
|
|
64f5dd942c | ||
|
|
9007e0b8c8 | ||
|
|
07a048975d | ||
|
|
b4e0a9b28b | ||
|
|
67845f8ebe | ||
|
|
a081e58273 | ||
|
|
1d48909012 | ||
|
|
d3722a6602 | ||
|
|
5f74f4c2fa | ||
|
|
9167b190d2 | ||
|
|
df8731f760 | ||
|
|
1fb9098c76 | ||
|
|
e9aa3c6c93 | ||
|
|
105e8195d5 | ||
|
|
eeb4e7a7f7 | ||
|
|
7ce85a2ddb | ||
|
|
804f227815 | ||
|
|
9939759690 | ||
|
|
b595651fe1 | ||
|
|
9cd6affcae | ||
|
|
e43cd2d989 | ||
|
|
f1e707bff4 | ||
|
|
2d92a6fd78 | ||
|
|
2e0e541ebf | ||
|
|
b4d7e34a5a | ||
|
|
b6eab1afd6 | ||
|
|
32cbd53423 |
@@ -206,6 +206,12 @@ Stylesheets/Caption: Stylesheets
|
||||
Stylesheets/Expand/Caption: Expand All
|
||||
Stylesheets/Hint: This is the rendered CSS of the current stylesheet tiddlers tagged with <<tag "$:/tags/Stylesheet">>
|
||||
Stylesheets/Restore/Caption: Restore
|
||||
TestCases/Caption: Test Cases
|
||||
TestCases/Hint: Test cases are self contained examples for testing and learning
|
||||
TestCases/All/Caption: All Test Cases
|
||||
TestCases/All/Hint: All Test Cases
|
||||
TestCases/Failed/Caption: Failed Test Cases
|
||||
TestCases/Failed/Hint: Only Failed Test Cases
|
||||
Theme/Caption: Theme
|
||||
Theme/Prompt: Current theme:
|
||||
TiddlerFields/Caption: Tiddler Fields
|
||||
|
||||
@@ -65,6 +65,9 @@ sidebar-tab-foreground-selected: Sidebar tab foreground for selected tabs
|
||||
sidebar-tab-foreground: Sidebar tab foreground
|
||||
sidebar-tiddler-link-foreground-hover: Sidebar tiddler link foreground hover
|
||||
sidebar-tiddler-link-foreground: Sidebar tiddler link foreground
|
||||
testcase-accent-level-1: Test case accent colour with no nesting
|
||||
testcase-accent-level-2: Test case accent colour with 2nd level nesting
|
||||
testcase-accent-level-3: Test case accent colour with 3rd level nesting or higher
|
||||
site-title-foreground: Site title foreground
|
||||
static-alert-foreground: Static alert foreground
|
||||
tab-background-selected: Tab background for selected tabs
|
||||
|
||||
@@ -30,6 +30,7 @@ name: The human readable name associated with a plugin tiddler
|
||||
parent-plugin: For a plugin, specifies which plugin of which it is a sub-plugin
|
||||
plugin-priority: A numerical value indicating the priority of a plugin tiddler
|
||||
plugin-type: The type of plugin in a plugin tiddler
|
||||
stability: The development status of a plugin: deprecated, experimental, stable, or legacy
|
||||
revision: The revision of the tiddler held at the server
|
||||
released: Date of a TiddlyWiki release
|
||||
source: The source URL associated with a tiddler
|
||||
|
||||
@@ -27,33 +27,8 @@ var Command = function(params,commander,callback) {
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var wiki = this.commander.wiki,
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
upgradeLibraryTitle = this.params[0] || UPGRADE_LIBRARY_TITLE,
|
||||
tiddlers = {};
|
||||
// Collect up the library plugins
|
||||
var collectPlugins = function(folder) {
|
||||
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var p=0; p<pluginFolders.length; p++) {
|
||||
if(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {
|
||||
pluginFields = $tw.loadPluginFolder(path.resolve(folder,"./" + pluginFolders[p]));
|
||||
if(pluginFields && pluginFields.title) {
|
||||
tiddlers[pluginFields.title] = pluginFields;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
collectPublisherPlugins = function(folder) {
|
||||
var publisherFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var t=0; t<publisherFolders.length; t++) {
|
||||
if(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {
|
||||
collectPlugins(path.resolve(folder,"./" + publisherFolders[t]));
|
||||
}
|
||||
}
|
||||
};
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,$tw.config.pluginsEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,$tw.config.themesEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,$tw.config.languagesEnvVar),collectPlugins);
|
||||
tiddlers = $tw.utils.getAllPlugins();
|
||||
// Save the upgrade library tiddler
|
||||
var pluginFields = {
|
||||
title: upgradeLibraryTitle,
|
||||
|
||||
@@ -43,7 +43,9 @@ Saves individual tiddlers in their raw text or binary format to the specified fi
|
||||
directory: path.resolve(self.commander.outputPath),
|
||||
pathFilters: [filenameFilter],
|
||||
wiki: wiki,
|
||||
fileInfo: {}
|
||||
fileInfo: {
|
||||
overwrite: true
|
||||
}
|
||||
});
|
||||
if(self.commander.verbose) {
|
||||
console.log("Saving \"" + title + "\" to \"" + fileInfo.filepath + "\"");
|
||||
|
||||
@@ -176,7 +176,10 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
|
||||
this.saveJSONFile(directory + path.sep + "plugin.info",pluginInfo);
|
||||
self.log("Writing " + directory + path.sep + "plugin.info: " + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));
|
||||
var pluginTiddlers = $tw.utils.parseJSONSafe(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
|
||||
$tw.utils.each(pluginTiddlers,function(tiddler) {
|
||||
$tw.utils.each(pluginTiddlers,function(tiddler,title) {
|
||||
if(!tiddler.title) {
|
||||
tiddler.title = title;
|
||||
}
|
||||
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,30 +3,7 @@ title: $:/core/modules/parsers/wikiparser/rules/quoteblock.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki text rule for quote blocks. For example:
|
||||
|
||||
```
|
||||
<<<.optionalClass(es) optional cited from
|
||||
a quote
|
||||
<<<
|
||||
|
||||
<<<.optionalClass(es)
|
||||
a quote
|
||||
<<< optional cited from
|
||||
```
|
||||
|
||||
Quotes can be quoted by putting more <s
|
||||
|
||||
```
|
||||
<<<
|
||||
Quote Level 1
|
||||
|
||||
<<<<
|
||||
QuoteLevel 2
|
||||
<<<<
|
||||
|
||||
<<<
|
||||
```
|
||||
Wiki text rule for quote blocks.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
@@ -47,16 +24,15 @@ exports.init = function(parser) {
|
||||
exports.parse = function() {
|
||||
var classes = ["tc-quote"];
|
||||
// Get all the details of the match
|
||||
var reEndString = "^" + this.match[1] + "(?!<)";
|
||||
var reEndString = "^\\s*" + this.match[1] + "(?!<)";
|
||||
// Move past the <s
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
// Parse any classes, whitespace and then the optional cite itself
|
||||
classes.push.apply(classes, this.parser.parseClasses());
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
var cite = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
// before handling the cite, parse the body of the quote
|
||||
var tree= this.parser.parseBlocks(reEndString);
|
||||
var tree = this.parser.parseBlocks(reEndString);
|
||||
// If we got a cite, put it before the text
|
||||
if(cite.length > 0) {
|
||||
tree.unshift({
|
||||
|
||||
@@ -140,6 +140,11 @@ function sendResponse(request,response,statusCode,headers,data,encoding) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// RFC 7231, 6.1. Overview of Status Codes:
|
||||
// Browser clients may cache 200, 203, 204, 206, 300, 301,
|
||||
// 404, 405, 410, 414, and 501 unless given explicit cache controls
|
||||
headers["Cache-Control"] = headers["Cache-Control"] || "no-store";
|
||||
}
|
||||
/*
|
||||
If the gzip=yes is set, check if the user agent permits compression. If so,
|
||||
|
||||
@@ -81,6 +81,8 @@ exports.startup = function() {
|
||||
deferredChanges = Object.create(null);
|
||||
$tw.hooks.invokeHook("th-page-refreshed");
|
||||
}
|
||||
var throttledRefresh = $tw.perf.report("throttledRefresh",refresh);
|
||||
|
||||
// Add the change event handler
|
||||
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
|
||||
// Check if only tiddlers that are throttled have changed
|
||||
@@ -101,7 +103,7 @@ exports.startup = function() {
|
||||
if(isNaN(timeout)) {
|
||||
timeout = THROTTLE_REFRESH_TIMEOUT;
|
||||
}
|
||||
timerId = setTimeout(refresh,timeout);
|
||||
timerId = setTimeout(throttledRefresh,timeout);
|
||||
$tw.utils.extend(deferredChanges,changes);
|
||||
} else {
|
||||
$tw.utils.extend(deferredChanges,changes);
|
||||
|
||||
@@ -47,11 +47,7 @@ exports.startup = function() {
|
||||
headers: getPropertiesWithPrefix(params,"header-"),
|
||||
passwordHeaders: getPropertiesWithPrefix(params,"password-header-"),
|
||||
queryStrings: getPropertiesWithPrefix(params,"query-"),
|
||||
passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-"),
|
||||
basicAuthUsername: params["basic-auth-username"],
|
||||
basicAuthUsernameFromStore: params["basic-auth-username-from-store"],
|
||||
basicAuthPassword: params["basic-auth-password"],
|
||||
basicAuthPasswordFromStore: params["basic-auth-password-from-store"]
|
||||
passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-")
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tm-http-cancel-all-requests",function(event) {
|
||||
|
||||
@@ -56,7 +56,7 @@ exports.startup = function() {
|
||||
return;
|
||||
}
|
||||
// Initialise the document
|
||||
srcDocument.write("<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
|
||||
srcDocument.close();
|
||||
srcDocument.title = windowTitle;
|
||||
srcWindow.addEventListener("beforeunload",function(event) {
|
||||
|
||||
@@ -100,10 +100,6 @@ headers: hashmap of header name to header value to be sent with the request
|
||||
passwordHeaders: hashmap of header name to password store name to be sent with the request
|
||||
queryStrings: hashmap of query string parameter name to parameter value to be sent with the request
|
||||
passwordQueryStrings: hashmap of query string parameter name to password store name to be sent with the request
|
||||
basicAuthUsername: plain username for basic authentication
|
||||
basicAuthUsernameFromStore: name of password store entry containing username
|
||||
basicAuthPassword: plain password for basic authentication
|
||||
basicAuthPasswordFromStore: name of password store entry containing password
|
||||
*/
|
||||
function HttpClientRequest(options) {
|
||||
var self = this;
|
||||
@@ -132,11 +128,6 @@ function HttpClientRequest(options) {
|
||||
$tw.utils.each(options.passwordHeaders,function(value,name) {
|
||||
self.requestHeaders[name] = $tw.utils.getPassword(value) || "";
|
||||
});
|
||||
this.basicAuthUsername = options.basicAuthUsername || (options.basicAuthUsernameFromStore && $tw.utils.getPassword(options.basicAuthUsernameFromStore)) || "";
|
||||
this.basicAuthPassword = options.basicAuthPassword || (options.basicAuthPasswordFromStore && $tw.utils.getPassword(options.basicAuthPasswordFromStore)) || "";
|
||||
if(this.basicAuthUsername && this.basicAuthPassword) {
|
||||
this.requestHeaders.Authorization = "Basic " + $tw.utils.base64Encode(this.basicAuthUsername + ":" + this.basicAuthPassword);
|
||||
}
|
||||
}
|
||||
|
||||
HttpClientRequest.prototype.send = function(callback) {
|
||||
@@ -292,7 +283,7 @@ exports.httpRequest = function(options) {
|
||||
// Set up the state change handler
|
||||
request.onreadystatechange = function() {
|
||||
if(this.readyState === 4) {
|
||||
if(this.status === 200 || this.status === 201 || this.status === 204) {
|
||||
if(this.status >= 200 && this.status < 300) {
|
||||
// Success!
|
||||
options.callback(null,this[returnProp],this);
|
||||
return;
|
||||
|
||||
@@ -316,11 +316,13 @@ Options include:
|
||||
pathFilters: optional array of filters to be used to generate the base path
|
||||
wiki: optional wiki for evaluating the pathFilters
|
||||
fileInfo: an existing fileInfo object to check against
|
||||
fileInfo.overwrite: if true, turns off filename clash numbers (defaults to false)
|
||||
*/
|
||||
exports.generateTiddlerFilepath = function(title,options) {
|
||||
var directory = options.directory || "",
|
||||
extension = options.extension || "",
|
||||
originalpath = (options.fileInfo && options.fileInfo.originalpath) ? options.fileInfo.originalpath : "",
|
||||
overwrite = options.fileInfo && options.fileInfo.overwrite || false,
|
||||
filepath;
|
||||
// Check if any of the pathFilters applies
|
||||
if(options.pathFilters && options.wiki) {
|
||||
@@ -381,19 +383,20 @@ exports.generateTiddlerFilepath = function(title,options) {
|
||||
filepath += char.charCodeAt(0).toString();
|
||||
});
|
||||
}
|
||||
// Add a uniquifier if the file already exists
|
||||
var fullPath, oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
|
||||
// Add a uniquifier if the file already exists (default)
|
||||
var fullPath = path.resolve(directory, filepath + extension);
|
||||
if (!overwrite) {
|
||||
var oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined,
|
||||
count = 0;
|
||||
do {
|
||||
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
||||
if(oldPath && oldPath == fullPath) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
} while(fs.existsSync(fullPath));
|
||||
do {
|
||||
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
|
||||
if(oldPath && oldPath == fullPath) break;
|
||||
count++;
|
||||
} while(fs.existsSync(fullPath));
|
||||
}
|
||||
// If the last write failed with an error, or if path does not start with:
|
||||
// the resolved options.directory, the resolved wikiPath directory, the wikiTiddlersPath directory,
|
||||
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to tiddler directory.
|
||||
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to options.directory.
|
||||
var writePath = $tw.hooks.invokeHook("th-make-tiddler-path",fullPath,fullPath),
|
||||
encode = (options.fileInfo || {writeError: false}).writeError == true;
|
||||
if(!encode) {
|
||||
|
||||
48
core/modules/utils/repository.js
Normal file
48
core/modules/utils/repository.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/repository.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Utilities for working with the TiddlyWiki repository file structure
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Get an object containing all the plugins as a hashmap by title of the JSON representation of the plugin
|
||||
*/
|
||||
exports.getAllPlugins = function() {
|
||||
var fs = require("fs"),
|
||||
path = require("path"),
|
||||
tiddlers = {};
|
||||
// Collect up the library plugins
|
||||
var collectPlugins = function(folder) {
|
||||
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var p=0; p<pluginFolders.length; p++) {
|
||||
if(!$tw.boot.excludeRegExp.test(pluginFolders[p])) {
|
||||
var pluginFields = $tw.loadPluginFolder(path.resolve(folder,"./" + pluginFolders[p]));
|
||||
if(pluginFields && pluginFields.title) {
|
||||
tiddlers[pluginFields.title] = pluginFields;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
collectPublisherPlugins = function(folder) {
|
||||
var publisherFolders = $tw.utils.getSubdirectories(folder) || [];
|
||||
for(var t=0; t<publisherFolders.length; t++) {
|
||||
if(!$tw.boot.excludeRegExp.test(publisherFolders[t])) {
|
||||
collectPlugins(path.resolve(folder,"./" + publisherFolders[t]));
|
||||
}
|
||||
}
|
||||
};
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.pluginsPath,$tw.config.pluginsEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.themesPath,$tw.config.themesEnvVar),collectPublisherPlugins);
|
||||
$tw.utils.each($tw.getLibraryItemSearchPaths($tw.config.languagesPath,$tw.config.languagesEnvVar),collectPlugins);
|
||||
return tiddlers;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -37,6 +37,7 @@ Compute the internal state of the widget
|
||||
DeleteFieldWidget.prototype.execute = function() {
|
||||
this.actionTiddler = this.getAttribute("$tiddler",this.getVariable("currentTiddler"));
|
||||
this.actionField = this.getAttribute("$field",null);
|
||||
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -69,11 +70,15 @@ DeleteFieldWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
$tw.utils.each(this.attributes,function(attribute,name) {
|
||||
if(name.charAt(0) !== "$" && name !== "title") {
|
||||
removeFields[name] = undefined;
|
||||
hasChanged = true;
|
||||
if(name in tiddler.fields) {
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if(hasChanged) {
|
||||
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,removeFields,this.wiki.getModificationFields()));
|
||||
var creationFields = this.actionTimestamp ? this.wiki.getCreationFields() : {};
|
||||
var modificationFields = this.actionTimestamp ? this.wiki.getModificationFields() : {};
|
||||
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,removeFields,modificationFields));
|
||||
}
|
||||
}
|
||||
return true; // Action was invoked
|
||||
|
||||
145
core/modules/widgets/data.js
Normal file
145
core/modules/widgets/data.js
Normal file
@@ -0,0 +1,145 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/data.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Widget to dynamically represent one or more tiddlers
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var DataWidget = function(parseTreeNode,options) {
|
||||
this.dataWidgetTag = parseTreeNode.type;
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
DataWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
DataWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
var jsonPayload = JSON.stringify(this.readDataTiddlerValues(),null,4);
|
||||
var textNode = this.document.createTextNode(jsonPayload);
|
||||
parent.insertBefore(textNode,nextSibling);
|
||||
this.domNodes.push(textNode);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
DataWidget.prototype.execute = function() {
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
/*
|
||||
Read the tiddler value(s) from a data widget – must be called after the .render() method
|
||||
*/
|
||||
DataWidget.prototype.readDataTiddlerValues = function() {
|
||||
var self = this;
|
||||
// Start with a blank object
|
||||
var item = Object.create(null);
|
||||
// Read any attributes not prefixed with $
|
||||
$tw.utils.each(this.attributes,function(value,name) {
|
||||
if(name.charAt(0) !== "$") {
|
||||
item[name] = value;
|
||||
}
|
||||
});
|
||||
item = new $tw.Tiddler(item);
|
||||
// Deal with $tiddler, $filter or $compound-tiddler attributes
|
||||
var tiddlers = [],title;
|
||||
if(this.hasAttribute("$tiddler")) {
|
||||
title = this.getAttribute("$tiddler");
|
||||
if(title) {
|
||||
var tiddler = this.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
tiddlers.push(tiddler);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.hasAttribute("$filter")) {
|
||||
var filter = this.getAttribute("$filter");
|
||||
if(filter) {
|
||||
var titles = this.wiki.filterTiddlers(filter);
|
||||
$tw.utils.each(titles,function(title) {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
tiddlers.push(tiddler);
|
||||
});
|
||||
}
|
||||
}
|
||||
if(this.hasAttribute("$compound-tiddler")) {
|
||||
title = this.getAttribute("$compound-tiddler");
|
||||
if(title) {
|
||||
tiddlers.push.apply(tiddlers,this.extractCompoundTiddler(title));
|
||||
}
|
||||
}
|
||||
// Convert the literal item to field strings
|
||||
item = item.getFieldStrings();
|
||||
if(tiddlers.length === 0) {
|
||||
if(Object.keys(item).length > 0 && !!item.title) {
|
||||
return [item];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
var results = [];
|
||||
$tw.utils.each(tiddlers,function(tiddler,index) {
|
||||
var fields = tiddler.getFieldStrings();
|
||||
results.push($tw.utils.extend({},fields,item));
|
||||
});
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Helper to extract tiddlers from text/vnd.tiddlywiki-multiple tiddlers
|
||||
*/
|
||||
DataWidget.prototype.extractCompoundTiddler = function(title) {
|
||||
var tiddler = this.wiki.getTiddler(title);
|
||||
if(tiddler && tiddler.fields.type === "text/vnd.tiddlywiki-multiple") {
|
||||
var text = tiddler.fields.text || "",
|
||||
rawTiddlers = text.split(/\r?\n\+\r?\n/),
|
||||
tiddlers = [];
|
||||
$tw.utils.each(rawTiddlers,function(rawTiddler) {
|
||||
var fields = Object.create(null),
|
||||
split = rawTiddler.split(/\r?\n\r?\n/mg);
|
||||
if(split.length >= 1) {
|
||||
fields = $tw.utils.parseFields(split[0],fields);
|
||||
}
|
||||
if(split.length >= 2) {
|
||||
fields.text = split.slice(1).join("\n\n");
|
||||
}
|
||||
tiddlers.push(new $tw.Tiddler(fields));
|
||||
});
|
||||
return tiddlers;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
DataWidget.prototype.refresh = function(changedTiddlers) {
|
||||
// It would be expensive to calculate whether the changedTiddlers impact the filter
|
||||
// identified by the $filter attribute so we just refresh ourselves unconditionally
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.data = DataWidget;
|
||||
|
||||
})();
|
||||
160
core/modules/widgets/testcase.js
Normal file
160
core/modules/widgets/testcase.js
Normal file
@@ -0,0 +1,160 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/testcase.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Widget to display a test case
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var TestCaseWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
TestCaseWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
TestCaseWidget.prototype.render = function(parent,nextSibling) {
|
||||
var self = this;
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Create container DOM node
|
||||
var domNode = this.document.createElement("div");
|
||||
this.domNodes.push(domNode);
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
// Render the children into a hidden DOM node
|
||||
var parser = {
|
||||
tree: [{
|
||||
type: "widget",
|
||||
attributes: {},
|
||||
orderedAttributes: [],
|
||||
children: this.parseTreeNode.children || []
|
||||
}]
|
||||
};
|
||||
this.contentRoot = this.wiki.makeWidget(parser,{
|
||||
document: $tw.fakeDocument,
|
||||
parentWidget: this
|
||||
});
|
||||
this.contentContainer = $tw.fakeDocument.createElement("div");
|
||||
this.contentRoot.render(this.contentContainer,null);
|
||||
// Create a wiki
|
||||
this.testcaseWiki = new $tw.Wiki();
|
||||
// Always load the core plugin
|
||||
var loadTiddler = function(title) {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
self.testcaseWiki.addTiddler(tiddler);
|
||||
}
|
||||
}
|
||||
loadTiddler("$:/core");
|
||||
loadTiddler("$:/plugins/tiddlywiki/codemirror");
|
||||
// Load tiddlers from child data widgets
|
||||
var tiddlers = [];
|
||||
this.findChildrenDataWidgets(this.contentRoot.children,"data",function(widget) {
|
||||
Array.prototype.push.apply(tiddlers,widget.readDataTiddlerValues());
|
||||
});
|
||||
var jsonPayload = JSON.stringify(tiddlers);
|
||||
this.testcaseWiki.addTiddlers(tiddlers);
|
||||
// Unpack plugin tiddlers
|
||||
this.testcaseWiki.readPluginInfo();
|
||||
this.testcaseWiki.registerPluginTiddlers("plugin");
|
||||
this.testcaseWiki.unpackPluginTiddlers();
|
||||
this.testcaseWiki.addIndexersToWiki();
|
||||
// Generate a `transclusion` variable that depends on the values of the payload tiddlers so that the template can easily make unique state tiddlers
|
||||
this.setVariable("transclusion",$tw.utils.hashString(jsonPayload));
|
||||
// Generate a `payloadTiddlers` variable that contains the payload in JSON format
|
||||
this.setVariable("payloadTiddlers",jsonPayload);
|
||||
// Render the test rendering if required
|
||||
if(this.testcaseTestOutput && this.testcaseTestExpectedResult) {
|
||||
var testcaseOutputContainer = $tw.fakeDocument.createElement("div");
|
||||
var testcaseOutputWidget = this.testcaseWiki.makeTranscludeWidget(this.testcaseTestOutput,{
|
||||
document: $tw.fakeDocument,
|
||||
parseAsInline: false,
|
||||
parentWidget: this,
|
||||
variables: {
|
||||
currentTiddler: this.testcaseTestOutput
|
||||
}
|
||||
});
|
||||
testcaseOutputWidget.render(testcaseOutputContainer);
|
||||
}
|
||||
// Clear changes queue
|
||||
this.testcaseWiki.clearTiddlerEventQueue();
|
||||
// Run the actions if provided
|
||||
if(this.testcaseWiki.tiddlerExists(this.testcaseTestActions)) {
|
||||
testcaseOutputWidget.invokeActionString(this.testcaseWiki.getTiddlerText(this.testcaseTestActions));
|
||||
testcaseOutputWidget.refresh(this.testcaseWiki.changedTiddlers,testcaseOutputContainer);
|
||||
}
|
||||
// Set up the test result variables
|
||||
var testResult = "",
|
||||
outputHTML = "",
|
||||
expectedHTML = "";
|
||||
if(this.testcaseTestOutput && this.testcaseTestExpectedResult) {
|
||||
outputHTML = testcaseOutputContainer.children[0].innerHTML;
|
||||
expectedHTML = this.testcaseWiki.getTiddlerText(this.testcaseTestExpectedResult);
|
||||
if(outputHTML === expectedHTML) {
|
||||
testResult = "pass";
|
||||
} else {
|
||||
testResult = "fail";
|
||||
}
|
||||
this.setVariable("outputHTML",outputHTML);
|
||||
this.setVariable("expectedHTML",expectedHTML);
|
||||
this.setVariable("testResult",testResult);
|
||||
this.setVariable("currentTiddler",this.testcaseTestOutput);
|
||||
}
|
||||
// Don't display anything if testHideIfPass is "yes" and the tests have passed
|
||||
if(this.testcaseHideIfPass === "yes" && testResult === "pass") {
|
||||
return;
|
||||
}
|
||||
// Render the page root template of the subwiki
|
||||
var rootWidget = this.testcaseWiki.makeTranscludeWidget(this.testcaseTemplate,{
|
||||
document: this.document,
|
||||
parseAsInline: false,
|
||||
parentWidget: this
|
||||
});
|
||||
rootWidget.render(domNode);
|
||||
// Trap changes in the wiki and refresh the rendering
|
||||
this.testcaseWiki.addEventListener("change",function(changes) {
|
||||
rootWidget.refresh(changes,domNode);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
TestCaseWidget.prototype.execute = function() {
|
||||
this.testcaseTemplate = this.getAttribute("template","$:/core/ui/testcases/DefaultTemplate");
|
||||
this.testcaseTestOutput = this.getAttribute("testOutput");
|
||||
this.testcaseTestActions = this.getAttribute("testActions");
|
||||
this.testcaseTestExpectedResult = this.getAttribute("testExpectedResult");
|
||||
this.testcaseHideIfPass = this.getAttribute("testHideIfPass");
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
TestCaseWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if($tw.utils.count(changedAttributes) > 0) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
return this.contentRoot.refresh(changedTiddlers);
|
||||
}
|
||||
};
|
||||
|
||||
exports["testcase"] = TestCaseWidget;
|
||||
|
||||
})();
|
||||
@@ -813,6 +813,21 @@ Widget.prototype.allowActionPropagation = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Find child <$data> widgets recursively. The tag name allows aliased versions of the widget to be found too
|
||||
*/
|
||||
Widget.prototype.findChildrenDataWidgets = function(children,tag,callback) {
|
||||
var self = this;
|
||||
$tw.utils.each(children,function(child) {
|
||||
if(child.dataWidgetTag === tag) {
|
||||
callback(child);
|
||||
}
|
||||
if(child.children) {
|
||||
self.findChildrenDataWidgets(child.children,tag,callback);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Evaluate a variable with parameters. This is a static convenience method that attempts to evaluate a variable as a function, returning an array of strings
|
||||
*/
|
||||
|
||||
@@ -95,6 +95,9 @@ table-footer-background: #a8a8a8
|
||||
table-header-background: #f0f0f0
|
||||
tag-background: #ec6
|
||||
tag-foreground: #ffffff
|
||||
testcase-accent-level-1: #84C5E6
|
||||
testcase-accent-level-2: #E3B740
|
||||
testcase-accent-level-3: #5FD564
|
||||
tiddler-background: <<colour background>>
|
||||
tiddler-border: <<colour background>>
|
||||
tiddler-controls-foreground-hover: #888888
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
"author": "JeremyRuston",
|
||||
"core-version": ">=5.0.0",
|
||||
"plugin-priority": "0",
|
||||
"list": "readme"
|
||||
"list": "readme",
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ title: $:/core/save/all-external-js
|
||||
\whitespace trim
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
|
||||
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
|
||||
|
||||
@@ -3,7 +3,7 @@ title: $:/core/save/offline-external-js
|
||||
\whitespace trim
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define defaultCoreURL() tiddlywikicore-$(version)$.js
|
||||
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
||||
|
||||
@@ -2,6 +2,6 @@ title: $:/core/save/all
|
||||
|
||||
\import [subfilter{$:/core/config/GlobalImportFilter}]
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
{{$:/core/templates/tiddlywiki5.html}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/core/save/empty
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
\end
|
||||
{{$:/core/templates/tiddlywiki5.html}}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
title: $:/core/save/lazy-all
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] [is[tiddler]type[application/javascript]] +[sort[title]]
|
||||
[is[system]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] [is[tiddler]type[application/javascript]] +[sort[title]]
|
||||
\end
|
||||
\define skinnySaveTiddlerFilter()
|
||||
[!is[system]] -[type[application/javascript]]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
title: $:/core/save/lazy-images
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]]
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[[$:/HistoryList]] -[[$:/boot/boot.css]] -[is[system]type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[!is[system]is[image]] +[sort[title]]
|
||||
\end
|
||||
\define skinnySaveTiddlerFilter()
|
||||
[!is[system]is[image]]
|
||||
|
||||
@@ -45,7 +45,17 @@ $:/config/Plugins/Disabled/$(currentTiddler)$
|
||||
<$view field="title"/>
|
||||
</h2>
|
||||
<h2>
|
||||
<div><em><$view field="version"/></em></div>
|
||||
<div>
|
||||
<%if [<currentTiddler>get[stability]match[STABILITY_0_DEPRECATED]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-deprecated">DEPRECATED</span>
|
||||
<%elseif [<currentTiddler>get[stability]match[STABILITY_1_EXPERIMENTAL]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-experimental">EXPERIMENTAL</span>
|
||||
<%elseif [<currentTiddler>get[stability]match[STABILITY_2_STABLE]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-stable">STABLE</span>
|
||||
<%elseif [<currentTiddler>get[stability]match[STABILITY_3_LEGACY]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-legacy">LEGACY</span>
|
||||
<%endif%>
|
||||
<em><$view field="version"/></em></div>
|
||||
</h2>
|
||||
</div>
|
||||
\end
|
||||
|
||||
@@ -70,9 +70,20 @@ $:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-description">
|
||||
<h1><strong><$text text={{{ [<assetInfo>get[name]] ~[<assetInfo>get[original-title]split[/]last[1]] }}}/></strong>:
|
||||
 
|
||||
<$view tiddler=<<assetInfo>> field="description"/></h1>
|
||||
<$view tiddler=<<assetInfo>> field="description"/>
|
||||
</h1>
|
||||
<h2><$view tiddler=<<assetInfo>> field="original-title"/></h2>
|
||||
<div><em><$view tiddler=<<assetInfo>> field="version"/></em></div>
|
||||
<div>
|
||||
<%if [<assetInfo>get[stability]match[STABILITY_0_DEPRECATED]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-deprecated">DEPRECATED</span>
|
||||
<%elseif [<assetInfo>get[stability]match[STABILITY_1_EXPERIMENTAL]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-experimental">EXPERIMENTAL</span>
|
||||
<%elseif [<assetInfo>get[stability]match[STABILITY_2_STABLE]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-stable">STABLE</span>
|
||||
<%elseif [<assetInfo>get[stability]match[STABILITY_3_LEGACY]] %>
|
||||
<span class="tc-plugin-info-stability tc-plugin-info-stability-legacy">LEGACY</span>
|
||||
<%endif%>
|
||||
<em><$view tiddler=<<assetInfo>> field="version"/></em></div>
|
||||
<$list filter="[<assetInfo>get[original-title]get[version]]" variable="installedVersion"><div><em>{{$:/language/ControlPanel/Plugins/AlreadyInstalled/Hint}}</em></div></$list>
|
||||
</div>
|
||||
<div class="tc-plugin-info-chunk tc-plugin-info-buttons">
|
||||
|
||||
10
core/ui/ControlPanel/TestCases.tid
Normal file
10
core/ui/ControlPanel/TestCases.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/core/ui/ControlPanel/TestCases
|
||||
tags: $:/tags/ControlPanel/Advanced
|
||||
caption: {{$:/language/ControlPanel/TestCases/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
{{$:/language/ControlPanel/TestCases/Hint}}
|
||||
|
||||
<div class="tc-control-panel">
|
||||
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/TestCases]!has[draft.of]]" default="$:/core/ui/ControlPanel/TestCases/All"/>
|
||||
</div>
|
||||
24
core/ui/ControlPanel/TestCasesAll.tid
Normal file
24
core/ui/ControlPanel/TestCasesAll.tid
Normal file
@@ -0,0 +1,24 @@
|
||||
title: $:/core/ui/ControlPanel/TestCases/All
|
||||
tags: $:/tags/ControlPanel/TestCases
|
||||
caption: {{$:/language/ControlPanel/TestCases/All/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/
|
||||
<<lingo TestCases/All/Hint>>
|
||||
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/wiki-test-spec]type[text/vnd.tiddlywiki-multiple]] [all[tiddlers+shadows]tag[$:/tags/wiki-test-spec-failing]type[text/vnd.tiddlywiki-multiple]]">
|
||||
|
||||
<h2>
|
||||
|
||||
<$link>
|
||||
|
||||
<$text text=<<currentTiddler>>/>
|
||||
|
||||
</$link>
|
||||
|
||||
</h2>
|
||||
|
||||
<$transclude
|
||||
$tiddler="$:/core/ui/TestCaseTemplate"
|
||||
/>
|
||||
|
||||
</$list>
|
||||
15
core/ui/ControlPanel/TestCasesFailed.tid
Normal file
15
core/ui/ControlPanel/TestCasesFailed.tid
Normal file
@@ -0,0 +1,15 @@
|
||||
title: $:/core/ui/ControlPanel/TestCases/Failed
|
||||
tags: $:/tags/ControlPanel/TestCases
|
||||
caption: {{$:/language/ControlPanel/TestCases/Failed/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/
|
||||
<<lingo TestCases/Failed/Hint>>
|
||||
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/wiki-test-spec]type[text/vnd.tiddlywiki-multiple]] [all[tiddlers+shadows]tag[$:/tags/wiki-test-spec-failing]type[text/vnd.tiddlywiki-multiple]]">
|
||||
|
||||
<$transclude
|
||||
$tiddler="$:/core/ui/TestCaseTemplate"
|
||||
hideIfPass="yes"
|
||||
/>
|
||||
|
||||
</$list>
|
||||
5
core/ui/KeyboardShortcuts/refresh.tid
Normal file
5
core/ui/KeyboardShortcuts/refresh.tid
Normal file
@@ -0,0 +1,5 @@
|
||||
title: $:/core/ui/KeyboardShortcuts/refresh
|
||||
tags: $:/tags/KeyboardShortcut
|
||||
key: ((refresh))
|
||||
|
||||
<$action-sendmessage $message="tm-browser-refresh"/>
|
||||
@@ -1,16 +1,14 @@
|
||||
title: $:/core/ui/PageTemplate/pagecontrols
|
||||
|
||||
\whitespace trim
|
||||
\define config-title() $:/config/PageControlButtons/Visibility/$(listItem)$
|
||||
\function config-title() [[$:/config/PageControlButtons/Visibility/$(listItem)$]substitute[]]
|
||||
|
||||
<div class="tc-page-controls">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]" variable="listItem">
|
||||
<$set name="hidden" value=<<config-title>>>
|
||||
<$list filter="[<hidden>!text[hide]]" storyview="pop" variable="ignore">
|
||||
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
|
||||
<$transclude tiddler=<<listItem>> mode="inline"/>
|
||||
</$set>
|
||||
</$list>
|
||||
</$set>
|
||||
<$list filter="[<config-title>!text[hide]]" storyview="pop" variable="ignore">
|
||||
<$let tv-config-toolbar-class={{{ [enlist<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]] +[join[ ]] }}}>
|
||||
<$transclude $tiddler=<<listItem>> $mode="inline"/>
|
||||
</$let>
|
||||
</$list>
|
||||
</$list>
|
||||
</div>
|
||||
</div>
|
||||
18
core/ui/TestCaseTemplate.tid
Normal file
18
core/ui/TestCaseTemplate.tid
Normal file
@@ -0,0 +1,18 @@
|
||||
title: $:/core/ui/TestCaseTemplate
|
||||
|
||||
\parameters (hideIfPass:"no")
|
||||
\whitespace trim
|
||||
<$let
|
||||
linkTarget="yes"
|
||||
displayFormat={{!!display-format}}
|
||||
>
|
||||
<$testcase
|
||||
testOutput="Output"
|
||||
testExpectedResult="ExpectedResult"
|
||||
testActions="Actions"
|
||||
testHideIfPass=<<hideIfPass>>
|
||||
>
|
||||
<$data $compound-tiddler=<<currentTiddler>>/>
|
||||
<$data title="Description" text={{!!description}}/>
|
||||
</$testcase>
|
||||
</$let>
|
||||
64
core/ui/TestCases/DefaultTemplate.tid
Normal file
64
core/ui/TestCases/DefaultTemplate.tid
Normal file
@@ -0,0 +1,64 @@
|
||||
title: $:/core/ui/testcases/DefaultTemplate
|
||||
|
||||
\whitespace trim
|
||||
\procedure linkcatcherActions()
|
||||
<%if [<navigateTo>has[title]] %>
|
||||
<$qualify title=<<state>> name="qualifiedState">
|
||||
<$action-setfield $tiddler=<<qualifiedState>> text=<<navigateTo>>/>
|
||||
</$qualify>
|
||||
<%endif%>
|
||||
\end
|
||||
|
||||
<$let
|
||||
state={{{ [<qualify "$:/state/testcase">] }}}
|
||||
>
|
||||
<div class="tc-test-case-wrapper">
|
||||
<div class="tc-test-case-header">
|
||||
<h2>
|
||||
<$genesis $type={{{ [<linkTarget>!match[]then[$link]else[div]] }}}>
|
||||
<%if [<testResult>!match[]] %>
|
||||
<span class={{{ tc-test-case-result-icon [<testResult>!match[fail]then[tc-test-case-result-icon-pass]] [<testResult>match[fail]then[tc-test-case-result-icon-fail]] +[join[ ]] }}}>
|
||||
<%if [<testResult>!match[fail]] %>
|
||||
{{$:/core/images/done-button}}
|
||||
<%else%>
|
||||
{{$:/core/images/close-button}}
|
||||
<%endif%>
|
||||
</span>
|
||||
<%endif%>
|
||||
<$view tiddler="Description" mode="inline"/>
|
||||
</$genesis>
|
||||
</h2>
|
||||
</div>
|
||||
<%if [[Narrative]is[tiddler]] %>
|
||||
<div class="tc-test-case-narrative">
|
||||
<$transclude $tiddler="Narrative" mode="block"/>
|
||||
</div>
|
||||
<%endif%>
|
||||
<%if [<testResult>match[fail]] %>
|
||||
<div class="tc-test-case-result-fail">
|
||||
<div class="tc-test-case-result-fail-header">
|
||||
TEST FAILED
|
||||
</div>
|
||||
<div class="tc-test-case-result-fail-body">
|
||||
<$diff-text source=<<expectedHTML>> dest=<<outputHTML>>/>
|
||||
</div>
|
||||
</div>
|
||||
<%endif%>
|
||||
<div class="tc-test-case-panes">
|
||||
<div class="tc-test-case-source">
|
||||
<$macrocall $name="tabs" tabsList="[all[tiddlers]sort[]] -[prefix<state>] -Description -Narrative -ExpectedResult -Output Output +[putfirst[]] -[has[plugin-type]]" state=<<state>> default="Output" template="$:/core/ui/testcases/DefaultTemplate/SourceTabs"/>
|
||||
</div>
|
||||
<div class="tc-test-case-divider">
|
||||
</div>
|
||||
<div class="tc-test-case-output">
|
||||
<%if [<displayFormat>!match[]else[wikitext]match[plaintext]] %>
|
||||
<pre><$view tiddler="Output" format="plainwikified" mode="block"/></pre>
|
||||
<%else%>
|
||||
<$linkcatcher actions=<<linkcatcherActions>>>
|
||||
<$transclude $tiddler="Output" $mode="block"/>
|
||||
</$linkcatcher>
|
||||
<%endif%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</$let>
|
||||
24
core/ui/TestCases/DefaultTemplateSourceTabs.tid
Normal file
24
core/ui/TestCases/DefaultTemplateSourceTabs.tid
Normal file
@@ -0,0 +1,24 @@
|
||||
title: $:/core/ui/testcases/DefaultTemplate/SourceTabs
|
||||
|
||||
\whitespace trim
|
||||
\procedure body()
|
||||
<$list filter="[<currentTab>fields[]] -text +[limit[1]]" variable="ignore">
|
||||
<table class="tc-field-table">
|
||||
<tbody>
|
||||
<$list filter="[<currentTab>fields[]sort[]] -text -title title +[putfirst[]]" variable="fieldName">
|
||||
<tr>
|
||||
<td>
|
||||
<$text text=<<fieldName>>/>
|
||||
</td>
|
||||
<td>
|
||||
<$view tiddler=<<currentTab>> field=<<fieldName>>/>
|
||||
</td>
|
||||
</tr>
|
||||
</$list>
|
||||
</tbody>
|
||||
</table>
|
||||
</$list>
|
||||
<$edit class="tc-edit-texteditor" tiddler=<<currentTab>>/>
|
||||
\end
|
||||
|
||||
<$transclude $variable="body" $mode="inline"/>
|
||||
4
core/ui/TestCases/RawJSONTemplate.tid
Normal file
4
core/ui/TestCases/RawJSONTemplate.tid
Normal file
@@ -0,0 +1,4 @@
|
||||
title: $:/core/ui/testcases/RawJSONTemplate
|
||||
|
||||
\whitespace trim
|
||||
<$text text=<<payloadTiddlers>>/>
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/library/v5.3.3/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}}
|
||||
tags: $:/tags/PluginLibrary
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
url: https://tiddlywiki5-git-plugin-stability-badges-jermolenes-projects.vercel.app/library/v5.3.3/index.html
|
||||
|
||||
{{$:/language/OfficialPluginLibrary/Hint}}
|
||||
Plugin library for https://tiddlywiki5-git-plugin-stability-badges-jermolenes-projects.vercel.app
|
||||
@@ -35,6 +35,7 @@ new-tiddler: {{$:/language/Buttons/NewTiddler/Hint}}
|
||||
picture: {{$:/language/Buttons/Picture/Hint}}
|
||||
preview: {{$:/language/Buttons/Preview/Hint}}
|
||||
quote: {{$:/language/Buttons/Quote/Hint}}
|
||||
refresh: {{$:/language/Buttons/Refresh/Hint}}
|
||||
save-tiddler: {{$:/language/Buttons/Save/Hint}}
|
||||
save-wiki: {{$:/language/Buttons/SaveWiki/Hint}}
|
||||
sidebar-search: {{$:/language/Buttons/SidebarSearch/Hint}}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
title: $:/config/ViewTemplateBodyFilters/
|
||||
tags: $:/tags/ViewTemplateBodyFilter
|
||||
|
||||
testcase: [tag[$:/tags/wiki-test-spec]type[text/vnd.tiddlywiki-multiple]then[$:/core/ui/TestCaseTemplate]] [tag[$:/tags/wiki-test-spec-failing]type[text/vnd.tiddlywiki-multiple]then[$:/core/ui/TestCaseTemplate]]
|
||||
stylesheet: [tag[$:/tags/Stylesheet]then[$:/core/ui/ViewTemplate/body/rendered-plain-text]]
|
||||
core-ui-tags: [tag[$:/tags/PageTemplate]] [tag[$:/tags/EditTemplate]] [tag[$:/tags/ViewTemplate]] [tag[$:/tags/KeyboardShortcut]] [tag[$:/tags/ImportPreview]] [tag[$:/tags/EditPreview]][tag[$:/tags/EditorToolbar]] [tag[$:/tags/Actions]] :then[[$:/core/ui/ViewTemplate/body/code]]
|
||||
system: [prefix[$:/boot/]] [prefix[$:/config/]] [prefix[$:/core/macros]] [prefix[$:/core/save/]] [prefix[$:/core/templates/]] [prefix[$:/info/]] [prefix[$:/language/]] [prefix[$:/languages/]] [prefix[$:/snippets/]] [prefix[$:/state/]] [prefix[$:/status/]] [prefix[$:/info/]] [prefix[$:/temp/]] +[!is[image]limit[1]then[$:/core/ui/ViewTemplate/body/code]]
|
||||
|
||||
@@ -6,4 +6,5 @@ underline: meta-U
|
||||
new-image: ctrl-I
|
||||
new-journal: ctrl-J
|
||||
new-tiddler: ctrl-N
|
||||
refresh: meta-R
|
||||
save-wiki: meta-S
|
||||
|
||||
@@ -6,3 +6,4 @@ underline: ctrl-U
|
||||
new-image: alt-I
|
||||
new-journal: alt-J
|
||||
new-tiddler: alt-N
|
||||
refresh: ctrl-R
|
||||
|
||||
@@ -1,167 +1,182 @@
|
||||
title: $:/core/macros/tag-picker
|
||||
tags: $:/tags/Macro $:/tags/Global
|
||||
first-search-filter: [tags[]!is[system]search:title<userInput>sort[]]
|
||||
second-search-filter: [tags[]is[system]search:title<userInput>sort[]]
|
||||
tags: tags: $:/tags/Macro $:/tags/Global
|
||||
first-search-filter: [subfilter<tagListFilter>!is[system]search:title<userInput>sort[]]
|
||||
second-search-filter: [subfilter<tagListFilter>is[system]search:title<userInput>sort[]]
|
||||
|
||||
\procedure get-tagpicker-focus-selector()
|
||||
\function currentTiddlerCSSEscaped() [<saveTiddler>escapecss[]]
|
||||
[data-tiddler-title=`$(currentTiddlerCSSEscaped)$`] .tc-add-tag-name input
|
||||
<!-- first-search-filter and second-search-filter fields are not used here in the code, but they are defined as parameters for keyboard-driven-input macro -->
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- tf.tagpicker-dropdown-id is needed if several tap-pickers are shown in one tiddler -->
|
||||
\function tf.tagpicker-dropdown-id()
|
||||
[<qualify $:/state/popup/tags-auto-complete>]
|
||||
[[$(saveTiddler)$-[$(tagField)$-$(tagListFilter)$]substitute[]sha256[]] +[join[/]]
|
||||
\end
|
||||
|
||||
\procedure delete-tag-state-tiddlers() <$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
|
||||
\function tf.tagpicker-dropdown-class() [<tf.tagpicker-dropdown-id>sha256[]addprefix[tc-]]
|
||||
\function tf.get-tagpicker-focus-selector() [<tf.tagpicker-dropdown-class>addprefix[.]] .tc-popup-handle +[join[ ]]
|
||||
|
||||
<!-- clean up temporary tiddlers, so the next "pick" starts with a clean input -->
|
||||
<!-- This could probably be optimized / removed if we would use different temp-tiddlers
|
||||
(future improvement because keeping track is comlex for humans)
|
||||
-->
|
||||
\procedure delete-tag-state-tiddlers()
|
||||
<$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
|
||||
\end
|
||||
|
||||
<!-- trigger __toggle tag__ by keyboard -->
|
||||
\procedure add-tag-actions()
|
||||
\whitespace trim
|
||||
<$let tag=<<tag>>>
|
||||
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter='+[toggle<tag>trim[]]'/>
|
||||
<$list
|
||||
filter="[<tag>] :intersection[<saveTiddler>get<tagField>enlist-input[]]"
|
||||
variable="ignore"
|
||||
emptyMessage="<<actions>>"
|
||||
/>
|
||||
</$let>
|
||||
<<delete-tag-state-tiddlers>>
|
||||
<$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
|
||||
\end
|
||||
|
||||
\procedure clear-tags-actions-inner()
|
||||
\whitespace trim
|
||||
<$list
|
||||
filter="[<storeTitle>has[text]] ~[<newTagNameTiddler>has[text]]"
|
||||
variable="ignore"
|
||||
emptyMessage="<<cancel-delete-tiddler-actions 'cancel'>>"
|
||||
>
|
||||
<$let tag=<<_tf.getTag>> >
|
||||
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter='+[toggle<tag>trim[]]'/>
|
||||
<% if [<tag>] :intersection[<saveTiddler>get<tagField>enlist-input[]] %>
|
||||
<!-- tag has been removed - do nothing -->
|
||||
<% else %>
|
||||
<<actions>>
|
||||
<% endif %>
|
||||
<<delete-tag-state-tiddlers>>
|
||||
</$list>
|
||||
<$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
|
||||
</$let>
|
||||
\end
|
||||
<!-- <$action-log /> -->
|
||||
|
||||
<!-- ESC key removes the text from the input
|
||||
The second ESC tries to close the "draft tiddler"
|
||||
-->
|
||||
\procedure clear-tags-actions-inner()
|
||||
<% if [<storeTitle>has[text]] ~[<newTagNameTiddler>has[text]] %>
|
||||
<<delete-tag-state-tiddlers>>
|
||||
<% else %>
|
||||
<<cancel-delete-tiddler-actions "cancel">>
|
||||
<% endif %>
|
||||
\end
|
||||
|
||||
<!-- triggered by keyboard only -->
|
||||
\procedure clear-tags-actions()
|
||||
\whitespace trim
|
||||
<$let userInput=<<userInput>>>
|
||||
<$list
|
||||
filter="[<newTagNameTiddler>get[text]!match<userInput>]"
|
||||
emptyMessage="<<clear-tags-actions-inner>>"
|
||||
>
|
||||
<$let userInput=<<_tf.getUserInput>> >
|
||||
<!-- this list __cannot__ be transformed to conditional IF. The list variable is used! -->
|
||||
<$list filter="[<newTagNameTiddler>get[text]!match<userInput>]" >
|
||||
<$list-empty>
|
||||
<<clear-tags-actions-inner>>
|
||||
</$list-empty>
|
||||
<$action-setfield $tiddler=<<newTagNameTiddler>> text=<<userInput>>/>
|
||||
<$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
|
||||
</$list>
|
||||
</$let>
|
||||
\end
|
||||
|
||||
<!-- similar to add-tag-actions __but__ add-only -->
|
||||
\procedure add-button-actions()
|
||||
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="[<tag>trim[]]"/>
|
||||
<<actions>>
|
||||
<<delete-tag-state-tiddlers>>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=<<get-tagpicker-focus-selector>>/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=<<tf.get-tagpicker-focus-selector>>/>
|
||||
\end
|
||||
<!-- <$action-log /> -->
|
||||
|
||||
\procedure list-tags(filter, suffix)
|
||||
\whitespace trim
|
||||
<$list
|
||||
filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]"
|
||||
emptyMessage="<div class='tc-search-results'>{{$:/language/Search/Search/TooShort}}</div>" variable="listItem"
|
||||
>
|
||||
<$list filter=<<filter>> variable="tag">
|
||||
<$let
|
||||
button-classes=`tc-btn-invisible ${ [<tag>addsuffix<suffix>] -[<tagSelectionState>get[text]] :then[[]] ~tc-tag-button-selected }$`
|
||||
currentTiddler=<<tag>>
|
||||
>
|
||||
{{||$:/core/ui/TagPickerTagTemplate}}
|
||||
</$let>
|
||||
<!-- create dropdown list -->
|
||||
\procedure tag-picker-listTags(filter, suffix)
|
||||
<$let userInput=<<_tf.getUserInput>> >
|
||||
<$list filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]"
|
||||
emptyMessage="<div class='tc-search-results'>{{$:/language/Search/Search/TooShort}}</div>" variable="listItem"
|
||||
>
|
||||
<$list filter=<<filter>> variable="tag">
|
||||
<!-- The buttonClasses filter is used to define tc-tag-button-selected state -->
|
||||
<!-- tf.get-tagpicker-focus-selector has to be resolved for $:/core/ui/TagPickerTagTemplate,
|
||||
othwerwise qualify in tf.tagpicker-dropdown-id causes problems -->
|
||||
<$let currentTiddler=<<tag>>
|
||||
button-classes=`tc-btn-invisible ${[<tag>addsuffix<suffix>] -[<tagSelectionState>get[text]] :then[[]] ~tc-tag-button-selected }$`
|
||||
get-tagpicker-focus-selector=`${[<tf.get-tagpicker-focus-selector>]}$`
|
||||
>
|
||||
{{||$:/core/ui/TagPickerTagTemplate}}
|
||||
</$let>
|
||||
</$list>
|
||||
</$list>
|
||||
</$list>
|
||||
</$let>
|
||||
\end
|
||||
|
||||
<!-- tag-picker-inner is the main function -->
|
||||
\procedure tag-picker-inner()
|
||||
\whitespace trim
|
||||
<div class={{{ [[tc-edit-add-tag]] [<tf.tagpicker-dropdown-class>] +[join[ ]] }}}>
|
||||
<div class="tc-edit-add-tag-ui">
|
||||
<span class="tc-add-tag-name tc-small-gap-right">
|
||||
<$macrocall $name="keyboard-driven-input"
|
||||
tiddler=<<newTagNameTiddler>>
|
||||
storeTitle=<<storeTitle>>
|
||||
refreshTitle=<<refreshTitle>>
|
||||
selectionStateTitle=<<tagSelectionState>>
|
||||
inputAcceptActions=<<add-tag-actions>>
|
||||
inputCancelActions=<<clear-tags-actions>>
|
||||
tag="input"
|
||||
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
|
||||
focusPopup=<<tf.tagpicker-dropdown-id>>
|
||||
class="tc-edit-texteditor tc-popup-handle"
|
||||
tabindex=<<tabIndex>>
|
||||
focus={{{ [{$:/config/AutoFocus}match[tags]then[true]] ~[[false]] }}}
|
||||
filterMinLength={{$:/config/Tags/MinLength}}
|
||||
cancelPopups=<<cancelPopups>>
|
||||
configTiddlerFilter="[[$:/core/macros/tag-picker]]"
|
||||
/>
|
||||
</span>
|
||||
<$button popup=<<tf.tagpicker-dropdown-id>> class="tc-btn-invisible tc-btn-dropdown"
|
||||
tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}
|
||||
>
|
||||
{{$:/core/images/down-arrow}}
|
||||
</$button>
|
||||
<% if [<storeTitle>has[text]] %>
|
||||
<$button actions=<<delete-tag-state-tiddlers>> class="tc-btn-invisible tc-small-gap tc-btn-dropdown"
|
||||
tooltip={{$:/language/EditTemplate/Tags/ClearInput/Hint}} aria-label={{$:/language/EditTemplate/Tags/ClearInput/Caption}}
|
||||
>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
<% endif %>
|
||||
<span class="tc-add-tag-button tc-small-gap-left">
|
||||
<$let tag=<<_tf.getTag>>>
|
||||
<$button set=<<newTagNameTiddler>> actions=<<add-button-actions>> >
|
||||
{{$:/language/EditTemplate/Tags/Add/Button}}
|
||||
</$button>
|
||||
</$let>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tc-block-dropdown-wrapper">
|
||||
<% if [<tf.tagpicker-dropdown-id>has[text]] %>
|
||||
<div class="tc-block-dropdown tc-block-tags-dropdown">
|
||||
<$macrocall $name="tag-picker-listTags" filter=<<nonSystemTagsFilter>> suffix="-primaryList" />
|
||||
<hr>
|
||||
<$macrocall $name="tag-picker-listTags" filter=<<systemTagsFilter>> suffix="-secondaryList" />
|
||||
</div>
|
||||
<% endif %>
|
||||
</div>
|
||||
</div>
|
||||
\end
|
||||
|
||||
<!-- prepare all variables for tag-picker keyboard handling -->
|
||||
\procedure tag-picker(actions, tagField:"tags", tiddler, tagListFilter:"[tags[]]")
|
||||
|
||||
\function _tf.getUserInput() [<storeTitle>get[text]]
|
||||
\function _tf.getTag() [<newTagNameTiddler>get[text]]
|
||||
|
||||
<!-- keep those variables because they may "blead" into macros using old syntax -->
|
||||
<$let
|
||||
newTagNameInputTiddlerQualified=<<qualify "$:/temp/NewTagName/input">>
|
||||
newTagNameSelectionTiddlerQualified=<<qualify "$:/temp/NewTagName/selected-item">>
|
||||
fallbackTarget={{{ [<palette>getindex[tag-background]] }}}
|
||||
palette={{$:/palette}}
|
||||
colourA={{{ [<palette>getindex[foreground]] }}}
|
||||
colourB={{{ [<palette>getindex[background]] }}}
|
||||
fallbackTarget={{{ [<palette>getindex[tag-background]] }}}
|
||||
|
||||
storeTitle={{{ [<newTagNameInputTiddler>!match[]] ~[<newTagNameInputTiddlerQualified>] }}}
|
||||
saveTiddler={{{ [<tiddler>is[blank]then<currentTiddler>else<tiddler>] }}}
|
||||
|
||||
newTagNameTiddler={{{ [[$:/temp/NewTagName]] [<tagField>!match[tags]] +[join[/]] [<qualify>] +[join[]] }}}
|
||||
storeTitle={{{ [[$:/temp/NewTagName/input]] [<tagField>!match[tags]] +[join[/]] [<qualify>] +[join[]] }}}
|
||||
|
||||
newTagNameSelectionTiddlerQualified=<<qualify "$:/temp/NewTagName/selected-item">>
|
||||
tagSelectionState={{{ [<newTagNameSelectionTiddler>!match[]] ~[<newTagNameSelectionTiddlerQualified>] }}}
|
||||
tagAutoComplete=<<qualify "$:/state/popup/tags-auto-complete">>
|
||||
|
||||
refreshTitle=<<qualify "$:/temp/NewTagName/refresh">>
|
||||
nonSystemTagsFilter="[tags[]!is[system]search:title<userInput>sort[]]"
|
||||
systemTagsFilter="[tags[]is[system]search:title<userInput>sort[]]"
|
||||
>
|
||||
<div class="tc-edit-add-tag">
|
||||
<div>
|
||||
<span class="tc-add-tag-name tc-small-gap-right">
|
||||
<$transclude
|
||||
$variable="keyboard-driven-input"
|
||||
tiddler=<<newTagNameTiddler>>
|
||||
storeTitle=<<storeTitle>>
|
||||
refreshTitle=<<refreshTitle>>
|
||||
selectionStateTitle=<<tagSelectionState>>
|
||||
inputAcceptActions=<<add-tag-actions>>
|
||||
inputCancelActions=<<clear-tags-actions>>
|
||||
tag="input"
|
||||
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
|
||||
focusPopup=<<tagAutoComplete>>
|
||||
class="tc-edit-texteditor tc-popup-handle"
|
||||
tabindex=<<tabIndex>>
|
||||
focus={{{ [{$:/config/AutoFocus}match[tags]then[true]] ~[[false]] }}}
|
||||
filterMinLength={{$:/config/Tags/MinLength}}
|
||||
cancelPopups=<<cancelPopups>>
|
||||
configTiddlerFilter="[[$:/core/macros/tag-picker]]"
|
||||
/>
|
||||
</span>
|
||||
<$button popup=<<tagAutoComplete>>
|
||||
class="tc-btn-invisible tc-btn-dropdown"
|
||||
tooltip={{$:/language/EditTemplate/Tags/Dropdown/Hint}}
|
||||
aria-label={{$:/language/EditTemplate/Tags/Dropdown/Caption}}
|
||||
>
|
||||
{{$:/core/images/down-arrow}}
|
||||
</$button>
|
||||
<$reveal state=<<storeTitle>> type="nomatch" text="">
|
||||
<$button actions=<<delete-tag-state-tiddlers>>
|
||||
class="tc-btn-invisible tc-small-gap tc-btn-dropdown"
|
||||
tooltip={{$:/language/EditTemplate/Tags/ClearInput/Hint}}
|
||||
aria-label={{$:/language/EditTemplate/Tags/ClearInput/Caption}}
|
||||
>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<span class="tc-add-tag-button tc-small-gap-left">
|
||||
<$let tag=<<tag>>>
|
||||
<$button set=<<newTagNameTiddler>> setTo=""
|
||||
actions=<<add-button-actions>>
|
||||
>
|
||||
{{$:/language/EditTemplate/Tags/Add/Button}}
|
||||
</$button>
|
||||
</$let>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tc-block-dropdown-wrapper">
|
||||
<$reveal state=<<tagAutoComplete>> type="nomatch" text="">
|
||||
<div class="tc-block-dropdown tc-block-tags-dropdown">
|
||||
<$let userInput=<<userInput>>>
|
||||
<$transclude $variable="list-tags" filter=<<nonSystemTagsFilter>> suffix="-primaryList" />
|
||||
<hr>
|
||||
<$transclude $variable="list-tags" filter=<<systemTagsFilter>> suffix="-secondaryList" />
|
||||
</$let>
|
||||
</div>
|
||||
</$reveal>
|
||||
</div>
|
||||
</div>
|
||||
</$let>
|
||||
\end
|
||||
refreshTitle=<<qualify "$:/temp/NewTagName/refresh">>
|
||||
|
||||
\procedure tag-picker(actions, tagField:"tags")
|
||||
\function userInput() [<storeTitle>get[text]]
|
||||
\function tag() [<newTagNameTiddler>get[text]]
|
||||
\whitespace trim
|
||||
<$let
|
||||
saveTiddler=<<currentTiddler>>
|
||||
palette={{$:/palette}}
|
||||
qualified=<<qualify "$:/temp/NewTagName">>
|
||||
newTagNameTiddler={{{ [<newTagNameTiddler>!match[]] ~[<qualified>] }}}
|
||||
nonSystemTagsFilter="[subfilter<tagListFilter>!is[system]search:title<userInput>sort[]]"
|
||||
systemTagsFilter="[subfilter<tagListFilter>is[system]search:title<userInput>sort[]]"
|
||||
|
||||
cancelPopups="yes"
|
||||
>
|
||||
<$transclude $variable="tag-picker-inner" />
|
||||
<$macrocall $name="tag-picker-inner"/>
|
||||
</$let>
|
||||
\end
|
||||
\end
|
||||
@@ -21,7 +21,9 @@ color:$(foregroundColor)$;
|
||||
>
|
||||
<<__actions__>>
|
||||
<$transclude tiddler=<<__icon__>>/>
|
||||
<$view tiddler=<<__tag__>> field="title" format="text" />
|
||||
<span class={{{ [<__tag__>is[missing]then[tc-tag-missing]else[tc-tag-exists]] }}}>
|
||||
<$view tiddler=<<__tag__>> field="title" format="text" />
|
||||
</span>
|
||||
</$element-tag$>
|
||||
</$let>
|
||||
\end
|
||||
|
||||
10
core/wiki/macros/testcase.tid
Normal file
10
core/wiki/macros/testcase.tid
Normal file
@@ -0,0 +1,10 @@
|
||||
title: $:/core/macros/testcase
|
||||
tags: $:/tags/Macro $:/tags/Global
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\procedure testcase(tiddler)
|
||||
<$tiddler tiddler=<<tiddler>>>
|
||||
<$transclude $tiddler="$:/core/ui/TestCaseTemplate">
|
||||
</$tiddler>
|
||||
\end
|
||||
@@ -1,2 +1,2 @@
|
||||
title: $:/tags/ViewTemplateBodyFilter
|
||||
list: $:/config/ViewTemplateBodyFilters/hide-body $:/config/ViewTemplateBodyFilters/code-body $:/config/ViewTemplateBodyFilters/stylesheet $:/config/ViewTemplateBodyFilters/core-ui-advanced-search $:/config/ViewTemplateBodyFilters/core-ui-tags $:/config/ViewTemplateBodyFilters/system $:/config/ViewTemplateBodyFilters/import $:/config/ViewTemplateBodyFilters/plugin $:/config/ViewTemplateBodyFilters/default
|
||||
list: $:/config/ViewTemplateBodyFilters/testcase $:/config/ViewTemplateBodyFilters/hide-body $:/config/ViewTemplateBodyFilters/code-body $:/config/ViewTemplateBodyFilters/stylesheet $:/config/ViewTemplateBodyFilters/core-ui-advanced-search $:/config/ViewTemplateBodyFilters/core-ui-tags $:/config/ViewTemplateBodyFilters/system $:/config/ViewTemplateBodyFilters/import $:/config/ViewTemplateBodyFilters/plugin $:/config/ViewTemplateBodyFilters/default
|
||||
@@ -10,12 +10,23 @@ description: Under development
|
||||
|
||||
! Major Improvements
|
||||
|
||||
<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7734">> several new features that together allow interactive learning tours to be created and presented in TiddlyWiki.
|
||||
|
||||
The demo TiddlyWiki interactive tour can be seen at https://tiddlywiki.com/prerelease/tour
|
||||
|
||||
The new features include:
|
||||
|
||||
* The new Tour Plugin itself
|
||||
* The new Confetti Plugin that allows animated bursts of confetti to be displayed
|
||||
* Improvements to the Dynannotate Plugin to add the ability to highlight screen elements using an animated spotlight effect
|
||||
|
||||
! Translation improvements
|
||||
|
||||
Improvements to the following translations:
|
||||
|
||||
*
|
||||
* Chinese
|
||||
* Macedonian
|
||||
* Polish
|
||||
|
||||
! Plugin Improvements
|
||||
|
||||
@@ -23,23 +34,44 @@ Improvements to the following translations:
|
||||
|
||||
! Widget Improvements
|
||||
|
||||
*
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/8115">> ''$timestamp'' attribute to ActionDeleteFieldWidget
|
||||
|
||||
! Filter Improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7966">> new [[backtranscludes Operator]]
|
||||
|
||||
! Usability Improvements
|
||||
|
||||
*
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/issues/8121">> new keyboard shortcut for refreshing the page
|
||||
|
||||
! Hackability Improvements
|
||||
|
||||
*
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7966">> button to the JavaScript error popup allowing tiddlers to be saved to a local JSON file
|
||||
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/issues/8120">> to latest version of modern-normalize 2.0.0
|
||||
|
||||
! Bug Fixes
|
||||
|
||||
*
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7933">> TiddlyWikiClassic build process
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7935">> LinkWidget not refreshing when the `to` attribute changes
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/3460">> parsing bug with empty procedures/macros
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7907">> functions to use variables set by filter runs
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7943">> edit widget not refreshing when the editor type changes
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7922">> editor preview width
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/9bf3c0602d4fd3fe5ac7411db697b51f87a79056">> [[WidgetMessage: tm-http-request]] not returning data in the event of an error
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/8150">> [[WidgetMessage: tm-http-request]] incorrectly interpreting 2XX status codes
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7949">> processing of path separators in `tiddlywiki.files` files on Windows
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7975">> incorrect state reference in advanced search
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7985">> clipping of popups in preview pane
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/8039">> JavaScript error when attempting to export missing tiddlers to a CSV file
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7909">> imported procedures defaulting to `\whitespace trim`
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/801ed0ea1164aab4f88547322f9d73704388143f">> crash with [[cycle Operator]] if the the step size is larger than the number of operands
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/8095">> proper DOCTYPE for the open window template
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7945">> theme font size settings to open in new window CSS
|
||||
|
||||
! Node.js Improvements
|
||||
|
||||
*
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/8141">> usage of "Cache-Control" header
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7878">> SaveCommand not overwriting files when required
|
||||
|
||||
! Performance Improvements
|
||||
|
||||
@@ -58,4 +90,29 @@ Improvements to the following translations:
|
||||
[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki:
|
||||
|
||||
<<.contributors """
|
||||
andjar
|
||||
AnthonyMuscio
|
||||
bimlas
|
||||
BramChen
|
||||
btheado
|
||||
BurningTreeC
|
||||
catter-fly
|
||||
eschlon
|
||||
etardiff
|
||||
flibbles
|
||||
FSpark
|
||||
hoelzro
|
||||
jinix6
|
||||
joshuafontany
|
||||
linonetwo
|
||||
mateuszwilczek
|
||||
mklauber
|
||||
oeyoews
|
||||
pmario
|
||||
PotOfCoffee2Go
|
||||
rmunn
|
||||
saqimtiaz
|
||||
sarna
|
||||
Telumire
|
||||
yaisog
|
||||
""">>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
caption: {{$:/language/OfficialPluginLibrary}}
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: https://tiddlywiki.com/prerelease/library/v5.3.3/index.html
|
||||
caption: {{$:/language/OfficialPluginLibrary}} (Prerelease)
|
||||
title: $:/config/OfficialPluginLibrary
|
||||
url: https://tiddlywiki5-git-plugin-stability-badges-jermolenes-projects.vercel.app/library/v5.3.3/index.html
|
||||
|
||||
The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team.
|
||||
Plugin library for https://tiddlywiki5-git-plugin-stability-badges-jermolenes-projects.vercel.app
|
||||
@@ -3,3 +3,7 @@ title: HelloThere
|
||||
This is TiddlyWiki's browser-based test runner for version <<version>>. See the bottom of this page for the test results.
|
||||
|
||||
https://tiddlywiki.com/
|
||||
|
||||
! Test Cases
|
||||
|
||||
{{$:/core/ui/ControlPanel/TestCases}}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
title: Macros/unusedtitle/basic-draft-exists
|
||||
description: test <<unusedtitle>> with basic macro parameters but they are empty
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Draft of 'test'
|
||||
draft.of: test
|
||||
draft.title: test
|
||||
|
||||
+
|
||||
title: Draft of 'asdf 0'
|
||||
draft.of: asdf 0
|
||||
draft.title: asdf 0
|
||||
|
||||
+
|
||||
title: Output
|
||||
|
||||
<!-- hanled in wiki.js -->
|
||||
<<unusedtitle baseName:"test">>
|
||||
|
||||
<!-- handled in unusedtitle.js -->
|
||||
<<unusedtitle baseName:"asdf" separator:" " template:"$basename$$separator$$count:1$">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>test 1</p><p>asdf 1</p>
|
||||
@@ -0,0 +1,23 @@
|
||||
title: Macros/unusedtitle/basic-params-empty-tiddler-exists
|
||||
description: test <<unusedtitle>> with basic macro parameters but they are empty
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: New Tiddler
|
||||
|
||||
+
|
||||
title: Output
|
||||
|
||||
<!-- hanled in wiki.js -->
|
||||
<<unusedtitle separator:"">>
|
||||
|
||||
<!-- handled in unusedtitle.js -->
|
||||
<<unusedtitle baseName:"">>
|
||||
|
||||
<!-- handled in wiki.js -->
|
||||
<<unusedtitle template:"">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler 1</p><p>New Tiddler 1</p><p>New Tiddler 1</p>
|
||||
@@ -0,0 +1,20 @@
|
||||
title: Macros/unusedtitle/basic-params-empty
|
||||
description: test <<unusedtitle>> with basic macro parameters but they are empty
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
<!-- hanled in wiki.js -->
|
||||
<<unusedtitle separator:"">>
|
||||
|
||||
<!-- handled in unusedtitle.js -->
|
||||
<<unusedtitle baseName:"">>
|
||||
|
||||
<!-- handled in wiki.js -->
|
||||
<<unusedtitle template:"">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler</p><p>New Tiddler</p><p>New Tiddler</p>
|
||||
@@ -0,0 +1,28 @@
|
||||
title: Macros/unusedtitle/basic-params-tiddlers-exist
|
||||
description: test <<unusedtitle>> with basic macro parameters, where new-name tiddlers already exist
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: New Tiddler
|
||||
|
||||
+
|
||||
title: anotherBase
|
||||
|
||||
+
|
||||
title: About
|
||||
|
||||
+
|
||||
title: Output
|
||||
|
||||
<<unusedtitle>>
|
||||
|
||||
<<unusedtitle separator:"-">>
|
||||
|
||||
<<unusedtitle baseName:"anotherBase">>
|
||||
|
||||
<<unusedtitle baseName:"About" separator:"-">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler 1</p><p>New Tiddler-1</p><p>anotherBase 1</p><p>About-1</p>
|
||||
@@ -0,0 +1,20 @@
|
||||
title: Macros/unusedtitle/basic-params
|
||||
description: test <<unusedtitle>> with basic macro parameters
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
<<unusedtitle>>
|
||||
|
||||
<!-- EDGECASE: separator is ignored if tiddler title does not exist -->
|
||||
<<unusedtitle separator:"-">>
|
||||
|
||||
<<unusedtitle baseName:"anotherBase">>
|
||||
|
||||
<<unusedtitle baseName:"About" separator:"-">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler</p><p>New Tiddler</p><p>anotherBase</p><p>About</p>
|
||||
@@ -0,0 +1,50 @@
|
||||
title: Macros/unusedtitle/template-empty-params-tiddler-exist
|
||||
description: test <<unusedtitle>> with templates where parameters are empty
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: New Tiddler
|
||||
|
||||
+
|
||||
title: xxx
|
||||
|
||||
+
|
||||
title: 00-New Tiddler
|
||||
|
||||
+
|
||||
title: 0000 asdf
|
||||
|
||||
+
|
||||
title: 0001 asdf
|
||||
|
||||
+
|
||||
title: 0000 abc
|
||||
|
||||
+
|
||||
title: Output
|
||||
|
||||
<!-- empty template - no template handling at all -->
|
||||
<<unusedtitle template:"">>
|
||||
|
||||
<!--
|
||||
uses basename AND separator if tiddler exists
|
||||
because it uses default naming build rules - no template handling
|
||||
-->
|
||||
<<unusedtitle template:"" separator:"-y-" baseName:"xxx">>
|
||||
|
||||
<<unusedtitle baseName:"" template:"$count:2$-$basename$">>
|
||||
|
||||
<!--
|
||||
EDGECASE: if separator is empty it will be initialized with a single space " "
|
||||
to have the same rules for templates and default title creation
|
||||
-->
|
||||
<<unusedtitle baseName:"asdf" separator:"" template:"$count:4$$separator$$basename$">>
|
||||
|
||||
<!-- separator = " " -->
|
||||
<<unusedtitle baseName:"abc" separator:" " template:"$count:4$$separator$$basename$">>
|
||||
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler 1</p><p>xxx-y-1</p><p>01-New Tiddler</p><p>0002 asdf</p><p>0001 abc</p>
|
||||
@@ -0,0 +1,24 @@
|
||||
title: Macros/unusedtitle/template-empty-params
|
||||
description: test <<unusedtitle>> with templates where parameters are empty
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
<!-- empty template -->
|
||||
<<unusedtitle template:"">>
|
||||
|
||||
<!--
|
||||
uses basename but ignores separator,
|
||||
because it uses default naming build rules -- no template handling is active
|
||||
-->
|
||||
<<unusedtitle template:"" separator:"-x-" baseName:"xxx">>
|
||||
|
||||
<<unusedtitle baseName:"" template:"$count:2$-$basename$">>
|
||||
|
||||
<<unusedtitle baseName:"asdf" separator:"" template:"$count:4$$separator$$basename$">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler</p><p>xxx</p><p>00-New Tiddler</p><p>0000 asdf</p>
|
||||
@@ -0,0 +1,28 @@
|
||||
title: Macros/unusedtitle/template
|
||||
description: test <<unusedtitle>> with templates
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
<!-- empty template - standard rules are used -->
|
||||
<<unusedtitle template:"">>
|
||||
|
||||
<<unusedtitle template:"count-missing">>
|
||||
|
||||
<<unusedtitle template:"$count:2$-new">>
|
||||
|
||||
<!-- template is handled using $tw.utils.formatTitleString -->
|
||||
<<unusedtitle baseName:"base" template:"$count:2$-$basename$">>
|
||||
|
||||
<<unusedtitle baseName:"" template:"$count:2$-$basename$">>
|
||||
|
||||
<!-- UPPERCASES are intentional in template strings. They should be case-insensistive -->
|
||||
<<unusedtitle baseName:"asdf" separator:"-" template:"$coUNT:2$$sepaRATor$$baseName$">>
|
||||
|
||||
<<unusedtitle baseName:"asdf" separator:"" template:"$count:2$$separator$$basename$">>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>New Tiddler</p><p>count-missing</p><p>00-new</p><p>00-base</p><p>00-New Tiddler</p><p>00-asdf</p><p>00 asdf</p>
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"directories": [
|
||||
"../../../../tw5.com/tiddlers/testcases"
|
||||
]
|
||||
}
|
||||
176
editions/test/tiddlers/tests/test-action-deletefield.js
Normal file
176
editions/test/tiddlers/tests/test-action-deletefield.js
Normal file
@@ -0,0 +1,176 @@
|
||||
/*\
|
||||
title: test-action-deletefield.js
|
||||
type: application/javascript
|
||||
tags: [[$:/tags/test-spec]]
|
||||
|
||||
Tests <$action-deletefield />.
|
||||
|
||||
\*/
|
||||
(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("<$action-deletefield /> tests", function() {
|
||||
|
||||
const TEST_TIDDLER_TITLE = "TargetTiddler";
|
||||
const TEST_TIDDLER_MODIFIED = "20240313114828368";
|
||||
|
||||
function setupWiki(condition, targetField, wikiOptions) {
|
||||
// Create a wiki
|
||||
var wiki = new $tw.Wiki({});
|
||||
var tiddlers = [{
|
||||
title: "Root",
|
||||
text: "Some dummy content"
|
||||
}];
|
||||
var tiddler;
|
||||
if(condition.targetTiddlerExists) {
|
||||
var fields = {
|
||||
title: TEST_TIDDLER_TITLE,
|
||||
};
|
||||
if(condition.modifiedFieldExists) {
|
||||
fields.modified = TEST_TIDDLER_MODIFIED;
|
||||
}
|
||||
if(condition.targetFieldExists) {
|
||||
fields[targetField] = "some text";
|
||||
}
|
||||
var tiddler = new $tw.Tiddler(fields);
|
||||
tiddlers.push(tiddler);
|
||||
}
|
||||
wiki.addTiddlers(tiddlers);
|
||||
wiki.addIndexersToWiki();
|
||||
var widgetNode = wiki.makeTranscludeWidget("Root",{document: $tw.fakeDocument, parseAsInline: true});
|
||||
var container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
return {
|
||||
wiki: wiki,
|
||||
widgetNode: widgetNode,
|
||||
contaienr: container,
|
||||
tiddler: tiddler,
|
||||
};
|
||||
}
|
||||
|
||||
function generateTestConditions() {
|
||||
var conditions = [];
|
||||
|
||||
$tw.utils.each([true, false], function(tiddlerArgumentIsPresent) {
|
||||
$tw.utils.each([true, false], function(targetTiddlerExists) {
|
||||
$tw.utils.each([true, false], function(targetFieldExists) {
|
||||
$tw.utils.each([true, false], function(fieldArgumentIsUsed) {
|
||||
$tw.utils.each([true, false], function(modifiedFieldExists) {
|
||||
$tw.utils.each(["", "yes", "no"], function(timestampArgument) {
|
||||
conditions.push({
|
||||
tiddlerArgumentIsPresent: tiddlerArgumentIsPresent,
|
||||
targetTiddlerExists: targetTiddlerExists,
|
||||
targetFieldExists: targetFieldExists,
|
||||
fieldArgumentIsUsed: fieldArgumentIsUsed,
|
||||
modifiedFieldExists: modifiedFieldExists,
|
||||
timestampArgument: timestampArgument,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return conditions;
|
||||
}
|
||||
|
||||
function generateActionWikitext(condition, targetField) {
|
||||
var actionPieces = [
|
||||
"<$action-deletefield",
|
||||
(condition.tiddlerArgumentIsPresent ? "$tiddler='" + TEST_TIDDLER_TITLE + "'" : ""),
|
||||
(condition.fieldArgumentIsUsed ? "$field='" + targetField + "'" : targetField),
|
||||
(condition.timestampArgument !== "" ? "$timestamp='" + condition.timestampArgument + "'" : ""),
|
||||
"/>",
|
||||
];
|
||||
|
||||
return actionPieces.join(" ");
|
||||
}
|
||||
|
||||
function generateTestContext(action, tiddler) {
|
||||
var expectationContext = "action: " + action + "\ntiddler:\n\n";
|
||||
if(tiddler) {
|
||||
expectationContext += tiddler.getFieldStringBlock({exclude: ["text"]});
|
||||
if(tiddler.text) {
|
||||
expectationContext += "\n\n" + tiddler.text;
|
||||
}
|
||||
expectationContext += "\n\n";
|
||||
} else {
|
||||
expectationContext += "null";
|
||||
}
|
||||
|
||||
return expectationContext;
|
||||
}
|
||||
|
||||
it("should correctly delete fields", function() {
|
||||
var fields = ['caption', 'description', 'text'];
|
||||
|
||||
var conditions = generateTestConditions();
|
||||
|
||||
$tw.utils.each(conditions, function(condition) {
|
||||
$tw.utils.each(fields, function(field) {
|
||||
var info = setupWiki(condition, field);
|
||||
var originalTiddler = info.tiddler;
|
||||
|
||||
var invokeActions = function(actions) {
|
||||
info.widgetNode.invokeActionString(actions,info.widgetNode,null,{
|
||||
currentTiddler: TEST_TIDDLER_TITLE,
|
||||
});
|
||||
};
|
||||
|
||||
var action = generateActionWikitext(condition,field);
|
||||
|
||||
invokeActions(action);
|
||||
|
||||
var testContext = generateTestContext(action,originalTiddler);
|
||||
|
||||
var tiddler = info.wiki.getTiddler(TEST_TIDDLER_TITLE);
|
||||
if(originalTiddler) {
|
||||
// assert that the tiddler doesn't have the target field anymore
|
||||
expect(tiddler.hasField(field)).withContext(testContext).toBeFalsy();
|
||||
|
||||
var targetFieldWasPresent = originalTiddler.hasField(field);
|
||||
var updateTimestamps = condition.timestampArgument !== "no";
|
||||
|
||||
// "created" should exist if it did beforehand, or if the tiddler changed and we asked the widget to update timestamps
|
||||
var createdFieldShouldExist = originalTiddler.hasField("created") || (targetFieldWasPresent && updateTimestamps);
|
||||
|
||||
// "created" should change only if it didn't exist beforehand and the tiddler changed and we asked the widget to update timestamps
|
||||
var createdFieldShouldChange = !originalTiddler.hasField("created") && (targetFieldWasPresent && updateTimestamps);
|
||||
|
||||
// "modified" should exist if it did beforehand, or if the tiddler changed and we asked the widget to update timestamps
|
||||
var modifiedFieldShouldExist = originalTiddler.hasField("modified") || (targetFieldWasPresent && updateTimestamps);
|
||||
|
||||
// "modified" should change if the tiddler changed and we asked the widget to update timestamps
|
||||
var modifiedFieldShouldChange = targetFieldWasPresent && updateTimestamps;
|
||||
|
||||
expect(tiddler.hasField("created")).withContext(testContext).toBe(createdFieldShouldExist);
|
||||
expect(tiddler.hasField("modified")).withContext(testContext).toBe(modifiedFieldShouldExist);
|
||||
|
||||
if(createdFieldShouldChange) {
|
||||
expect(tiddler.fields.created).withContext(testContext).not.toEqual(originalTiddler.fields.created);
|
||||
} else {
|
||||
expect(tiddler.fields.created).withContext(testContext).toEqual(originalTiddler.fields.created);
|
||||
}
|
||||
|
||||
if(modifiedFieldShouldChange) {
|
||||
expect(tiddler.fields.modified).withContext(testContext).not.toEqual(originalTiddler.fields.modified);
|
||||
} else {
|
||||
expect(tiddler.fields.modified).withContext(testContext).toEqual(originalTiddler.fields.modified);
|
||||
}
|
||||
} else {
|
||||
// assert that the tiddler didn't get created if it didn't exist already
|
||||
expect(tiddler).withContext(testContext).toBeUndefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
44
editions/test/tiddlers/tests/test-plugins.js
Normal file
44
editions/test/tiddlers/tests/test-plugins.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/*\
|
||||
title: test-plugins.js
|
||||
type: application/javascript
|
||||
tags: [[$:/tags/test-spec]]
|
||||
|
||||
Tests for integrity of the core plugins, languages, themes and editions
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
describe("Plugin tests", function() {
|
||||
|
||||
// Get all the plugins as a hashmap by title of a JSON string with the plugin content
|
||||
var tiddlers = $tw.utils.getAllPlugins();
|
||||
// console.log(JSON.stringify(Object.keys(tiddlers),null,4));
|
||||
describe("every plugin should have the required standard fields", function() {
|
||||
var titles = Object.keys(tiddlers);
|
||||
$tw.utils.each(titles,function(title) {
|
||||
it("plugin " + title + " should have the required standard fields",function() {
|
||||
var fields = tiddlers[title];
|
||||
expect(fields["plugin-type"]).toMatch(/^(?:plugin|language|theme)$/);
|
||||
switch(fields["plugin-type"]) {
|
||||
case "plugin":
|
||||
expect(!!(fields.name && fields.description && fields.list)).toEqual(true);
|
||||
expect(fields.stability).toMatch(/^(?:STABILITY_0_DEPRECATED|STABILITY_1_EXPERIMENTAL|STABILITY_2_STABLE|STABILITY_3_LEGACY)$/);
|
||||
break;
|
||||
case "language":
|
||||
expect(!!(fields.name && fields.description)).toEqual(true);
|
||||
break;
|
||||
case "theme":
|
||||
expect(!!(fields.name && fields.description)).toEqual(true);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
31
editions/tw5.com/tiddlers/concepts/CompoundTiddlers.tid
Normal file
31
editions/tw5.com/tiddlers/concepts/CompoundTiddlers.tid
Normal file
@@ -0,0 +1,31 @@
|
||||
title: CompoundTiddlers
|
||||
modified: 20240507221902644
|
||||
created: 20240507221902644
|
||||
tags: Concepts
|
||||
|
||||
Compound tiddlers are a special type of tiddler that can store one or more payload tiddlers. The tiddlers within a compound tiddler are only accessible via special operations, typically with the TestCaseWidget.
|
||||
|
||||
The compound tiddler format is extremely simple, and includes the notable flaw that it does not permit tiddlers that contain a plus sign (`+`) on a line by itself. It is not intended as a general purpose way of storing tiddler data.
|
||||
|
||||
Compound tiddlers are identified by having their type field set to `text/vnd.tiddlywiki-multiple`.
|
||||
|
||||
The content of a compound tiddler consists of a sequence of tiddlers separated by a plus sign (`+`) on a line by itself. Each tiddler uses the same format as [[.tid files|TiddlerFiles]].
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
title: First
|
||||
tags: one two
|
||||
|
||||
This is the first tiddler
|
||||
+
|
||||
title: Second
|
||||
tags: three four
|
||||
|
||||
This is the second tiddler
|
||||
+
|
||||
title: third
|
||||
tags: five six
|
||||
|
||||
This is the third tiddler
|
||||
```
|
||||
27
editions/tw5.com/tiddlers/concepts/TestCaseTiddlers.tid
Normal file
27
editions/tw5.com/tiddlers/concepts/TestCaseTiddlers.tid
Normal file
@@ -0,0 +1,27 @@
|
||||
title: TestCaseTiddlers
|
||||
modified: 20240507221902644
|
||||
created: 20240507221902644
|
||||
tags: Concepts
|
||||
|
||||
Test case tiddlers encapsulate one or more tiddlers that can be displayed as a [[test case|TestCaseWidget]]: an independent embedded wiki that can be used for testing or learning purposes.
|
||||
|
||||
Test case tiddlers are formatted as CompoundTiddlers, allowing them to contain multiple tiddlers packed into one.
|
||||
|
||||
Test case tiddlers have the following fields:
|
||||
|
||||
|!Field |!Description |
|
||||
|<<.field type>> | Should be set to `text/vnd.tiddlywiki-multiple` |
|
||||
|<<.field tags>> | Test cases are tagged [[$:/tags/wiki-test-spec]]. Test cases that intentionally fail are tagged [[$:/tags/wiki-test-spec-failing]] |
|
||||
|<<.field description>> |Descriptive heading for the test, intended to make it easy to identify the test |
|
||||
|<<.field display-format>> |Optional, defaults to `wikitext`. Set to `plaintext` to cause the output to be rended as plain text |
|
||||
|
||||
Test case tiddlers with the appropriate tag are shown in $:/ControlPanel
|
||||
|
||||
Some payload tiddlers are set aside for special purposes:
|
||||
|
||||
|!Tiddler |!Description |
|
||||
|''Narrative'' |Narrative description of the test, intended to explain the purpose and operation of the test |
|
||||
|''Output'' |The tiddler that produces the test output |
|
||||
|''~ExpectedResult'' |HTML of expected result of rendering the ''Output'' tiddler |
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
created: 20130825213300000
|
||||
modified: 20220109101407050
|
||||
modified: 20240520162904479
|
||||
tags: Concepts
|
||||
title: TiddlerFields
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define lingo-base() $:/language/Docs/Fields/
|
||||
~TiddlerFields are name:value pairs that make up a [[tiddler|Tiddlers]]. Field names must be lowercase letters, digits or the characters `-` (dash), `_` (underscore) and `.` (period).
|
||||
~TiddlerFields are name:value pairs that make up a [[tiddler|Tiddlers]]. Field names may contain any combination of characters (prior to [[v5.2.0|Release 5.2.0]], fields were constrained to be lowercase letters, digits or the characters `-` (dash), `_` (underscore) and `.` (period)).
|
||||
|
||||
The standard fields are:
|
||||
|
||||
@@ -39,6 +39,7 @@ Other fields used by the core are:
|
||||
|`name` |<<lingo name>> |
|
||||
|`plugin-priority` |<<lingo plugin-priority>> |
|
||||
|`plugin-type` |<<lingo plugin-type>> |
|
||||
|`stability` |<<lingo stability>> |
|
||||
|`source` |<<lingo source>> |
|
||||
|`subtitle` |<<lingo subtitle>> |
|
||||
|`throttle.refresh` |<<lingo throttle.refresh>> |
|
||||
|
||||
@@ -4,7 +4,7 @@ tags: [[Filter Expression]]
|
||||
title: Filter Run Prefix
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
There are 2 types of filter run prefixes that are interchangeable. Named prefixes and shortcut prefixes.
|
||||
There are 2 types of filter run prefixes that are interchangeable; [[named prefixes|Named Filter Run Prefix]] and [[shortcut prefixes|Shortcut Filter Run Prefix]].
|
||||
|
||||
<$railroad text="""
|
||||
\start none
|
||||
|
||||
@@ -5,7 +5,7 @@ tags: TableOfContents
|
||||
title: HelloThere
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!!.tc-hero-heading ''Welcome to TiddlyWiki, a unique [[non-linear|Philosophy of Tiddlers]] notebook for [[capturing|Creating and editing tiddlers]], [[organising|Structuring TiddlyWiki]] and [[sharing|Sharing your tiddlers with others]] complex information''
|
||||
!!.tc-hero-heading ''Welcome to TiddlyWiki, a unique [[non-linear|Philosophy of Tiddlers]] notebook for [[capturing|Creating and editing tiddlers]], [[organising|Structuring TiddlyWiki]] and [[sharing|Sharing your tiddlers with others]] complex information''
|
||||
|
||||
Use it to keep your [[to-do list|TaskManagementExample]], to plan an [[essay or novel|"TiddlyWiki for Scholars" by Alberto Molina]], or to organise your wedding. Record every thought that crosses your brain, or build a flexible and responsive website.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: tag
|
||||
created: 20141206130540337
|
||||
modified: 20230725201240201
|
||||
modified: 20240228131301798
|
||||
tags: Macros [[Core Macros]]
|
||||
title: tag Macro
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -11,7 +11,35 @@ The <<.def tag>> [[macro|Macros]] generates a tag pill for a specified tag. Clic
|
||||
|
||||
!! Parameters
|
||||
|
||||
;tag
|
||||
; tag
|
||||
: The title of the tag, defaulting to the [[current tiddler|Current Tiddler]]
|
||||
|
||||
!! CSS classes
|
||||
|
||||
<<.from-version "v5.3.4">>
|
||||
|
||||
; `tc-tag-missing`
|
||||
: This class is defined if a tag does ''not exist'' as a tiddler.
|
||||
|
||||
; `tc-tag-exists`
|
||||
: This class is defined if a tag does exist as a tiddler
|
||||
|
||||
!!! Defining the class
|
||||
|
||||
To define the `tc-tag-missing` class a stylesheet tiddler needs to be created. The default font-style for missing tiddler links is //italic//, so it's used for the example code below. Eg:
|
||||
|
||||
''title:'' `myTagsStylesheet`<br>
|
||||
''tag:'' `$:/tags/Stylesheet`
|
||||
|
||||
<<copy-to-clipboard-above-right src:"""
|
||||
.tc-tag-missing {
|
||||
font-style: italic;
|
||||
}
|
||||
""">>
|
||||
```
|
||||
.tc-tag-missing {
|
||||
font-style: italic;
|
||||
}
|
||||
```
|
||||
|
||||
<<.macro-examples "tag">>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20150221211317000
|
||||
modified: 20230725203751870
|
||||
modified: 20240228131331605
|
||||
tags: [[tag Macro]] [[Macro Examples]]
|
||||
title: tag Macro (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -7,22 +7,26 @@ type: text/vnd.tiddlywiki
|
||||
<$macrocall $name=".example" n="1" eg="""<<tag>>"""/>
|
||||
<$macrocall $name=".example" n="2" eg="""<<tag Concepts>>"""/>
|
||||
|
||||
The Following tag can be shown with a font-style: //italic// if the corresponding stylesheet exists. See: [[tag Macro]]
|
||||
|
||||
<$macrocall $name=".example" n="3" eg="""<<tag "Does not exist">>"""/>
|
||||
|
||||
If a [[list widget|ListWidget]] generates multiple tag macros for the same tag, clicking any of them opens dropdowns on all of them, as in the example below. This is usually unwanted.
|
||||
<$macrocall $name=".example" n="3" eg="""<$list filter="[tag[HelloThere]]">
|
||||
<$macrocall $name=".example" n="4" eg="""<$list filter="[tag[HelloThere]]">
|
||||
|
||||
* <$link/> is tagged with: <$list filter="[<currentTiddler>tags[]]"> <<tag>> </$list>
|
||||
|
||||
</$list>"""/>
|
||||
|
||||
Adding the `counter="transclusion"` attribute to the list widget that generates multiple identical tag macros causes each of them to be identified as a unique one. Clicking on any of them opens only a single dropdown.
|
||||
<$macrocall $name=".example" n="4" eg="""<$list filter="[tag[HelloThere]]" counter="transclusion">
|
||||
<$macrocall $name=".example" n="5" eg="""<$list filter="[tag[HelloThere]]" counter="transclusion">
|
||||
|
||||
* <$link/> is tagged with: <$list filter="[<currentTiddler>tags[]]"> <<tag>> </$list>
|
||||
|
||||
</$list>"""/>
|
||||
|
||||
A slightly more performant option is to use the `variable="transclusion"` attribute in the list widget. In this case, the variable `<<transclusion>>` has to be used inside the list widget instead of the `<<currentTiddler>>` .
|
||||
<$macrocall $name=".example" n="5" eg="""<$list filter="[tag[HelloThere]]" variable="transclusion">
|
||||
<$macrocall $name=".example" n="6" eg="""<$list filter="[tag[HelloThere]]" variable="transclusion">
|
||||
|
||||
* <$link to=<<transclusion>>/> is tagged with: <$list filter="[<transclusion>tags[]]"> <<tag>> </$list>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: tag-picker
|
||||
created: 20161128191316701
|
||||
modified: 20161128191435641
|
||||
modified: 20230616114543787
|
||||
tags: Macros [[Core Macros]]
|
||||
title: tag-picker Macro
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -9,9 +9,17 @@ The <<.def tag-picker>> [[macro|Macros]] generates a combination of a text box a
|
||||
|
||||
!! Parameters
|
||||
|
||||
;actions
|
||||
: Action widgets to be triggered when the pill is clicked. Within the text, the variable ''tag'' contains the title of the selected tag.
|
||||
;tagField
|
||||
: <<.from-version 5.1.23>> The ''field'' that gets updated with the selected tag. Defaults to ''tags''.
|
||||
; actions
|
||||
: Action widgets to be triggered when the pill is clicked. Within the text, the variable <<.var tag>> contains the title of the selected tag.
|
||||
|
||||
; tagField
|
||||
: <<.from-version 5.1.23>> The specified ''field'' that gets updated with the selected tag. Defaults to `tags`.
|
||||
|
||||
; tiddler
|
||||
: <<.from-version 5.3.4>> Defines the target tiddler, which should be manipulated. Defaults to: <<.var currentTiddler>>.
|
||||
|
||||
; tagListFilter
|
||||
: <<.from-version 5.3.4>> This parameter defaults to: `[tags[]]` which creates a list of all existing tags. If the tag list should come from a different source the filter should look similar to eg: `[<listSource>get[field-name]enlist-input[]]`.
|
||||
|
||||
|
||||
<<.macro-examples "tag-picker">>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20130826122000000
|
||||
modified: 20220613124446953
|
||||
modified: 20240520162828577
|
||||
tags: Mechanisms
|
||||
title: PluginMechanism
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -16,6 +16,10 @@ By convention, plugin titles have the form `$:/plugins/<publisher>/<name>`. Plug
|
||||
|
||||
When [[running TiddlyWiki under Node.js|TiddlyWiki on Node.js]], plugins can also be stored as individual tiddler files in [[PluginFolders]].
|
||||
|
||||
! Plugin Stability
|
||||
|
||||
{{Plugin Stability}}
|
||||
|
||||
! Plugin Types
|
||||
|
||||
{{Plugin Types}}
|
||||
|
||||
@@ -23,10 +23,6 @@ The following parameters are used:
|
||||
|header-* |Headers with string values |
|
||||
|password-header-* |Headers with values taken from the password store |
|
||||
|password-query-* |Query string parameters with values taken from the password store |
|
||||
|basic-auth-username |<<.from-version "5.3.4">> Optional username for HTTP basic authentication |
|
||||
|basic-auth-username-from-store |<<.from-version "5.3.4">> Optional username for HTTP basic authentication, specified as the name of the entry in the password store containing the username |
|
||||
|basic-auth-password |<<.from-version "5.3.4">> Optional password for HTTP basic authentication |
|
||||
|basic-auth-password-from-store |<<.from-version "5.3.4">> Optional password for HTTP basic authentication, specified as the name of the entry in the password store containing the password |
|
||||
|var-* |Variables to be passed to the completion and progress handlers (without the "var-" prefix) |
|
||||
|bind-status |Title of tiddler to which the status of the request ("pending", "complete", "error") should be bound |
|
||||
|bind-progress |Title of tiddler to which the progress of the request (0 to 100) should be bound |
|
||||
|
||||
@@ -4,7 +4,7 @@ tags: [[Releases]]
|
||||
title: TiddlyWiki5 Versioning
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Each release of TiddlyWiki5 is identified by a version number that complies with the [[Semantic Versioning 2.0.0|http://semver.org/]] standard.
|
||||
Each release of TiddlyWiki5 is identified by a version number that complies with a variant of [[Semantic Versioning 2.0.0|http://semver.org/]] standard.
|
||||
|
||||
! TiddlyWiki Core Version
|
||||
|
||||
|
||||
14
editions/tw5.com/tiddlers/plugins/Plugin Stability.tid
Normal file
14
editions/tw5.com/tiddlers/plugins/Plugin Stability.tid
Normal file
@@ -0,0 +1,14 @@
|
||||
created: 20240520155341641
|
||||
modified: 20240520162820882
|
||||
tags: PluginMechanism
|
||||
title: Plugin Stability
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Plugins are recommended to have a `stability` field that communicates the state of development of the plugin. It can contain the following values:
|
||||
|
||||
* ''STABILITY_0_DEPRECATED'' - Deprecated. This plugin is not recommended for new projects
|
||||
* ''STABILITY_1_EXPERIMENTAL'' - Experimental. Non-backward compatible changes or removal may occur in any future release. Use of the plugin is not recommended in production environments
|
||||
* ''STABILITY_2_STABLE'' - Stable.
|
||||
* ''STABILITY_3_LEGACY'' - Legacy. Although this plugin is unlikely to be removed, it is no longer actively maintained, and other alternatives are available
|
||||
|
||||
These stability levels are taken from the Node.js project - https://nodejs.org/api/documentation.html#stability-index.
|
||||
@@ -1,8 +1,8 @@
|
||||
code-body: yes
|
||||
created: 20150117152607000
|
||||
modified: 20240229155550000
|
||||
modified: 20240317091700545
|
||||
tags: $:/tags/Macro
|
||||
title: $:/editions/tw5.com/doc-macros
|
||||
code-body: yes
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\whitespace trim
|
||||
@@ -165,7 +165,7 @@ This is an example tiddler. See [[Table-of-Contents Macros (Examples)]].
|
||||
<dd><$button set=<<.state>> setTo="">Hide</$button></dd>
|
||||
</dl>
|
||||
<blockquote class="doc-example-result">
|
||||
<<eg>>
|
||||
<$transclude $variable="eg" $mode="block"/>
|
||||
</blockquote>
|
||||
</$reveal>
|
||||
</$list>
|
||||
|
||||
69
editions/tw5.com/tiddlers/tag-picker Macro (Examples).tid
Normal file
69
editions/tw5.com/tiddlers/tag-picker Macro (Examples).tid
Normal file
@@ -0,0 +1,69 @@
|
||||
created: 20230616104546608
|
||||
modified: 20240214174032498
|
||||
tags: [[tag-picker Macro]] [[Macro Examples]]
|
||||
title: tag-picker Macro (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.warning """The first example will set the tag of the <<.tid currentTiddler>> so you should copy / paste it to a new tiddler for testing. Otherwise you'll change "this tiddler" """>>
|
||||
|
||||
<$macrocall $name=".example" n="1"
|
||||
eg="""Use all existing tags and set the ''tags'' field here: <<tag-picker>>
|
||||
"""/>
|
||||
|
||||
----
|
||||
|
||||
<$let transclusion=test>
|
||||
|
||||
<<.tip """The following examples use a temporary tiddler: $:/temp/test/tag-picker. So this tiddler will not be changed """>>
|
||||
|
||||
|
||||
<$macrocall $name=".example" n="2"
|
||||
eg="""$:/temp/test/tag-picker ''tags'': <$text text={{{ [[$:/temp/test/tag-picker]get[tags]enlist-input[]join[, ]else[n/a]] }}}/>
|
||||
|
||||
Use all existing tags and set the $:/temp/test/tag-picker ''tags'' field: <<tag-picker tiddler:"$:/temp/test/tag-picker">>
|
||||
"""/>
|
||||
|
||||
----
|
||||
|
||||
<<.tip """Use the following example to populate the $:/temp/test/tag-picker ''foo''-field, which are needed by some examples below """>>
|
||||
|
||||
<$macrocall $name=".example" n="3"
|
||||
eg="""$:/temp/test/tag-picker ''foo'': <$text text={{{ [[$:/temp/test/tag-picker]get[foo]enlist-input[]join[, ]else[n/a]] }}}/>
|
||||
|
||||
Use all existing tags and set the $:/temp/test/tag-picker ''foo'' field: <<tag-picker tagField:"foo" tiddler:"$:/temp/test/tag-picker">>
|
||||
"""/>
|
||||
|
||||
----
|
||||
|
||||
<<.tip """The following example expects some values in the "foo" field of the tiddler $:/temp/test/tag-picker, which can be created by the example above.""">>
|
||||
|
||||
<$macrocall $name=".example" n="4" eg="""\procedure listSource() $:/temp/test/tag-picker
|
||||
|
||||
$:/temp/test/tag-picker foo: <$text text={{{ [[$:/temp/test/tag-picker]get[foo]enlist-input[]join[, ]else[n/a]] }}}/><br>
|
||||
$:/temp/test/tag-picker bar: <$text text={{{ [[$:/temp/test/tag-picker]get[bar]enlist-input[]join[, ]else[n/a]] }}}/>
|
||||
|
||||
Use $:/temp/test/tag-picker ''foo'' field as source and set ''bar'': <<tag-picker tagField:"bar" tagListFilter:"[<listSource>get[foo]enlist-input[]]" tiddler:"$:/temp/test/tag-picker">>
|
||||
"""/>
|
||||
|
||||
----
|
||||
|
||||
<<.tip """The following example expects some values in the "foo" field of the tiddler $:/temp/test/tag-picker, which can be created by the example above.<br>
|
||||
It will also add completely new tags to the bar-field and the source tiddlers foo-field. New tags can be entered by typing into the tag-name input
|
||||
""">>
|
||||
|
||||
<$macrocall $name=".example" n="5" eg="""
|
||||
\procedure listSource() $:/temp/test/tag-picker
|
||||
\procedure listSourceField() foo
|
||||
|
||||
\procedure addNewTagToSource()
|
||||
<$action-listops $tiddler=<<listSource>> $field=<<listSourceField>> $subfilter='[<listSource>get<listSourceField>enlist-input[]] [<tag>trim[]]'/>
|
||||
\end
|
||||
|
||||
$:/temp/test/tag-picker foo: <$text text={{{ [[$:/temp/test/tag-picker]get[foo]enlist-input[]join[, ]else[n/a]] }}}/><br>
|
||||
$:/temp/test/tag-picker ''bar'': <$text text={{{ [[$:/temp/test/tag-picker]get[bar]enlist-input[]join[, ]else[n/a]] }}}/>
|
||||
|
||||
Use $:/temp/test/tag-picker ''foo'' field as source and set ''bar'': <$macrocall $name="tag-picker" tagField="bar" tagListFilter="[<listSource>get<listSourceField>enlist-input[]]" tiddler="$:/temp/test/tag-picker" actions=<<addNewTagToSource>>/>
|
||||
|
||||
"""/>
|
||||
|
||||
</$let>
|
||||
@@ -0,0 +1,33 @@
|
||||
title: TestCases/DataWidget/ImportCompound
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
description: Importing a compound payload tiddler and adding custom fields
|
||||
display-format: plaintext
|
||||
|
||||
title: Narrative
|
||||
|
||||
Using the data widget to import a tiddler stored in a compound tiddler
|
||||
+
|
||||
title: Output
|
||||
|
||||
<$data $compound-tiddler="Compound" custom="Alpha"/>
|
||||
+
|
||||
title: Compound
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Payload Tiddler
|
||||
tags: Alpha Beta Gamma
|
||||
|
||||
This is a payload tiddler from a compound tiddler
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>[
|
||||
{
|
||||
"title": "Payload Tiddler",
|
||||
"tags": "Alpha Beta Gamma",
|
||||
"text": "This is a payload tiddler from a compound tiddler",
|
||||
"custom": "Alpha"
|
||||
}
|
||||
]</p>
|
||||
@@ -0,0 +1,49 @@
|
||||
title: TestCases/DataWidget/ImportedFilter
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
description: Imported filter definition
|
||||
display-format: plaintext
|
||||
|
||||
title: Narrative
|
||||
|
||||
Using the data widget to create copies of all the tiddlers with the title prefix "Day: T", adding the field "custom" set to "Beta"
|
||||
+
|
||||
title: Output
|
||||
|
||||
<$data $filter="[prefix[Day: T]]" custom="Beta"/>
|
||||
+
|
||||
title: Day: Monday
|
||||
text: Today is Monday
|
||||
+
|
||||
title: Day: Tuesday
|
||||
text: Today is Tuesday
|
||||
+
|
||||
title: Day: Wednesday
|
||||
text: Today is Wednesday
|
||||
+
|
||||
title: Day: Thursday
|
||||
text: Today is Thursday
|
||||
+
|
||||
title: Day: Friday
|
||||
text: Today is Friday
|
||||
+
|
||||
title: Day: Saturday
|
||||
text: Today is Saturday
|
||||
+
|
||||
title: Day: Sunday
|
||||
text: Today is Sunday
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>[
|
||||
{
|
||||
"title": "Day: Thursday",
|
||||
"text": "Today is Thursday",
|
||||
"custom": "Beta"
|
||||
},
|
||||
{
|
||||
"title": "Day: Tuesday",
|
||||
"text": "Today is Tuesday",
|
||||
"custom": "Beta"
|
||||
}
|
||||
]</p>
|
||||
@@ -0,0 +1,29 @@
|
||||
title: TestCases/DataWidget/ImportedTiddler
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
description: Imported tiddler definition
|
||||
display-format: plaintext
|
||||
|
||||
title: Narrative
|
||||
|
||||
Using the data widget to create a tiddler that is a copy of the tiddler "Hello" with the addition of the field "custom" set to "Alpha"
|
||||
+
|
||||
title: Output
|
||||
|
||||
<$data $tiddler="Hello" custom="Alpha"/>
|
||||
+
|
||||
title: Hello
|
||||
modifier: JoeBloggs
|
||||
|
||||
This is the Hello tiddler
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>[
|
||||
{
|
||||
"title": "Hello",
|
||||
"modifier": "JoeBloggs",
|
||||
"text": "This is the Hello tiddler",
|
||||
"custom": "Alpha"
|
||||
}
|
||||
]</p>
|
||||
@@ -0,0 +1,30 @@
|
||||
title: TestCases/DataWidget/Refreshing
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
description: Refreshing the data widget
|
||||
display-format: plaintext
|
||||
|
||||
title: Narrative
|
||||
|
||||
Verifying that the JSON output of the data widget is correctly refreshed when the data changes
|
||||
+
|
||||
title: Output
|
||||
|
||||
<$data title="Epsilon" text={{Subject}}/>
|
||||
+
|
||||
title: Subject
|
||||
|
||||
Nothing
|
||||
+
|
||||
title: Actions
|
||||
|
||||
<$action-setfield $tiddler="Subject" text="Theta"/>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>[
|
||||
{
|
||||
"title": "Epsilon",
|
||||
"text": "Theta"
|
||||
}
|
||||
]</p>
|
||||
@@ -0,0 +1,22 @@
|
||||
title: TestCases/DataWidget/SimpleTiddler
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
description: Simple tiddler definition
|
||||
display-format: plaintext
|
||||
|
||||
title: Narrative
|
||||
|
||||
Using the data widget to create a tiddler with the title "Epsilon" and the text "Theta"
|
||||
+
|
||||
title: Output
|
||||
|
||||
<$data title="Epsilon" text="Theta"/>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>[
|
||||
{
|
||||
"title": "Epsilon",
|
||||
"text": "Theta"
|
||||
}
|
||||
]</p>
|
||||
@@ -0,0 +1,15 @@
|
||||
title: TestCases/TestCaseWidget/FailingTest
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec-failing]]
|
||||
description: An example of a failing test
|
||||
|
||||
title: Narrative
|
||||
|
||||
This test case intentionally fails to show how failures are displayed.
|
||||
+
|
||||
title: Output
|
||||
|
||||
The sum is <$text text={{{ [[2]add[2]] }}}/>.
|
||||
+
|
||||
title: ExpectedResult
|
||||
text: <p>The sum is not 8.</p>
|
||||
@@ -0,0 +1,16 @@
|
||||
description: currentTiddler should be properly set
|
||||
tags: $:/tags/wiki-test-spec
|
||||
title: TestCases/TestCaseTiddler/currentTiddler
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
currentTiddler variable in Output tiddler should be "Output"
|
||||
+
|
||||
title: Output
|
||||
|
||||
<$text text=<<currentTiddler>>>
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>Output</p>
|
||||
@@ -0,0 +1,23 @@
|
||||
title: TestCases/TranscludeWidget/SimpleTransclusion
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
description: Simple transclusion
|
||||
|
||||
title: Narrative
|
||||
|
||||
This test case demonstrates transclusion of and links to other tiddlers.
|
||||
+
|
||||
title: Output
|
||||
|
||||
Good morning, my [[name|Name]] is {{Name}} and I [[live in|Address]] {{Address}}
|
||||
+
|
||||
title: Name
|
||||
|
||||
Robert Rabbit
|
||||
+
|
||||
title: Address
|
||||
|
||||
14 Carrot Street, Vegetabletown
|
||||
+
|
||||
title: ExpectedResult
|
||||
text: <p>Good morning, my <a class="tc-tiddlylink tc-tiddlylink-resolves" href="#Name">name</a> is Robert Rabbit and I <a class="tc-tiddlylink tc-tiddlylink-resolves" href="#Address">live in</a> 14 Carrot Street, Vegetabletown</p>
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20180905075846391
|
||||
modified: 20230319130830880
|
||||
modified: 20240413045138914
|
||||
tags: [[WebServer Guides]]
|
||||
title: Using the external JavaScript template
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -20,7 +20,7 @@ The remaining inefficiency when working in the client server configuration is th
|
||||
|
||||
! Using the external ~JavaScript template with the client-server configuration
|
||||
|
||||
The mechanism is 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.
|
||||
The mechanism is 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|WebServer Parameter: use-browser-cache]]. 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20180703095630828
|
||||
modified: 20180703100445719
|
||||
modified: 20240413045124764
|
||||
tags: [[WebServer Guides]]
|
||||
title: Using the integrated static file server
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -13,4 +13,19 @@ Static files can be referenced directly:
|
||||
* `[ext[./files/a-big-document.pdf]]` - to make a link to a PDF
|
||||
* `[img[./files/a-big-image.png]]` - to embed an image
|
||||
|
||||
Alternatively, the ''_canonical_uri'' field can be used to reference the files as [[external tiddlers|ExternalImages]].
|
||||
Alternatively, the ''_canonical_uri'' field can be used to reference the files as [[external tiddlers|ExternalImages]].
|
||||
|
||||
If [[WebServer Parameter: use-browser-cache]] is used, these files will be cached by the client's browser to save on bandwidth. In this case, the `cache busting strategy` can be used to make sure the client always has the latest updated files.
|
||||
|
||||
|
||||
<<<
|
||||
https://javascript.plainenglish.io/what-is-cache-busting-55366b3ac022
|
||||
|
||||
!! Cache Busting
|
||||
|
||||
There are a couple different ways of changing the names of files so that they will load when they change. One way is to use version numbers and have them somewhere in the file name when loading. You could have a subdirectory for every version, `v1/index.js` `v2/index.css` . You could also have the version in queries in the URLs, `index.js?v1` , `index.css?v2` .
|
||||
|
||||
Another way is to change the name of the file, `index.v1.js` , `index.v2.css` . These ways are not as manageable because this can become very hard once you have a ton of files that are being changed.
|
||||
|
||||
A more popular and manageable way is to keep hashes inside the file names. Hashes, if you don’t know, are fixed length character representations of any content and they are irreversible, meaning you can get the hash from the file but you can’t get the file from the hash. Hashes are perfect for this, because when a file changes its hash will change, so if we keep the hash inside the filename `index.[someHashHere].js` browsers will detect it and load it instead of an old file.
|
||||
<<<
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
caption: use-browse-cache
|
||||
created: 20240413042652008
|
||||
modified: 20240413050841387
|
||||
tags: [[WebServer Parameters]]
|
||||
title: WebServer Parameter: use-browser-cache
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
The [[web server configuration parameter|WebServer Parameters]] ''use-browser-cache=yes'' activates 200 OK browser caching via the `Cache-Control` header and a smart a Etag header:
|
||||
|
||||
* The server javascript creates an MD5 `hash` object.
|
||||
* Adds the data of the current `request:response` (for example: json text or an image binary) to the hash object.
|
||||
* Adds the current `headers` of the response to the hash object.
|
||||
* If the response data has an `encoding` value, adds the encoding to the hash object.
|
||||
* Calculates the final MD5 hash string as a `contentDigest` javascript variable, and saves it as an `Etag: "<<contentDigest>>"` header.
|
||||
|
||||
If the incoming request contains a header named `if-none-match`, then the server will check the generated Etag against all values.
|
||||
|
||||
If any `if-none-match` value DOES match the current Etag, the server will send a `304 NOT MODIFIED` response with the current response headers, instead of the data with a `200 OK` response.
|
||||
|
||||
This saves bandwidth, as the client can be sure they have already received the exact data and has it in their current cache.
|
||||
|
||||
If ''use-browser-cache=no'' (or any other value including null), then the server will return a `Cache-Control: no-store` header by default.
|
||||
|
||||
If any customer server route module defines custom `Cache-Control` header behavior, then the server will pass that header through instead of the default.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20180626150526207
|
||||
modified: 20181216181934282
|
||||
modified: 20240413043741157
|
||||
tags: ListenCommand ServerCommand Features
|
||||
title: WebServer
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -16,6 +16,7 @@ The ''action-deletefield'' widget is invisible. Any content within it is ignored
|
||||
|!Attribute |!Description |
|
||||
|$tiddler |The title of the tiddler whose fields are to be modified (if not provided defaults to the [[current tiddler|Current Tiddler]]) |
|
||||
|$field |Optional name of a field to delete |
|
||||
|$timestamp |<<.from-version "5.3.4">> 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" |
|
||||
|//{any attributes not starting with $}// |Each attribute name specifies a field to be deleted. The attribute value is ignored and need not be specified |
|
||||
|
||||
! Examples
|
||||
|
||||
42
editions/tw5.com/tiddlers/widgets/DataWidget.tid
Normal file
42
editions/tw5.com/tiddlers/widgets/DataWidget.tid
Normal file
@@ -0,0 +1,42 @@
|
||||
caption: data
|
||||
created: 20240507221902644
|
||||
modified: 20240507221902644
|
||||
tags: Widgets
|
||||
title: DataWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
! Introduction
|
||||
|
||||
The data widget is used with the <<.wlink TestCaseWidget>> widget and the [[Innerwiki Plugin]] to specify payload tiddlers that are to be included in the test case or innerwiki.
|
||||
|
||||
! Content and Attributes
|
||||
|
||||
The content of the data widget is ignored. It supports the following attributes:
|
||||
|
||||
|!Attribute |!Description |
|
||||
|<<.attr $tiddler>> |Optional title of a tiddler to be used as a payload tiddler (optional) |
|
||||
|<<.attr $filter>> |Optional filter string identifying tiddlers to be used as payload tiddlers (optional) |
|
||||
|<<.attr $compound-tiddler>> |Optional title of a tiddler containing payload tiddlers in `text/vnd.tiddlywiki-multiple` format (see below) |
|
||||
|//any attribute<br>not starting<br>with $// |Field values to be assigned to the payload tiddler(s) |
|
||||
|
||||
The data widget is not rendered when used within the <<.wlink TestCaseWidget>> widget or the [[Innerwiki Plugin]] but for ease of testing, when used elsewhere it renders a JSON representation of the payload tiddlers.
|
||||
|
||||
Without any of the attributes <<.attr $tiddler>>, <<.attr $filter>> or <<.attr $compound-tiddler>>, any attributes whose name does not start with $ are used as the field values for creating a single new tiddler.
|
||||
|
||||
<<testcase "TestCases/DataWidget/SimpleTiddler">>
|
||||
|
||||
If any of the attributes <<.attr $tiddler>>, <<.attr $filter>> or <<.attr $compound-tiddler>> are specified then they are used to generate base tiddlers that are then modified with the addition of fields derived from any attributes whose name does not start with $.
|
||||
|
||||
The attribute <<.attr $tiddler>> is used to ingest a single tiddler from the wiki containing the data widget:
|
||||
|
||||
<<testcase "TestCases/DataWidget/ImportedTiddler">>
|
||||
|
||||
The attribute <<.attr $filter>> is used to ingest multiple tiddlers from the wiki containing the data widget:
|
||||
|
||||
<<testcase "TestCases/DataWidget/ImportedFilter">>
|
||||
|
||||
! Compound Tiddlers
|
||||
|
||||
[[Compound tiddlers|CompoundTiddlers]] provide a way to easily create multiple tiddlers from within a single tiddler. They are contained in tiddlers of type `text/vnd.tiddlywiki-multiple`. The text field consists of a series of tiddlers in the same format as `.tid` files, each separated by a line containing a single `+` character.
|
||||
|
||||
<<testcase "TestCases/DataWidget/ImportCompound">>
|
||||
101
editions/tw5.com/tiddlers/widgets/TestCaseWidget.tid
Normal file
101
editions/tw5.com/tiddlers/widgets/TestCaseWidget.tid
Normal file
@@ -0,0 +1,101 @@
|
||||
caption: testcase
|
||||
created: 20240507221902644
|
||||
modified: 20240507221902644
|
||||
tags: Widgets
|
||||
title: TestCaseWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
! Introduction
|
||||
|
||||
The <<.wid testcase>> widget is designed to present interactive example test cases that are useful for learning and testing. It functions by creating an independent subwiki loaded with the specified payload tiddlers and then rendering a specified template from within the subwiki. The <<.wid testcase>> widget can optionally also be used to run and verify test results within the subwiki.
|
||||
|
||||
This makes it possible to run independent tests that also serve as documentation examples.
|
||||
|
||||
The <<.wid testcase>> widget can be used directly as documented below, but it is generally easier to create [[TestCaseTiddlers]]. These are special CompoundTiddlers that can contain multiple payload tiddlers making up a test case.
|
||||
|
||||
!! Features
|
||||
|
||||
Here is an example of a test case showing the default split view with the source tiddlers on the left and the tiddler titled `Output` rendered on the right.
|
||||
|
||||
<<testcase "TestCases/TranscludeWidget/SimpleTransclusion">>
|
||||
|
||||
Notice also that clicking on links within the output pane will switch to the tab containing that tiddler.
|
||||
|
||||
The text of the payload tiddlers listed on the left are editable, with the results being immediately reflected in the preview pane on the right. However, if the <<.wid testcase>> widget is refreshed then the modifications are lost.
|
||||
|
||||
The green tick at the top left of a test case indicates that a test has been set up and that it passes.
|
||||
|
||||
If the test fails, a red cross is shown, and there is a display of the differences between the actual results and the expected results:
|
||||
|
||||
<<testcase "TestCases/TestCaseWidget/FailingTest">>
|
||||
|
||||
! Limitations
|
||||
|
||||
The <<.wid testcase>> widget creates a lightweight TiddlyWiki environment that is a parasite of the main wiki. Because it is not a full, independent TiddlyWiki environment, there are some important limitations:
|
||||
|
||||
* Output is rendered into a DIV, and so cannot be styled independently of the host wiki
|
||||
* Any changes to the wiki made interactively by the user are volatile, and are lost when the <<.wid testcase>> widget is refreshed
|
||||
* Startup actions are not supported
|
||||
* Only plugins available in the host wiki can be included in the test case
|
||||
|
||||
If these limitations are a problem, the [[Innerwiki Plugin]] offers the ability to embed a fully independent subwiki via an `<iframe>` element, but without the testing related features of the <<.wid testcase>> widget.
|
||||
|
||||
! Content and Attributes
|
||||
|
||||
The content of the `<$testcase>` widget is not displayed but instead is scanned for <<.wlink DataWidget>> widgets that define the payload tiddlers to be included in the test case.
|
||||
|
||||
|!Attribute |!Description |
|
||||
|<<.attr template>> |Optional title of the template used to display the test case (defaults to $:/core/ui/testcases/DefaultTemplate). Note that custom templates will need to be explicitly added to the payload |
|
||||
|<<.attr testOutput>> |Optional title of the tiddler whose output should be subject to testing (note that both <<.attr testOutput>> and <<.attr testExpectedResult>> must be provided in order for testing to occur) |
|
||||
|<<.attr testExpectedResult>> |Optional title of the tiddler whose content is the expected result of rendering the output tiddler (note that both <<.attr testOutput>> and <<.attr testExpectedResult>> must be provided in order for testing to occur) |
|
||||
|<<.attr testActions>> |Optional title of the tiddler containing actions that should be executed before the test occurs |
|
||||
|<<.attr testHideIfPass>> |If set to "yes", hides the <<.wid testcase>> widget if the test passes |
|
||||
|
||||
! Payload Tiddlers
|
||||
|
||||
The payload tiddlers are the tiddler values that are loaded into the subwiki that is created to run the tests. They are created via <<.wlink DataWidget>> widgets within the body of the `<$testcase>` widget. The `$:/core` plugin is automatically included in the payload.
|
||||
|
||||
! Testcase Templates
|
||||
|
||||
The <<.attr template>> attribute defaults to $:/core/ui/testcases/DefaultTemplate
|
||||
|
||||
The default test case template assigns special meanings to a number of payload tiddlers:
|
||||
|
||||
|!Tiddler |!Description |
|
||||
|''Description'' |Descriptive heading for the test, intended to make it easy to identify the test |
|
||||
|''Narrative'' |Narrative description of the test, intended to explain the purpose and operation of the test |
|
||||
|''Output'' |The tiddler that produces the test output |
|
||||
|''~ExpectedResult'' |HTML of expected result of rendering the ''Output'' tiddler |
|
||||
|
||||
The test case wiki will inherit variables that are visible to the <<.wid testcase>> widget itself. The default template uses several variables that can be set by the user:
|
||||
|
||||
|!Variable |!Description |
|
||||
|<<.var linkTarget>> |Causes the test case description to be rendered as a link to the current tiddler |
|
||||
|<<.var displayFormat>> |Defaults to "wikitext", can also be "plaintext" to force plain text display |
|
||||
|
||||
A custom template can be specified for special purposes. For example, the provided template $:/core/ui/testcases/RawJSONTemplate just displays the payload tiddlers in JSON, which can be used for debugging purposes.
|
||||
|
||||
! Test Czase Template Variables
|
||||
|
||||
The <<.wid testcase>> widget makes the following variables available within the rendered template:
|
||||
|
||||
|!Variable |!Description |
|
||||
|<<.var transclusion>> |A hash that reflects the names and values of all the payload tiddlers. This makes it easier for test case templates to create unique state tiddler titles using the [[qualify Macro]] or QualifyWidget |
|
||||
|<<.var payloadTiddlers>> |JSON array of payload tiddler fields |
|
||||
|<<.var outputHTML>> |The actual output HTML if running tests |
|
||||
|<<.var expectedHTML>> |The expected output HTML if running tests |
|
||||
|<<.var testResult>> |The tests result if running tests (may be "pass" or "fail") |
|
||||
|
||||
! Example
|
||||
|
||||
Here is an example of setting up a test case that includes expected test results:
|
||||
|
||||
<$testcase>
|
||||
<$data title="Description" text="Example of a test case with expected results"/>
|
||||
<$data title="Output" text="""<$testcase testOutput="Output" testExpectedResult="ExpectedResult">
|
||||
<$data title="Description" text="How to calculate 2 plus 2"/>
|
||||
<$data title="Output" text="<$text text={{{ [[2]add[2]] }}}/>"/>
|
||||
<$data title="ExpectedResult" text="<p>8</p>"/>
|
||||
</$testcase>
|
||||
"""/>
|
||||
</$testcase>
|
||||
@@ -1,14 +1,14 @@
|
||||
created: 20140908130500000
|
||||
modified: 20150219182745000
|
||||
modified: 20240326164134356
|
||||
tags: Concepts Reference
|
||||
title: Widgets
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
~TiddlyWiki's display is driven by an underlying collection of <<.def widgets>>. These are organised into a tree structure: each widget has a parent widget and zero or more child widgets.
|
||||
|
||||
~TiddlyWiki generates this <<.def "widget tree">> by parsing the WikiText of tiddlers. Each component of the WikiText syntax, including even the trivial case of ordinary text, generates a corresponding widget. The widget tree is an intermediate representation that is subsequently rendered into the actual display.
|
||||
~TiddlyWiki generates this <<.def "widget tree">> by parsing the ~WikiText of tiddlers. Each component of the ~WikiText syntax, including even the trivial case of ordinary text, generates a corresponding widget. The widget tree is an intermediate representation that is subsequently rendered into the actual display.
|
||||
|
||||
Widgets are analogous to elements in an HTML document. Indeed, HTML tags in WikiText generate dedicated <<.def "element widgets">>.
|
||||
Widgets are analogous to elements in an HTML document. Indeed, HTML tags in ~WikiText generate dedicated <<.def "element widgets">>.
|
||||
|
||||
Each class of widget contributes a specific ability to the overall functionality, such as the ability to <<.wlink2 "display an image" ImageWidget>> or <<.wlink2 "a button" ButtonWidget>>, to <<.wlink2 "call a macro" MacroCallWidget>> or <<.wlink2 "transclude text from elsewhere" TranscludeWidget>>, or to [[mark a piece of text as a heading|HTML in WikiText]].
|
||||
|
||||
@@ -16,4 +16,4 @@ The more specialised widgets use a general-purpose [[widget syntax|Widgets in Wi
|
||||
|
||||
The following classes of widget are built into the core:
|
||||
|
||||
<<list-links "[tag[Widgets]]">>
|
||||
<<list-links "[tag[Widgets]]" class:"multi-columns">>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: Block Quotes
|
||||
created: 20131206154636572
|
||||
modified: 20170417165145317
|
||||
modified: 20240512000910702
|
||||
tags: WikiText
|
||||
title: Block Quotes in WikiText
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -72,3 +72,34 @@ You can also mix block quotes with other list items. For example:
|
||||
**> Another quote
|
||||
* List Three
|
||||
">>
|
||||
|
||||
! Advanced Wikitext and Block Quotes
|
||||
You can also mix block quotes with paragraphs and other block wikitext. Be mindful of block mode - if other quoted content follows a paragraph, end it with a blank line. The final paragraph in the quote does not need to end with a blank line. If using indentation, make sure __not to indent the blank lines__. The parser will interpret this as additional inline content and not return to block mode. For example:
|
||||
|
||||
<<wikitext-example src:'<<< Mixing Block Quotes with Inline Wikitext
|
||||
A paragraph appears before other //wikitext//, which needs to end with a blank line.
|
||||
|
||||
* List One
|
||||
** List Two
|
||||
**> A quote
|
||||
"""
|
||||
A poem
|
||||
with line beaks
|
||||
needs to have
|
||||
a blank line after
|
||||
the final quotes
|
||||
if followed
|
||||
by other content
|
||||
"""
|
||||
|
||||
<<<< Deep Block Quote
|
||||
A paragraph before other //wikitext//, which ends with a blank line.
|
||||
|
||||
! A Header
|
||||
Another paragraph, which needs to end with a blank line.
|
||||
|
||||
!! Sub Header
|
||||
A final paragraph, which __does not__ need to end with a blank line as the Block Quote ends.
|
||||
<<<<
|
||||
<<<
|
||||
'>>
|
||||
@@ -1,9 +1,9 @@
|
||||
caption: Hard Linebreaks
|
||||
created: 20131214165710101
|
||||
modified: 20131214170106553
|
||||
modified: 20240512001649319
|
||||
tags: WikiText
|
||||
title: Hard Linebreaks in WikiText
|
||||
type: text/vnd.tiddlywiki
|
||||
caption: Hard Linebreaks
|
||||
|
||||
The usual handling of [[paragraphs in wikitext|Paragraphs in WikiText]] causes single line breaks to be ignored, and double linebreaks to be interpreted as the end of a paragraph.
|
||||
|
||||
@@ -15,4 +15,8 @@ and this is a new line
|
||||
while this is yet another line
|
||||
and this is the final one
|
||||
apart from this one
|
||||
"""'>>
|
||||
"""
|
||||
|
||||
'>>
|
||||
|
||||
<<.tip 'Note: <strong>Hard Linebreaks in ~WikiText</strong> require an extra blank line after the trailing `"""` before the parser will return to [[block mode|Block Mode WikiText]].'>>.
|
||||
@@ -1,6 +1,6 @@
|
||||
caption: block parser mode
|
||||
created: 20220110234234616
|
||||
modified: 20220122182842032
|
||||
modified: 20240512001555383
|
||||
tags: [[WikiText Parser Modes]]
|
||||
title: Block Mode WikiText
|
||||
type: text/vnd.tiddlywiki
|
||||
@@ -28,7 +28,7 @@ Common characteristics of such block mode WikiText:
|
||||
The above WikiText types are only recognised in ''block mode''. However, the text <<.em enclosed>> by most of them will be parsed in ''inline mode'' ([[Block Quotes in WikiText]] and [[Styles and Classes in WikiText]] are the two exceptions in which the parser will continue in ''block mode''). While in ''inline mode'' the parser may encounter something which moves it to ''block mode'' (see [[WikiText parser mode transitions]]).
|
||||
|
||||
At the end of the terminating line, the parser will return to ''block mode''.
|
||||
<<.tip 'Note: [[Hard Linebreaks in WikiText]] require an extra blank line after the trailing `"""` before the parser will return to <b>block mode</b>'>>.
|
||||
<<.tip 'Note: [[Hard Linebreaks in WikiText]] require an extra blank line after the trailing `"""` before the parser will return to <strong>block mode</strong>.'>>
|
||||
|
||||
If the punctuation for the above types of WikiText is encountered while the parser is in ''inline mode'', it will be //ignored// and output as-is.
|
||||
|
||||
|
||||
@@ -31,46 +31,46 @@ Date/DaySuffix/28: .
|
||||
Date/DaySuffix/29: .
|
||||
Date/DaySuffix/30: .
|
||||
Date/DaySuffix/31: .
|
||||
Date/Long/Day/0: Niedziela
|
||||
Date/Long/Day/1: Poniedziałek
|
||||
Date/Long/Day/2: Wtorek
|
||||
Date/Long/Day/3: Środa
|
||||
Date/Long/Day/4: Czwartek
|
||||
Date/Long/Day/5: Piątek
|
||||
Date/Long/Day/6: Sobota
|
||||
Date/Long/Month/1: Styczeń
|
||||
Date/Long/Month/2: Luty
|
||||
Date/Long/Month/3: Marzec
|
||||
Date/Long/Month/4: Kwiecień
|
||||
Date/Long/Month/5: Maj
|
||||
Date/Long/Month/6: Czerwiec
|
||||
Date/Long/Month/7: Lipiec
|
||||
Date/Long/Month/8: Sierpień
|
||||
Date/Long/Month/9: Wrzesień
|
||||
Date/Long/Month/10: Październik
|
||||
Date/Long/Month/11: Listopad
|
||||
Date/Long/Month/12: Grudzień
|
||||
Date/Period/am: AM
|
||||
Date/Period/pm: PM
|
||||
Date/Short/Day/0: nd
|
||||
Date/Short/Day/1: pn
|
||||
Date/Short/Day/2: wt
|
||||
Date/Short/Day/3: śr
|
||||
Date/Short/Day/4: cz
|
||||
Date/Short/Day/5: pt
|
||||
Date/Short/Day/6: sb
|
||||
Date/Short/Month/1: st
|
||||
Date/Short/Month/2: lut
|
||||
Date/Short/Month/3: mrz
|
||||
Date/Short/Month/4: kw
|
||||
Date/Short/Month/5: maj
|
||||
Date/Short/Month/6: cz
|
||||
Date/Short/Month/7: lip
|
||||
Date/Short/Month/8: sier
|
||||
Date/Short/Month/9: wrz
|
||||
Date/Short/Month/10: paź
|
||||
Date/Short/Month/11: lis
|
||||
Date/Short/Month/12: gr
|
||||
Date/Long/Day/0: niedziela
|
||||
Date/Long/Day/1: poniedziałek
|
||||
Date/Long/Day/2: wtorek
|
||||
Date/Long/Day/3: środa
|
||||
Date/Long/Day/4: czwartek
|
||||
Date/Long/Day/5: piątek
|
||||
Date/Long/Day/6: sobota
|
||||
Date/Long/Month/1: stycznia
|
||||
Date/Long/Month/2: lutego
|
||||
Date/Long/Month/3: marca
|
||||
Date/Long/Month/4: kwietnia
|
||||
Date/Long/Month/5: maja
|
||||
Date/Long/Month/6: czerwca
|
||||
Date/Long/Month/7: lipca
|
||||
Date/Long/Month/8: sierpnia
|
||||
Date/Long/Month/9: września
|
||||
Date/Long/Month/10: października
|
||||
Date/Long/Month/11: listopada
|
||||
Date/Long/Month/12: grudnia
|
||||
Date/Period/am: rano
|
||||
Date/Period/pm: po południu
|
||||
Date/Short/Day/0: niedz.
|
||||
Date/Short/Day/1: pon.
|
||||
Date/Short/Day/2: wt.
|
||||
Date/Short/Day/3: śr.
|
||||
Date/Short/Day/4: czw.
|
||||
Date/Short/Day/5: pt.
|
||||
Date/Short/Day/6: sob.
|
||||
Date/Short/Month/1: I
|
||||
Date/Short/Month/2: II
|
||||
Date/Short/Month/3: III
|
||||
Date/Short/Month/4: IV
|
||||
Date/Short/Month/5: V
|
||||
Date/Short/Month/6: VI
|
||||
Date/Short/Month/7: VII
|
||||
Date/Short/Month/8: VIII
|
||||
Date/Short/Month/9: IX
|
||||
Date/Short/Month/10: X
|
||||
Date/Short/Month/11: XI
|
||||
Date/Short/Month/12: XII
|
||||
RelativeDate/Future/Days: <<period>> dni od teraz
|
||||
RelativeDate/Future/Hours: <<period>> godzin od teraz
|
||||
RelativeDate/Future/Minutes: <<period>> minut od teraz
|
||||
@@ -79,7 +79,7 @@ RelativeDate/Future/Second: 1 sekunda od teraz
|
||||
RelativeDate/Future/Seconds: <<period>> sekund od teraz
|
||||
RelativeDate/Future/Years: <<period>> lat od teraz
|
||||
RelativeDate/Past/Days: <<period>> dni temu
|
||||
RelativeDate/Past/Hours: <<period>> godizn temu
|
||||
RelativeDate/Past/Hours: <<period>> godzin temu
|
||||
RelativeDate/Past/Minutes: <<period>> minut temu
|
||||
RelativeDate/Past/Months: <<period>> miesięcy temu
|
||||
RelativeDate/Past/Second: 1 sekundę temu
|
||||
|
||||
@@ -563,3 +563,9 @@ John Long, @drevarr, 2023/12/12
|
||||
Ed Holsinger, @eschlon, 2024/02/08
|
||||
|
||||
Kim I. McKinley, @PotOfCoffee2Go, 2024/03/16
|
||||
|
||||
@Jinix6, 2024/03/31
|
||||
|
||||
Anders Jarmund, @andjar, 2024/04/05
|
||||
|
||||
@sarna, 2024/04/28
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "Async",
|
||||
"description": "async.js library",
|
||||
"author": "Caolan McMahon",
|
||||
"list": "readme license"
|
||||
"list": "readme license",
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "AWS",
|
||||
"description": "Amazon Web Services extensions and tools",
|
||||
"list": "readme setup commands lambda",
|
||||
"dependents": ["$:/plugins/tiddlywiki/async","$:/plugins/tiddlywiki/jszip"]
|
||||
"dependents": ["$:/plugins/tiddlywiki/async","$:/plugins/tiddlywiki/jszip"],
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"name": "BibTeX",
|
||||
"description": "BibTeX importer",
|
||||
"author": "Henrik Muehe and Mikola Lysenko",
|
||||
"list": "readme license"
|
||||
"list": "readme license",
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"title": "$:/plugins/tiddlywiki/blog",
|
||||
"name": "Blog",
|
||||
"description": "Blog publishing tools",
|
||||
"list": "readme docs"
|
||||
"list": "readme docs",
|
||||
"stability": "STABILITY_0_DEPRECATED"
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"title": "$:/plugins/tiddlywiki/browser-sniff",
|
||||
"name": "Browser Sniff",
|
||||
"description": "Browser feature detection",
|
||||
"list": "readme usage"
|
||||
"list": "readme usage",
|
||||
"stability": "STABILITY_2_STABLE"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user