mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-23 11:24:40 +00:00
Compare commits
1 Commits
built-in-l
...
twitter-ar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f922149b32 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,4 +4,3 @@
|
||||
tmp/
|
||||
output/
|
||||
node_modules/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# Default to the current version number for building the plugin library
|
||||
|
||||
if [ -z "$TW5_BUILD_VERSION" ]; then
|
||||
TW5_BUILD_VERSION=v5.2.4
|
||||
TW5_BUILD_VERSION=v5.2.3
|
||||
fi
|
||||
|
||||
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
|
||||
@@ -459,7 +459,7 @@ node $TW5_BUILD_TIDDLYWIKI \
|
||||
--verbose \
|
||||
--load $TW5_BUILD_OUTPUT/build.tid \
|
||||
--output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \
|
||||
--build library\
|
||||
--build \
|
||||
|| exit 1
|
||||
|
||||
# Delete the temporary build tiddler
|
||||
|
||||
@@ -9,7 +9,6 @@ node ./tiddlywiki.js \
|
||||
--verbose \
|
||||
--version \
|
||||
--rendertiddler $:/core/save/all test.html text/plain \
|
||||
--test \
|
||||
|| exit 1
|
||||
|
||||
echo To run the tests in a browser, open "editions/test/output/test.html"
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
title: $:/core/images/layout-button
|
||||
tags: $:/tags/Image
|
||||
|
||||
<svg width="22pt" height="22pt" class="tc-image-layout-button tc-image-button" viewBox="0 0 24 24" stroke-width="1" stroke="none"><path d="M0 0h24v24H0z" fill="none"/><rect x="2" y="2" width="7" height="7" rx="2"/><rect x="2" y="13" width="7" height="9" rx="2"/><rect x="12" y="2" width="10" height="20" rx="2"/></svg>
|
||||
@@ -1,6 +0,0 @@
|
||||
title: $:/core/images/mastodon
|
||||
tags: $:/tags/Image
|
||||
|
||||
<svg width="22pt" height="22pt" class="tc-image-mastodon tc-image-button" viewBox="0 0 128 128">
|
||||
<path d="M112.716,76.735C111.231,85.764 99.411,95.646 85.836,97.561C78.757,98.559 71.787,99.476 64.355,99.073C52.201,98.415 42.61,95.646 42.61,95.646C42.61,97.044 42.683,98.374 42.829,99.619C44.409,113.79 54.723,114.639 64.493,115.035C74.354,115.434 83.134,112.163 83.134,112.163L83.539,122.695C83.539,122.695 76.642,127.071 64.355,127.875C57.58,128.315 49.167,127.674 39.369,124.61C18.118,117.965 14.463,91.202 13.904,64.048C13.733,55.985 13.839,48.383 13.839,42.024C13.839,14.257 29.238,6.118 29.238,6.118C37.002,1.905 50.326,0.134 64.177,-0L64.517,-0C78.369,0.134 91.701,1.905 99.465,6.118C99.465,6.118 114.864,14.257 114.864,42.024C114.864,42.024 115.057,62.511 112.716,76.735ZM96.7,44.179C96.7,37.307 95.219,31.847 92.245,27.807C89.177,23.767 85.16,21.696 80.174,21.696C74.403,21.696 70.034,24.316 67.146,29.556L64.337,35.118L61.529,29.556C58.64,24.316 54.271,21.696 48.501,21.696C43.514,21.696 39.497,23.767 36.43,27.807C33.455,31.847 31.974,37.307 31.974,44.179L31.974,77.8L43.249,77.8L43.249,45.167C43.249,38.288 45.699,34.796 50.599,34.796C56.017,34.796 58.733,38.938 58.733,47.128L58.733,64.99L69.941,64.99L69.941,47.128C69.941,38.938 72.657,34.796 78.075,34.796C82.975,34.796 85.425,38.288 85.425,45.167L85.425,77.8L96.7,77.8L96.7,44.179Z"/>
|
||||
</svg>
|
||||
@@ -59,8 +59,6 @@ Home/Caption: home
|
||||
Home/Hint: Open the default tiddlers
|
||||
Language/Caption: language
|
||||
Language/Hint: Choose the user interface language
|
||||
LayoutSwitcher/Hint: Open layout switcher
|
||||
LayoutSwitcher/Caption: layout
|
||||
Manager/Caption: tiddler manager
|
||||
Manager/Hint: Open tiddler manager
|
||||
More/Caption: more
|
||||
|
||||
@@ -7,7 +7,7 @@ Appearance/Hint: Ways to customise the appearance of your TiddlyWiki.
|
||||
Basics/AnimDuration/Prompt: Animation duration
|
||||
Basics/AutoFocus/Prompt: Default focus field for new tiddlers
|
||||
Basics/Caption: Basics
|
||||
Basics/DefaultTiddlers/BottomHint: Use [[double square brackets]] for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}}
|
||||
Basics/DefaultTiddlers/BottomHint: Use [[double square brackets]] for titles with spaces. Or you can choose to <$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]">retain story ordering</$button>
|
||||
Basics/DefaultTiddlers/Prompt: Default tiddlers
|
||||
Basics/DefaultTiddlers/TopHint: Choose which tiddlers are displayed at startup
|
||||
Basics/Language/Prompt: Hello! Current language:
|
||||
@@ -90,8 +90,8 @@ Plugins/Languages/Caption: Languages
|
||||
Plugins/Languages/Hint: Language pack plugins
|
||||
Plugins/NoInfoFound/Hint: No ''"<$text text=<<currentTab>>/>"'' found
|
||||
Plugins/NotInstalled/Hint: This plugin is not currently installed
|
||||
Plugins/OpenPluginLibrary: Open plugin library
|
||||
Plugins/ClosePluginLibrary: Close plugin library
|
||||
Plugins/OpenPluginLibrary: open plugin library
|
||||
Plugins/ClosePluginLibrary: close plugin library
|
||||
Plugins/PluginWillRequireReload: (requires reload)
|
||||
Plugins/Plugins/Caption: Plugins
|
||||
Plugins/Plugins/Hint: Plugins
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
title: $:/language/Help/commands
|
||||
description: Run commands returned from a filter
|
||||
|
||||
Sequentially run the command tokens returned from a filter
|
||||
|
||||
```
|
||||
--commands <filter>
|
||||
```
|
||||
|
||||
Examples
|
||||
|
||||
```
|
||||
--commands "[enlist{$:/build-commands-as-text}]"
|
||||
```
|
||||
|
||||
```
|
||||
--commands "[{$:/build-commands-as-json}jsonindexes[]] :map[{$:/build-commands-as-json}jsonget<currentTiddler>]"
|
||||
```
|
||||
@@ -1,42 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/commands.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Runs the commands returned from a filter
|
||||
|
||||
\*/
|
||||
|
||||
(function() {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "commands",
|
||||
synchronous: true
|
||||
};
|
||||
|
||||
var Command = function(params, commander) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
// Parse the filter
|
||||
var filter = this.params[0];
|
||||
if(!filter) {
|
||||
return "No filter specified";
|
||||
}
|
||||
var commands = this.commander.wiki.filterTiddlers(filter)
|
||||
if(commands.length === 0) {
|
||||
return "No tiddlers found for filter '" + filter + "'";
|
||||
}
|
||||
this.commander.addCommandTokens(commands);
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -298,7 +298,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
|
||||
Propogate keydown events to our container for the keyboard widgets benefit
|
||||
*/
|
||||
EditTextWidget.prototype.propogateKeydownEvent = function(event) {
|
||||
var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]);
|
||||
var newEvent = this.cloneEvent(event,["keyCode","which","metaKey","ctrlKey","altKey","shiftKey"]);
|
||||
return !this.parentDomNode.dispatchEvent(newEvent);
|
||||
};
|
||||
|
||||
|
||||
@@ -17,23 +17,9 @@ exports["jsonget"] = function(source,operator,options) {
|
||||
source(function(tiddler,title) {
|
||||
var data = $tw.utils.parseJSONSafe(title,title);
|
||||
if(data) {
|
||||
var items = getDataItemValueAsStrings(data,operator.operands);
|
||||
if(items !== undefined) {
|
||||
results.push.apply(results,items);
|
||||
}
|
||||
}
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
exports["jsonextract"] = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
var data = $tw.utils.parseJSONSafe(title,title);
|
||||
if(data) {
|
||||
var item = getDataItem(data,operator.operands);
|
||||
var item = getDataItemValueAsString(data,operator.operands);
|
||||
if(item !== undefined) {
|
||||
results.push(JSON.stringify(item));
|
||||
results.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -45,9 +31,9 @@ exports["jsonindexes"] = function(source,operator,options) {
|
||||
source(function(tiddler,title) {
|
||||
var data = $tw.utils.parseJSONSafe(title,title);
|
||||
if(data) {
|
||||
var items = getDataItemKeysAsStrings(data,operator.operands);
|
||||
if(items !== undefined) {
|
||||
results.push.apply(results,items);
|
||||
var item = getDataItemKeysAsStrings(data,operator.operands);
|
||||
if(item !== undefined) {
|
||||
results.push.apply(results,item);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -71,11 +57,11 @@ exports["jsontype"] = function(source,operator,options) {
|
||||
/*
|
||||
Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid
|
||||
*/
|
||||
function getDataItemValueAsStrings(data,indexes) {
|
||||
function getDataItemValueAsString(data,indexes) {
|
||||
// Get the item
|
||||
var item = getDataItem(data,indexes);
|
||||
// Return the item as a string list
|
||||
return convertDataItemValueToStrings(item);
|
||||
// Return the item as a string
|
||||
return convertDataItemValueToString(item);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -91,34 +77,15 @@ function getDataItemKeysAsStrings(data,indexes) {
|
||||
/*
|
||||
Return an array of the string representation of the values of a data item, or "undefined" if the item is undefined
|
||||
*/
|
||||
function convertDataItemValueToStrings(item) {
|
||||
function convertDataItemValueToString(item) {
|
||||
// Return the item as a string
|
||||
if(item === undefined) {
|
||||
return undefined;
|
||||
} else if(item === null) {
|
||||
return ["null"]
|
||||
} else if(typeof item === "object") {
|
||||
var results = [],i,t;
|
||||
if($tw.utils.isArray(item)) {
|
||||
// Return all the items in arrays recursively
|
||||
for(i=0; i<item.length; i++) {
|
||||
t = convertDataItemValueToStrings(item[i])
|
||||
if(t !== undefined) {
|
||||
results.push.apply(results,t);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Return all the values in objects recursively
|
||||
$tw.utils.each(Object.keys(item).sort(),function(key) {
|
||||
t = convertDataItemValueToStrings(item[key]);
|
||||
if(t !== undefined) {
|
||||
results.push.apply(results,t);
|
||||
}
|
||||
});
|
||||
}
|
||||
return results;
|
||||
return item;
|
||||
}
|
||||
return [item.toString()];
|
||||
if(typeof item === "object") {
|
||||
return JSON.stringify(item);
|
||||
}
|
||||
return item.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/library.js
|
||||
type: application/javascript
|
||||
module-type: global
|
||||
|
||||
Library handling utilities
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
function Library(options) {
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
Library.prototype.getLibraryItems = function() {
|
||||
if(!this.items) {
|
||||
this.loadLibraryItems();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
Library.prototype.loadLibraryItems = function() {
|
||||
var self = this,
|
||||
fs = require("fs"),
|
||||
path = require("path");
|
||||
// Collect the library items from disk
|
||||
this.items = {};
|
||||
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) {
|
||||
self.items[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);
|
||||
// Compile the metadata
|
||||
this.itemMetadata = [];
|
||||
$tw.utils.each(Object.keys(self.items),function(title) {
|
||||
var tiddler = self.items[title];
|
||||
// Collect the skinny list data
|
||||
var pluginTiddlers = $tw.utils.parseJSONSafe(tiddler.text),
|
||||
readmeContent = (pluginTiddlers.tiddlers[title + "/readme"] || {}).text,
|
||||
doesRequireReload = !!$tw.wiki.doesPluginInfoRequireReload(pluginTiddlers),
|
||||
iconTiddler = pluginTiddlers.tiddlers[title + "/icon"] || {},
|
||||
iconType = iconTiddler.type,
|
||||
iconText = iconTiddler.text,
|
||||
iconContent;
|
||||
if(iconType && iconText) {
|
||||
iconContent = $tw.utils.makeDataUri(iconText,iconType);
|
||||
}
|
||||
self.itemMetadata.push($tw.utils.extend({},tiddler,{
|
||||
text: undefined,
|
||||
readme: readmeContent,
|
||||
"requires-reload": doesRequireReload ? "yes" : "no",
|
||||
icon: iconContent
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
Library.prototype.getMetadata = function() {
|
||||
this.loadLibraryItems();
|
||||
return this.itemMetadata;
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
Library.prototype.getItem = function(title) {
|
||||
this.loadLibraryItems();
|
||||
if($tw.utils.hop(this.items,title)) {
|
||||
return this.items[title];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
exports.Library = Library;
|
||||
|
||||
})();
|
||||
@@ -13,11 +13,6 @@ The CSV text parser processes CSV files into a table wrapped in a scrollable wid
|
||||
"use strict";
|
||||
|
||||
var CsvParser = function(type,text,options) {
|
||||
// Special handler for tab-delimited files
|
||||
if (type === 'text/tab-delimited-values' && !options.separator) {
|
||||
options.separator = "\t";
|
||||
}
|
||||
|
||||
// Table framework
|
||||
this.tree = [{
|
||||
"type": "scrollable", "children": [{
|
||||
@@ -29,33 +24,30 @@ var CsvParser = function(type,text,options) {
|
||||
}]
|
||||
}];
|
||||
// Split the text into lines
|
||||
var lines = $tw.utils.parseCsvString(text, options),
|
||||
var lines = text.split(/\r?\n/mg),
|
||||
tag = "th";
|
||||
var maxColumns = 0;
|
||||
$tw.utils.each(lines, function(columns) {
|
||||
maxColumns = Math.max(columns.length, maxColumns);
|
||||
});
|
||||
|
||||
for(var line=0; line<lines.length; line++) {
|
||||
var columns = lines[line];
|
||||
var row = {
|
||||
"type": "element", "tag": "tr", "children": []
|
||||
};
|
||||
for(var column=0; column<maxColumns; column++) {
|
||||
row.children.push({
|
||||
"type": "element", "tag": tag, "children": [{
|
||||
"type": "text",
|
||||
"text": columns[column] || ''
|
||||
}]
|
||||
});
|
||||
var lineText = lines[line];
|
||||
if(lineText) {
|
||||
var row = {
|
||||
"type": "element", "tag": "tr", "children": []
|
||||
};
|
||||
var columns = lineText.split(",");
|
||||
for(var column=0; column<columns.length; column++) {
|
||||
row.children.push({
|
||||
"type": "element", "tag": tag, "children": [{
|
||||
"type": "text",
|
||||
"text": columns[column]
|
||||
}]
|
||||
});
|
||||
}
|
||||
tag = "td";
|
||||
this.tree[0].children[0].children[0].children.push(row);
|
||||
}
|
||||
tag = "td";
|
||||
this.tree[0].children[0].children[0].children.push(row);
|
||||
}
|
||||
};
|
||||
|
||||
exports["text/csv"] = CsvParser;
|
||||
exports["text/tab-delimited-values"] = CsvParser;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ exports.parse = function() {
|
||||
var reEnd;
|
||||
if(this.match[3]) {
|
||||
// If so, the end of the body is marked with \end
|
||||
reEnd = new RegExp("(\\r?\\n\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg");
|
||||
reEnd = /(\r?\n\\end[^\S\n\r]*(?:$|\r?\n))/mg;
|
||||
} else {
|
||||
// Otherwise, the end of the definition is marked by the end of the line
|
||||
reEnd = /($|\r?\n)/mg;
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/parsers/wikiparser/rules/parsermode.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki pragma rule for parser mode specifications
|
||||
|
||||
```
|
||||
\parsermode block
|
||||
\parsermode inline
|
||||
```
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.name = "parsermode";
|
||||
exports.types = {pragma: true};
|
||||
|
||||
/*
|
||||
Instantiate parse rule
|
||||
*/
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /^\\parsermode[^\S\n]/mg;
|
||||
};
|
||||
|
||||
/*
|
||||
Parse the most recent match
|
||||
*/
|
||||
exports.parse = function() {
|
||||
// Move past the pragma invocation
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
// Parse whitespace delimited tokens terminated by a line break
|
||||
var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
|
||||
parserMode = undefined;
|
||||
reMatch.lastIndex = this.parser.pos;
|
||||
var match = reMatch.exec(this.parser.source);
|
||||
while(match && match.index === this.parser.pos) {
|
||||
this.parser.pos = reMatch.lastIndex;
|
||||
// Exit if we've got the line break
|
||||
if(match[2]) {
|
||||
break;
|
||||
}
|
||||
// Process the token
|
||||
if(match[1]) {
|
||||
parserMode = match[1];
|
||||
}
|
||||
// Match the next token
|
||||
match = reMatch.exec(this.parser.source);
|
||||
}
|
||||
// Process the tokens
|
||||
if(parserMode !== undefined) {
|
||||
if(parserMode === "block") {
|
||||
this.parser.parseAsInline = false;
|
||||
} else if(parserMode === "inline") {
|
||||
this.parser.parseAsInline = true;
|
||||
}
|
||||
}
|
||||
// No parse tree nodes to return
|
||||
return [];
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -47,8 +47,6 @@ var WikiParser = function(type,text,options) {
|
||||
this.sourceLength = this.source.length;
|
||||
// Flag for ignoring whitespace
|
||||
this.configTrimWhiteSpace = false;
|
||||
// Parser mode
|
||||
this.parseAsInline = options.parseAsInline;
|
||||
// Set current parse position
|
||||
this.pos = 0;
|
||||
// Start with empty output
|
||||
@@ -85,7 +83,7 @@ var WikiParser = function(type,text,options) {
|
||||
// Parse any pragmas
|
||||
var topBranch = this.parsePragmas();
|
||||
// Parse the text into inline runs or blocks
|
||||
if(this.parseAsInline) {
|
||||
if(options.parseAsInline) {
|
||||
topBranch.push.apply(topBranch,this.parseInlineRun());
|
||||
} else {
|
||||
topBranch.push.apply(topBranch,this.parseBlocks());
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/server/routes/get-library-html.js
|
||||
type: application/javascript
|
||||
module-type: route
|
||||
|
||||
GET /library/{:title}
|
||||
|
||||
\*/
|
||||
(function() {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/library$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var text = state.wiki.getTiddlerText("$:/core/templates/library.template.html","");
|
||||
state.sendResponse(200,{"Content-Type": "text/html"},text,"utf8");
|
||||
};
|
||||
|
||||
}());
|
||||
@@ -1,31 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/server/routes/get-library-item.js
|
||||
type: application/javascript
|
||||
module-type: route
|
||||
|
||||
GET /library
|
||||
|
||||
\*/
|
||||
(function() {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/library\/(.+)$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var title = $tw.utils.decodeURIComponentSafe($tw.utils.decodeURIComponentSafe(state.params[0])),
|
||||
item = $tw.library.getItem(title);
|
||||
if(item) {
|
||||
var text = JSON.stringify(item);
|
||||
state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8");
|
||||
} else {
|
||||
response.writeHead(404);
|
||||
response.end();
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
@@ -1,24 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/server/routes/get-library.js
|
||||
type: application/javascript
|
||||
module-type: route
|
||||
|
||||
GET /library
|
||||
|
||||
\*/
|
||||
(function() {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/library\/$/;
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var text = JSON.stringify($tw.library.getMetadata());
|
||||
state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8");
|
||||
};
|
||||
|
||||
}());
|
||||
@@ -119,15 +119,9 @@ exports.startup = function() {
|
||||
$tw.syncadaptor = new module.adaptorClass({wiki: $tw.wiki});
|
||||
}
|
||||
});
|
||||
// Kick off the library manager
|
||||
$tw.library = new $tw.Library();
|
||||
// Set up the syncer object if we've got a syncadaptor
|
||||
if($tw.syncadaptor) {
|
||||
$tw.syncer = new $tw.Syncer({
|
||||
wiki: $tw.wiki,
|
||||
syncadaptor: $tw.syncadaptor,
|
||||
logging: $tw.wiki.getTiddlerText('$:/config/SyncLogging', "yes") === "yes"
|
||||
});
|
||||
$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});
|
||||
}
|
||||
// Setup the saver handler
|
||||
$tw.saverHandler = new $tw.SaverHandler({
|
||||
|
||||
@@ -12,113 +12,35 @@ A barebones CSV parser
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var QUOTE = '"';
|
||||
|
||||
var getCellInfo = function(text, start, length, SEPARATOR) {
|
||||
var isCellQuoted = text.charAt(start) === QUOTE;
|
||||
var cellStart = isCellQuoted ? start + 1 : start;
|
||||
|
||||
if (text.charAt(i) === SEPARATOR) {
|
||||
return [cellStart, cellStart, false];
|
||||
}
|
||||
|
||||
for (var i = cellStart; i < length; i++) {
|
||||
var cellCharacter = text.charAt(i);
|
||||
var isEOL = cellCharacter === "\n" || cellCharacter === "\r";
|
||||
|
||||
if (isEOL && !isCellQuoted) {
|
||||
return [cellStart, i, false];
|
||||
|
||||
} else if (cellCharacter === SEPARATOR && !isCellQuoted) {
|
||||
return [cellStart, i, false];
|
||||
|
||||
} else if (cellCharacter === QUOTE && isCellQuoted) {
|
||||
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
|
||||
if (nextCharacter !== QUOTE) {
|
||||
return [cellStart, i, true];
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [cellStart, i, isCellQuoted];
|
||||
}
|
||||
|
||||
exports.parseCsvString = function(text, options) {
|
||||
if (!text) {
|
||||
return [];
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
var SEPARATOR = options.separator || ",",
|
||||
length = text.length,
|
||||
rows = [],
|
||||
nextRow = [];
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var cellInfo = getCellInfo(text, i, length, SEPARATOR);
|
||||
var cellText = text.substring(cellInfo[0], cellInfo[1]);
|
||||
if (cellInfo[2]) {
|
||||
cellText = cellText.replace(/""/g, '"');
|
||||
cellInfo[1]++;
|
||||
}
|
||||
nextRow.push(cellText);
|
||||
|
||||
i = cellInfo[1];
|
||||
|
||||
var character = text.charAt(i);
|
||||
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
|
||||
|
||||
if (character === "\r" || character === "\n") {
|
||||
// Edge case for empty rows
|
||||
if (nextRow.length === 1 && nextRow[0] === '') {
|
||||
nextRow.length = 0;
|
||||
}
|
||||
rows.push(nextRow);
|
||||
nextRow = [];
|
||||
|
||||
if (character === "\r") {
|
||||
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
|
||||
|
||||
if (nextCharacter === "\n") {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special case if last cell in last row is an empty cell
|
||||
if (text.charAt(length - 1) === SEPARATOR) {
|
||||
nextRow.push("");
|
||||
}
|
||||
|
||||
rows.push(nextRow);
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
/*
|
||||
Parse a CSV string with a header row and return an array of hashmaps.
|
||||
*/
|
||||
exports.parseCsvStringWithHeader = function(text,options) {
|
||||
var csv = $tw.utils.parseCsvString(text, options);
|
||||
var headers = csv[0];
|
||||
|
||||
csv = csv.slice(1);
|
||||
for (var i = 0; i < csv.length; i++) {
|
||||
var row = csv[i];
|
||||
var rowObject = Object.create(null);
|
||||
|
||||
for(var columnIndex=0; columnIndex<headers.length; columnIndex++) {
|
||||
var columnName = headers[columnIndex];
|
||||
if (columnName) {
|
||||
rowObject[columnName] = $tw.utils.trim(row[columnIndex] || "");
|
||||
}
|
||||
}
|
||||
csv[i] = rowObject;
|
||||
options = options || {};
|
||||
var separator = options.separator || ",",
|
||||
rows = text.split(/\r?\n/mg).map(function(row) {
|
||||
return $tw.utils.trim(row);
|
||||
}).filter(function(row) {
|
||||
return row !== "";
|
||||
});
|
||||
if(rows.length < 1) {
|
||||
return "Missing header row";
|
||||
}
|
||||
return csv;
|
||||
var headings = rows[0].split(separator),
|
||||
results = [];
|
||||
for(var row=1; row<rows.length; row++) {
|
||||
var columns = rows[row].split(separator),
|
||||
columnResult = Object.create(null);
|
||||
if(columns.length !== headings.length) {
|
||||
return "Malformed CSV row '" + rows[row] + "'";
|
||||
}
|
||||
for(var column=0; column<columns.length; column++) {
|
||||
var columnName = headings[column];
|
||||
columnResult[columnName] = $tw.utils.trim(columns[column] || "");
|
||||
}
|
||||
results.push(columnResult);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -12,8 +12,6 @@ Various static DOM-related utility functions.
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
/*
|
||||
Determines whether element 'a' contains element 'b'
|
||||
Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
|
||||
@@ -296,21 +294,8 @@ exports.collectDOMVariables = function(selectedNode,domNode,event) {
|
||||
});
|
||||
|
||||
if(selectedNode.offsetLeft) {
|
||||
// Add variables with a (relative and absolute) popup coordinate string for the selected node
|
||||
var nodeRect = {
|
||||
left: selectedNode.offsetLeft,
|
||||
top: selectedNode.offsetTop,
|
||||
width: selectedNode.offsetWidth,
|
||||
height: selectedNode.offsetHeight
|
||||
};
|
||||
variables["tv-popup-coords"] = Popup.buildCoordinates(Popup.coordinatePrefix.csOffsetParent,nodeRect);
|
||||
|
||||
var absRect = $tw.utils.extend({}, nodeRect);
|
||||
for (var currentNode = selectedNode.offsetParent; currentNode; currentNode = currentNode.offsetParent) {
|
||||
absRect.left += currentNode.offsetLeft;
|
||||
absRect.top += currentNode.offsetTop;
|
||||
}
|
||||
variables["tv-popup-abs-coords"] = Popup.buildCoordinates(Popup.coordinatePrefix.csAbsolute,absRect);
|
||||
// Add a variable with a popup coordinate string for the selected node
|
||||
variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")";
|
||||
|
||||
// Add variables for offset of selected node
|
||||
variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString();
|
||||
|
||||
@@ -26,8 +26,6 @@ Display a modal dialogue
|
||||
options: see below
|
||||
Options include:
|
||||
downloadLink: Text of a big download link to include
|
||||
event: widget event
|
||||
variables: from event.paramObject
|
||||
*/
|
||||
Modal.prototype.display = function(title,options) {
|
||||
options = options || {};
|
||||
@@ -211,10 +209,6 @@ Modal.prototype.display = function(title,options) {
|
||||
headerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||
bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||
footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
|
||||
// Whether to close the modal dialog when the mask (area outside the modal) is clicked
|
||||
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true")) {
|
||||
modalBackdrop.addEventListener("click",closeHandler,false);
|
||||
}
|
||||
// Set the initial styles for the message
|
||||
$tw.utils.setStyle(modalBackdrop,[
|
||||
{opacity: "0"}
|
||||
|
||||
@@ -22,19 +22,6 @@ var Popup = function(options) {
|
||||
this.popups = []; // Array of {title:,wiki:,domNode:} objects
|
||||
};
|
||||
|
||||
/*
|
||||
Global regular expression for parsing the location of a popup.
|
||||
This is also used by the Reveal widget.
|
||||
*/
|
||||
exports.popupLocationRegExp = /^(@?)\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/
|
||||
|
||||
/*
|
||||
Objekt containing the available prefixes for coordinates build with the `buildCoordinates` function:
|
||||
- csOffsetParent: Uses a coordinate system based on the offset parent (no prefix).
|
||||
- csAbsolute: Use an absolute coordinate system (prefix "@").
|
||||
*/
|
||||
exports.coordinatePrefix = { csOffsetParent: "", csAbsolute: "@" }
|
||||
|
||||
/*
|
||||
Trigger a popup open or closed. Parameters are in a hashmap:
|
||||
title: title of the tiddler where the popup details are stored
|
||||
@@ -149,17 +136,8 @@ Popup.prototype.show = function(options) {
|
||||
height: options.domNode.offsetHeight
|
||||
};
|
||||
}
|
||||
if(options.absolute && options.domNode) {
|
||||
// Walk the offsetParent chain and add the position of the offsetParents to make
|
||||
// the position absolute to the root node of the page.
|
||||
var currentNode = options.domNode.offsetParent;
|
||||
while(currentNode) {
|
||||
rect.left += currentNode.offsetLeft;
|
||||
rect.top += currentNode.offsetTop;
|
||||
currentNode = currentNode.offsetParent;
|
||||
}
|
||||
}
|
||||
var popupRect = exports.buildCoordinates(options.absolute?exports.coordinatePrefix.csAbsolute:exports.coordinatePrefix.csOffsetParent,rect);
|
||||
var popupRect = "(" + rect.left + "," + rect.top + "," +
|
||||
rect.width + "," + rect.height + ")";
|
||||
if(options.noStateReference) {
|
||||
options.wiki.setText(options.title,"text",undefined,popupRect);
|
||||
} else {
|
||||
@@ -194,54 +172,13 @@ Popup.prototype.cancel = function(level) {
|
||||
};
|
||||
|
||||
/*
|
||||
Returns true if the specified title and text identifies an active popup.
|
||||
This function is safe to call, even if the popup class was not initialized.
|
||||
Returns true if the specified title and text identifies an active popup
|
||||
*/
|
||||
exports.readPopupState = function(text) {
|
||||
return exports.popupLocationRegExp.test(text);
|
||||
Popup.prototype.readPopupState = function(text) {
|
||||
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/;
|
||||
return popupLocationRegExp.test(text);
|
||||
};
|
||||
|
||||
/*
|
||||
Parses a coordinate string in the format `(x,y,w,h)` or `@(x,y,z,h)` and returns
|
||||
an object containing the position, width and height. The absolute-Mark is boolean
|
||||
value that indicates the coordinate system of the coordinates. If they start with
|
||||
an `@`, `absolute` is set to true and the coordinates are relative to the root
|
||||
element. If the initial `@` is missing, they are relative to the offset parent
|
||||
element and `absoute` is false.
|
||||
This function is safe to call, even if the popup class was not initialized.
|
||||
*/
|
||||
exports.parseCoordinates = function(coordinates) {
|
||||
var match = exports.popupLocationRegExp.exec(coordinates);
|
||||
if(match) {
|
||||
return {
|
||||
absolute: (match[1] === "@"),
|
||||
left: parseFloat(match[2]),
|
||||
top: parseFloat(match[3]),
|
||||
width: parseFloat(match[4]),
|
||||
height: parseFloat(match[5])
|
||||
};
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Builds a coordinate string from a coordinate system identifier and an object
|
||||
containing the left, top, width and height values.
|
||||
Use constants defined in coordinatePrefix to specify a coordinate system.
|
||||
If one of the parameters is invalid for building a coordinate string `(0,0,0,0)`
|
||||
will be returned.
|
||||
This function is safe to call, even if the popup class was not initialized.
|
||||
*/
|
||||
exports.buildCoordinates = function(prefix,position) {
|
||||
var coord = prefix + "(" + position.left + "," + position.top + "," + position.width + "," + position.height + ")";
|
||||
if (exports.popupLocationRegExp.test(coord)) {
|
||||
return coord;
|
||||
} else {
|
||||
return "(0,0,0,0)";
|
||||
}
|
||||
}
|
||||
|
||||
exports.Popup = Popup;
|
||||
|
||||
})();
|
||||
|
||||
@@ -15,11 +15,10 @@ function LinkedList() {
|
||||
|
||||
LinkedList.prototype.clear = function() {
|
||||
// LinkedList performs the duty of both the head and tail node
|
||||
this.next = new LLMap();
|
||||
this.prev = new LLMap();
|
||||
// Linked list head initially points to itself
|
||||
this.next.set(null, null);
|
||||
this.prev.set(null, null);
|
||||
this.next = Object.create(null);
|
||||
this.prev = Object.create(null);
|
||||
this.first = undefined;
|
||||
this.last = undefined;
|
||||
this.length = 0;
|
||||
};
|
||||
|
||||
@@ -42,29 +41,28 @@ Push behaves like array.push and accepts multiple string arguments. But it also
|
||||
accepts a single array argument too, to be consistent with its other methods.
|
||||
*/
|
||||
LinkedList.prototype.push = function(/* values */) {
|
||||
var i, values = arguments;
|
||||
var values = arguments;
|
||||
if($tw.utils.isArray(values[0])) {
|
||||
values = values[0];
|
||||
}
|
||||
for(i = 0; i < values.length; i++) {
|
||||
for(var i = 0; i < values.length; i++) {
|
||||
_assertString(values[i]);
|
||||
}
|
||||
for(i = 0; i < values.length; i++) {
|
||||
for(var i = 0; i < values.length; i++) {
|
||||
_linkToEnd(this,values[i]);
|
||||
}
|
||||
return this.length;
|
||||
};
|
||||
|
||||
LinkedList.prototype.pushTop = function(value) {
|
||||
var t;
|
||||
if($tw.utils.isArray(value)) {
|
||||
for (t=0; t<value.length; t++) {
|
||||
for (var t=0; t<value.length; t++) {
|
||||
_assertString(value[t]);
|
||||
}
|
||||
for(t=0; t<value.length; t++) {
|
||||
for(var t=0; t<value.length; t++) {
|
||||
_removeOne(this,value[t]);
|
||||
}
|
||||
for(t=0; t<value.length; t++) {
|
||||
for(var t=0; t<value.length; t++) {
|
||||
_linkToEnd(this,value[t]);
|
||||
}
|
||||
} else {
|
||||
@@ -76,11 +74,11 @@ LinkedList.prototype.pushTop = function(value) {
|
||||
|
||||
LinkedList.prototype.each = function(callback) {
|
||||
var visits = Object.create(null),
|
||||
value = this.next.get(null);
|
||||
while(value !== null) {
|
||||
value = this.first;
|
||||
while(value !== undefined) {
|
||||
callback(value);
|
||||
var next = this.next.get(value);
|
||||
if(Array.isArray(next)) {
|
||||
var next = this.next[value];
|
||||
if(typeof next === "object") {
|
||||
var i = visits[value] || 0;
|
||||
visits[value] = i+1;
|
||||
value = next[i];
|
||||
@@ -107,79 +105,91 @@ LinkedList.prototype.makeTiddlerIterator = function(wiki) {
|
||||
};
|
||||
|
||||
function _removeOne(list,value) {
|
||||
var nextEntry = list.next.get(value);
|
||||
if(nextEntry === undefined) {
|
||||
return;
|
||||
}
|
||||
var prevEntry = list.prev.get(value),
|
||||
var prevEntry = list.prev[value],
|
||||
nextEntry = list.next[value],
|
||||
prev = prevEntry,
|
||||
next = nextEntry,
|
||||
ref;
|
||||
if(Array.isArray(nextEntry)) {
|
||||
next = nextEntry;
|
||||
if(typeof nextEntry === "object") {
|
||||
next = nextEntry[0];
|
||||
prev = prevEntry[0];
|
||||
}
|
||||
// Relink preceding element.
|
||||
ref = list.next.get(prev);
|
||||
if(Array.isArray(ref)) {
|
||||
var i = ref.indexOf(value);
|
||||
ref[i] = next;
|
||||
if(list.first === value) {
|
||||
list.first = next
|
||||
} else if(prev !== undefined) {
|
||||
if(typeof list.next[prev] === "object") {
|
||||
if(next === undefined) {
|
||||
// Must have been last, and 'i' would be last element.
|
||||
list.next[prev].pop();
|
||||
} else {
|
||||
var i = list.next[prev].indexOf(value);
|
||||
list.next[prev][i] = next;
|
||||
}
|
||||
} else {
|
||||
list.next[prev] = next;
|
||||
}
|
||||
} else {
|
||||
list.next.set(prev,next);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now relink following element
|
||||
ref = list.prev.get(next);
|
||||
if(Array.isArray(ref)) {
|
||||
var i = ref.indexOf(value);
|
||||
ref[i] = prev;
|
||||
// Check "next !== undefined" rather than "list.last === value" because
|
||||
// we need to know if the FIRST value is the last in the list, not the last.
|
||||
if(next !== undefined) {
|
||||
if(typeof list.prev[next] === "object") {
|
||||
if(prev === undefined) {
|
||||
// Must have been first, and 'i' would be 0.
|
||||
list.prev[next].shift();
|
||||
} else {
|
||||
var i = list.prev[next].indexOf(value);
|
||||
list.prev[next][i] = prev;
|
||||
}
|
||||
} else {
|
||||
list.prev[next] = prev;
|
||||
}
|
||||
} else {
|
||||
list.prev.set(next,prev);
|
||||
list.last = prev;
|
||||
}
|
||||
|
||||
// Delink actual value. If it uses arrays, just remove first entries.
|
||||
if(Array.isArray(nextEntry) && nextEntry.length > 1) {
|
||||
if(typeof nextEntry === "object") {
|
||||
nextEntry.shift();
|
||||
prevEntry.shift();
|
||||
} else {
|
||||
list.next.set(value,undefined);
|
||||
list.prev.set(value,undefined);
|
||||
list.next[value] = undefined;
|
||||
list.prev[value] = undefined;
|
||||
}
|
||||
list.length -= 1;
|
||||
};
|
||||
|
||||
// Sticks the given node onto the end of the list.
|
||||
function _linkToEnd(list,value) {
|
||||
var old = list.next.get(value);
|
||||
var last = list.prev.get(null);
|
||||
// Does it already exists?
|
||||
if(old !== undefined) {
|
||||
if(!Array.isArray(old)) {
|
||||
old = [old];
|
||||
list.next.set(value,old);
|
||||
list.prev.set(value,[list.prev.get(value)]);
|
||||
}
|
||||
old.push(null);
|
||||
list.prev.get(value).push(last);
|
||||
if(list.first === undefined) {
|
||||
list.first = value;
|
||||
} else {
|
||||
list.next.set(value,null);
|
||||
list.prev.set(value,last);
|
||||
}
|
||||
// Make the old last point to this new one.
|
||||
if(value !== last) {
|
||||
var array = list.next.get(last);
|
||||
if(Array.isArray(array)) {
|
||||
array[array.length-1] = value;
|
||||
// Does it already exists?
|
||||
if(list.first === value || list.prev[value] !== undefined) {
|
||||
if(typeof list.next[value] === "string") {
|
||||
list.next[value] = [list.next[value]];
|
||||
list.prev[value] = [list.prev[value]];
|
||||
} else if(typeof list.next[value] === "undefined") {
|
||||
// list.next[value] must be undefined.
|
||||
// Special case. List already has 1 value. It's at the end.
|
||||
list.next[value] = [];
|
||||
list.prev[value] = [list.prev[value]];
|
||||
}
|
||||
list.prev[value].push(list.last);
|
||||
// We do NOT append a new value onto "next" list. Iteration will
|
||||
// figure out it must point to End-of-List on its own.
|
||||
} else {
|
||||
list.next.set(last,value);
|
||||
list.prev[value] = list.last;
|
||||
}
|
||||
// Make the old last point to this new one.
|
||||
if(typeof list.next[list.last] === "object") {
|
||||
list.next[list.last].push(value);
|
||||
} else {
|
||||
list.next[list.last] = value;
|
||||
}
|
||||
list.prev.set(null,value);
|
||||
} else {
|
||||
// Edge case, the pushed value was already the last value.
|
||||
// The second-to-last nextPtr for that value must point to itself now.
|
||||
var array = list.next.get(last);
|
||||
array[array.length-2] = value;
|
||||
}
|
||||
list.last = value;
|
||||
list.length += 1;
|
||||
};
|
||||
|
||||
@@ -189,20 +199,6 @@ function _assertString(value) {
|
||||
}
|
||||
};
|
||||
|
||||
var LLMap = function() {
|
||||
this.map = Object.create(null);
|
||||
};
|
||||
|
||||
// Just a wrapper so our object map can also accept null.
|
||||
LLMap.prototype = {
|
||||
set: function(key,val) {
|
||||
(key === null) ? (this.null = val) : (this.map[key] = val);
|
||||
},
|
||||
get: function(key) {
|
||||
return (key === null) ? this.null : this.map[key];
|
||||
}
|
||||
};
|
||||
|
||||
exports.LinkedList = LinkedList;
|
||||
|
||||
})();
|
||||
|
||||
@@ -354,9 +354,6 @@ exports.formatDateString = function(date,template) {
|
||||
var result = "",
|
||||
t = template,
|
||||
matches = [
|
||||
[/^TIMESTAMP/, function() {
|
||||
return date.getTime();
|
||||
}],
|
||||
[/^0hh12/, function() {
|
||||
return $tw.utils.pad($tw.utils.getHours12(date));
|
||||
}],
|
||||
|
||||
@@ -14,8 +14,6 @@ Action widget to trigger a popup.
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
var ActionPopupWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
@@ -59,20 +57,20 @@ Invoke the action associated with this widget
|
||||
*/
|
||||
ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
||||
// Trigger the popup
|
||||
var coordinates = Popup.parseCoordinates(this.actionCoords || "");
|
||||
if(coordinates) {
|
||||
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
|
||||
match = popupLocationRegExp.exec(this.actionCoords || "");
|
||||
if(match) {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: null,
|
||||
domNodeRect: {
|
||||
left: coordinates.left,
|
||||
top: coordinates.top,
|
||||
width: coordinates.width,
|
||||
height: coordinates.height
|
||||
left: parseFloat(match[1]),
|
||||
top: parseFloat(match[2]),
|
||||
width: parseFloat(match[3]),
|
||||
height: parseFloat(match[4])
|
||||
},
|
||||
title: this.actionState,
|
||||
wiki: this.wiki,
|
||||
floating: this.floating,
|
||||
absolute: coordinates.absolute
|
||||
floating: this.floating
|
||||
});
|
||||
} else {
|
||||
$tw.popup.cancel(0);
|
||||
|
||||
@@ -14,8 +14,6 @@ Button widget
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
var ButtonWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
@@ -149,7 +147,7 @@ ButtonWidget.prototype.isSelected = function() {
|
||||
|
||||
ButtonWidget.prototype.isPoppedUp = function() {
|
||||
var tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup);
|
||||
var result = tiddler && tiddler.fields.text ? Popup.readPopupState(tiddler.fields.text) : false;
|
||||
var result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -175,7 +173,6 @@ ButtonWidget.prototype.triggerPopup = function(event) {
|
||||
if(this.popupTitle) {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: this.domNodes[0],
|
||||
absolute: (this.popupAbsCoords === "yes"),
|
||||
title: this.popupTitle,
|
||||
wiki: this.wiki,
|
||||
noStateReference: true
|
||||
@@ -183,7 +180,6 @@ ButtonWidget.prototype.triggerPopup = function(event) {
|
||||
} else {
|
||||
$tw.popup.triggerPopup({
|
||||
domNode: this.domNodes[0],
|
||||
absolute: (this.popupAbsCoords === "yes"),
|
||||
title: this.popup,
|
||||
wiki: this.wiki
|
||||
});
|
||||
@@ -227,7 +223,6 @@ ButtonWidget.prototype.execute = function() {
|
||||
this.setField = this.getAttribute("setField");
|
||||
this.setIndex = this.getAttribute("setIndex");
|
||||
this.popupTitle = this.getAttribute("popupTitle");
|
||||
this.popupAbsCoords = this.getAttribute("popupAbsCoords", "no");
|
||||
this.tabIndex = this.getAttribute("tabindex");
|
||||
this.isDisabled = this.getAttribute("disabled","no");
|
||||
// Make child widgets
|
||||
@@ -257,7 +252,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
||||
*/
|
||||
ButtonWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else if(changedAttributes["class"]) {
|
||||
|
||||
@@ -14,8 +14,6 @@ Reveal widget
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
var RevealWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
@@ -96,13 +94,6 @@ RevealWidget.prototype.positionPopup = function(domNode) {
|
||||
left = Math.max(0,left);
|
||||
top = Math.max(0,top);
|
||||
}
|
||||
if (this.popup.absolute) {
|
||||
// Traverse the offsetParent chain and correct the offset to make it relative to the parent node.
|
||||
for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
|
||||
left -= offsetParentDomNode.offsetLeft;
|
||||
top -= offsetParentDomNode.offsetTop;
|
||||
}
|
||||
}
|
||||
domNode.style.left = left + "px";
|
||||
domNode.style.top = top + "px";
|
||||
};
|
||||
@@ -192,11 +183,19 @@ RevealWidget.prototype.compareStateText = function(state) {
|
||||
};
|
||||
|
||||
RevealWidget.prototype.readPopupState = function(state) {
|
||||
this.popup = Popup.parseCoordinates(state);
|
||||
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
|
||||
match = popupLocationRegExp.exec(state);
|
||||
// Check if the state matches the location regexp
|
||||
if(this.popup) {
|
||||
if(match) {
|
||||
// If so, we're open
|
||||
this.isOpen = true;
|
||||
// Get the location
|
||||
this.popup = {
|
||||
left: parseFloat(match[1]),
|
||||
top: parseFloat(match[2]),
|
||||
width: parseFloat(match[3]),
|
||||
height: parseFloat(match[4])
|
||||
};
|
||||
} else {
|
||||
// If not, we're closed
|
||||
this.isOpen = false;
|
||||
|
||||
@@ -42,9 +42,6 @@ SelectWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.execute();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
this.setSelectValue();
|
||||
if(this.selectFocus == "yes") {
|
||||
this.getSelectDomNode().focus();
|
||||
}
|
||||
$tw.utils.addEventListeners(this.getSelectDomNode(),[
|
||||
{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}
|
||||
]);
|
||||
@@ -146,7 +143,6 @@ SelectWidget.prototype.execute = function() {
|
||||
this.selectMultiple = this.getAttribute("multiple", false);
|
||||
this.selectSize = this.getAttribute("size");
|
||||
this.selectTooltip = this.getAttribute("tooltip");
|
||||
this.selectFocus = this.getAttribute("focus");
|
||||
// Make the child widgets
|
||||
var selectNode = {
|
||||
type: "element",
|
||||
|
||||
@@ -4,7 +4,5 @@ title: $:/core/save/all-external-js
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define defaultCoreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js
|
||||
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
||||
{{$:/core/templates/tiddlywiki5-external-js.html}}
|
||||
</$let>
|
||||
\define coreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js
|
||||
{{$:/core/templates/tiddlywiki5-external-js.html}}
|
||||
|
||||
@@ -4,7 +4,5 @@ title: $:/core/save/offline-external-js
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
|
||||
\end
|
||||
\define defaultCoreURL() tiddlywikicore-$(version)$.js
|
||||
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
|
||||
{{$:/core/templates/tiddlywiki5-external-js.html}}
|
||||
</$let>
|
||||
\define coreURL() tiddlywikicore-$(version)$.js
|
||||
{{$:/core/templates/tiddlywiki5-external-js.html}}
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
title: $:/core/templates/library.template.html
|
||||
type: text/html
|
||||
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name="application-name" content="TiddlyWiki Plugin Library" />
|
||||
<meta name="application-version" content="v0.0.0" />
|
||||
<meta name="copyright" content="Copyright 2015 Jeremy Ruston" />
|
||||
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
|
||||
<title>Plugin Library</title>
|
||||
<script>
|
||||
/*
|
||||
A simple HTTP-over-window.postMessage implementation of a standard TiddlyWeb-compatible server. It uses real HTTP to load the individual tiddler JSON files.
|
||||
*/
|
||||
|
||||
// Listen for window messages
|
||||
window.addEventListener("message",function listener(event){
|
||||
console.log("plugin library: Received message from",event.origin);
|
||||
console.log("plugin library: Message content",event.data);
|
||||
switch(event.data.verb) {
|
||||
case "GET":
|
||||
if(event.data.url === "recipes/library/tiddlers.json") {
|
||||
// Route for recipes/library/tiddlers.json
|
||||
var url = "library/";
|
||||
httpGet(url,function(err,responseText) {
|
||||
if(err) {
|
||||
event.source.postMessage({
|
||||
verb: "GET-RESPONSE",
|
||||
status: "404",
|
||||
cookies: event.data.cookies,
|
||||
url: event.data.url,
|
||||
type: "text/plain",
|
||||
body: "Not found"
|
||||
},"*");
|
||||
} else {
|
||||
event.source.postMessage({
|
||||
verb: "GET-RESPONSE",
|
||||
status: "200",
|
||||
cookies: event.data.cookies,
|
||||
url: event.data.url,
|
||||
type: "application/json",
|
||||
body: responseText
|
||||
},"*");
|
||||
}
|
||||
});
|
||||
} else if(event.data.url.indexOf("recipes/library/tiddlers/") === 0) {
|
||||
var url = "library/" + encodeURIComponent(removeSuffix(removePrefix(event.data.url,"recipes/library/tiddlers/"),".json"));
|
||||
// Route for recipes/library/tiddlers/<uri-encoded-tiddler-title>.json
|
||||
httpGet(url,function(err,responseText) {
|
||||
if(err) {
|
||||
event.source.postMessage({
|
||||
verb: "GET-RESPONSE",
|
||||
status: "404",
|
||||
cookies: event.data.cookies,
|
||||
url: event.data.url,
|
||||
type: "text/plain",
|
||||
body: "Not found"
|
||||
},"*");
|
||||
} else {
|
||||
event.source.postMessage({
|
||||
verb: "GET-RESPONSE",
|
||||
status: "200",
|
||||
cookies: event.data.cookies,
|
||||
url: event.data.url,
|
||||
type: "application/json",
|
||||
body: responseText
|
||||
},"*");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.source.postMessage({
|
||||
verb: "GET-RESPONSE",
|
||||
status: "404",
|
||||
cookies: event.data.cookies,
|
||||
url: event.data.url,
|
||||
type: "text/plain",
|
||||
body: "Not found"
|
||||
},"*");
|
||||
}
|
||||
break;
|
||||
}
|
||||
},false);
|
||||
|
||||
// Helper to remove string prefixes
|
||||
function removePrefix(string,prefix) {
|
||||
if(string.indexOf(prefix) === 0) {
|
||||
return string.substr(prefix.length);
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to remove string suffixes
|
||||
function removeSuffix(string,suffix) {
|
||||
if(string.indexOf(suffix) === string.length - suffix.length) {
|
||||
return string.substr(0,string.length - suffix.length);
|
||||
} else {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for HTTP GET
|
||||
function httpGet(url,callback) {
|
||||
var http = new XMLHttpRequest();
|
||||
http.open("GET",url,true);
|
||||
http.onreadystatechange = function() {
|
||||
if(http.readyState == 4 && http.status == 200) {
|
||||
callback(null,http.responseText);
|
||||
}
|
||||
};
|
||||
http.send();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>HelloThere</h1>
|
||||
|
||||
<p>This is the TiddlyWiki plugin library. It is not intended to be opened directly in the browser.</p>
|
||||
|
||||
<p>See <a href="https://tiddlywiki.com/" target="_blank">https://tiddlywiki.com/</a> for details of how to install plugins.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,7 +14,7 @@ tags: $:/tags/AdvancedSearch/FilterButton
|
||||
<$linkcatcher actions="<$action-setfield $tiddler='$:/temp/advancedsearch' text=<<navigateTo>>/><$action-setfield $tiddler='$:/temp/advancedsearch/input' text=<<navigateTo>>/><$action-setfield $tiddler='$:/temp/advancedsearch/refresh' text='yes'/><$action-sendmessage $message='tm-focus-selector' $param='.tc-advanced-search input' />">
|
||||
<div class="tc-block-dropdown-wrapper">
|
||||
<div class="tc-block-dropdown tc-edit-type-dropdown">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]!is[draft]]">
|
||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]]">
|
||||
<$link to={{!!filter}}><$let tv-wikilinks="no"><$transclude field="description"/></$let></$link>
|
||||
</$list>
|
||||
</div>
|
||||
|
||||
@@ -20,16 +20,15 @@ caption: {{$:/language/ControlPanel/Basics/Caption}}
|
||||
\end
|
||||
\whitespace trim
|
||||
|
||||
|tc-max-width tc-edit-max-width|k
|
||||
|<<lingo Version/Prompt>> |''<<version>>'' |
|
||||
|<$link to="$:/SiteTitle"><<lingo Title/Prompt>></$link> |<$edit-text tiddler="$:/SiteTitle" default="" tag="input"/> |
|
||||
|<$link to="$:/SiteSubtitle"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler="$:/SiteSubtitle" default="" tag="input"/> |
|
||||
|<$link to="$:/status/UserName"><<lingo Username/Prompt>></$link> |<$edit-text tiddler="$:/status/UserName" default="" tag="input"/> |
|
||||
|<$link to="$:/config/AnimationDuration"><<lingo AnimDuration/Prompt>></$link> |<$edit-text tiddler="$:/config/AnimationDuration" default="" tag="input"/> |
|
||||
|<$link to="$:/DefaultTiddlers"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit class="tc-edit-texteditor" tiddler="$:/DefaultTiddlers"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |
|
||||
|<$link to="$:/DefaultTiddlers"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag="textarea" tiddler="$:/DefaultTiddlers" class="tc-edit-texteditor"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |
|
||||
|<$link to="$:/language/DefaultNewTiddlerTitle"><<lingo NewTiddler/Title/Prompt>></$link> |<$edit-text tiddler="$:/language/DefaultNewTiddlerTitle" default="" tag="input"/> |
|
||||
|<$link to="$:/config/NewJournal/Title"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler="$:/config/NewJournal/Title" default="" tag="input"/> |
|
||||
|<$link to="$:/config/NewJournal/Text"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler="$:/config/NewJournal/Text" class="tc-edit-texteditor" default=""/> |
|
||||
|<$link to="$:/config/NewJournal/Text"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler="$:/config/NewJournal/Text" tag="textarea" class="tc-edit-texteditor" default=""/> |
|
||||
|<$link to="$:/config/NewTiddler/Tags"><<lingo NewTiddler/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewTiddler/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> |
|
||||
|<$link to="$:/config/NewJournal/Tags"><<lingo NewJournal/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewJournal/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> |
|
||||
|<$link to="$:/config/AutoFocus"><<lingo AutoFocus/Prompt>></$link> |{{$:/snippets/minifocusswitcher}} |
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
title: $:/snippets/retain-story-ordering-button
|
||||
|
||||
<$button set="$:/DefaultTiddlers" setTo={{$:/config/ControlPanel/Basics/DefaultTiddlers/RetainStory}} ><<currentTiddler>></$button>
|
||||
@@ -1,12 +1,7 @@
|
||||
title: $:/core/ui/EditTemplate
|
||||
|
||||
\define delete-edittemplate-state-tiddlers()
|
||||
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
|
||||
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<newFieldNameInputTiddler>] [<newFieldNameSelectionTiddler>] [<newTagNameTiddler>] [<newTagNameInputTiddler>] [<newTagNameSelectionTiddler>] [<typeInputTiddler>] [<typeSelectionTiddler>]"/>
|
||||
</$set>
|
||||
\end
|
||||
\define delete-edittemplate-state-tiddlers() <$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix<newFieldValueTiddlerPrefix>] [<newFieldNameInputTiddler>] [<newFieldNameSelectionTiddler>] [<newTagNameTiddler>] [<newTagNameInputTiddler>] [<newTagNameSelectionTiddler>] [<typeInputTiddler>] [<typeSelectionTiddler>]"/>
|
||||
|
||||
<!-- Beware this is duplicated from fields.tid. For details see bug #7054 -->
|
||||
\define get-field-value-tiddler-filter() [subfilter<get-field-editor-filter>sha256[16]addprefix[/]addprefix<newFieldValueTiddlerPrefix>]
|
||||
\define get-field-editor-filter() [<newFieldNameTiddler>get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
|
||||
|
||||
<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/>
|
||||
|
||||
<div class="tc-tiddler-preview-preview" data-tiddler-title={{!!draft.title}} data-tags={{!!tags}}>
|
||||
<div class="tc-tiddler-preview-preview">
|
||||
|
||||
<$transclude tiddler={{$:/state/editpreviewtype}} mode="inline">
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$
|
||||
[[hide]] -[title{$(config-title)$}]
|
||||
\end
|
||||
|
||||
<!-- Beware this is duplicated from EditTemplate.tid. For details see bug #7054 -->
|
||||
\define get-field-value-tiddler-filter() [subfilter<get-field-editor-filter>sha256[16]addprefix[/]addprefix<newFieldValueTiddlerPrefix>]
|
||||
\define get-field-editor-filter() [<newFieldNameTiddler>get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
|
||||
|
||||
\define current-tiddler-new-field-selector()
|
||||
[data-tiddler-title="$(currentTiddlerCSSescaped)$"] .tc-edit-field-add-name-wrapper input
|
||||
\end
|
||||
@@ -21,9 +17,7 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$
|
||||
\define new-field-actions()
|
||||
\whitespace trim
|
||||
<$action-sendmessage $message="tm-add-field" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldNameTiddler>get[text]] :map[subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
|
||||
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
|
||||
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
|
||||
</$set>
|
||||
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix<newFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=<<current-tiddler-new-field-selector>>/>
|
||||
\end
|
||||
|
||||
@@ -58,9 +52,7 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$
|
||||
<$action-sendmessage $message="tm-add-field"
|
||||
$name=<<name>>
|
||||
$value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
|
||||
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
|
||||
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
|
||||
</$set>
|
||||
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix<newFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
|
||||
<<lingo Fields/Add/Button>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
@@ -73,7 +65,6 @@ $value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
|
||||
\end
|
||||
\whitespace trim
|
||||
|
||||
<$set name="newFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
|
||||
<div class="tc-edit-fields">
|
||||
<table class={{{ [all[current]fields[]] :filter[lookup[$:/config/EditTemplateFields/Visibility/]!match[hide]] +[count[]!match[0]] +[then[tc-edit-fields]] ~[[tc-edit-fields tc-edit-fields-small]] }}}>
|
||||
<tbody>
|
||||
@@ -157,4 +148,3 @@ $value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
|
||||
</$vars>
|
||||
</div>
|
||||
</$fieldmangler>
|
||||
</$set>
|
||||
@@ -117,15 +117,15 @@ title: $:/core/ui/ImportListing
|
||||
</div>
|
||||
</td>
|
||||
</$reveal>
|
||||
<$reveal type="match" text="yes" state=<<previewPopupState>> tag="tr">
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<$reveal type="match" text="yes" state=<<previewPopupState>> tag="div">
|
||||
<$list filter="[{$:/state/importpreviewtype}has[text]]" variable="listItem" emptyMessage={{$:/core/ui/ImportPreviews/Text}}>
|
||||
<div>
|
||||
<$transclude tiddler={{$:/state/importpreviewtype}}/>
|
||||
</div>
|
||||
<$transclude tiddler={{$:/state/importpreviewtype}}/>
|
||||
</$list>
|
||||
</td>
|
||||
</$reveal>
|
||||
</td>
|
||||
</tr>
|
||||
</$list>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -4,6 +4,6 @@ key: ((advanced-search))
|
||||
|
||||
\whitespace trim
|
||||
<$navigator story="$:/StoryList" history="$:/HistoryList">
|
||||
<$action-navigate $to="$:/AdvancedSearch" $scroll="yes"/>
|
||||
<$action-navigate $to="$:/AdvancedSearch"/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param="""[data-tiddler-title="$:/AdvancedSearch"] .tc-search input""" preventScroll="true"/>
|
||||
</$navigator>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
title: $:/core/ui/Buttons/layout
|
||||
tags: $:/tags/PageControls
|
||||
caption: {{$:/core/images/layout-button}} {{$:/language/Buttons/LayoutSwitcher/Caption}}
|
||||
description: {{$:/language/LayoutSwitcher/Description}}
|
||||
|
||||
\whitespace trim
|
||||
<$button tooltip={{$:/language/Buttons/LayoutSwitcher/Hint}} aria-label={{$:/language/Buttons/LayoutSwitcher/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$action-sendmessage $message="tm-show-switcher" switch="layout"/>
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/core/images/layout-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/LayoutSwitcher/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
||||
@@ -3,6 +3,6 @@ tags: $:/tags/SideBar
|
||||
caption: {{$:/language/SideBar/More/Caption}}
|
||||
|
||||
\whitespace trim
|
||||
<div class={{{ [{$:/config/ui/SideBar/More/horizontal}match[yes]then[tc-sidebar-tabs]else[tc-more-sidebar]] }}}>
|
||||
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]" default={{$:/config/DefaultMoreSidebarTab}} state="$:/state/tab/moresidebar" class={{{ [{$:/config/ui/SideBar/More/horizontal}match[yes]then[tc-sidebar-tabs-more]else[tc-vertical tc-sidebar-tabs-more]] }}} explicitState="$:/state/tab/moresidebar-1850697562"/>
|
||||
<div class="tc-more-sidebar">
|
||||
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]" default={{$:/config/DefaultMoreSidebarTab}} state="$:/state/tab/moresidebar" class="tc-vertical tc-sidebar-tabs-more" explicitState="$:/state/tab/moresidebar-1850697562"/>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
title: $:/core/ui/SwitcherModal
|
||||
subtitle: <$text text={{{[<switch>lookup[$:/language/Switcher/Subtitle/]]}}}/>
|
||||
class: tc-modal-centered
|
||||
mask-closable: yes
|
||||
|
||||
<$tiddler tiddler={{{[<switch>lookup[$:/config/SwitcherTargets/]]}}}>
|
||||
|
||||
|
||||
@@ -3,101 +3,89 @@ icon: $:/core/images/tag-button
|
||||
color: #bbb
|
||||
|
||||
\define lingo-base() $:/language/TagManager/
|
||||
|
||||
\define iconEditorTab(type)
|
||||
\whitespace trim
|
||||
<$link to=""><<lingo Icons/None>></$link>
|
||||
<$list filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[sort[title]] +[$type$is[system]]">
|
||||
<$link to={{!!title}}>
|
||||
<$transclude/> <$view field="title"/>
|
||||
</$link>
|
||||
<$link to={{!!title}}>
|
||||
<$transclude/> <$view field="title"/>
|
||||
</$link>
|
||||
</$list>
|
||||
\end
|
||||
|
||||
\define iconEditor(title)
|
||||
\whitespace trim
|
||||
<div class="tc-drop-down-wrapper">
|
||||
<$button popupTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} class="tc-btn-invisible tc-btn-dropdown">
|
||||
{{$:/core/images/down-arrow}}
|
||||
</$button>
|
||||
<$reveal stateTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} type="popup" position="belowleft" text="" default="">
|
||||
<div class="tc-drop-down">
|
||||
<$linkcatcher actions="""<$action-setfield $tiddler=<<__title__>> icon=<<navigateTo>>/>""">
|
||||
<<iconEditorTab type:"!">>
|
||||
<hr/>
|
||||
<<iconEditorTab type:"">>
|
||||
</$linkcatcher>
|
||||
</div>
|
||||
</$reveal>
|
||||
<$button popupTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} class="tc-btn-invisible tc-btn-dropdown">{{$:/core/images/down-arrow}}</$button>
|
||||
<$reveal stateTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} type="popup" position="belowleft" text="" default="">
|
||||
<div class="tc-drop-down">
|
||||
<$linkcatcher actions="""<$action-setfield $tiddler=<<__title__>> icon=<<navigateTo>>/>""">
|
||||
<<iconEditorTab type:"!">>
|
||||
<hr/>
|
||||
<<iconEditorTab type:"">>
|
||||
</$linkcatcher>
|
||||
</div>
|
||||
</$reveal>
|
||||
</div>
|
||||
\end
|
||||
|
||||
\define toggleButton(state)
|
||||
\whitespace trim
|
||||
<$reveal stateTitle=<<__state__>> type="match" text="closed" default="closed">
|
||||
<$button setTitle=<<__state__>> setTo="open" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected">
|
||||
{{$:/core/images/info-button}}
|
||||
</$button>
|
||||
<$button setTitle=<<__state__>> setTo="open" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected">
|
||||
{{$:/core/images/info-button}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal stateTitle=<<__state__>> type="match" text="open" default="closed">
|
||||
<$button setTitle=<<__state__>> setTo="closed" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected">
|
||||
{{$:/core/images/info-button}}
|
||||
</$button>
|
||||
<$button setTitle=<<__state__>> setTo="closed" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected">
|
||||
{{$:/core/images/info-button}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
\end
|
||||
|
||||
\whitespace trim
|
||||
<table class="tc-tag-manager-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th><<lingo Colour/Heading>></th>
|
||||
<th class="tc-tag-manager-tag"><<lingo Tag/Heading>></th>
|
||||
<th><<lingo Count/Heading>></th>
|
||||
<th><<lingo Icon/Heading>></th>
|
||||
<th><<lingo Info/Heading>></th>
|
||||
</tr>
|
||||
<$list filter="[tags[]!is[system]sort[title]]">
|
||||
<tr>
|
||||
<td><$edit-text field="color" tag="input" type="color"/></td>
|
||||
<td>{{||$:/core/ui/TagTemplate}}</td>
|
||||
<td><$count filter="[all[current]tagging[]]"/></td>
|
||||
<td>
|
||||
<$macrocall $name="iconEditor" title={{!!title}}/>
|
||||
</td>
|
||||
<td>
|
||||
<$macrocall $name="toggleButton" state={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="4">
|
||||
<$reveal stateTitle={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} type="match" text="open" default="">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><<lingo Colour/Heading>></td>
|
||||
<td><$edit-text field="color" tag="input" type="text" size="9"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><<lingo Icon/Heading>></td>
|
||||
<td><$edit-text field="icon" tag="input" size="45"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</$reveal>
|
||||
</td>
|
||||
</tr>
|
||||
</$list>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="position:relative;">
|
||||
{{$:/core/ui/UntaggedTemplate}}
|
||||
</td>
|
||||
<td>
|
||||
<small class="tc-menu-list-count"><$count filter="[untagged[]!is[system]] -[tags[]]"/></small>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><<lingo Colour/Heading>></th>
|
||||
<th class="tc-tag-manager-tag"><<lingo Tag/Heading>></th>
|
||||
<th><<lingo Count/Heading>></th>
|
||||
<th><<lingo Icon/Heading>></th>
|
||||
<th><<lingo Info/Heading>></th>
|
||||
</tr>
|
||||
<$list filter="[tags[]!is[system]sort[title]]">
|
||||
<tr>
|
||||
<td><$edit-text field="color" tag="input" type="color"/></td>
|
||||
<td>{{||$:/core/ui/TagTemplate}}</td>
|
||||
<td><$count filter="[all[current]tagging[]]"/></td>
|
||||
<td>
|
||||
<$macrocall $name="iconEditor" title={{!!title}}/>
|
||||
</td>
|
||||
<td>
|
||||
<$macrocall $name="toggleButton" state={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="4">
|
||||
<$reveal stateTitle={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} type="match" text="open" default="">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr><td><<lingo Colour/Heading>></td><td><$edit-text field="color" tag="input" type="text" size="9"/></td></tr>
|
||||
<tr><td><<lingo Icon/Heading>></td><td><$edit-text field="icon" tag="input" size="45"/></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</$reveal>
|
||||
</td>
|
||||
</tr>
|
||||
</$list>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="position:relative;">
|
||||
{{$:/core/ui/UntaggedTemplate}}
|
||||
</td>
|
||||
<td>
|
||||
<small class="tc-menu-list-count"><$count filter="[untagged[]!is[system]] -[tags[]]"/></small>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -2,21 +2,17 @@ title: $:/core/ui/ViewTemplate/unfold
|
||||
tags: $:/tags/ViewTemplate
|
||||
|
||||
\whitespace trim
|
||||
<div class="tc-reveal">
|
||||
<$list filter="[{$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar}match[show]]" variable="ignore">
|
||||
<$reveal tag="div" type="nomatch" state="$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar" text="hide">
|
||||
<$reveal tag="div" type="nomatch" stateTitle=<<folded-state>> text="hide" default="show" retain="yes" animate="yes">
|
||||
<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class="tc-fold-banner">
|
||||
<$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/>
|
||||
{{$:/core/images/chevron-up}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
</$list>
|
||||
<$list filter="[{$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar}match[show]] :else[<folded-state>get[text]match[hide]]" variable="ignore">
|
||||
<$reveal tag="div" type="nomatch" stateTitle=<<folded-state>> text="show" default="show" retain="yes" animate="yes">
|
||||
<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class="tc-unfold-banner">
|
||||
<$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/>
|
||||
{{$:/core/images/chevron-down}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
</$list>
|
||||
</div>
|
||||
</$reveal>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
title: $:/config/ControlPanel/Basics/DefaultTiddlers/RetainStory
|
||||
|
||||
[list[$:/StoryList]]
|
||||
@@ -21,5 +21,4 @@ core/ui/Buttons/print: hide
|
||||
core/ui/Buttons/storyview: hide
|
||||
core/ui/Buttons/timestamp: hide
|
||||
core/ui/Buttons/theme: hide
|
||||
core/ui/Buttons/layout: hide
|
||||
core/ui/Buttons/unfold-all: hide
|
||||
|
||||
@@ -3,11 +3,14 @@ modified: 20141212110330815
|
||||
tags: $:/tags/Macro
|
||||
title: $:/core/macros/timeline
|
||||
|
||||
<!-- Override one or both of the following two macros with a global or local macro of the same name
|
||||
if you need to change how titles are displayed on a timeline -->
|
||||
|
||||
\define timeline-title() <$view field="title"/>
|
||||
\define timeline-link() <$link to={{!!title}}><<timeline-title>></$link>
|
||||
\define timeline-title()
|
||||
\whitespace trim
|
||||
<!-- Override this macro with a global macro
|
||||
of the same name if you need to change
|
||||
how titles are displayed on the timeline
|
||||
-->
|
||||
<$view field="title"/>
|
||||
\end
|
||||
\define timeline(limit:"100",format:"DDth MMM YYYY",subfilter:"",dateField:"modified")
|
||||
\whitespace trim
|
||||
<div class="tc-timeline">
|
||||
@@ -16,7 +19,7 @@ if you need to change how titles are displayed on a timeline -->
|
||||
<$view field="$dateField$" format="date" template="$format$"/>
|
||||
<$list filter="[sameday:$dateField${!!$dateField$}!is[system]$subfilter$!sort[$dateField$]]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<<timeline-link>>
|
||||
<$link to={{!!title}}><<timeline-title>></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
title: $:/core/macros/toc
|
||||
tags: $:/tags/Macro
|
||||
|
||||
|
||||
\define toc-open-icon() $:/core/images/down-arrow
|
||||
\define toc-closed-icon() $:/core/images/right-arrow
|
||||
|
||||
\define toc-caption()
|
||||
\whitespace trim
|
||||
<span class="tc-toc-caption tc-tiny-gap-left">
|
||||
@@ -49,12 +45,12 @@ tags: $:/tags/Macro
|
||||
<$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>
|
||||
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-closed-icon>> />
|
||||
{{$:/core/images/right-arrow}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-open-icon>> />
|
||||
{{$:/core/images/down-arrow}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<<toc-caption>>
|
||||
@@ -75,13 +71,13 @@ tags: $:/tags/Macro
|
||||
<li class=<<toc-item-class>>>
|
||||
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-closed-icon>> />
|
||||
{{$:/core/images/right-arrow}}
|
||||
<<toc-caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-open-icon>> />
|
||||
{{$:/core/images/down-arrow}}
|
||||
<<toc-caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
@@ -121,12 +117,12 @@ tags: $:/tags/Macro
|
||||
<$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>">
|
||||
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-closed-icon>> />
|
||||
{{$:/core/images/right-arrow}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-open-icon>> />
|
||||
{{$:/core/images/down-arrow}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
</$list>
|
||||
@@ -148,13 +144,13 @@ tags: $:/tags/Macro
|
||||
<$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>">
|
||||
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-closed-icon>> />
|
||||
{{$:/core/images/right-arrow}}
|
||||
<<toc-caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
<$reveal type="match" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-open-icon>> />
|
||||
{{$:/core/images/down-arrow}}
|
||||
<<toc-caption>>
|
||||
</$button>
|
||||
</$reveal>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
title: $:/tags/PageControls
|
||||
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/layout]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]
|
||||
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
created: 20221114225038703
|
||||
modified: 20221114230502925
|
||||
tags: howto
|
||||
title: How to run a local plugin library for testing
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! Start the Library Server
|
||||
|
||||
The "pluginlibrary" edition contains the components needed to set up a local server for ~TiddlyWiki plugin library testing or development.
|
||||
|
||||
The following commands will create the library files and start a test server at http://localhost:8888
|
||||
|
||||
```
|
||||
cd /your/path/to/TiddlyWiki5/editions/pluginlibrary
|
||||
tiddlywiki --build test-server
|
||||
```
|
||||
|
||||
!! Important
|
||||
|
||||
''This server is read-only. Nothing is saved back to the filesystem''
|
||||
|
||||
!! Test the Library with a Single File Wiki
|
||||
|
||||
* Open a single file wiki and import the configuration tiddler form http://localhost:8888/#%24%3A%2Fconfig%2FLocalPluginLibrary
|
||||
* Open the ''$:/ControlPanel : Plugins : "Get More Plugins"'' modal
|
||||
|
||||
!! Test the Library with a Node.js Wiki
|
||||
|
||||
* Create a new wiki with eg:
|
||||
|
||||
<<<
|
||||
```
|
||||
cd /temp/
|
||||
tiddlywiki my-wiki --init server
|
||||
tiddlywiki my-wiki --listen
|
||||
```
|
||||
<<<
|
||||
|
||||
* Open "my-wiki" from http://localhost:8080
|
||||
* Import the http://localhost:8888/#%24%3A%2Fconfig%2FLocalPluginLibrary tiddler into "my-wiki"
|
||||
* Open the ''$:/ControlPanel : Plugins : "Get More Plugins"'' modal
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
title: GettingStarted
|
||||
|
||||
This edition contains the components needed to set up a local server for ~TiddlyWiki plugin library testing or development.
|
||||
|
||||
!! Import Configuration
|
||||
|
||||
Import the configuration tiddler: $:/config/LocalPluginLibrary to your "test wiki".
|
||||
|
||||
!! Important
|
||||
|
||||
''This server is read-only. Nothing is saved back to the filesystem''
|
||||
|
||||
!! Start the Library Server
|
||||
|
||||
The following commands will create the library files and start a test server at http://localhost:8888
|
||||
|
||||
```
|
||||
cd /your/path/to/TiddlyWiki5/editions/pluginlibrary
|
||||
tiddlywiki --build test-server
|
||||
```
|
||||
|
||||
!! Test the Library with a Single File Wiki
|
||||
|
||||
* Open a single file wiki and import the configuration tiddler form http://localhost:8888/#%24%3A%2Fconfig%2FLocalPluginLibrary
|
||||
* Open the ''$:/ControlPanel : Plugins : "Get More Plugins"'' modal
|
||||
|
||||
!! Test the Library with a Node.js Wiki
|
||||
|
||||
* Create a new wiki with eg:
|
||||
|
||||
<<<
|
||||
```
|
||||
cd /temp/
|
||||
tiddlywiki my-wiki --init server
|
||||
tiddlywiki my-wiki --listen
|
||||
```
|
||||
<<<
|
||||
|
||||
* Open my-wiki from http://localhost:8080
|
||||
* Import the http://localhost:8888/#%24%3A%2Fconfig%2FLocalPluginLibrary tiddler into "my-wiki"
|
||||
* Open the ''~$:/ControlPanel : Plugins : "Get More Plugins"'' modal
|
||||
|
||||
!! ~ControlPanel Plugin Tab
|
||||
|
||||
{{$:/core/ui/ControlPanel/Plugins}}
|
||||
@@ -1,6 +0,0 @@
|
||||
title: $:/config/LocalPluginLibrary
|
||||
tags: $:/tags/PluginLibrary
|
||||
url: http://localhost:8888/files/local/library/tmp/index.html
|
||||
caption: Local TiddlyWiki Plugin Library Test Server
|
||||
|
||||
A locally installed version of the plugin library //Requires a local web server to share the library//
|
||||
@@ -1,3 +0,0 @@
|
||||
title: $:/SiteSubtitle
|
||||
|
||||
<<version>>
|
||||
@@ -1,3 +0,0 @@
|
||||
title: $:/SiteTitle
|
||||
|
||||
Library test edition, plugin development
|
||||
@@ -1,3 +0,0 @@
|
||||
title: $:/themes/tiddlywiki/vanilla/options/sidebarlayout
|
||||
|
||||
fluid-fixed
|
||||
@@ -4,17 +4,10 @@
|
||||
"tiddlywiki/pluginlibrary"
|
||||
],
|
||||
"themes": [
|
||||
"tiddlywiki/vanilla",
|
||||
"tiddlywiki/snowwhite"
|
||||
],
|
||||
"includeWikis": [
|
||||
],
|
||||
"build": {
|
||||
"test-server": [
|
||||
"--output", "./files/local/library/tmp",
|
||||
"--build", "library",
|
||||
"--listen", "port=8888"
|
||||
],
|
||||
"library": [
|
||||
"--makelibrary","$:/UpgradeLibrary",
|
||||
"--savelibrarytiddlers","$:/UpgradeLibrary","[prefix[$:/]] -[[$:/plugins/tiddlywiki/upgrade]] -[[$:/plugins/tiddlywiki/translators]] -[[$:/plugins/tiddlywiki/pluginlibrary]] -[[$:/plugins/tiddlywiki/jasmine]]","recipes/library/tiddlers/","$:/UpgradeLibrary/List",
|
||||
|
||||
@@ -1,33 +1,21 @@
|
||||
caption: 5.2.4
|
||||
created: 20221127133944178
|
||||
modified: 20221127133944178
|
||||
created: 20221101094408196
|
||||
modified: 20221101094408196
|
||||
tags: ReleaseNotes
|
||||
title: Release 5.2.4
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.3...master]]//
|
||||
|
||||
<<.banner-credits
|
||||
credit:"""Congratulations to [[dmikh|https://talk.tiddlywiki.org/u/dmikh]] for their winning design for the banner for this release (here is the [[competition thread|https://talk.tiddlywiki.org/t/new-release-banner-competition-for-v5-2-4/4982]] and the [[voting thread|https://talk.tiddlywiki.org/t/vote-for-the-v5-2-4-new-release-banner/5140/2]]).
|
||||
"""
|
||||
url:"https://raw.githubusercontent.com/Jermolene/TiddlyWiki5/0dc30086e933cf2272cddb076a9fcbedad252735/editions/tw5.com/tiddlers/images/New%20Release%20Banner.png"
|
||||
>>
|
||||
! Plugin Improvements
|
||||
|
||||
! Major Improvements
|
||||
|
||||
New [ext[Twitter Archivist|./editions/twitter-archivist]] plugin to import the tweets and associated media from a Twitter Archive as individual tiddlers.
|
||||
|
||||
<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6961">> new GenesisWidget that allows the dynamic construction of another widget, where the name and attributes of the new widget can be dynamically determined, without needing to be known in advance
|
||||
|
||||
<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6936">> new operators for reading and formatting JSON data: [[jsonget Operator]], [[jsonindexes Operator]], [[jsontype Operator]], [[jsonextract Operator]] and [[format Operator]]
|
||||
*
|
||||
|
||||
! Translation improvement
|
||||
|
||||
Improvements to the following translations:
|
||||
|
||||
* Chinese
|
||||
* French
|
||||
* German
|
||||
* Polish
|
||||
* Spanish
|
||||
* Japanese
|
||||
@@ -37,6 +25,10 @@ Improvements to the translation features of TiddlyWiki:
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6882">> the [[Translators Edition|Translate TiddlyWiki into your language]] to add an option to display the original English text underneath the text area
|
||||
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/6933">> "delete" button text in $:/AdvancedSearch so that it is translatable
|
||||
|
||||
! Accessibility Improvements
|
||||
|
||||
*
|
||||
|
||||
! Usability Improvements
|
||||
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/d62a16ee464fb9984b766b48504829a1a3eb143b">> problem with long presses on tiddler links triggering a preview on iOS/iPadOS
|
||||
@@ -45,93 +37,67 @@ Improvements to the translation features of TiddlyWiki:
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/36896c3db8c9678c0385a561996248a6f00a45ff">> opening a tiddler in a new window to use the [[View Template Body Cascade]]
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6970">> detection of infinite recursion errors in widgets and filters
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/6877">> default styles for [[styled runs|Styles and Classes in WikiText]]
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6881">> upgrade wizard to make the version number more prominent
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7042">> parsing of tiddlers containing CSV data for greater compatibility
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7076">> new page control button to summon the layout switcher
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7084">> folded tiddlers to ensure that the unfold button is always visible
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7072">> handling of [[Modals]] to optionally allow them to be dismissed by clicking on the background
|
||||
|
||||
! Widget Improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6961">> new GenesisWidget that allows the dynamic construction of another widget, where the name and attributes of the new widget can be dynamically determined, without needing to be known in advance
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/127f660c91020dcbb43897d954066b31af729e74">> EditTextWidget to remove the default text "Type the text for the tiddler 'foo'"
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7081">> ''focus'' attribute to SelectWidget
|
||||
* <<.link-badge-removed "https://github.com/Jermolene/TiddlyWiki5/commit/1df4c29d73073788ba3859668112e8bb46171a6c">> restriction of the LetWidget being unable to create variables whose names begin with a dollar sign
|
||||
|
||||
! Filter improvements
|
||||
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/6303">> issue with availability of variables within filter runs
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7065">> issue with removing multiple items from a linked list during filter processing
|
||||
*
|
||||
|
||||
! Hackability Improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7004">> support for nested [[macro definitions|Macro Definitions in WikiText]]
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6976">> support for [[SystemTag: $:/tags/ClassFilters/TiddlerTemplate]] and [[SystemTag: $:/tags/ClassFilters/PageTemplate]] to assign dynamic CSS classes to both tiddler frames and the page template
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6936">> new operators for reading and formatting JSON data: [[jsonget Operator]], [[jsonindexes Operator]], [[jsontype Operator]] and [[format Operator]]
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/c5d3d4c26e8fe27f272dda004aec27d6b66c4f60">> safe mode to disable wiki store indexers
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/166a1565843878083fb1eba47c73b8e67b78400d">> safe mode to prevent globally disabling parser rules
|
||||
* <<.link-badge-removed "https://github.com/Jermolene/TiddlyWiki5/commit/1df4c29d73073788ba3859668112e8bb46171a6c">> restriction of the LetWidget being unable to create variables whose names begin with a dollar sign
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/6735">> keyboard shortcut handling to allow to global shortcuts to override all other shortcuts
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/965bd090a905f5756e79124b698c894f7f72ad5b">> [[list-links Macro]] to allow the rendered field to be overriden
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6913">> [[Table-of-Contents Macros]] to allow the default icons to be overridden
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6939">> ''data-tags-*'' and ''data-tiddler-title'' attributes to the edit preview area
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/5947">> [[timeline Macro]] to override the link template
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7043">> support for Unix epoch timestamps in [[date format strings|DateFormat]]
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7064">> the "big green download button" to use the defined palette colour
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7063">> new hidden setting [[to use horizontal tabs for the "more" sidebar tab|Hidden Setting: More Tabs Horizontal]]
|
||||
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/commit/bef11fe6a25fb849dee40c4aa4337d6a30daf0b4">> the [[external JavaScript templates|]] to allow the URL of the external script file to be configured
|
||||
|
||||
|
||||
! Bug Fixes
|
||||
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7099">> truncated search results on small screens
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7010">> table contents overflow on small screens
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/fb34df84ed41882c1c2a6ff54f0e908b43ef95a3">> "new image" keyboard shortcut not to assign journal tags
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/6987">> SelectWidget class to update if it uses a filter
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/6303">> issue with availability of variables within filter runs
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7017">> issue with wikification within the advanced search filter dropdown
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7057">> the table in $:/Import to avoid creating hidden empty rows
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7008">> advanced search keyboard shortcut not navigating correctly
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7083">> erroneous display of drafts within the advanced search filter dropdown
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7092">> backwards compatibility of new field editor cascade introduced in v5.2.3
|
||||
|
||||
! Developer Improvements
|
||||
|
||||
*
|
||||
|
||||
! Node.js Improvements
|
||||
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7073">> new CommandsCommand to enable command tokens to be dynamically generated from a filter
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6947">> console logging to avoid spaces and `<empty string>` message
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7014">> problem with lazy loading deleting tiddler bodies under certian circumstances
|
||||
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/344110e2890caf711ab8f3c4f4deaa7d86771231">> handling of ".mp4" file extension so that it defaults to video not audio
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6588">> test server to the plugin library edition
|
||||
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7049">> [[Hidden Setting: Sync Logging]] to control logging of sync-related messages
|
||||
* <<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/6944">> Jasmine plugin to require the explicit use of the `--test` command in order to cause the tests to be run
|
||||
|
||||
! Performance Improvements
|
||||
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/53d229592df76c6dd607e40be5bea4d5e063c48e">> performance of `wiki.getTiddler()`
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/commit/81ac9874846b3ead275f67010fcfdb49f3d2f43c">> performance of variable prototype chain handling
|
||||
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/6056">> performance of list handling during filter processing
|
||||
|
||||
|
||||
! Acknowledgements
|
||||
|
||||
[[@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 """
|
||||
AnthonyMuscio
|
||||
bestony
|
||||
btheado
|
||||
BramChen
|
||||
carlo-colombo
|
||||
EvidentlyCube
|
||||
FlashSystems
|
||||
flibbles
|
||||
fu-sen
|
||||
joebordes
|
||||
hoelzro
|
||||
kookma
|
||||
linonetwo
|
||||
Marxsal
|
||||
oflg
|
||||
pmario
|
||||
rmunn
|
||||
roma0104
|
||||
saqimtiaz
|
||||
talha131
|
||||
Telumire
|
||||
tw-FRed
|
||||
twMat
|
||||
xcazin
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
title: TiddlyWiki Pre-release
|
||||
modified: 20150428204930183
|
||||
|
||||
This is a pre-release build of TiddlyWiki provided for testing and review purposes. ''Please don't try to depend on the pre-release for anything important'' -- you should use the latest official release from https://tiddlywiki.com.
|
||||
|
||||
All of the changes in this pre-release are provisional until it is released and they become frozen by our backwards compatibility policies. This is the perfect time to raise questions or make suggestions. Please [[open a ticket at GitHub|https://github.com/Jermolene/TiddlyWiki5/issues/new/choose]] or make a post at https://talk.tiddlywiki.org/.
|
||||
|
||||
The pre-release is also available as an [[empty wiki|https://tiddlywiki.com/prerelease/empty.html]] ready for reuse.
|
||||
This is a pre-release build of TiddlyWiki, [[also available in empty form|https://tiddlywiki.com/prerelease/empty.html]]. It is provided for testing purposes. ''Please don't try to use it for anything important'' -- you should use the latest official release from https://tiddlywiki.com.
|
||||
|
||||
<$list filter="[tag[ReleaseNotes]!has[released]!sort[created]]">
|
||||
<div class="tc-titlebar">
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
title: csv-cases
|
||||
type: text/plain
|
||||
description: A file containing a JSON with test CSVs as string as well as expected results
|
||||
|
||||
[
|
||||
{
|
||||
"name": "Empty string",
|
||||
"options": {},
|
||||
"csv": "",
|
||||
"json": [],
|
||||
"jsonWithHeaders": []
|
||||
},
|
||||
{
|
||||
"name": "Null value",
|
||||
"options": {},
|
||||
"csv": null,
|
||||
"json": [],
|
||||
"jsonWithHeaders": []
|
||||
},
|
||||
{
|
||||
"name": "Simple CSV with no tricks",
|
||||
"options": {},
|
||||
"csv": "cell-11,cell-12,cell-13\r\ncell-21,cell-22,cell-23\r\ncell-31,cell-32,cell-33",
|
||||
"json": [
|
||||
["cell-11", "cell-12", "cell-13"],
|
||||
["cell-21", "cell-22", "cell-23"],
|
||||
["cell-31", "cell-32", "cell-33"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "cell-21", "cell-12": "cell-22", "cell-13": "cell-23"},
|
||||
{"cell-11": "cell-31", "cell-12": "cell-32", "cell-13": "cell-33"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Custom separator",
|
||||
"options": {"separator": "\t"},
|
||||
"csv": ",cell-11,\t,cell-12,\t,cell-13,\r\n,cell-21,\t,cell-22,\t,cell-23,\r\n,cell-31,\t,cell-32,\t,cell-33,",
|
||||
"json": [
|
||||
[",cell-11,", ",cell-12,", ",cell-13,"],
|
||||
[",cell-21,", ",cell-22,", ",cell-23,"],
|
||||
[",cell-31,", ",cell-32,", ",cell-33,"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{",cell-11,": ",cell-21,", ",cell-12,": ",cell-22,", ",cell-13,": ",cell-23,"},
|
||||
{",cell-11,": ",cell-31,", ",cell-12,": ",cell-32,", ",cell-13,": ",cell-33,"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Support empty rows",
|
||||
"options": {},
|
||||
"csv": "cell-11,cell-12,cell-13\r\n\r\ncell-31,cell-32,cell-33",
|
||||
"json": [
|
||||
["cell-11", "cell-12", "cell-13"],
|
||||
[],
|
||||
["cell-31", "cell-32", "cell-33"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "", "cell-12": "", "cell-13": ""},
|
||||
{"cell-11": "cell-31", "cell-12": "cell-32", "cell-13": "cell-33"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Support empty cells",
|
||||
"options": {},
|
||||
"csv": "cell-11,cell-12,cell-13\r\n,,\r\ncell-31,cell-32,cell-33",
|
||||
"json": [
|
||||
["cell-11", "cell-12", "cell-13"],
|
||||
["", "", ""],
|
||||
["cell-31", "cell-32", "cell-33"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "", "cell-12": "", "cell-13": ""},
|
||||
{"cell-11": "cell-31", "cell-12": "cell-32", "cell-13": "cell-33"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Support LF line endings",
|
||||
"options": {},
|
||||
"csv": "cell-11,cell-12,cell-13\ncell-21,cell-22,cell-23\ncell-31,cell-32,cell-33",
|
||||
"json": [
|
||||
["cell-11", "cell-12", "cell-13"],
|
||||
["cell-21", "cell-22", "cell-23"],
|
||||
["cell-31", "cell-32", "cell-33"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "cell-21", "cell-12": "cell-22", "cell-13": "cell-23"},
|
||||
{"cell-11": "cell-31", "cell-12": "cell-32", "cell-13": "cell-33"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Mixed line endings",
|
||||
"options": {},
|
||||
"csv": "cell-11,cell-12,cell-13\ncell-21,cell-22,cell-23\r\ncell-31,cell-32,cell-33",
|
||||
"json": [
|
||||
["cell-11", "cell-12", "cell-13"],
|
||||
["cell-21", "cell-22", "cell-23"],
|
||||
["cell-31", "cell-32", "cell-33"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "cell-21", "cell-12": "cell-22", "cell-13": "cell-23"},
|
||||
{"cell-11": "cell-31", "cell-12": "cell-32", "cell-13": "cell-33"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Quoted cells",
|
||||
"options": {},
|
||||
"csv": "cell-11,\"cell-12\",cell-13\r\n\"cell-21\",cell-22,cell-23\r\ncell-31,cell-32,\"cell-33\"",
|
||||
"json": [
|
||||
["cell-11", "cell-12", "cell-13"],
|
||||
["cell-21", "cell-22", "cell-23"],
|
||||
["cell-31", "cell-32", "cell-33"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "cell-21", "cell-12": "cell-22", "cell-13": "cell-23"},
|
||||
{"cell-11": "cell-31", "cell-12": "cell-32", "cell-13": "cell-33"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Escaped quotes in cells",
|
||||
"options": {},
|
||||
"csv": "cell-11,\"\"\"cell-12\"\"\",cell-13\r\n\"cell\"\"\"\"-21\",cell-22,cell-23\r\ncell-31,cell-32,\"\"\"\"\"cell\"\"\"\"-33\"\"\"\"\"",
|
||||
"json": [
|
||||
["cell-11", "\"cell-12\"", "cell-13"],
|
||||
["cell\"\"-21", "cell-22", "cell-23"],
|
||||
["cell-31", "cell-32", "\"\"cell\"\"-33\"\""]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": "cell\"\"-21", "\"cell-12\"": "cell-22", "cell-13": "cell-23"},
|
||||
{"cell-11": "cell-31", "\"cell-12\"": "cell-32", "cell-13": "\"\"cell\"\"-33\"\""}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Separator in quoted cells",
|
||||
"options": {},
|
||||
"csv": "cell-11,\",c,e,l,l,-,1,2,\",cell-13\r\n\",c,e,l,l,-,2,1,\",cell-22,cell-23\r\ncell-31,cell-32,\",c,e,l,l,-,3,3,\"",
|
||||
"json": [
|
||||
["cell-11", ",c,e,l,l,-,1,2,", "cell-13"],
|
||||
[",c,e,l,l,-,2,1,", "cell-22", "cell-23"],
|
||||
["cell-31", "cell-32", ",c,e,l,l,-,3,3,"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11": ",c,e,l,l,-,2,1,", ",c,e,l,l,-,1,2,": "cell-22", "cell-13": "cell-23"},
|
||||
{"cell-11": "cell-31", ",c,e,l,l,-,1,2,": "cell-32", "cell-13": ",c,e,l,l,-,3,3,"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UTF-8 characters",
|
||||
"options": {},
|
||||
"csv": "ᑖcell-11™,°cell-12ą,ćcell-13ś\r\nżcell-21ę,łcell-22ó,Ócell-23↑\r\nŹcell-31Ż,Ącell-32Ń,Ęcell-33ę",
|
||||
"json": [
|
||||
["ᑖcell-11™", "°cell-12ą", "ćcell-13ś"],
|
||||
["żcell-21ę", "łcell-22ó", "Ócell-23↑"],
|
||||
["Źcell-31Ż", "Ącell-32Ń", "Ęcell-33ę"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"ᑖcell-11™": "żcell-21ę", "°cell-12ą": "łcell-22ó", "ćcell-13ś": "Ócell-23↑"},
|
||||
{"ᑖcell-11™": "Źcell-31Ż", "°cell-12ą": "Ącell-32Ń", "ćcell-13ś": "Ęcell-33ę"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "All in one",
|
||||
"options": {},
|
||||
"csv": "\"\"\",\r\n,\"\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"\"\",ҡ͟¼lj·˨Քƣйʊ͕Έӕ,😣👁🔵⛔️🌹\r\n\"\"\",\r\n,\"\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"\"\",ҡ͟¼lj·˨Քƣйʊ͕Έӕ,😣👁🔵⛔️🌹\n\"\"\",\r\n,\"\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"\"\",ҡ͟¼lj·˨Քƣйʊ͕Έӕ,😣👁🔵⛔️🌹",
|
||||
"json": [
|
||||
["\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹"],
|
||||
["\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹"],
|
||||
["\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"": "\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ": "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹": "😣👁🔵⛔️🌹"},
|
||||
{"\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"": "\",\r\n,\",\r\nĄŚĆżóŁ\n\n\n\r\n,\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ": "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹": "😣👁🔵⛔️🌹"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "All in one - custom separator",
|
||||
"options": {"separator": "\t"},
|
||||
"csv": "\"\"\"\t\r\n\t\"\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"\"\"\tҡ͟¼lj·˨Քƣйʊ͕Έӕ\t😣👁🔵⛔️🌹\r\n\"\"\"\t\r\n\t\"\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"\"\"\tҡ͟¼lj·˨Քƣйʊ͕Έӕ\t😣👁🔵⛔️🌹\n\"\"\"\t\r\n\t\"\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"\"\"\tҡ͟¼lj·˨Քƣйʊ͕Έӕ\t😣👁🔵⛔️🌹",
|
||||
"json": [
|
||||
["\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹"],
|
||||
["\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹"],
|
||||
["\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"": "\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ": "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹": "😣👁🔵⛔️🌹"},
|
||||
{"\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"": "\"\t\r\n\t\"\t\r\nĄŚĆżóŁ\n\n\n\r\n\t\"", "ҡ͟¼lj·˨Քƣйʊ͕Έӕ": "ҡ͟¼lj·˨Քƣйʊ͕Έӕ", "😣👁🔵⛔️🌹": "😣👁🔵⛔️🌹"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Edge case - only empty rows",
|
||||
"options": {},
|
||||
"csv": "\r\n\r\n",
|
||||
"json": [
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{},
|
||||
{}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Edge case - only empty cells",
|
||||
"options": {},
|
||||
"csv": ",,\r\n,,\r\n,,",
|
||||
"json": [
|
||||
["", "", ""],
|
||||
["", "", ""],
|
||||
["", "", ""]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{},
|
||||
{}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Edge case - Newline -> Comma -> Text",
|
||||
"options": {},
|
||||
"csv": "A,B\r\n,C",
|
||||
"json": [
|
||||
["A", "B"],
|
||||
["", "C"]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"A": "", "B": "C"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Edge case - single comma",
|
||||
"options": {},
|
||||
"csv": ",",
|
||||
"json": [
|
||||
["", ""]
|
||||
],
|
||||
"jsonWithHeaders": []
|
||||
},
|
||||
{
|
||||
"@comment": "The behavior here is undefined - the only thing that matters is it should not throw an exception, the result is free to make no sense.",
|
||||
"name": "Edge case - quote separator",
|
||||
"options": {"separator": "\""},
|
||||
"csv": "cell-11,\"cell-12\",cell-13\r\n\"cell-21\",cell-22,cell-23\r\ncell-31,cell-32,\"cell-33\"",
|
||||
"json": [
|
||||
["cell-11,", "cell-12", ",cell-13"],
|
||||
["cell-21", "cell-22,cell-23"],
|
||||
["cell-31,cell-32,", "cell-33", ""]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11,": "cell-21", "cell-12": "cell-22,cell-23", ",cell-13": ""},
|
||||
{"cell-11,": "cell-31,cell-32,", "cell-12": "cell-33", ",cell-13": ""}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@comment": "The behavior here is undefined - the only thing that matters is it should not throw an exception, the result is free to make no sense.",
|
||||
"name": "Edge case - carriage return separator",
|
||||
"options": {"separator": "\r"},
|
||||
"csv": "cell-11,\"cell-12\",cell-13\r\n\"cell-21\",cell-22,cell-23\r\ncell-31,cell-32,\"cell-33\"",
|
||||
"json": [
|
||||
["cell-11,\"cell-12\",cell-13"],
|
||||
["cell-21", "cell-22,cell-23"],
|
||||
["cell-31,cell-32,\"cell-33\""]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11,\"cell-12\",cell-13": "cell-21" },
|
||||
{"cell-11,\"cell-12\",cell-13": "cell-31,cell-32,\"cell-33\""}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@comment": "The behavior here is undefined - the only thing that matters is it should not throw an exception, the result is free to make no sense.",
|
||||
"name": "Edge case - newline separator",
|
||||
"options": {"separator": "\n"},
|
||||
"csv": "cell-11,\"cell-12\",cell-13\r\n\"cell-21\",cell-22,cell-23\r\ncell-31,cell-32,\"cell-33\"",
|
||||
"json": [
|
||||
["cell-11,\"cell-12\",cell-13"],
|
||||
["cell-21", "cell-22,cell-23"],
|
||||
["cell-31,cell-32,\"cell-33\""]
|
||||
],
|
||||
"jsonWithHeaders": [
|
||||
{"cell-11,\"cell-12\",cell-13": "cell-21" },
|
||||
{"cell-11,\"cell-12\",cell-13": "cell-31,cell-32,\"cell-33\""}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,36 +0,0 @@
|
||||
title: Macros/NestedMacros
|
||||
description: Nested Macros
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
\define outer()
|
||||
\whitespace trim
|
||||
|
||||
\define middle()
|
||||
\whitespace trim
|
||||
|
||||
\define inner()
|
||||
\whitespace trim
|
||||
|
||||
Jaguar
|
||||
|
||||
\end inner
|
||||
|
||||
<<inner>>
|
||||
|
||||
\end middle
|
||||
|
||||
<<middle>>
|
||||
|
||||
\end outer
|
||||
|
||||
<<outer>>
|
||||
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
<p>Jaguar</p>
|
||||
@@ -1,36 +0,0 @@
|
||||
title: Pragmas/Parsermode
|
||||
description: parsermode pragma
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
{{AlwaysInline}}
|
||||
|
||||
{{AlwaysBlock}}
|
||||
|
||||
{{AlwaysInline}}{{AlwaysBlock}}
|
||||
|
||||
+
|
||||
title: AlwaysInline
|
||||
|
||||
\parsermode inline
|
||||
! Not Heading
|
||||
|
||||
Text with ''bold''
|
||||
+
|
||||
title: AlwaysBlock
|
||||
|
||||
\parsermode block
|
||||
! Heading
|
||||
|
||||
Text with ''bold''
|
||||
+
|
||||
title: ExpectedResult
|
||||
|
||||
! Not Heading
|
||||
|
||||
Text with <strong>bold</strong><h1 class="">Heading</h1><p>Text with <strong>bold</strong></p><p>! Not Heading
|
||||
|
||||
Text with <strong>bold</strong><h1 class="">Heading</h1><p>Text with <strong>bold</strong></p>
|
||||
</p>
|
||||
@@ -1,33 +0,0 @@
|
||||
/*\
|
||||
title: modules/utils/test-csv.js
|
||||
type: application/javascript
|
||||
tags: [[$:/tags/test-spec]]
|
||||
|
||||
Tests the backlinks mechanism.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
describe('CSV Parsing', function() {
|
||||
var tid = $tw.wiki.getTiddler('csv-cases');
|
||||
var testCases = JSON.parse(tid.fields.text);
|
||||
|
||||
$tw.utils.each(testCases, function(testCase) {
|
||||
if (testCase.skip) {
|
||||
return;
|
||||
}
|
||||
it("Test case: " + testCase.name, function() {
|
||||
var parsedCsv = $tw.utils.parseCsvString(testCase.csv, testCase.options);
|
||||
expect(parsedCsv).withContext("The generated CSV should match the expected one").toEqual(testCase.json);
|
||||
|
||||
var parsedCsvWithHeaders = $tw.utils.parseCsvStringWithHeader(testCase.csv, testCase.options);
|
||||
expect(parsedCsvWithHeaders).withContext("The generated CSV with headers should match the expected one").toEqual(testCase.jsonWithHeaders);
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -23,7 +23,7 @@ describe("json filter tests", function() {
|
||||
type: "application/json"
|
||||
},{
|
||||
title: "Second",
|
||||
text: '["une","deux","trois",["quatre","cinq"]]',
|
||||
text: '["une","deux","trois"]',
|
||||
type: "application/json"
|
||||
},{
|
||||
title: "Third",
|
||||
@@ -38,14 +38,14 @@ describe("json filter tests", function() {
|
||||
|
||||
it("should support the jsonget operator", function() {
|
||||
expect(wiki.filterTiddlers("[{Third}jsonget[]]")).toEqual(["This is not JSON"]);
|
||||
expect(wiki.filterTiddlers("[{Second}jsonget[]]")).toEqual(["une","deux","trois","quatre","cinq"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[]]")).toEqual(["one","","1.618","four","five","six","true","false","null"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[a]]")).toEqual(["one"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[b]]")).toEqual([""]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[missing-property]]")).toEqual([]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d]]")).toEqual(["four","five","six","true","false","null"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d]]")).toEqual(['{"e":"four","f":["five","six",true,false,null]}']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d]jsonget[f]]")).toEqual(['["five","six",true,false,null]']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[e]]")).toEqual(["four"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[f]]")).toEqual(["five","six","true","false","null"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[f]]")).toEqual(['["five","six",true,false,null]']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[0]]")).toEqual(["five"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[1]]")).toEqual(["six"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[2]]")).toEqual(["true"]);
|
||||
@@ -53,25 +53,8 @@ describe("json filter tests", function() {
|
||||
expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[4]]")).toEqual(["null"]);
|
||||
});
|
||||
|
||||
it("should support the jsonextract operator", function() {
|
||||
expect(wiki.filterTiddlers("[{Third}jsonextract[]]")).toEqual(['"This is not JSON"']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[a]]")).toEqual(['"one"']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[b]]")).toEqual(['""']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[missing-property]]")).toEqual([]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d]]")).toEqual(['{"e":"four","f":["five","six",true,false,null]}']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d]jsonextract[f]]")).toEqual(['["five","six",true,false,null]']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[e]]")).toEqual(['"four"']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[f]]")).toEqual(['["five","six",true,false,null]']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[0]]")).toEqual(['"five"']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[1]]")).toEqual(['"six"']);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[2]]")).toEqual(["true"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[3]]")).toEqual(["false"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[4]]")).toEqual(["null"]);
|
||||
});
|
||||
|
||||
it("should support the jsonindexes operator", function() {
|
||||
expect(wiki.filterTiddlers("[{Second}jsonindexes[]]")).toEqual(["0","1","2","3"]);
|
||||
expect(wiki.filterTiddlers("[{Second}jsonindexes[]]")).toEqual(["0","1","2"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonindexes[]]")).toEqual(["a","b","c","d"]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonindexes[a]]")).toEqual([]);
|
||||
expect(wiki.filterTiddlers("[{First}jsonindexes[b]]")).toEqual([]);
|
||||
|
||||
@@ -59,35 +59,10 @@ describe("LinkedList class tests", function() {
|
||||
return pair;
|
||||
};
|
||||
|
||||
// This returns an array in reverse using a LinkList's prev member. Thus
|
||||
// testing that prev is not corrupt. It doesn't exist in the LinkList module
|
||||
// itself to avoid full support for it. Maybe that will change later.
|
||||
function toReverseArray(list) {
|
||||
var visits = Object.create(null),
|
||||
value = list.prev.get(null),
|
||||
array = [];
|
||||
while(value !== null) {
|
||||
array.push(value);
|
||||
var prev = list.prev.get(value);
|
||||
if(Array.isArray(prev)) {
|
||||
var i = (visits[value] || prev.length) - 1;
|
||||
visits[value] = i;
|
||||
value = prev[i];
|
||||
} else {
|
||||
value = prev;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
};
|
||||
|
||||
// compares an array and a linked list to make sure they match up
|
||||
function compare(pair) {
|
||||
var forward = pair.list.toArray();
|
||||
expect(forward).toEqual(pair.array);
|
||||
expect(pair.list.toArray()).toEqual(pair.array);
|
||||
expect(pair.list.length).toBe(pair.array.length);
|
||||
// Now we reverse the linked list and test it back to front, thus
|
||||
// confirming that the list.prev isn't corrupt.
|
||||
expect(toReverseArray(pair.list)).toEqual(forward.reverse());
|
||||
return pair;
|
||||
};
|
||||
|
||||
@@ -140,7 +115,7 @@ describe("LinkedList class tests", function() {
|
||||
// for list.last to be anything other than a string, but I
|
||||
// can't figure out how to make that corruption manifest a problem.
|
||||
// So I dig into its private members. Bleh...
|
||||
expect(typeof pair.list.prev.get(null)).toBe("string");
|
||||
expect(typeof pair.list.last).toBe("string");
|
||||
});
|
||||
|
||||
it("can pushTop value linked to by a repeat item", function() {
|
||||
@@ -162,21 +137,6 @@ describe("LinkedList class tests", function() {
|
||||
compare(pushTop(newPair(["C", "X", "A", "A"]), "X")); // CAAX
|
||||
});
|
||||
|
||||
it("can remove all instances of a multi-instance value #7059", function() {
|
||||
// Remove duplicate items when one or more items between the duplicates
|
||||
// are not removed and the first of those duplicates is not the first item.
|
||||
// These tests used to fail prior to the fix to #7059
|
||||
compare(remove(newPair(["A", "A", "C", "B", "A"]), ["A", "C", "A", "A"])); // B
|
||||
compare(remove(newPair(["A", "A", "C", "B", "A"]), ["C", "A", "A", "A"])); // B
|
||||
compare(remove(newPair(["A", "A", "C", "B", "A"]), ["A", "A", "A"])); // CB
|
||||
compare(remove(newPair(["A", "A", "C", "B", "A"]), ["A", "A", "A", "C"])); // B
|
||||
compare(remove(newPair(["A", "A", "B", "A"]), ["A", "A", "A"])); // B
|
||||
compare(remove(newPair(["A", "A", "B", "A"]), ["A", "A", "A", "B"])); //
|
||||
compare(remove(newPair(["C", "A", "B", "A"]), ["C", "A", "A"])); // B
|
||||
compare(remove(newPair(["C", "A", "B", "A", "C"]), ["C", "A", "A", "C"])); // B
|
||||
compare(remove(newPair(["B", "A", "B", "A"]), ["B", "A", "A"])); // B
|
||||
});
|
||||
|
||||
it("can handle particularly nasty pushTop pitfall", function() {
|
||||
var pair = newPair(["A", "B", "A", "C"]);
|
||||
pushTop(pair, "A"); // BACA
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*\
|
||||
title: test-popup.js
|
||||
type: application/javascript
|
||||
tags: [[$:/tags/test-spec]]
|
||||
|
||||
Tests some utility function of the Popup prototype.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
describe("Popup tests", function() {
|
||||
|
||||
it("parseCoordinates should parse valid coordinates", function() {
|
||||
var popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
expect(popup.parseCoordinates("(1,2,3,4)")).toEqual({absolute: false, left: 1, top: 2, width: 3, height: 4});
|
||||
expect(popup.parseCoordinates("(1.5,2.6,3.7,4.8)")).toEqual({absolute: false, left: 1.5, top: 2.6, width: 3.7, height: 4.8});
|
||||
expect(popup.parseCoordinates("@(1,2,3,4)")).toEqual({absolute: true, left: 1, top: 2, width: 3, height: 4});
|
||||
expect(popup.parseCoordinates("@(1.5,2.6,3.7,4.8)")).toEqual({absolute: true, left: 1.5, top: 2.6, width: 3.7, height: 4.8});
|
||||
});
|
||||
|
||||
it("parseCoordinates should not parse invalid coordinates", function() {
|
||||
var popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
expect(popup.parseCoordinates("#(1,2,3,4)")).toEqual(false);
|
||||
expect(popup.parseCoordinates("(1,2,3,4")).toEqual(false);
|
||||
expect(popup.parseCoordinates("(1,2,3)")).toEqual(false);
|
||||
});
|
||||
|
||||
it("buildCoordinates should create valid coordinates", function() {
|
||||
var popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
var coordinates = {
|
||||
left: 1.5,
|
||||
top: 2.6,
|
||||
width: 3.7,
|
||||
height: 4.8
|
||||
};
|
||||
|
||||
expect(popup.buildCoordinates(popup.coordinatePrefix.csOffsetParent, coordinates)).toEqual("(1.5,2.6,3.7,4.8)");
|
||||
expect(popup.buildCoordinates(popup.coordinatePrefix.csAbsolute, coordinates)).toEqual("@(1.5,2.6,3.7,4.8)");
|
||||
});
|
||||
|
||||
it("buildCoordinates should detect invalid input", function() {
|
||||
var popup = require("$:/core/modules/utils/dom/popup.js");
|
||||
|
||||
var coordinates = {
|
||||
left: "invalid",
|
||||
top: 2.6,
|
||||
width: 3.7,
|
||||
height: 4.8
|
||||
};
|
||||
|
||||
expect(popup.buildCoordinates(popup.coordinatePrefix.csOffsetParent, coordinates)).toEqual("(0,0,0,0)");
|
||||
expect(popup.buildCoordinates("dummy", coordinates)).toEqual("(0,0,0,0)");
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -78,7 +78,6 @@ describe("Utility tests", function() {
|
||||
expect(fds(d,"ddd hh mm ssss")).toBe("Sun 17 41 2828");
|
||||
expect(fds(d,"MM0DD")).toBe("1109");
|
||||
expect(fds(d,"MM0\\D\\D")).toBe("110DD");
|
||||
expect(fds(d,"TIMESTAMP")).toBe(d.getTime().toString());
|
||||
const day = d.getUTCDate();
|
||||
const dayStr = ("" + day).padStart(2, '0');
|
||||
const hours = d.getUTCHours();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
],
|
||||
"build": {
|
||||
"index": [
|
||||
"--rendertiddler","$:/core/save/all","test.html","text/plain",
|
||||
"--test"]
|
||||
"--rendertiddler","$:/core/save/all","test.html","text/plain"]
|
||||
}
|
||||
}
|
||||
@@ -13,5 +13,4 @@ core/ui/Buttons/more-page-actions: show
|
||||
core/ui/Buttons/new-journal: hide
|
||||
core/ui/Buttons/permaview: hide
|
||||
core/ui/Buttons/storyview: hide
|
||||
core/ui/Buttons/layout: hide
|
||||
core/ui/Buttons/theme: hide
|
||||
|
||||
@@ -14,10 +14,10 @@ We do need a small amount of money on an ongoing basis to pay the costs of runni
|
||||
|
||||
We use Open Collective to allow you to contribute towards these costs. You can contribute a one-off donation, or make an ongoing monthly commitment. Find out more:
|
||||
|
||||
https://opencollective.com/tiddlywiki
|
||||
https://opencollective.com/tiddlywikidotorg
|
||||
|
||||
!! Community Projects
|
||||
|
||||
We also use Open Collective to raise funds to support the development of major new features, plugins or community infrastructure. These projects generally involve a small team of individuals getting together and making a proposal to the rest of the community.
|
||||
|
||||
For example, the [[File Upload Plugin Project|https://opencollective.com/tiddlywiki/projects/tiddlywiki-file-upload]] aims to radically simplify working with attached images.
|
||||
For example, the [[File Upload Plugin Project|https://opencollective.com/tiddlywikidotorg/projects/tiddlywiki-file-upload]] aims to radically simplify working with attached images.
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
created: 20220817153236691
|
||||
modified: 20221010074314452
|
||||
tags: [[Tables in WikiText]]
|
||||
title: Tables in WikiText CSS Utility Classes
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
~WikiText tables can be styled by applying CSS classes. For basic information on wiktext tables and how to style them, see [[Tables in WikiText]].
|
||||
|
||||
{{Table Classes, Captions, Headers and Footers}}
|
||||
|
||||
As seen above, the resulting table is left aligned and grows to fit the content. This is the browser default layout behaviour for tables. To get another behaviour, various CSS classes can be added into the "`k` row".
|
||||
|
||||
! Utility Classes
|
||||
|
||||
{{Utility Classes}}
|
||||
|
||||
! Examples
|
||||
|
||||
The following examples apply the style classes to tables but the "General Utility Classes" can as well be used on DIVs or other [[HTML block elements|HTML Block Elements]]
|
||||
|
||||
!! Centred Table
|
||||
|
||||
To center a table horizontally, use `tc-center`:
|
||||
|
||||
<<wikitext-example-without-html src:"""|tc-center|k
|
||||
|This is a caption |c
|
||||
|Cell1 |Cell2 |
|
||||
|Cell3 |Cell4 |
|
||||
|Header|Header|h
|
||||
|Footer|Footer|f
|
||||
""">>
|
||||
|
||||
!! Centred Table, 80% Width
|
||||
|
||||
To add empty left and right margins to a table that is otherwise full-tiddler-width, you can use `tc-max-width-80`
|
||||
|
||||
<<wikitext-example-without-html src:"""|tc-center tc-max-width-80|k
|
||||
|This is a caption |c
|
||||
|Cell1 |<<.lorem>> |
|
||||
|<<.lorem>> |Cell4 |
|
||||
|Header|Header|h
|
||||
""">>
|
||||
|
||||
!! Table with Maximum Width
|
||||
|
||||
To expand a table to full tiddler width, use `tc-max-width`
|
||||
|
||||
<<wikitext-example-without-html src:"""|tc-max-width|k
|
||||
|Header|Header|h
|
||||
|Cell1 |Cell2 |
|
||||
|Cell3 |Cell4 |
|
||||
""">>
|
||||
|
||||
!! Table with First Column Minimum Width
|
||||
|
||||
The following example shows a simple "form" where the first columns width is adjusted to its content by means of `tc-first-col-min-width`
|
||||
|
||||
<<wikitext-example-without-html src:"""|tc-max-width tc-first-col-min-width|k
|
||||
|Header|Header|h
|
||||
|Cell1 |<$edit-text tiddler="$:/temp/test-table-input" tag="input" field="test"/> |
|
||||
|Cell3 |<$edit-text tiddler="$:/temp/test-table-input" field="text"/> |
|
||||
""">>
|
||||
|
||||
!! Table with Maximum Width ~TextWidgets
|
||||
|
||||
Here, the previous "form" is styled further to give the [[TextWidget]]s full width by adding the class `tc-edit-max-width`
|
||||
|
||||
<<wikitext-example-without-html src:"""|tc-max-width tc-first-col-min-width tc-edit-max-width|k
|
||||
|Header|Header|h
|
||||
|Cell1 |<$edit-text tiddler="$:/temp/test-table-input" tag="input" field="test"/> |
|
||||
|Cell3 |<$edit-text tiddler="$:/temp/test-table-input" field="text"/> |
|
||||
""">>
|
||||
|
||||
!! Table with No Borders
|
||||
|
||||
The following is a table with maximum width. It contains [[TextWidget]]s with maximum width. The first column is set to be minimum width. Further, all links in the first column are set to __not__ line break (wrap) regardless of window resize.
|
||||
|
||||
<<wikitext-example-without-html src:"""|tc-max-width tc-first-col-min-width tc-edit-max-width tc-table-no-border tc-first-link-nowrap|k
|
||||
| Cell1|<$edit-text tiddler="$:/temp/test-table-input" tag="input" field="test"/> |
|
||||
|^ [[Link to a tiddler]]<br>some more text|<$edit-text tiddler="$:/temp/test-table-input" field="text"/> |
|
||||
""">>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
@@ -1,3 +0,0 @@
|
||||
title: $:/_tw_shared/favicons/marketplace
|
||||
type: image/png
|
||||
tags: TiddlyWikiSitesMenu
|
||||
@@ -1,6 +0,0 @@
|
||||
title: $:/_tw_shared/sites/marketplace
|
||||
tags: $:/tags/TiddlyWikiSites TiddlyWikiSitesMenu
|
||||
caption: marketplace
|
||||
description: Commercial Products and Services
|
||||
url: https://talk.tiddlywiki.org/c/marketplace/22
|
||||
icon: $:/_tw_shared/favicons/marketplace
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/tags/TiddlyWikiSites
|
||||
list: $:/_tw_shared/sites/tiddlywiki.com $:/_tw_shared/sites/tiddlywiki.org $:/_tw_shared/sites/talk.tiddlywiki.org $:/_tw_shared/sites/links.tiddlywiki.org $:/_tw_shared/sites/tiddlywiki.com.upgrade $:/_tw_shared/sites/tiddlywiki.com.dev $:/_tw_shared/sites/tiddlywiki.com.prerelease $:/_tw_shared/sites/classic.tiddlywiki.com $:/_tw_shared/sites/marketplace
|
||||
list: $:/_tw_shared/sites/tiddlywiki.com $:/_tw_shared/sites/tiddlywiki.org $:/_tw_shared/sites/talk.tiddlywiki.org $:/_tw_shared/sites/links.tiddlywiki.org $:/_tw_shared/sites/tiddlywiki.com.upgrade $:/_tw_shared/sites/tiddlywiki.com.dev $:/_tw_shared/sites/tiddlywiki.com.prerelease $:/_tw_shared/sites/classic.tiddlywiki.com
|
||||
tags: TiddlyWikiSitesMenu
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
title: Funding TiddlyWiki
|
||||
tags: About HelloThere
|
||||
modified: 20221204165636777
|
||||
created: 20221204165636777
|
||||
|
||||
TiddlyWiki is more useful to everybody if it is free to use, with no financial barriers to long term adoption. It is not altruism; we believe that removing or reducing barriers to adoption will help to ensure TiddlyWiki's future by making the community larger and stronger.
|
||||
|
||||
Nonetheless, TiddlyWiki is a relatively big, complex machine that requires a significant amount of ongoing work to maintain and improve. Some community infrastructure also requires monthly fees to operate (notably the [[TiddlyWiki forum|Forums]]).
|
||||
|
||||
The people in the community that do the work have widely varying needs:
|
||||
|
||||
* At one end, a good proportion of the work on TiddlyWiki is performed by community members on a purely voluntary basis. For those people, the satisfaction of helping others is sufficient reward. Indeed, for many people, unpaid voluntary activities are a satisfying antidote to everyday paid work
|
||||
* At the other extreme, JeremyRuston and some other contributors are trying to make a full-time living working on TiddlyWiki by offering commercial products and services around it
|
||||
* In between, there are other people who would appreciate an ocassional token to reward them for their work
|
||||
|
||||
To support these needs in the community, we have two initiatives:
|
||||
|
||||
* We use [[Open Collective]] to collect donations for the infrastructure costs of the Community and to crowdfund specific developments by individuals or organisations
|
||||
* The [[TiddlyWiki Marketplace]] provides a shop window for individuals and organisations offering commercial products and services
|
||||
@@ -1,14 +0,0 @@
|
||||
title: Open Collective
|
||||
modified: 20221204165636777
|
||||
created: 20221204165636777
|
||||
tags: About HelloThere [[Open Collective]]
|
||||
|
||||
Open Collective is a platform for transparent fundraising and expenses for projects like TiddlyWiki. It is the official TiddlyWiki community fundraising space.
|
||||
|
||||
https://opencollective.com/tiddlywiki
|
||||
|
||||
You can make a fixed one-time donation, or setup a recurring contribution.
|
||||
|
||||
The main goals listed for donations are to cover basic costs for community infrastructure like the Discourse forum, and a new goal for supporting the TiddlyWiki Core.
|
||||
|
||||
Additionally, the community can make use of the platform for special projects - to pool funds to pay for development, design, or anything else. The [[File Upload Plugin|https://opencollective.com/tiddlywiki/projects/tiddlywiki-file-upload]] is the first of these, and we want to welcome others to launch projects here.
|
||||
@@ -1,8 +0,0 @@
|
||||
created: 20221204202531478
|
||||
modified: 20221204202531478
|
||||
tags: Commands
|
||||
title: CommandsCommand
|
||||
type: text/vnd.tiddlywiki
|
||||
caption: commands
|
||||
|
||||
{{$:/language/Help/commands}}
|
||||
@@ -1,4 +1,5 @@
|
||||
created: 20171107181449175
|
||||
creator: Ste Willson
|
||||
modified: 20210106151027136
|
||||
tags: [[Community Plugins]]
|
||||
title: "JD Mobile Layout plugin" by JD
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
created: 20171111192738730
|
||||
creator: MAS
|
||||
modified: 20210106151027013
|
||||
tags: [[Other Resources]]
|
||||
title: "Dropboard" by Reid Gould
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
created: 20161226165024380
|
||||
creator: Thomas Elmiger
|
||||
modified: 20210106151027097
|
||||
modifier: Thomas Elmiger
|
||||
tags: [[Other Resources]]
|
||||
title: "Hacks" by Thomas Elmiger
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
created: 20161226165024380
|
||||
creator: Ste Willson
|
||||
modified: 20210106151027156
|
||||
tags: [[Other Resources]]
|
||||
title: "MathCell" by Stephen Kimmel
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
created: 20161226165024380
|
||||
creator: Matt Lauber
|
||||
modified: 20211113230709926
|
||||
tags: [[Other Resources]]
|
||||
title: "TiddlyServer" by Matt Lauber
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
created: 20171107175718679
|
||||
creator: Ste Willson
|
||||
modified: 20210106151027400
|
||||
tags: [[Other Resources]]
|
||||
title: "X3DOM for TiddlyWiki 5" by Jamal Wills
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
created: 20220810201659784
|
||||
modified: 20220810201659784
|
||||
tags: Concepts
|
||||
title: Coordinate Systems
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
TiddlyWiki (primarily the RevealWidget) supports two coordinate systems for positioning popups (see PopupMechanism to learn more about popups).
|
||||
|
||||
<<.from-version "5.2.4">> We introduced absolute coordinates that may not work with all extensions and plugins. For maximum backwards compatibility, use absolute coordinates only where necessary.
|
||||
|
||||
!! Relative coordinate system
|
||||
|
||||
The default coordinate system is relative to the nearest positioned ancestor element. This is either:
|
||||
|
||||
* an element with a non-static position, or
|
||||
* a ''td'', ''th'', ''table'' in case the element itself is static positioned.
|
||||
|
||||
For tiddlers the nearest positioned ancestor element mostly is the body of the tiddler. Read the next chapter to learn about the exceptions.
|
||||
|
||||
Relative coordinates are expressed in the form ''(x,y,w,h)''. Where ''x'' and ''y'' represent the position and ''w'' and ''h'' the width and height of the element.
|
||||
|
||||
!! Absolute coordinate system
|
||||
|
||||
The relative coordinate system works flawless most of the time. Problems occure if the target element (for example, a popup) and the source element (the triggering button) do not share the same positioned ancherstor element. This is often the case if the popup is declared outside a table and the triggering button is declared within a table cell. In this case the coordiante systems have different origins and the popup will be displayed in the wrong location.
|
||||
|
||||
Absolute coordinates can fix this problem by using the root element of the page (the upper-left corner of the page) as the origin of the coordinate system. Absolute coordinates are expressed in the form ''@(x,y,w,h)''. Where ''x'' and ''y'' represent the position and ''w'' and ''h'' the width and height of the element. The leading ''@''-symbol marks these coordinates as absolute.
|
||||
|
||||
The ButtonWidget has an option (''popupAbsCoords'') to put absolute coordinates into the state tiddler. The DraggableWidget and the EventCatcherWidget provide the absolute coordinate of an event within the attribute `tv-popup-abs-coords`.
|
||||
|
||||
|
||||
!! Example
|
||||
|
||||
The following example shows a popup that is triggerd from within a table cell. The table cell is the nearest positioned ancestor element. The popup was defined outside the table cell. The button using relative coordinates will open the popup in the wrong location because the button and the popup do not agree on the same coordinate system. Using absolute coordinates fixes this problem.
|
||||
|
||||
<<wikitext-example-without-html '<$reveal type="popup" state="$:/state/CoordinateSampleReveal">
|
||||
<div class="tc-drop-down">
|
||||
Popup
|
||||
</div>
|
||||
</$reveal>
|
||||
|
||||
| Table Row 1 |<$button popup="$:/state/CoordinateSampleReveal">Relative coordinates</$button>|
|
||||
| Table Row 2 |<$button popup="$:/state/CoordinateSampleReveal" popupAbsCoords="yes">Absolute coordinates</$button>|'>>
|
||||
@@ -1,21 +1,9 @@
|
||||
created: 20130825154900000
|
||||
modified: 20170718160846820
|
||||
modified: 20221204165636777
|
||||
tags: Definitions
|
||||
title: Federatial
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Federatial Limited helps organisations explore new user interaction concepts through rapid prototyping of sophisticated web-based tools. Services include:
|
||||
|
||||
* Consultancy advice on TiddlyWiki adoption
|
||||
* Development of custom solutions based on TiddlyWiki
|
||||
* Multi-user TiddlyWiki hosting – no outages since 2016
|
||||
* Sponsorship of TiddlyWiki core development
|
||||
Federatial Limited is a software consultancy founded by JeremyRuston, the creator of TiddlyWiki. Federatial helps organisations explore new user interaction concepts through rapid prototyping of sophisticated web-based tools.
|
||||
|
||||
See https://federatial.com/ and https://twitter.com/federatial for more information.
|
||||
|
||||
JeremyRuston founded Federatial Limited in 2011 to support his work on TiddlyWiki for the advertised 25 years. Since then, Federatial has been privileged to have worked with a wide range of fantastic clients in very different sectors, on some very diverse projects:
|
||||
|
||||
* For a law firm in the Washington DC, developing a custom multi-user ~TiddlyWiki application. It replaced a Microsoft Word document hosted on ~SharePoint that had grown to 18,000 pages and 10 million words, and was increasingly unwieldy to manage. We converted the document to a non-linear TiddlyWiki structure. Startup, searching and browsing are an order of magnitude faster than using Word and ~SharePoint
|
||||
* For a publishing firm in Paris, devising a new TiddlyWiki-based format for interactive electronic publications (including conversion from the established EPUB format). See https://twpub-tools.org/
|
||||
* For a charity in London, maintaining a multiuser instance of TiddlyWiki running on Amazon's serverless infrastructure. It has more than 1,000 users, and over 15,000 tiddlers in 500 interlinked wikis. See https://manuals.annafreud.org/ambit
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
created: 20220818091959523
|
||||
modified: 20220818092101307
|
||||
tags: Definitions
|
||||
title: HTML Block Elements
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<<
|
||||
HTML (Hypertext Markup Language) elements historically were categorized as either "block-level" elements or "inline-level" elements. Since this is a presentational characteristic it is nowadays specified by CSS in the Flow Layout. A Block-level element occupies the entire horizontal space of its parent element (container), and vertical space equal to the height of its contents, thereby creating a "block".
|
||||
<<< https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
|
||||
@@ -4,8 +4,6 @@ tags: Definitions
|
||||
title: TiddlyWikiClassic
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
[img[TiddlyWiki Classic.png]]
|
||||
|
||||
"~TiddlyWiki Classic" refers to versions prior to 5.0, before TiddlyWiki was completely rewritten. TiddlyWiki Classic is still actively maintained at:
|
||||
"~TiddlyWiki Classic" refers to versions prior to 5.0, before TiddlyWiki was completely rewritten from the ground up. TiddlyWiki Classic is still being maintained at:
|
||||
|
||||
https://classic.tiddlywiki.com/
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
caption: Selective (custom icons)
|
||||
created: 20220819080004663
|
||||
modified: 20220819081049054
|
||||
order: 5
|
||||
tags: table-of-contents-example
|
||||
title: Example Table of Contents: Selectively Expandable (custom icons)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.2.4">> It is possible to define the `toc-open-icon` and `toc-closed-icon` variable, to change the icons used by the toc macros. This setting works for all toc-macro variants
|
||||
|
||||
<$macrocall $name=".example" n="1"
|
||||
eg="""<$let toc-open-icon="$:/core/images/fold-button" toc-closed-icon="$:/core/images/folder">
|
||||
<div class="tc-table-of-contents">
|
||||
<<toc-selective-expandable "Contents">>
|
||||
</div>
|
||||
</$let>"""/>
|
||||
@@ -16,7 +16,7 @@ This is a version of the TaskManagementExample enhanced with the ability to drag
|
||||
|
||||
//(Listed in reverse order of completion)//
|
||||
|
||||
<$list filter="[!has[draft.of]tag[task]tag[done]sort[modified]]">
|
||||
<$list filter="[!has[draft.of]tag[task]tag[done]sort[created]]">
|
||||
<div>
|
||||
<$checkbox tag="done"> ~~<$link/>~~</$checkbox>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
created: 20140418142957325
|
||||
modified: 20221121131150032
|
||||
modified: 20210912115121622
|
||||
tags: Features
|
||||
title: DateFormat
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
The default representation of dates is a compact string such as `20211002153802059`. For example, the `created` and `modified` fields are stored like this.
|
||||
The default representation of dates is a compact string such as `20211002153802059`. For example, the `created` and `modified` fields are stored like this.
|
||||
|
||||
The display format for this string can be controlled with a template. For example, transcluding the `modified` field automatically applies a template to display the date as `Sat Oct 02 2021 17:40:50 GMT+0200 (Central European Summer Time)`. A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget:
|
||||
|
||||
`<$view field=modified format=date template="DDth mmm YYYY 0hh:0mm:0ss" />`
|
||||
`<$view field=modified format=date template=“DDth mmm YYYY 0hh:0mm:0ss” />`
|
||||
|
||||
The date string is processed with the following substitutions:
|
||||
|
||||
@@ -46,7 +46,6 @@ The date string is processed with the following substitutions:
|
||||
|`am` or `pm` |Lower case AM/PM indicator |
|
||||
|`AM` or `PM` |Upper case AM/PM indicator |
|
||||
|`TZD` |Timezone offset |
|
||||
|`TIMESTAMP` |<<.from-version "5.2.4">> Number of milliseconds since the [[ECMAScript epoch|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#the_ecmascript_epoch_and_timestamps]], 1 January 1970. |
|
||||
|`\x` |Used to escape a character that would otherwise have special meaning |
|
||||
|`[UTC]`|Time-shift the represented date to UTC. Must be at very start of format string|
|
||||
|
||||
@@ -60,26 +59,3 @@ The `{era:BCE||CE}` notation can specify different strings for years that are ne
|
||||
|`DDth MMM YYYY` |16th February 2011 |
|
||||
|`DDth MMM \M\M\M YYYY` |16th February MMM 2011 |
|
||||
|`DDth mmm YYYY 0hh:0mm:0ss` |16th Feb 2011 11:38:42 |
|
||||
|
||||
!! Using `TIMESTAMP` to calculate time difference
|
||||
|
||||
You can calculate the difference between two dates by doing the following:
|
||||
|
||||
# Convert both dates to timestamps
|
||||
# Subtract the later date from the earlier one -- if you don't know which one is earlier use the <<.olink "abs">> operator to get an absolute value after subtraction
|
||||
# Divide the resulting number by the number of milliseconds in your chosen interval
|
||||
|
||||
Here is an example of calculating the number of days that passed between creation and last modification of current tiddler:
|
||||
|
||||
* Fields `modified` and `created` contain their respective datetimes in the format `[UTC]YYYY0MM0DD0hh0mm0ssXXX` so convert them to timestamps
|
||||
* `86400000` is the number of milliseconds in a day (1000 * 60 * 60 * 24)
|
||||
|
||||
<$macrocall $name=".example" n="0" eg="""<$let
|
||||
timestamp-modified={{{ [{!!modified}format:date[TIMESTAMP]] }}}
|
||||
timestamp-created={{{ [{!!created}format:date[TIMESTAMP]] }}}
|
||||
difference-days={{{ [<timestamp-modified>subtract<timestamp-created>divide[86400000]floor[]] }}}>
|
||||
|
||||
* ''Modified date:'' <$text text={{{ [{!!modified}format:date[YYYY-0MM-0DD]] }}}/>
|
||||
* ''Created date:'' <$text text={{{ [{!!created}format:date[YYYY-0MM-0DD]] }}}/>
|
||||
* ''Difference in days:'' <<difference-days>> days
|
||||
</$let>"""/>
|
||||
@@ -2,7 +2,7 @@ title: JSON in TiddlyWiki
|
||||
tags: Features
|
||||
type: text/vnd.tiddlywiki
|
||||
created: 20220427174702859
|
||||
modified: 20220611104737314
|
||||
modified: 20220427174702859
|
||||
|
||||
!! Introduction
|
||||
|
||||
|
||||
@@ -13,12 +13,9 @@ The tiddler to be displayed can contain the following optional fields that are u
|
||||
|subtitle|The subtitle text for a modal, displayed in a `h3` html tag|
|
||||
|class|An additional class to apply to the modal wrapper|
|
||||
|help|An optional external link that will be displayed at the left of the footer with the text "Help"|
|
||||
|mask-closable|When set to ''yes'' or ''true'', will close the modal dialog when the mask (area outside the modal) is clicked|
|
||||
|
||||
Note that the footer and subtitle fields are not limited to plain text, and wiki text features such as widgets and transclusions can be used as well.
|
||||
|
||||
Modals are displayed with the [[WidgetMessage: tm-modal]].
|
||||
|
||||
<$button message="tm-modal" param="SampleWizard">Open demo modal</$button>
|
||||
|
||||
<<.tip """<$macrocall $name=".from-version" version="5.2.4"/> allow using "mask-closable" field""">>
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
created: 20220611104737314
|
||||
modified: 20220611104737314
|
||||
tags: [[Filter Operators]] [[JSON Operators]]
|
||||
title: jsonextract Operator
|
||||
caption: jsonextract
|
||||
op-purpose: retrieve the JSON string of a property from JSON strings
|
||||
op-input: a selection of JSON strings
|
||||
op-parameter: one or more indexes of the property to retrieve
|
||||
op-output: the JSON string values of each of the retrieved properties
|
||||
|
||||
<<.from-version "5.2.4">> See [[JSON in TiddlyWiki]] for background.
|
||||
|
||||
The <<.op jsonextract>> operator is used to retrieve values from JSON data as JSON substrings. See also the following related operators:
|
||||
|
||||
* <<.olink jsonget>> to retrieve the values of a property in JSON data
|
||||
* <<.olink jsontype>> to retrieve the type of a JSON value
|
||||
* <<.olink jsonindexes>> to retrieve the names of the fields of a JSON object, or the indexes of a JSON array
|
||||
|
||||
Properties within a JSON object are identified by a sequence of indexes. In the following example, the value at `[a]` is `one`, and the value at `[d][f][0]` is `five`.
|
||||
|
||||
```
|
||||
{
|
||||
"a": "one",
|
||||
"b": "",
|
||||
"c": "three",
|
||||
"d": {
|
||||
"e": "four",
|
||||
"f": [
|
||||
"five",
|
||||
"six",
|
||||
true,
|
||||
false,
|
||||
null
|
||||
],
|
||||
"g": {
|
||||
"x": "max",
|
||||
"y": "may",
|
||||
"z": "maize"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The following examples assume that this JSON data is contained in a variable called `jsondata`.
|
||||
|
||||
The <<.op jsonextract>> operator uses multiple operands to specify the indexes of the property to retrieve. Values are returned as literal JSON strings:
|
||||
|
||||
```
|
||||
[<jsondata>jsonextract[a]] --> "one"
|
||||
[<jsondata>jsonextract[d],[e]] --> "four"
|
||||
[<jsondata>jsonextract[d],[f],[0]] --> "five"
|
||||
[<jsondata>jsonextract[d],[f]] --> ["five","six",true,false,null]
|
||||
[<jsondata>jsonextract[d],[g]] --> {"x":"max","y":"may","z":"maize"}
|
||||
```
|
||||
|
||||
Indexes can be dynamically composed from variables and transclusions:
|
||||
|
||||
```
|
||||
[<jsondata>jsonextract<variable>,{!!field},[0]]
|
||||
```
|
||||
|
||||
A subtlety is that the special case of a single blank operand is used to identify the root object. Thus:
|
||||
|
||||
```
|
||||
[<jsondata>jsonextract[]] --> {"a":"one","b":"","c":"three","d":{"e":"four","f":["five","six",true,false,null],"g":{"x":"max","y":"may","z":"maize"}}}
|
||||
```
|
||||
@@ -10,11 +10,10 @@ op-output: the values of each of the retrieved properties
|
||||
|
||||
<<.from-version "5.2.4">> See [[JSON in TiddlyWiki]] for background.
|
||||
|
||||
The <<.op jsonget>> operator is used to retrieve values from JSON data as strings. See also the following related operators:
|
||||
The <<.op jsonget>> operator is used to retrieve values from JSON data. See also the following related operators:
|
||||
|
||||
* <<.olink jsontype>> to retrieve the type of a JSON value
|
||||
* <<.olink jsonindexes>> to retrieve the names of the fields of a JSON object, or the indexes of a JSON array
|
||||
* <<.olink jsonextract>> to retrieve a JSON value as a string of JSON
|
||||
|
||||
Properties within a JSON object are identified by a sequence of indexes. In the following example, the value at `[a]` is `one`, and the value at `[d][f][0]` is `five`.
|
||||
|
||||
@@ -66,11 +65,11 @@ Boolean values and null are returned as normal strings. The <<.olink jsontype>>
|
||||
[<jsondata>jsontype[d],[f],[2]] --> "boolean"
|
||||
```
|
||||
|
||||
Using the <<.op jsonget>> operator to retrieve an object or an array returns a list of the values. For example:
|
||||
Using the <<.op jsonget>> operator to retrieve an object or an array returns a JSON string of the values. For example:
|
||||
|
||||
```
|
||||
[<jsondata>jsonget[d],[f]] --> "five","six","true","false","null"
|
||||
[<jsondata>jsonget[d],[g]] --> "max","may","maize"
|
||||
[<jsondata>jsonget[d],[f]] --> `["five","six",true,false,null]`
|
||||
[<jsondata>jsonget[d],[g]] --> `{"x": "max","y": "may","z": "maize"}`
|
||||
```
|
||||
|
||||
The <<.olink jsonindexes>> operator retrieves the corresponding indexes:
|
||||
@@ -80,12 +79,6 @@ The <<.olink jsonindexes>> operator retrieves the corresponding indexes:
|
||||
[<jsondata>jsonindexes[d],[g]] --> "x", "y", "z"
|
||||
```
|
||||
|
||||
If the object or array contains nested child objects or arrays then the values are retrieved recursively and returned flattened into a list. For example:
|
||||
|
||||
```
|
||||
[<jsondata>jsonget[d]] --> "four","five","six","true","false","null","max","may","maize"
|
||||
```
|
||||
|
||||
A subtlety is that the special case of a single blank operand is used to identify the root object. Thus:
|
||||
|
||||
```
|
||||
|
||||
@@ -14,7 +14,6 @@ The <<.op jsonindexes>> operator is used to retrieve the property names of JSON
|
||||
|
||||
* <<.olink jsonget>> to retrieve the values of a property in JSON data
|
||||
* <<.olink jsontype>> to retrieve the type of a JSON value
|
||||
* <<.olink jsonextract>> to retrieve a JSON value as a string of JSON
|
||||
|
||||
Properties within a JSON object are identified by a sequence of indexes. In the following example, the value at `[a]` is `one`, and the value at `[d][f][0]` is `five`.
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ The <<.op jsontype>> operator is used to retrieve the type of a property in JSON
|
||||
|
||||
* <<.olink jsonget>> to retrieve the values of a property in JSON data
|
||||
* <<.olink jsonindexes>> to retrieve the names of the fields of a JSON object, or the indexes of a JSON array
|
||||
* <<.olink jsonextract>> to retrieve a JSON value as a string of JSON
|
||||
|
||||
JSON supports the following data types:
|
||||
|
||||
|
||||
@@ -1,39 +1,32 @@
|
||||
created: 20130822170200000
|
||||
list: [[A Gentle Guide to TiddlyWiki]] [[Discover TiddlyWiki]] [[Some of the things you can do with TiddlyWiki]] [[Ten reasons to switch to TiddlyWiki]] Examples [[What happened to the original TiddlyWiki?]]
|
||||
modified: 20221204165636777
|
||||
list: [[A Gentle Guide to TiddlyWiki]] [[Discover TiddlyWiki]] [[Some of the things you can do with TiddlyWiki]] [[Ten reasons to switch to TiddlyWiki]] Examples [[What happened to the original TiddlyWiki?]] [[HelloThumbnail - TWEUM2017]]
|
||||
modified: 20220802122551819
|
||||
tags: TableOfContents
|
||||
title: HelloThere
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! ''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''
|
||||
''Have you ever had the feeling that your head is not quite big enough to hold everything you need to remember?''
|
||||
|
||||
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.
|
||||
|
||||
Unlike conventional online services, TiddlyWiki lets you choose where to keep your data, guaranteeing that in the decades to come you will [[still be able to use|Future Proof]] the notes you take today.
|
||||
|
||||
!! ''Find Out More''
|
||||
|
||||
<div class="tc-cards">
|
||||
<$list filter="[tag[HelloThumbnail]]">
|
||||
<$macrocall $name="flex-card" captionField="caption" descriptionField="text"/>
|
||||
</$list>
|
||||
<div style="font-size:0.7em;text-align:center;margin-top:2em;margin-bottom:2em;">
|
||||
<<list-thumbnails filter:"[tag[HelloThumbnail]]" width:"168" height:"95">>
|
||||
</div>
|
||||
|
||||
!! ''~TiddlyWiki Hubs''
|
||||
Unlike conventional online services, TiddlyWiki lets you choose where to keep your data, guaranteeing that in the decades to come you will [[still be able to use|Future Proof]] the notes you take today.
|
||||
|
||||
<div class="tc-cards" style="font-size:0.7em;text-align:center;margin:3em auto;">
|
||||
<div style="font-size:0.7em;text-align:center;margin:3em auto;">
|
||||
<a href="https://talk.tiddlywiki.org/" class="tc-btn-big-green" style="border-radius:4px;background-color:#FF8C19;" target="_blank" rel="noopener noreferrer">
|
||||
{{$:/core/images/help}} ~TalkTW
|
||||
</a>
|
||||
<a href="https://www.youtube.com/c/JeremyRuston" class="tc-btn-big-green" style="border-radius:4px;background-color:#e52d27;" target="_blank" rel="noopener noreferrer">
|
||||
{{$:/core/images/video}} ~YouTube
|
||||
</a>
|
||||
<a href="https://twitter.com/TiddlyWiki" class="tc-btn-big-green" style="border-radius:4px;background-color:#1DA1F2;" target="_blank" rel="noopener noreferrer">
|
||||
<a href="https://twitter.com/TiddlyWiki" class="tc-btn-big-green" style="border-radius:4px;background-color:#5E9FCA;" target="_blank" rel="noopener noreferrer">
|
||||
{{$:/core/images/twitter}} Twitter
|
||||
</a>
|
||||
<a rel="me" href="https://fosstodon.org/@TiddlyWiki" class="tc-btn-big-green" style="border-radius:4px;background-color:#2b90d9;" target="_blank" rel="noopener noreferrer">
|
||||
{{$:/core/images/globe}} Mastodon
|
||||
</a>
|
||||
<a href="https://github.com/Jermolene/TiddlyWiki5" class="tc-btn-big-green" style="border-radius:4px;background-color:#444;" target="_blank" rel="noopener noreferrer">
|
||||
{{$:/core/images/github}} ~GitHub
|
||||
</a>
|
||||
@@ -42,10 +35,16 @@ Unlike conventional online services, TiddlyWiki lets you choose where to keep yo
|
||||
</a>
|
||||
</div>
|
||||
|
||||
!! ''Testimonials & Reviews''
|
||||
<<<.tc-big-quote
|
||||
''The ~TiddlyWiki is the best software I've ever found for organising my ideas.''
|
||||
|
||||
<div class="tc-cards">
|
||||
<$list filter="[tag[Testimonial]]">
|
||||
<$macrocall $name="flex-card" class="tc-card-quote" captionField="caption" descriptionField="text"/>
|
||||
</$list>
|
||||
</div>
|
||||
It's well worth spending an hour or so playing with it to see how it can help you. This will be time well-spent and will change how you think and how you organise your ideas.
|
||||
<<< [[Joe Armstrong, Co-inventor of Erlang|https://joearms.github.io/]]
|
||||
|
||||
<<<.tc-big-quote
|
||||
''~TiddlyWiki gets a Gearhead rating of 6 out of 5 (it's that good).''
|
||||
|
||||
Finding code that works flawlessly after just two or three years is magical enough but after seven years?!
|
||||
<<< [[Mark Gibbs, Network World|http://www.networkworld.com/article/3028098/open-source-tools/tiddlywiki-a-free-open-source-wiki-revisited.html]]
|
||||
|
||||
<div style="font-size:0.7em;text-align:center;margin:3em auto;">{{Product Hunt Link}}</div>
|
||||
@@ -1,5 +1,5 @@
|
||||
created: 20150414070451144
|
||||
list: [[HelloThumbnail - Introduction Video]] [[HelloThumbnail - Grok TiddlyWiki]] [[HelloThumbnail - Latest Version]] [[HelloThumbnail - TiddlyWikiLinks]] [[HelloThumbnail - Developers]] [[HelloThumbnail - Funding]] [[HelloThumbnail - Marketplace]] [[HelloThumbnail - Federatial]]
|
||||
list: [[HelloThumbnail - Introduction Video]] [[HelloThumbnail - Gentle Guide]] [[HelloThumbnail - Grok TiddlyWiki]] [[HelloThumbnail - Firefox Apocalypse]] [[HelloThumbnail - Latest Version]] [[HelloThumbnail - TiddlyWikiLinks]] [[HelloThumbnail - TiddlyMap]] [[HelloThumbnail - HelpingTiddlyWiki]] [[HelloThumbnail - Developers]] [[HelloThumbnail - Classic]]
|
||||
modified: 20150414070948246
|
||||
title: HelloThumbnail
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user