1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-23 11:24:40 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
jeremy@jermolene.com
f922149b32 First commit 2022-11-12 17:06:54 +00:00
231 changed files with 762 additions and 3261 deletions

1
.gitignore vendored
View File

@@ -4,4 +4,3 @@
tmp/
output/
node_modules/

View File

@@ -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

View File

@@ -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"

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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 &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}}
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; 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

View File

@@ -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>]"
```

View File

@@ -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;
})();

View File

@@ -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);
};

View File

@@ -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();
}
/*

View File

@@ -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;
})();

View File

@@ -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;
})();

View File

@@ -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;

View File

@@ -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 [];
};
})();

View File

@@ -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());

View File

@@ -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");
};
}());

View File

@@ -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();
}
};
}());

View File

@@ -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");
};
}());

View File

@@ -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({

View File

@@ -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;
}
})();

View File

@@ -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();

View File

@@ -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"}

View File

@@ -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;
})();

View File

@@ -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;
})();

View File

@@ -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));
}],

View File

@@ -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);

View File

@@ -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"]) {

View File

@@ -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;

View File

@@ -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",

View File

@@ -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}}

View File

@@ -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}}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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}} |

View File

@@ -1,3 +0,0 @@
title: $:/snippets/retain-story-ordering-button
<$button set="$:/DefaultTiddlers" setTo={{$:/config/ControlPanel/Basics/DefaultTiddlers/RetainStory}} ><<currentTiddler>></$button>

View File

@@ -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}]

View File

@@ -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">

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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/]]}}}>

View File

@@ -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>

View File

@@ -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>

View File

@@ -1,3 +0,0 @@
title: $:/config/ControlPanel/Basics/DefaultTiddlers/RetainStory
[list[$:/StoryList]]

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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]]

View File

@@ -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

View File

@@ -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}}

View File

@@ -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//

View File

@@ -1,3 +0,0 @@
title: $:/SiteSubtitle
<<version>>

View File

@@ -1,3 +0,0 @@
title: $:/SiteTitle
Library test edition, plugin development

View File

@@ -1,3 +0,0 @@
title: $:/themes/tiddlywiki/vanilla/options/sidebarlayout
fluid-fixed

View File

@@ -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",

View File

@@ -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

View File

@@ -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">

View File

@@ -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\""}
]
}
]

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
});
})
});
})();

View File

@@ -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([]);

View File

@@ -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

View File

@@ -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)");
});
});
})();

View File

@@ -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();

View File

@@ -9,7 +9,6 @@
],
"build": {
"index": [
"--rendertiddler","$:/core/save/all","test.html","text/plain",
"--test"]
"--rendertiddler","$:/core/save/all","test.html","text/plain"]
}
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -1,3 +0,0 @@
title: $:/_tw_shared/favicons/marketplace
type: image/png
tags: TiddlyWikiSitesMenu

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -1,8 +0,0 @@
created: 20221204202531478
modified: 20221204202531478
tags: Commands
title: CommandsCommand
type: text/vnd.tiddlywiki
caption: commands
{{$:/language/Help/commands}}

View File

@@ -1,4 +1,5 @@
created: 20171107181449175
creator: Ste Willson
modified: 20210106151027136
tags: [[Community Plugins]]
title: "JD Mobile Layout plugin" by JD

View File

@@ -1,4 +1,5 @@
created: 20171111192738730
creator: MAS
modified: 20210106151027013
tags: [[Other Resources]]
title: "Dropboard" by Reid Gould

View File

@@ -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

View File

@@ -1,4 +1,5 @@
created: 20161226165024380
creator: Ste Willson
modified: 20210106151027156
tags: [[Other Resources]]
title: "MathCell" by Stephen Kimmel

View File

@@ -1,4 +1,5 @@
created: 20161226165024380
creator: Matt Lauber
modified: 20211113230709926
tags: [[Other Resources]]
title: "TiddlyServer" by Matt Lauber

View File

@@ -1,4 +1,5 @@
created: 20171107175718679
creator: Ste Willson
modified: 20210106151027400
tags: [[Other Resources]]
title: "X3DOM for TiddlyWiki 5" by Jamal Wills

View File

@@ -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>|'>>

View File

@@ -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

View File

@@ -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

View File

@@ -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/

View File

@@ -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>"""/>

View File

@@ -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>

View File

@@ -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>"""/>

View File

@@ -2,7 +2,7 @@ title: JSON in TiddlyWiki
tags: Features
type: text/vnd.tiddlywiki
created: 20220427174702859
modified: 20220611104737314
modified: 20220427174702859
!! Introduction

View File

@@ -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""">>

View File

@@ -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"}}}
```

View File

@@ -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:
```

View File

@@ -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`.

View File

@@ -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:

View File

@@ -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>

View File

@@ -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