1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-23 18:17:20 +00:00

merged with latest master

This commit is contained in:
pekopeko1 2014-04-27 00:14:41 +09:00
commit 37c50bae61
88 changed files with 1294 additions and 484 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.DS_Store .DS_Store
tmp/ tmp/
output/

View File

@ -352,7 +352,7 @@ $tw.utils.parseVersion = function(version) {
}; };
/* /*
Returns true if the version string A is greater than the version string B Returns true if the version string A is greater than the version string B. Returns true if the versions are the same
*/ */
$tw.utils.checkVersions = function(versionStringA,versionStringB) { $tw.utils.checkVersions = function(versionStringA,versionStringB) {
var defaultVersion = { var defaultVersion = {
@ -369,7 +369,8 @@ $tw.utils.checkVersions = function(versionStringA,versionStringB) {
]; ];
return (diff[0] > 0) || return (diff[0] > 0) ||
(diff[0] === 0 && diff[1] > 0) || (diff[0] === 0 && diff[1] > 0) ||
(diff[0] === 0 && diff[1] === 0 && diff[2] > 0); (diff[0] === 0 && diff[1] === 0 && diff[2] > 0) ||
(diff[0] === 0 && diff[1] === 0 && diff[2] === 0);
}; };
/* /*
@ -749,7 +750,7 @@ $tw.Tiddler = function(/* [fields,] fields */) {
var arg = arguments[c], var arg = arguments[c],
src = (arg instanceof $tw.Tiddler) ? arg.fields : arg; src = (arg instanceof $tw.Tiddler) ? arg.fields : arg;
for(var t in src) { for(var t in src) {
if(src[t] === undefined) { if(src[t] === undefined || src[t] === null) {
if(t in this.fields) { if(t in this.fields) {
delete this.fields[t]; // If we get a field that's undefined, delete any previous field value delete this.fields[t]; // If we get a field that's undefined, delete any previous field value
} }
@ -1043,6 +1044,37 @@ $tw.Wiki.prototype.defineShadowModules = function() {
}); });
}; };
/*
Enable safe mode by deleting any tiddlers that override a shadow tiddler
*/
$tw.Wiki.prototype.processSafeMode = function() {
var self = this,
overrides = [];
// Find the overriding tiddlers
this.each(function(tiddler,title) {
if(self.isShadowTiddler(title)) {
console.log(title);
overrides.push(title);
}
});
// Assemble a report tiddler
var titleReportTiddler = "TiddlyWiki Safe Mode",
report = [];
report.push("TiddlyWiki has been started in [[safe mode|http://tiddlywiki.com/static/SafeMode.html]]. Most customisations have been disabled by renaming the following tiddlers:")
// Delete the overrides
overrides.forEach(function(title) {
var tiddler = self.getTiddler(title),
newTitle = "SAFE: " + title;
self.deleteTiddler(title);
self.addTiddler(new $tw.Tiddler(tiddler, {title: newTitle}));
report.push("* [[" + title + "|" + newTitle + "]]");
});
report.push()
this.addTiddler(new $tw.Tiddler({title: titleReportTiddler, text: report.join("\n\n")}));
// Set $:/DefaultTiddlers to point to our report
this.addTiddler(new $tw.Tiddler({title: "$:/DefaultTiddlers", text: "[[" + titleReportTiddler + "]]"}));
};
/* /*
Extracts tiddlers from a typed block of text, specifying default field values Extracts tiddlers from a typed block of text, specifying default field values
*/ */
@ -1562,6 +1594,8 @@ readBrowserTiddlers: whether to read tiddlers from the HTML file we're executing
*/ */
$tw.boot.startup = function(options) { $tw.boot.startup = function(options) {
options = options || {}; options = options || {};
// Check for safe mode
$tw.safeMode = $tw.browser && location.hash === "#:safe";
// Initialise some more $tw properties // Initialise some more $tw properties
$tw.utils.deepDefaults($tw,{ $tw.utils.deepDefaults($tw,{
modules: { // Information about each module modules: { // Information about each module
@ -1578,6 +1612,7 @@ $tw.boot.startup = function(options) {
wikiThemesSubDir: "./themes", wikiThemesSubDir: "./themes",
wikiLanguagesSubDir: "./languages", wikiLanguagesSubDir: "./languages",
wikiTiddlersSubDir: "./tiddlers", wikiTiddlersSubDir: "./tiddlers",
wikiOutputSubDir: "./output",
jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)", jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)",
fileExtensionInfo: Object.create(null), // Map file extension to {type:} fileExtensionInfo: Object.create(null), // Map file extension to {type:}
contentTypeInfo: Object.create(null) // Map type to {encoding:,extension:} contentTypeInfo: Object.create(null) // Map type to {encoding:,extension:}
@ -1645,6 +1680,10 @@ $tw.boot.startup = function(options) {
$tw.wiki.readPluginInfo(); $tw.wiki.readPluginInfo();
$tw.wiki.registerPluginTiddlers("plugin"); $tw.wiki.registerPluginTiddlers("plugin");
$tw.wiki.unpackPluginTiddlers(); $tw.wiki.unpackPluginTiddlers();
// Process "safe mode"
if($tw.safeMode) {
$tw.wiki.processSafeMode();
}
// Register typed modules from the tiddlers we've just loaded // Register typed modules from the tiddlers we've just loaded
$tw.wiki.defineTiddlerModules(); $tw.wiki.defineTiddlerModules();
// And any modules within plugins // And any modules within plugins

View File

@ -0,0 +1,11 @@
title: $:/language/Help/build
description: Automatically run configured commands
Build the specified build targets for the current wiki. If no build targets are specified then all available targets will be built.
```
--build <target> [<target> ...]
```
Build targets are defined in the `tiddlywiki.info` file of a wiki folder.

View File

@ -0,0 +1,8 @@
title: $:/language/Help/clearpassword
description: Set a password for subsequent crypto operations
Clear the password for subsequent crypto operations
```
--clearpassword
```

View File

@ -0,0 +1,10 @@
title: $:/language/Help/output
description: Set the base output directory for subsequent commands
Sets the base output directory for subsequent commands. The default output directory is the current working directory.
```
--output <pathname>
```
If the specified pathname is relative then it is resolved relative to the current output directory.

View File

@ -6,3 +6,5 @@ Render an individual tiddler as a specified ContentType, defaults to `text/html`
``` ```
--rendertiddler <title> <filename> [<type>] --rendertiddler <title> <filename> [<type>]
``` ```
Any missing directories in the path to the filename are automatically created.

View File

@ -12,3 +12,5 @@ For example:
``` ```
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain --rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain
``` ```
Any files in the target directory are deleted. The target directory is recursively created if it is missing.

View File

@ -6,3 +6,5 @@ Saves an individual tiddler in its raw text or binary format to the specified fi
``` ```
--savetiddler <title> <filename> --savetiddler <title> <filename>
``` ```
Any missing directories in the path to the filename are automatically created.

View File

@ -20,11 +20,20 @@ Parse a sequence of commands
callback: a callback invoked as callback(err) where err is null if there was no error callback: a callback invoked as callback(err) where err is null if there was no error
*/ */
var Commander = function(commandTokens,callback,wiki,streams) { var Commander = function(commandTokens,callback,wiki,streams) {
var path = require("path");
this.commandTokens = commandTokens; this.commandTokens = commandTokens;
this.nextToken = 0; this.nextToken = 0;
this.callback = callback; this.callback = callback;
this.wiki = wiki; this.wiki = wiki;
this.streams = streams; this.streams = streams;
this.outputPath = process.cwd();
};
/*
Add a string of tokens to the command queue
*/
Commander.prototype.addCommandTokens = function(commandTokens) {
Array.prototype.push.apply(this.commandTokens,commandTokens);
}; };
/* /*

View File

@ -0,0 +1,52 @@
/*\
title: $:/core/modules/commands/build.js
type: application/javascript
module-type: command
Command to build a build target
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "build",
synchronous: true
};
var Command = function(params,commander) {
this.params = params;
this.commander = commander;
};
Command.prototype.execute = function() {
// Get the build targets defined in the wiki
var buildTargets = $tw.boot.wikiInfo.build;
if(!buildTargets) {
return "No build targets defined"
}
// Loop through each of the specified targets
var targets;
if(this.params.length > 0) {
targets = this.params;
} else {
targets = Object.keys(buildTargets);
}
for(var targetIndex=0; targetIndex<targets.length; targetIndex++) {
var target = targets[targetIndex],
commands = buildTargets[target];
if(!commands) {
return "Build target '" + target + "' not found";
}
// Add the commands to the queue
this.commander.addCommandTokens(commands);
}
return null;
};
exports.Command = Command;
})();

View File

@ -0,0 +1,33 @@
/*\
title: $:/core/modules/commands/clearpassword.js
type: application/javascript
module-type: command
Clear password for crypto operations
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "clearpassword",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
$tw.crypto.setPassword(null);
return null;
};
exports.Command = Command;
})();

View File

@ -0,0 +1,38 @@
/*\
title: $:/core/modules/commands/output.js
type: application/javascript
module-type: command
Command to set the default output location (defaults to current working directory)
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "output",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
var fs = require("fs"),
path = require("path");
if(this.params.length < 1) {
return "Missing output path";
}
this.commander.outputPath = path.resolve(this.commander.outputPath,this.params[0]);
return null;
};
exports.Command = Command;
})();

View File

@ -31,8 +31,9 @@ Command.prototype.execute = function() {
fs = require("fs"), fs = require("fs"),
path = require("path"), path = require("path"),
title = this.params[0], title = this.params[0],
filename = this.params[1], filename = path.resolve(this.commander.outputPath,this.params[1]),
type = this.params[2] || "text/html"; type = this.params[2] || "text/html";
$tw.utils.createFileDirectories(filename);
fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) { fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) {
self.callback(err); self.callback(err);
}); });

View File

@ -35,10 +35,12 @@ Command.prototype.execute = function() {
wiki = this.commander.wiki, wiki = this.commander.wiki,
filter = this.params[0], filter = this.params[0],
template = this.params[1], template = this.params[1],
pathname = this.params[2], pathname = path.resolve(this.commander.outputPath,this.params[2]),
type = this.params[3] || "text/html", type = this.params[3] || "text/html",
extension = this.params[4] || ".html", extension = this.params[4] || ".html",
tiddlers = wiki.filterTiddlers(filter); tiddlers = wiki.filterTiddlers(filter);
$tw.utils.deleteDirectory(pathname);
$tw.utils.createDirectory(pathname);
$tw.utils.each(tiddlers,function(title) { $tw.utils.each(tiddlers,function(title) {
var parser = wiki.parseTiddler(template), var parser = wiki.parseTiddler(template),
widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}}); widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});

View File

@ -31,10 +31,11 @@ Command.prototype.execute = function() {
fs = require("fs"), fs = require("fs"),
path = require("path"), path = require("path"),
title = this.params[0], title = this.params[0],
filename = this.params[1], filename = path.resolve(this.commander.outputPath,this.params[1]),
tiddler = this.commander.wiki.getTiddler(title), tiddler = this.commander.wiki.getTiddler(title),
type = tiddler.fields.type || "text/vnd.tiddlywiki", type = tiddler.fields.type || "text/vnd.tiddlywiki",
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"}; contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"};
$tw.utils.createFileDirectories(filename);
fs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) { fs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {
self.callback(err); self.callback(err);
}); });

View File

@ -5,7 +5,7 @@ module-type: filteroperator
Filter operator for selecting tiddlers Filter operator for selecting tiddlers
[all[tiddlers+shadows]] [all[shadows+tiddlers]]
\*/ \*/
(function(){ (function(){

View File

@ -0,0 +1,37 @@
/*\
title: $:/core/modules/filters/is/tag.js
type: application/javascript
module-type: isfilteroperator
Filter function for [is[tag]]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.tag = function(source,prefix,options) {
var results = [],
tagMap = options.wiki.getTagMap();
if(prefix === "!") {
source(function(tiddler,title) {
if(!$tw.utils.hop(tagMap,title)) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if($tw.utils.hop(tagMap,title)) {
results.push(title);
}
});
}
return results;
};
})();

View File

@ -25,11 +25,9 @@ exports.untagged = function(source,operator,options) {
}); });
} else { } else {
source(function(tiddler,title) { source(function(tiddler,title) {
if(tiddler) { if(!tiddler || !tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
if(!tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
$tw.utils.pushTop(results,title); $tw.utils.pushTop(results,title);
} }
}
}); });
} }
return results; return results;

View File

@ -0,0 +1,268 @@
/*\
title: $:/core/modules/utils/parseutils.js
type: application/javascript
module-type: utils
Utility functions concerned with parsing text into tokens.
Most functions have the following pattern:
* The parameters are:
** `source`: the source string being parsed
** `pos`: the current parse position within the string
** Any further parameters are used to identify the token that is being parsed
* The return value is:
** null if the token was not found at the specified position
** an object representing the token with the following standard fields:
*** `type`: string indicating the type of the token
*** `start`: start position of the token in the source string
*** `end`: end position of the token in the source string
*** Any further fields required to describe the token
The exception is `skipWhiteSpace`, which just returns the position after the whitespace.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Look for a whitespace token. Returns null if not found, otherwise returns {type: "whitespace", start:, end:,}
*/
exports.parseWhiteSpace = function(source,pos) {
var node = {
type: "whitespace",
start: pos
};
var re = /(\s)+/g;
re.lastIndex = pos;
var match = re.exec(source);
if(match && match.index === pos) {
node.end = pos + match[0].length;
return node;
}
return null;
};
/*
Convenience wrapper for parseWhiteSpace. Returns the position after the whitespace
*/
exports.skipWhiteSpace = function(source,pos) {
var whitespace = $tw.utils.parseWhiteSpace(source,pos);
if(whitespace) {
return whitespace.end;
}
return pos;
};
/*
Look for a given string token. Returns null if not found, otherwise returns {type: "token", value:, start:, end:,}
*/
exports.parseTokenString = function(source,pos,token) {
var match = source.indexOf(token,pos) === pos;
if(match) {
return {
type: "token",
value: token,
start: pos,
end: pos + token.length
};
}
return null;
};
/*
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
*/
exports.parseTokenRegExp = function(source,pos,reToken) {
var node = {
type: "regexp",
start: pos
};
reToken.lastIndex = pos;
node.match = reToken.exec(source);
if(node.match && node.match.index === pos) {
node.end = pos + node.match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a string literal. Returns null if not found, otherwise returns {type: "string", value:, start:, end:,}
*/
exports.parseStringLiteral = function(source,pos) {
var node = {
type: "string",
start: pos
};
var reString = /(?:"([^"]*)")|(?:'([^']*)')/g;
reString.lastIndex = pos;
var match = reString.exec(source);
if(match && match.index === pos) {
node.value = match[1] === undefined ? match[2] : match[1];
node.end = pos + match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
*/
exports.parseMacroParameter = function(source,pos) {
var node = {
type: "macro-parameter",
start: pos
};
// Define our regexp
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^\s>"'=]+)))/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the parameter
var token = $tw.utils.parseTokenRegExp(source,pos,reMacroParameter);
if(!token) {
return null;
}
pos = token.end;
// Get the parameter details
node.value = token.match[2] !== undefined ? token.match[2] : (
token.match[3] !== undefined ? token.match[3] : (
token.match[4] !== undefined ? token.match[4] : (
token.match[5] !== undefined ? token.match[5] : (
""
)
)
)
);
if(token.match[1]) {
node.name = token.match[1];
}
// Update the end position
node.end = pos;
return node;
};
/*
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
*/
exports.parseMacroInvocation = function(source,pos) {
var node = {
type: "macrocall",
start: pos,
params: []
};
// Define our regexps
var reMacroName = /([^\s>"'=]+)/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double less than sign
var token = $tw.utils.parseTokenString(source,pos,"<<");
if(!token) {
return null;
}
pos = token.end;
// Get the macro name
var name = $tw.utils.parseTokenRegExp(source,pos,reMacroName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Process parameters
var parameter = $tw.utils.parseMacroParameter(source,pos);
while(parameter) {
node.params.push(parameter);
pos = parameter.end;
// Get the next parameter
parameter = $tw.utils.parseMacroParameter(source,pos);
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double greater than sign
token = $tw.utils.parseTokenString(source,pos,">>");
if(!token) {
return null;
}
pos = token.end;
// Update the end position
node.end = pos;
return node;
};
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
*/
exports.parseAttribute = function(source,pos) {
var node = {
start: pos
};
// Define our regexps
var reAttributeName = /([^\/\s>"'=]+)/g,
reUnquotedAttribute = /([^\/\s<>"'=]+)/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Get the attribute name
var name = $tw.utils.parseTokenRegExp(source,pos,reAttributeName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for an equals sign
var token = $tw.utils.parseTokenString(source,pos,"=");
if(token) {
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
} else {
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocation(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
node.type = "string";
node.value = "true";
}
}
}
}
} else {
node.type = "string";
node.value = "true";
}
// Update the end position
node.end = pos;
return node;
};
})();

View File

@ -15,11 +15,11 @@ The plain text parser processes blocks of source text into a degenerate parse tr
var TextParser = function(type,text,options) { var TextParser = function(type,text,options) {
this.tree = [{ this.tree = [{
type: "element", type: "element",
tag: "pre", tag: "$codeblock",
children: [{ attributes: {
type: "text", code: {type: "string", value: text},
text: text language: {type: "string", value: type}
}] }
}]; }];
}; };

View File

@ -48,7 +48,7 @@ exports.parse = function() {
// Advance the parser position to past the tag // Advance the parser position to past the tag
this.parser.pos = tag.end; this.parser.pos = tag.end;
// Check for an immediately following double linebreak // Check for an immediately following double linebreak
var hasLineBreak = !tag.isSelfClosing && !!this.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g); var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g);
// Set whether we're in block mode // Set whether we're in block mode
tag.isBlock = this.is.block || hasLineBreak; tag.isBlock = this.is.block || hasLineBreak;
// Parse the body if we need to // Parse the body if we need to
@ -71,244 +71,7 @@ exports.parse = function() {
}; };
/* /*
Look for a whitespace token. Returns null if not found, otherwise returns {type: "whitespace", start:, end:,} Look for an HTML tag. Returns null if not found, otherwise returns {type: "element", name:, attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseWhiteSpace = function(source,pos) {
var node = {
type: "whitespace",
start: pos
};
var re = /(\s)+/g;
re.lastIndex = pos;
var match = re.exec(source);
if(match && match.index === pos) {
node.end = pos + match[0].length;
return node;
}
return null;
};
/*
Convenience wrapper for parseWhiteSpace
*/
exports.skipWhiteSpace = function(source,pos) {
var whitespace = this.parseWhiteSpace(source,pos);
if(whitespace) {
return whitespace.end;
}
return pos;
};
/*
Look for a given string token. Returns null if not found, otherwise returns {type: "token", value:, start:, end:,}
*/
exports.parseTokenString = function(source,pos,token) {
var match = source.indexOf(token,pos) === pos;
if(match) {
return {
type: "token",
value: token,
start: pos,
end: pos + token.length
};
}
return null;
};
/*
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
*/
exports.parseTokenRegExp = function(source,pos,reToken) {
var node = {
type: "regexp",
start: pos
};
reToken.lastIndex = pos;
node.match = reToken.exec(source);
if(node.match && node.match.index === pos) {
node.end = pos + node.match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a string literal. Returns null if not found, otherwise returns {type: "string", value:, start:, end:,}
*/
exports.parseStringLiteral = function(source,pos) {
var node = {
type: "string",
start: pos
};
var reString = /(?:"([^"]*)")|(?:'([^']*)')/g;
reString.lastIndex = pos;
var match = reString.exec(source);
if(match && match.index === pos) {
node.value = match[1] === undefined ? match[2] : match[1];
node.end = pos + match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
*/
exports.parseMacroParameter = function(source,pos) {
var node = {
type: "macro-parameter",
start: pos
};
// Define our regexp
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^\s>"'=]+)))/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for the parameter
var token = this.parseTokenRegExp(source,pos,reMacroParameter);
if(!token) {
return null;
}
pos = token.end;
// Get the parameter details
node.value = token.match[2] !== undefined ? token.match[2] : (
token.match[3] !== undefined ? token.match[3] : (
token.match[4] !== undefined ? token.match[4] : (
token.match[5] !== undefined ? token.match[5] : (
""
)
)
)
);
if(token.match[1]) {
node.name = token.match[1];
}
// Update the end position
node.end = pos;
return node;
};
/*
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
*/
exports.parseMacroInvocation = function(source,pos) {
var node = {
type: "macrocall",
start: pos,
params: []
};
// Define our regexps
var reMacroName = /([^\s>"'=]+)/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for a double less than sign
var token = this.parseTokenString(source,pos,"<<");
if(!token) {
return null;
}
pos = token.end;
// Get the macro name
var name = this.parseTokenRegExp(source,pos,reMacroName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Process parameters
var parameter = this.parseMacroParameter(source,pos);
while(parameter) {
node.params.push(parameter);
pos = parameter.end;
// Get the next parameter
parameter = this.parseMacroParameter(source,pos);
}
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for a double greater than sign
token = this.parseTokenString(source,pos,">>");
if(!token) {
return null;
}
pos = token.end;
// Update the end position
node.end = pos;
return node;
};
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
*/
exports.parseAttribute = function(source,pos) {
var node = {
start: pos
};
// Define our regexps
var reAttributeName = /([^\/\s>"'=]+)/g,
reUnquotedAttribute = /([^\/\s<>"'=]+)/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Get the attribute name
var name = this.parseTokenRegExp(source,pos,reAttributeName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for an equals sign
var token = this.parseTokenString(source,pos,"=");
if(token) {
pos = token.end;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = this.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
} else {
// Look for an indirect value
var indirectValue = this.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a unquoted value
var unquotedValue = this.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = this.parseMacroInvocation(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
node.type = "string";
node.value = "true";
}
}
}
}
} else {
node.type = "string";
node.value = "true";
}
// Update the end position
node.end = pos;
return node;
};
/*
Look for an HTML tag. Returns null if not found, otherwise returns {type: "tag", name:, attributes: [], isSelfClosing:, start:, end:,}
*/ */
exports.parseTag = function(source,pos,options) { exports.parseTag = function(source,pos,options) {
options = options || {}; options = options || {};
@ -321,45 +84,45 @@ exports.parseTag = function(source,pos,options) {
// Define our regexps // Define our regexps
var reTagName = /([a-zA-Z0-9\-\$]+)/g; var reTagName = /([a-zA-Z0-9\-\$]+)/g;
// Skip whitespace // Skip whitespace
pos = this.skipWhiteSpace(source,pos); pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a less than sign // Look for a less than sign
token = this.parseTokenString(source,pos,"<"); token = $tw.utils.parseTokenString(source,pos,"<");
if(!token) { if(!token) {
return null; return null;
} }
pos = token.end; pos = token.end;
// Get the tag name // Get the tag name
token = this.parseTokenRegExp(source,pos,reTagName); token = $tw.utils.parseTokenRegExp(source,pos,reTagName);
if(!token) { if(!token) {
return null; return null;
} }
node.tag = token.match[1]; node.tag = token.match[1];
pos = token.end; pos = token.end;
// Process attributes // Process attributes
var attribute = this.parseAttribute(source,pos); var attribute = $tw.utils.parseAttribute(source,pos);
while(attribute) { while(attribute) {
node.attributes[attribute.name] = attribute; node.attributes[attribute.name] = attribute;
pos = attribute.end; pos = attribute.end;
// Get the next attribute // Get the next attribute
attribute = this.parseAttribute(source,pos); attribute = $tw.utils.parseAttribute(source,pos);
} }
// Skip whitespace // Skip whitespace
pos = this.skipWhiteSpace(source,pos); pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a closing slash // Look for a closing slash
token = this.parseTokenString(source,pos,"/"); token = $tw.utils.parseTokenString(source,pos,"/");
if(token) { if(token) {
pos = token.end; pos = token.end;
node.isSelfClosing = true; node.isSelfClosing = true;
} }
// Look for a greater than sign // Look for a greater than sign
token = this.parseTokenString(source,pos,">"); token = $tw.utils.parseTokenString(source,pos,">");
if(!token) { if(!token) {
return null; return null;
} }
pos = token.end; pos = token.end;
// Check for a required line break // Check for a required line break
if(options.requireLineBreak) { if(options.requireLineBreak) {
token = this.parseTokenRegExp(source,pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g); token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g);
if(!token) { if(!token) {
return null; return null;
} }

View File

@ -0,0 +1,137 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/image.js
type: application/javascript
module-type: wikirule
Wiki text inline rule for embedding images. For example:
```
[img[http://tiddlywiki.com/fractalveg.jpg]]
[img width=23 height=24 [http://tiddlywiki.com/fractalveg.jpg]]
[img 23x24 [http://tiddlywiki.com/fractalveg.jpg]]
[img width={{!!width}} height={{!!height}} [http://tiddlywiki.com/fractalveg.jpg]]
[img {{!!width}}x{{!!height}} [http://tiddlywiki.com/fractalveg.jpg]]
[img[Description of image|http://tiddlywiki.com/fractalveg.jpg]]
[img[TiddlerTitle]]
[img[Description of image|TiddlerTitle]]
```
Generates the `<$image>` widget.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "image";
exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
};
exports.findNextMatch = function(startPos) {
// Find the next tag
this.nextImage = this.findNextImage(this.parser.source,startPos);
return this.nextImage ? this.nextImage.start : undefined;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.nextImage.end;
var node = {
type: "element",
tag: "$image",
attributes: this.nextImage.attributes
};
return [node];
};
/*
Find the next image from the current position
*/
exports.findNextImage = function(source,pos) {
// A regexp for finding candidate HTML tags
var reLookahead = /(\[img)/g;
// Find the next candidate
reLookahead.lastIndex = pos;
var match = reLookahead.exec(source);
while(match) {
// Try to parse the candidate as a tag
var tag = this.parseImage(source,match.index);
// Return success
if(tag) {
return tag;
}
// Look for the next match
reLookahead.lastIndex = match.index + 1;
match = reLookahead.exec(source);
}
// Failed
return null;
};
/*
Look for an image at the specified position. Returns null if not found, otherwise returns {type: "element", name: "$image", attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseImage = function(source,pos) {
var token,
node = {
type: "element",
name: "$image",
start: pos,
attributes: {}
};
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the `[img`
token = $tw.utils.parseTokenString(source,pos,"[img");
if(!token) {
return null;
}
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Process attributes
if(source.charAt(pos) !== "[") {
var attribute = $tw.utils.parseAttribute(source,pos);
while(attribute) {
node.attributes[attribute.name] = attribute;
pos = attribute.end;
pos = $tw.utils.skipWhiteSpace(source,pos);
if(source.charAt(pos) !== "[") {
// Get the next attribute
attribute = $tw.utils.parseAttribute(source,pos);
} else {
attribute = null;
}
}
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the `[` after the attributes
token = $tw.utils.parseTokenString(source,pos,"[");
if(!token) {
return null;
}
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Get the source up to the terminating `]]`
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/g);
if(!token) {
return null;
}
pos = token.end;
if(token.match[1]) {
node.attributes.tooltip = {type: "string", value: token.match[1].trim()};
}
node.attributes.source = {type: "string", value: (token.match[2] || "").trim()};
// Update the end position
node.end = pos;
return node;
};
})();

View File

@ -19,13 +19,27 @@ TiddlyFoxSaver.prototype.save = function(text,method,callback) {
var messageBox = document.getElementById("tiddlyfox-message-box"); var messageBox = document.getElementById("tiddlyfox-message-box");
if(messageBox) { if(messageBox) {
// Get the pathname of this document // Get the pathname of this document
var pathname = document.location.pathname; var pathname = document.location.toString();
// Test for a Windows path of the form /x:/blah/blah // Replace file://localhost/ with file:///
if(/^\/[A-Z]\:\//i.test(pathname)) { if(pathname.indexOf("file://localhost/") == 0) {
// Remove the leading slash pathname = "file://" + pathname.substr(16);
pathname = pathname.substr(1); }
// Convert slashes to backslashes // Windows path file:///x:/blah/blah --> x:\blah\blah
pathname = pathname.replace(/\//g,"\\"); if(/^file\:\/\/\/[A-Z]\:\//i.test(pathname)) {
// Remove the leading slash and convert slashes to backslashes
pathname = pathname.substr(8).replace(/\//g,"\\");
// Firefox Windows network path file://///server/share/blah/blah --> //server/share/blah/blah
} else if(pathname.indexOf("file://///") === 0) {
pathname = "\\\\" + unescape(pathname.substr(10)).replace(/\//g,"\\");
// Mac/Unix local path file:///path/path --> /path/path
} else if(pathname.indexOf("file:///") == 0) {
pathname = unescape(pathname.substr(7));
// Mac/Unix local path file:/path/path --> /path/path
} else if(pathname.indexOf("file:/") == 0) {
pathname = unescape(pathname.substr(5));
// Otherwise Windows networth path file://server/share/path/path --> \\server\share\path\path
} else {
pathname = "\\\\" + unescape(pathname.substr(7)).replace(new RegExp("/","g"),"\\");
} }
// Create the message element and put it in the message box // Create the message element and put it in the message box
var message = document.createElement("div"); var message = document.createElement("div");

View File

@ -87,9 +87,13 @@ exports.removeTrailingSeparator = function(dirPath) {
Recursively create a directory Recursively create a directory
*/ */
exports.createDirectory = function(dirPath) { exports.createDirectory = function(dirPath) {
var parts = dirPath.split(path.sep); if(dirPath.substr(dirPath.length-1,1) !== path.sep) {
for(var component=0; component<parts.length; component++) { dirPath = dirPath + path.sep;
var subDirPath = parts.slice(0,component+1).join(path.sep); }
var pos = 1;
pos = dirPath.indexOf(path.sep,pos);
while(pos !== -1) {
var subDirPath = dirPath.substr(0,pos);
if(!$tw.utils.isDirectory(subDirPath)) { if(!$tw.utils.isDirectory(subDirPath)) {
try { try {
fs.mkdirSync(subDirPath); fs.mkdirSync(subDirPath);
@ -97,6 +101,33 @@ exports.createDirectory = function(dirPath) {
return "Error creating directory '" + subDirPath + "'"; return "Error creating directory '" + subDirPath + "'";
} }
} }
pos = dirPath.indexOf(path.sep,pos + 1);
}
return null;
};
/*
Recursively create directories needed to contain a specified file
*/
exports.createFileDirectories = function(filePath) {
return $tw.utils.createDirectory(path.dirname(filePath));
};
/*
Recursively delete a directory
*/
exports.deleteDirectory = function(dirPath) {
if(fs.existsSync(dirPath)) {
var entries = fs.readdirSync(dirPath);
for(var entryIndex=0; entryIndex<entries.length; entryIndex++) {
var currPath = dirPath + path.sep + entries[entryIndex];
if(fs.lstatSync(currPath).isDirectory()) {
$tw.utils.deleteDirectory(currPath);
} else {
fs.unlinkSync(currPath);
}
}
fs.rmdirSync(dirPath);
} }
return null; return null;
}; };

View File

@ -0,0 +1,123 @@
/*\
title: $:/core/modules/widgets/image.js
type: application/javascript
module-type: widget
The image widget displays an image referenced with an external URI or with a local tiddler title.
```
<$image src="TiddlerTitle" width="320" height="400" class="classnames">
```
The image source can be the title of an existing tiddler or the URL of an external image.
External images always generate an HTML `<img>` tag.
Tiddlers that have a _canonical_uri field generate an HTML `<img>` tag with the src attribute containing the URI.
Tiddlers that contain image data generate an HTML `<img>` tag with the src attribute containing a base64 representation of the image.
Tiddlers that contain wikitext could be rendered to a DIV of the usual size of a tiddler, and then transformed to the size requested.
The width and height attributes are interpreted as a number of pixels, and do not need to include the "px" suffix.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var ImageWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
ImageWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ImageWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
// Create element
// Determine what type of image it is
var tag = "img", src = "",
tiddler = this.wiki.getTiddler(this.imageSource);
if(!tiddler) {
// The source isn't the title of a tiddler, so we'll assume it's a URL
src = this.imageSource;
} else {
// Check if it is an image tiddler
if(this.wiki.isImageTiddler(this.imageSource)) {
// Render the appropriate element for the image type
var type = tiddler.fields.type,
text = tiddler.fields.text;
switch(type) {
case "application/pdf":
tag = "embed";
src = "data:application/pdf;base64," + text;
break;
case "image/svg+xml":
src = "data:image/svg+xml," + encodeURIComponent(text);
break;
default:
src = "data:" + type + ";base64," + text;
break;
}
}
}
// Create the element and assign the attributes
var domNode = this.document.createElement(tag);
domNode.setAttribute("src",src);
if(this.imageClass) {
domNode.setAttribute("class",this.imageClass);
}
if(this.imageWidth) {
domNode.setAttribute("width",parseInt(this.imageWidth,10) + "px");
}
if(this.imageHeight) {
domNode.setAttribute("height",parseInt(this.imageHeight,10) + "px");
}
if(this.imageTooltip) {
domNode.setAttribute("title",this.imageTooltip);
}
// Insert element
parent.insertBefore(domNode,nextSibling);
this.domNodes.push(domNode);
};
/*
Compute the internal state of the widget
*/
ImageWidget.prototype.execute = function() {
// Get our parameters
this.imageSource = this.getAttribute("source");
this.imageWidth = this.getAttribute("width");
this.imageHeight = this.getAttribute("height");
this.imageClass = this.getAttribute("class");
this.imageTooltip = this.getAttribute("tooltip");
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ImageWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes["class"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) {
this.refreshSelf();
return true;
} else {
return false;
}
};
exports.image = ImageWidget;
})();

View File

@ -305,28 +305,20 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
a = self.getTiddler(a).fields[sortField] || ""; a = self.getTiddler(a).fields[sortField] || "";
b = self.getTiddler(b).fields[sortField] || ""; b = self.getTiddler(b).fields[sortField] || "";
} }
if(!isNumeric || isNaN(a) || isNaN(b)) { if(isNumeric) {
a = Number(a);
b = Number(b);
return isDescending ? b - a : a - b;
} else if($tw.utils.isDate(a) && $tw.utils.isDate(b)) {
return isDescending ? b - a : a - b;
} else {
a = String(a);
b = String(b);
if(!isCaseSensitive) { if(!isCaseSensitive) {
if(typeof a === "string") {
a = a.toLowerCase(); a = a.toLowerCase();
}
if(typeof b === "string") {
b = b.toLowerCase(); b = b.toLowerCase();
} }
} return isDescending ? b.localeCompare(a) : a.localeCompare(b);
}
else {
a-= 0;
b-= 0;
}
if(a < b) {
return isDescending ? +1 : -1;
} else {
if(a > b) {
return isDescending ? -1 : +1;
} else {
return 0;
}
} }
}); });
}; };

View File

@ -1,5 +1,5 @@
title: $:/AdvancedSearch title: $:/AdvancedSearch
<div class="tw-advanced-search"> <div class="tw-advanced-search">
<<tabs "[all[tiddlers+shadows]tag[$:/tags/AdvancedSearch]!has[draft.of]]" "$:/core/ui/AdvancedSearch/System">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/AdvancedSearch]!has[draft.of]]" "$:/core/ui/AdvancedSearch/System">>
</div> </div>

View File

@ -12,7 +12,7 @@ caption: {{$:/language/Search/Filter/Caption}}
<div class="tw-block-dropdown-wrapper"> <div class="tw-block-dropdown-wrapper">
<$reveal state=<<qualify "$:/state/filterDropdown">> type="nomatch" text="" default=""> <$reveal state=<<qualify "$:/state/filterDropdown">> type="nomatch" text="" default="">
<div class="tw-block-dropdown tw-edit-type-dropdown"> <div class="tw-block-dropdown tw-edit-type-dropdown">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/Filter]]"><$link to={{!!filter}}><$transclude field="description"/></$link> <$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]]"><$link to={{!!filter}}><$transclude field="description"/></$link>
</$list> </$list>
</div> </div>
</$reveal> </$reveal>

View File

@ -1,5 +1,5 @@
title: $:/ControlPanel title: $:/ControlPanel
<div class="tw-control-panel"> <div class="tw-control-panel">
<<tabs "[all[tiddlers+shadows]tag[$:/tags/ControlPanel]!has[draft.of]]" "$:/core/ui/ControlPanel/Basics">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/ControlPanel]!has[draft.of]]" "$:/core/ui/ControlPanel/Basics">>
</div> </div>

View File

@ -5,5 +5,5 @@ caption: {{$:/language/ControlPanel/Advanced/Caption}}
{{$:/language/ControlPanel/Advanced/Hint}} {{$:/language/ControlPanel/Advanced/Hint}}
<div class="tw-control-panel"> <div class="tw-control-panel">
<<tabs "[all[tiddlers+shadows]tag[$:/tags/ControlPanel/Advanced]!has[draft.of]]" "$:/core/ui/ControlPanel/Advanced/TiddlerFields">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Advanced]!has[draft.of]]" "$:/core/ui/ControlPanel/Advanced/TiddlerFields">>
</div> </div>

View File

@ -5,5 +5,5 @@ caption: {{$:/language/ControlPanel/Appearance/Caption}}
{{$:/language/ControlPanel/Appearance/Hint}} {{$:/language/ControlPanel/Appearance/Hint}}
<div class="tw-control-panel"> <div class="tw-control-panel">
<<tabs "[all[tiddlers+shadows]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]" "$:/core/ui/ControlPanel/Appearance/Theme">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]" "$:/core/ui/ControlPanel/Appearance/Theme">>
</div> </div>

View File

@ -6,7 +6,7 @@ tw-tiddler-frame tw-tiddler-edit-frame $(missingTiddlerClass)$ $(shadowTiddlerCl
<div class=<<frame-classes>>> <div class=<<frame-classes>>>
<$set name="storyTiddler" value=<<currentTiddler>>> <$set name="storyTiddler" value=<<currentTiddler>>>
<$keyboard key="ctrl+enter" message="tw-save-tiddler"> <$keyboard key="ctrl+enter" message="tw-save-tiddler">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/EditTemplate]!has[draft.of]]" variable="listItem"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>>/> <$transclude tiddler=<<listItem>>/>
</$list> </$list>
</$keyboard> </$keyboard>

View File

@ -1,4 +1,4 @@
title: $:/core/ui/EditTemplate/controls title: $:/core/ui/EditTemplate/controls
tags: $:/tags/EditTemplate tags: $:/tags/EditTemplate
<span class="tw-tiddler-controls titlebar"> <$list filter="[all[tiddlers+shadows]tag[$:/tags/EditToolbar]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list> </span> <span class="tw-tiddler-controls titlebar"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list> </span>

View File

@ -8,7 +8,7 @@ tags: $:/tags/EditTemplate
<$reveal state=<<qualify "$:/state/typeDropdown">> type="nomatch" text="" default=""> <$reveal state=<<qualify "$:/state/typeDropdown">> type="nomatch" text="" default="">
<div class="tw-block-dropdown tw-edit-type-dropdown"> <div class="tw-block-dropdown tw-edit-type-dropdown">
<$linkcatcher to="!!type"> <$linkcatcher to="!!type">
<$list filter="[all[tiddlers+shadows]prefix[$:/language/Docs/Types/]] +[sort[description]]"><$link to={{!!name}}><$view field="description"/> (<$view field="name"/>)</$link> <$list filter="[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]] +[sort[description]]"><$link to={{!!name}}><$view field="description"/> (<$view field="name"/>)</$link>
</$list> </$list>
</$linkcatcher> </$linkcatcher>
</div> </div>

View File

@ -1,5 +1,5 @@
title: $:/core/Filters/SystemTags title: $:/core/Filters/SystemTags
tags: $:/tags/Filter tags: $:/tags/Filter
filter: [all[tiddlers+shadows]tags[]is[system]sort[title]] filter: [all[shadows+tiddlers]tags[]is[system]sort[title]]
description: {{$:/language/Filters/SystemTags}} description: {{$:/language/Filters/SystemTags}}

View File

@ -3,7 +3,7 @@ tags: $:/tags/MoreSideBar
caption: {{$:/language/SideBar/Tags/Caption}} caption: {{$:/language/SideBar/Tags/Caption}}
\define lingo-base() $:/language/SideBar/Tags/ \define lingo-base() $:/language/SideBar/Tags/
<$button to="$:/TagManager"><<lingo TagManager/Caption>></$button> <$button to="$:/TagManager" class="btn"><<lingo TagManager/Caption>></$button>
<$list filter="[tags[]!is[system]sort[title]]"> <$list filter="[tags[]!is[system]sort[title]]">

View File

@ -2,7 +2,7 @@ title: $:/core/ui/MoreSideBar/Types
tags: $:/tags/MoreSideBar tags: $:/tags/MoreSideBar
caption: {{$:/language/SideBar/Types/Caption}} caption: {{$:/language/SideBar/Types/Caption}}
<$list filter="[!is[system]has[type]each[type]sort[type]]"> <$list filter="[!is[system]has[type]each[type]sort[type]] -[type[text/vnd.tiddlywiki]]">
<div class="tw-menu-list-item"> <div class="tw-menu-list-item">
<$view field="type"/> <$view field="type"/>
<$list filter="[type{!!type}!is[system]sort[title]]"> <$list filter="[type{!!type}!is[system]sort[title]]">

View File

@ -54,6 +54,6 @@ background-image: -ms-linear-gradient($gradient$);
\end \end
<$list filter="[all[tiddlers+shadows]tag[$:/tags/stylesheet]]"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/stylesheet]]">
<$transclude/> <$transclude/>
</$list> </$list>

View File

@ -16,7 +16,7 @@ tw-page-container tw-page-view-$(themeTitle)$ tw-language-$(languageTitle)$
<$dropzone> <$dropzone>
<$list filter="[all[tiddlers+shadows]tag[$:/tags/PageTemplate]!has[draft.of]]" variable="listItem"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/PageTemplate]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>>/> <$transclude tiddler=<<listItem>>/>

View File

@ -3,6 +3,6 @@ tags: $:/tags/PageTemplate
<div class="tw-alerts"> <div class="tw-alerts">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/Alert]!has[draft.of]]" template="$:/core/ui/AlertTemplate" storyview="pop"/> <$list filter="[all[shadows+tiddlers]tag[$:/tags/Alert]!has[draft.of]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>
</div> </div>

View File

@ -21,7 +21,7 @@ tags: $:/tags/PageTemplate
<div class="tw-page-controls"> <div class="tw-page-controls">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/PageControls]!has[draft.of]]" variable="listItem"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>> mode="inline"/> <$transclude tiddler=<<listItem>> mode="inline"/>

View File

@ -3,6 +3,10 @@ tags: $:/tags/PageTemplate
<span class="tw-topbar tw-topbar-left"> <span class="tw-topbar tw-topbar-left">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/TopLeftBar]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list> <$list filter="[all[shadows+tiddlers]tag[$:/tags/TopLeftBar]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>> mode="inline"/>
</$list>
</span> </span>

View File

@ -3,6 +3,10 @@ tags: $:/tags/PageTemplate
<span class="tw-topbar tw-topbar-right"> <span class="tw-topbar tw-topbar-right">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/TopRightBar]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list> <$list filter="[all[shadows+tiddlers]tag[$:/tags/TopRightBar]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>> mode="inline"/>
</$list>
</span> </span>

View File

@ -3,5 +3,5 @@ tags: $:/tags/SideBar
caption: {{$:/language/SideBar/More/Caption}} caption: {{$:/language/SideBar/More/Caption}}
<div class="tw-more-sidebar"> <div class="tw-more-sidebar">
<<tabs "[all[tiddlers+shadows]tag[$:/tags/MoreSideBar]!has[draft.of]]" "$:/core/ui/MoreSideBar/Tags" "$:/state/tab/moresidebar">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]" "$:/core/ui/MoreSideBar/Tags" "$:/state/tab/moresidebar">>
</div> </div>

View File

@ -18,6 +18,6 @@ title: $:/core/ui/SideBarLists
</div> </div>
</$reveal> </$reveal>
<$reveal state="$:/temp/search" type="match" text=""> <$reveal state="$:/temp/search" type="match" text="">
<<tabs "[all[tiddlers+shadows]tag[$:/tags/SideBar]!has[draft.of]]" "$:/core/ui/SideBar/Open" "$:/state/tab/sidebar">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]" "$:/core/ui/SideBar/Open" "$:/state/tab/sidebar">>
</$reveal> </$reveal>
</div> </div>

View File

@ -7,7 +7,7 @@ title: $:/TagManager
<$reveal state=<<qualify "$:/state/iconDropdown/$title$">> type="nomatch" text="" default=""> <$reveal state=<<qualify "$:/state/iconDropdown/$title$">> type="nomatch" text="" default="">
<$linkcatcher to="$title$!!icon"> <$linkcatcher to="$title$!!icon">
<div class="tw-block-dropdown tw-edit-type-dropdown"> <div class="tw-block-dropdown tw-edit-type-dropdown">
<$list filter="[all[tiddlers+shadows]is[image]] [all[tiddlers+shadows]tag[$:/tags/Image]] +[sort[title]]"> <$list filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] +[sort[title]]">
<$link to={{!!title}}> <$link to={{!!title}}>
<$view field="title"/> <$view field="title"/>
</$link> </$link>

View File

@ -1,3 +1,3 @@
title: $:/core/ui/TiddlerInfo title: $:/core/ui/TiddlerInfo
<<tabs "[all[tiddlers+shadows]tag[$:/tags/TiddlerInfo]!has[draft.of]]" "$:/core/ui/TiddlerInfo/References">> <<tabs "[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo]!has[draft.of]]" "$:/core/ui/TiddlerInfo/References">>

View File

@ -2,7 +2,7 @@ title: $:/core/ui/TiddlerInfo/Advanced
tags: $:/tags/TiddlerInfo tags: $:/tags/TiddlerInfo
caption: {{$:/language/TiddlerInfo/Advanced/Caption}} caption: {{$:/language/TiddlerInfo/Advanced/Caption}}
<$list filter="[all[tiddlers+shadows]tag[$:/tags/TiddlerInfo/Advanced]!has[draft.of]]" variable="listItem"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/TiddlerInfo/Advanced]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>>/> <$transclude tiddler=<<listItem>>/>
</$list> </$list>

View File

@ -1,4 +0,0 @@
title: $:/core/ui/TopBar/home
tags: $:/tags/TopLeftBar
<$button message="tw-home" class="btn-invisible">{{$:/core/images/home-button}}</$button>

View File

@ -3,6 +3,6 @@ title: $:/core/ui/ViewTemplate
\define frame-classes() \define frame-classes()
tw-tiddler-frame tw-tiddler-view-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$ tw-tiddler-frame tw-tiddler-view-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$
\end \end
<$set name="storyTiddler" value=<<currentTiddler>>><$set name="tiddlerInfoState" value=<<qualify "$:/state/tiddlerInfo">>><$tiddler tiddler=<<currentTiddler>>><div class=<<frame-classes>>><$list filter="[all[tiddlers+shadows]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list> <$set name="storyTiddler" value=<<currentTiddler>>><$set name="tiddlerInfoState" value=<<qualify "$:/state/tiddlerInfo">>><$tiddler tiddler=<<currentTiddler>>><div class=<<frame-classes>>><$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
</div> </div>
</$tiddler></$set></$set> </$tiddler></$set></$set>

View File

@ -1,7 +1,6 @@
title: $:/core/ui/ViewTemplate/body title: $:/core/ui/ViewTemplate/body
tags: $:/tags/ViewTemplate tags: $:/tags/ViewTemplate
\define lingo-base() $:/language/MissingTiddler/
<div class="body"> <div class="body">
<$transclude> <$transclude>

View File

@ -7,7 +7,7 @@ fill:$(foregroundColor)$;
<div class="tw-tiddler-title"> <div class="tw-tiddler-title">
<div class="titlebar"> <div class="titlebar">
<span class="tw-tiddler-controls"> <span class="tw-tiddler-controls">
<$list filter="[all[tiddlers+shadows]tag[$:/tags/ViewToolbar]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list> <$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
</span> </span>
<$set name="foregroundColor" value={{!!color}}> <$set name="foregroundColor" value={{!!color}}>
<span style=<<title-styles>>> <span style=<<title-styles>>>

View File

@ -4,7 +4,7 @@ title: $:/snippets/paletteswitcher
<<lingo Prompt>> <$view tiddler={{$:/palette}} field="name"/> <<lingo Prompt>> <$view tiddler={{$:/palette}} field="name"/>
<$linkcatcher to="$:/palette"> <$linkcatcher to="$:/palette">
<div class="tw-chooser"><$list filter="[all[tiddlers+shadows]tag[$:/tags/Palette]sort[description]]"><div class="tw-chooser-item"><$link to={{!!title}}><div><$reveal state="$:/palette" type="match" text={{!!title}}>&bull;</$reveal><$reveal state="$:/palette" type="nomatch" text={{!!title}}>&nbsp;</$reveal> ''<$view field="name" format="text"/>'' - <$view field="description" format="text"/></div><$transclude tiddler="$:/snippets/currpalettepreview"/></$link></div> <div class="tw-chooser"><$list filter="[all[shadows+tiddlers]tag[$:/tags/Palette]sort[description]]"><div class="tw-chooser-item"><$link to={{!!title}}><div><$reveal state="$:/palette" type="match" text={{!!title}}>&bull;</$reveal><$reveal state="$:/palette" type="nomatch" text={{!!title}}>&nbsp;</$reveal> ''<$view field="name" format="text"/>'' - <$view field="description" format="text"/></div><$transclude tiddler="$:/snippets/currpalettepreview"/></$link></div>
</$list> </$list>
</div> </div>
</$linkcatcher> </$linkcatcher>

View File

@ -1,6 +1,6 @@
title: $:/snippets/recentchanges title: $:/snippets/recentchanges
<$list filter="[!is[system]has[modified]!sort[modified]limit[250]eachday[modified]]"> <$list filter="[!is[system]has[modified]!sort[modified]limit[100]eachday[modified]]">
<div class="tw-menu-list-item"> <div class="tw-menu-list-item">
<$view field="modified" format="date" template={{$:/language/RecentChanges/DateFormat}}/> <$view field="modified" format="date" template={{$:/language/RecentChanges/DateFormat}}/>
<$list filter="[sameday{!!modified}!is[system]!sort[modified]]"> <$list filter="[sameday{!!modified}!is[system]!sort[modified]]">

View File

@ -23,127 +23,127 @@ describe("HTML tag new parser tests", function() {
var parser = new FakeParser(); var parser = new FakeParser();
it("should parse whitespace", function() { it("should parse whitespace", function() {
expect(parser.parseWhiteSpace("p ",0)).toEqual( expect($tw.utils.parseWhiteSpace("p ",0)).toEqual(
null null
); );
expect(parser.parseWhiteSpace("p ",1)).toEqual( expect($tw.utils.parseWhiteSpace("p ",1)).toEqual(
{ type : 'whitespace', start : 1, end : 3 } { type : 'whitespace', start : 1, end : 3 }
); );
}); });
it("should parse string tokens", function() { it("should parse string tokens", function() {
expect(parser.parseTokenString("p= ",0,"=")).toEqual( expect($tw.utils.parseTokenString("p= ",0,"=")).toEqual(
null null
); );
expect(parser.parseTokenString("p= ",1,"=")).toEqual( expect($tw.utils.parseTokenString("p= ",1,"=")).toEqual(
{ type : 'token', value : '=', start : 1, end : 2 } { type : 'token', value : '=', start : 1, end : 2 }
); );
}); });
it("should parse regexp tokens", function() { it("should parse regexp tokens", function() {
expect(parser.parseTokenRegExp("p=' ",0,/(=(?:'|"))/)).toEqual( expect($tw.utils.parseTokenRegExp("p=' ",0,/(=(?:'|"))/)).toEqual(
null null
); );
expect(parser.parseTokenRegExp("p=' ",1,/(=(?:'|"))/g).match[0]).toEqual( expect($tw.utils.parseTokenRegExp("p=' ",1,/(=(?:'|"))/g).match[0]).toEqual(
'=\'' '=\''
); );
expect(parser.parseTokenRegExp("p=blah ",2,/([^\s>]+)/g).match[0]).toEqual( expect($tw.utils.parseTokenRegExp("p=blah ",2,/([^\s>]+)/g).match[0]).toEqual(
'blah' 'blah'
); );
}); });
it("should parse string literals", function() { it("should parse string literals", function() {
expect(parser.parseStringLiteral("p='blah' ",0)).toEqual( expect($tw.utils.parseStringLiteral("p='blah' ",0)).toEqual(
null null
); );
expect(parser.parseStringLiteral("p='blah' ",2)).toEqual( expect($tw.utils.parseStringLiteral("p='blah' ",2)).toEqual(
{ type : 'string', start : 2, value : 'blah', end : 8 } { type : 'string', start : 2, value : 'blah', end : 8 }
); );
expect(parser.parseStringLiteral("p='' ",2)).toEqual( expect($tw.utils.parseStringLiteral("p='' ",2)).toEqual(
{ type : 'string', start : 2, value : '', end : 4 } { type : 'string', start : 2, value : '', end : 4 }
); );
expect(parser.parseStringLiteral("p=\"blah' ",2)).toEqual( expect($tw.utils.parseStringLiteral("p=\"blah' ",2)).toEqual(
null null
); );
expect(parser.parseStringLiteral("p=\"\" ",2)).toEqual( expect($tw.utils.parseStringLiteral("p=\"\" ",2)).toEqual(
{ type : 'string', start : 2, value : '', end : 4 } { type : 'string', start : 2, value : '', end : 4 }
); );
}); });
it("should parse macro parameters", function() { it("should parse macro parameters", function() {
expect(parser.parseMacroParameter("me",0)).toEqual( expect($tw.utils.parseMacroParameter("me",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'me', end : 2 } { type : 'macro-parameter', start : 0, value : 'me', end : 2 }
); );
expect(parser.parseMacroParameter("me:one",0)).toEqual( expect($tw.utils.parseMacroParameter("me:one",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'one', name : 'me', end : 6 } { type : 'macro-parameter', start : 0, value : 'one', name : 'me', end : 6 }
); );
expect(parser.parseMacroParameter("me:'one two three'",0)).toEqual( expect($tw.utils.parseMacroParameter("me:'one two three'",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 18 } { type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 18 }
); );
expect(parser.parseMacroParameter("'one two three'",0)).toEqual( expect($tw.utils.parseMacroParameter("'one two three'",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'one two three', end : 15 } { type : 'macro-parameter', start : 0, value : 'one two three', end : 15 }
); );
expect(parser.parseMacroParameter("me:[[one two three]]",0)).toEqual( expect($tw.utils.parseMacroParameter("me:[[one two three]]",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 20 } { type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 20 }
); );
expect(parser.parseMacroParameter("[[one two three]]",0)).toEqual( expect($tw.utils.parseMacroParameter("[[one two three]]",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'one two three', end : 17 } { type : 'macro-parameter', start : 0, value : 'one two three', end : 17 }
); );
expect(parser.parseMacroParameter("myparam>",0)).toEqual( expect($tw.utils.parseMacroParameter("myparam>",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'myparam', end : 7 } { type : 'macro-parameter', start : 0, value : 'myparam', end : 7 }
); );
}); });
it("should parse macro invocations", function() { it("should parse macro invocations", function() {
expect(parser.parseMacroInvocation("<<mymacro",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<mymacro",0)).toEqual(
null null
); );
expect(parser.parseMacroInvocation("<<mymacro>>",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<mymacro>>",0)).toEqual(
{ type : 'macrocall', start : 0, params : [ ], name : 'mymacro', end : 11 } { type : 'macrocall', start : 0, params : [ ], name : 'mymacro', end : 11 }
); );
expect(parser.parseMacroInvocation("<<mymacro one two three>>",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<mymacro one two three>>",0)).toEqual(
{ type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', end : 13 }, { type : 'macro-parameter', start : 13, value : 'two', end : 17 }, { type : 'macro-parameter', start : 17, value : 'three', end : 23 } ], name : 'mymacro', end : 25 } { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', end : 13 }, { type : 'macro-parameter', start : 13, value : 'two', end : 17 }, { type : 'macro-parameter', start : 17, value : 'three', end : 23 } ], name : 'mymacro', end : 25 }
); );
expect(parser.parseMacroInvocation("<<mymacro p:one q:two three>>",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<mymacro p:one q:two three>>",0)).toEqual(
{ type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', name : 'p', end : 15 }, { type : 'macro-parameter', start : 15, value : 'two', name : 'q', end : 21 }, { type : 'macro-parameter', start : 21, value : 'three', end : 27 } ], name : 'mymacro', end : 29 } { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', name : 'p', end : 15 }, { type : 'macro-parameter', start : 15, value : 'two', name : 'q', end : 21 }, { type : 'macro-parameter', start : 21, value : 'three', end : 27 } ], name : 'mymacro', end : 29 }
); );
expect(parser.parseMacroInvocation("<<mymacro 'one two three'>>",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<mymacro 'one two three'>>",0)).toEqual(
{ type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', end : 25 } ], name : 'mymacro', end : 27 } { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', end : 25 } ], name : 'mymacro', end : 27 }
); );
expect(parser.parseMacroInvocation("<<mymacro r:'one two three'>>",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<mymacro r:'one two three'>>",0)).toEqual(
{ type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', name : 'r', end : 27 } ], name : 'mymacro', end : 29 } { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', name : 'r', end : 27 } ], name : 'mymacro', end : 29 }
); );
expect(parser.parseMacroInvocation("<<myMacro one:two three:'four and five'>>",0)).toEqual( expect($tw.utils.parseMacroInvocation("<<myMacro one:two three:'four and five'>>",0)).toEqual(
{ type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'two', name : 'one', end : 17 }, { type : 'macro-parameter', start : 17, value : 'four and five', name : 'three', end : 39 } ], name : 'myMacro', end : 41 } { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'two', name : 'one', end : 17 }, { type : 'macro-parameter', start : 17, value : 'four and five', name : 'three', end : 39 } ], name : 'myMacro', end : 41 }
); );
}); });
it("should parse HTML attributes", function() { it("should parse HTML attributes", function() {
expect(parser.parseAttribute("p='blah' ",1)).toEqual( expect($tw.utils.parseAttribute("p='blah' ",1)).toEqual(
null null
); );
expect(parser.parseAttribute("p='blah' ",0)).toEqual( expect($tw.utils.parseAttribute("p='blah' ",0)).toEqual(
{ type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 }
); );
expect(parser.parseAttribute("p=\"blah\" ",0)).toEqual( expect($tw.utils.parseAttribute("p=\"blah\" ",0)).toEqual(
{ type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 }
); );
expect(parser.parseAttribute("p=blah ",0)).toEqual( expect($tw.utils.parseAttribute("p=blah ",0)).toEqual(
{ type : 'string', start : 0, name : 'p', value : 'blah', end : 6 } { type : 'string', start : 0, name : 'p', value : 'blah', end : 6 }
); );
expect(parser.parseAttribute("p =blah ",0)).toEqual( expect($tw.utils.parseAttribute("p =blah ",0)).toEqual(
{ type : 'string', start : 0, name : 'p', value : 'blah', end : 7 } { type : 'string', start : 0, name : 'p', value : 'blah', end : 7 }
); );
expect(parser.parseAttribute("p= blah ",0)).toEqual( expect($tw.utils.parseAttribute("p= blah ",0)).toEqual(
{ type : 'string', start : 0, name : 'p', value : 'blah', end : 7 } { type : 'string', start : 0, name : 'p', value : 'blah', end : 7 }
); );
expect(parser.parseAttribute("p = blah ",0)).toEqual( expect($tw.utils.parseAttribute("p = blah ",0)).toEqual(
{ type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 }
); );
expect(parser.parseAttribute("p = >blah ",0)).toEqual( expect($tw.utils.parseAttribute("p = >blah ",0)).toEqual(
{ type : 'string', value : 'true', start : 0, name : 'p', end : 4 } { type : 'string', value : 'true', start : 0, name : 'p', end : 4 }
); );
expect(parser.parseAttribute(" attrib1>",0)).toEqual( expect($tw.utils.parseAttribute(" attrib1>",0)).toEqual(
{ type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 } { type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 }
); );
}); });

View File

@ -83,7 +83,7 @@ describe("Tag tests", function() {
// Our tests // Our tests
it("should handle custom tag ordering", function() { it("should handle custom tag ordering", function() {
expect(wiki.filterTiddlers("[tag[TiddlerSeventh]]").join(",")).toBe("Tiddler10,TiddlerOne,Tiddler11,Tiddler Three,Tiddler9,a fourth tiddler"); expect(wiki.filterTiddlers("[tag[TiddlerSeventh]]").join(",")).toBe("Tiddler10,TiddlerOne,Tiddler Three,Tiddler11,Tiddler9,a fourth tiddler");
}); });
}); });

View File

@ -33,7 +33,7 @@ Previously, it was common to have `[is[shadow]]` at the start of a filter string
In 5.0.9, that filter has been changed to: In 5.0.9, that filter has been changed to:
``` ```
[all[tiddlers+shadows]tag[$:/tags/AdvancedSearch]!has[draft.of]] [all[shadows+tiddlers]tag[$:/tags/AdvancedSearch]!has[draft.of]]
``` ```
Note how the ''all'' operator allows operations to be performed on tiddlers from combinations of sources. Note how the ''all'' operator allows operations to be performed on tiddlers from combinations of sources.

View File

@ -0,0 +1,40 @@
created: 20140416160234142
modified: 20140416160234142
tags: releasenote
title: Release 5.0.10-beta
type: text/vnd.tiddlywiki
released: 201404191305
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.0.9-beta...v5.0.10-beta]]//
!! Highlights
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/ad4b03506a62d7110cb30aaa3d6f8dbfc712f246]] new syntax for [[Images in WikiText]] and a new ImageWidget
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/ba576d9f1b2146cec293447b2968e34f0c594a05]] support for a SafeMode that disables customisations
!! Documentation Improvements
* Added DateFormat documentation
!! Usability Improvements
* [[Refactor|https://github.com/Jermolene/TiddlyWiki5/commit/bb42c0ab360760917ad5bde84f15350186a9471a]] sorting to respect accented characters
* [[Support|https://github.com/Jermolene/TiddlyWiki5/commit/45b0966013c760abab5b3f7faea0e59af2ca5619]] embedded images in Markdown tiddlers
* [[Refactored|https://github.com/Jermolene/TiddlyWiki5/commit/821f1f1428f92160ae8bc4fa71dd3f947243f09e]] sidebar hiding action so that the story river border is maintained
!! Hackability Improvements
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/15d0c27e2a82359616ce6c7883557cd2ef1886cd]] `[is[tag]]` to the [[FilterOperator: is]]
* [[Hide|https://github.com/Jermolene/TiddlyWiki5/commit/95d291daac4a26664f0c232175f54780f0fa678f]] the top bars in the print stylesheet
!! Bug Fixes
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/4758874d13430338da07727997d0c4df7f328ac1]] support for saving changes on Windows network drives
* [[Refactored|https://github.com/Jermolene/TiddlyWiki5/commit/9fbe72a8778ae94c7d6322ad4b9155c83f753113]] configuration processing so that ordinary tiddlers are processed after shadow tiddlers. This resolves an issue whereby user stylesheets were being overridden by shadow stylesheets
* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/d6054f10392c535ca430f3e73b9b68d0f8c18498]] issue with offline snapshot of server edition erroneously including shadow tiddlers
* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/bd4a031df8a68287475a41ad84b423ad83f735a3]] problem with corrupted upgrades from 5.0.x-prerelease to 5.0.x-beta
* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/73cfd1021809e97906ecfd5dacdf2337da3abae9]] bug with `[untagged[]]` filter operator
* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/d336ffea02621e382f6d7135847d11e49e77bc26]] incorrect background colour for tag pills in the sidebar
* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/f57e04787738ad30fb05ac0e592239075b90507e]] issues with null fields under TiddlyWeb
* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/768489128547cf54e80fc321f3f1f4f5cd191862]] problem with hamburger overlapping scrollbars

View File

@ -3,18 +3,23 @@ modified: 201403021809
tags: releasenote tags: releasenote
title: Release 5.0.9-beta title: Release 5.0.9-beta
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
released: 201404152139
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.0.8-beta...v5.0.9-beta]]// //[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.0.8-beta...v5.0.9-beta]]//
!! Highlights !! Highlights
* Improved layout, including a ''hamburger'' icon for dismissing the sidebar * Improved layout, including a ''hamburger'' icon for dismissing the sidebar and expanding the story river to fill the space
* Added new ''Seamless'' theme
* New ''Filter'' tab in [[$:/AdvancedSearch]] * New ''Filter'' tab in [[$:/AdvancedSearch]]
* Initial implementation of CecilyView * Initial implementation of CecilyView
* Overhaul of inconsistencies in TiddlerFilters (see [[Changes to filters in 5.0.9-beta]]) * Overhaul of inconsistencies in TiddlerFilters (see [[Changes to filters in 5.0.9-beta]])
* New translations for Italian and Japanese
* Performance improvements, particularly [[during editing|https://github.com/Jermolene/TiddlyWiki5/commit/0aa559cd23b3742c8f10c5ac144860d816699782]]
!! Documentation Improvements !! Documentation Improvements
* Improved and reorganised documentation for TiddlerFilters
* Demo of [[Making curved text with SVG]] * Demo of [[Making curved text with SVG]]
* [[Community]] links are now broken up into individual tiddlers * [[Community]] links are now broken up into individual tiddlers
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/a19432541e776bfb63b1b985a60f472e9f1d4352]] overview diagram of [[TiddlyWiki Architecture]] * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/a19432541e776bfb63b1b985a60f472e9f1d4352]] overview diagram of [[TiddlyWiki Architecture]]
@ -24,7 +29,7 @@ type: text/vnd.tiddlywiki
* Made the dropdown arrow icon [[skinnier|https://github.com/Jermolene/TiddlyWiki5/commit/ec90ac99cf2767b6ff20902d8b01aa1c36778147]] * Made the dropdown arrow icon [[skinnier|https://github.com/Jermolene/TiddlyWiki5/commit/ec90ac99cf2767b6ff20902d8b01aa1c36778147]]
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/bca1d552803c1839e7385765314f81c5307632b8]] validation of legal characters for fieldnames * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/bca1d552803c1839e7385765314f81c5307632b8]] validation of legal characters for fieldnames
* Added blacklisting of unsage HTML [[elements|https://github.com/Jermolene/TiddlyWiki5/commit/ba6edd42c125cb19d955a1cb3f54a2d367cb79dc]] and [[attributes|https://github.com/Jermolene/TiddlyWiki5/commit/ba6edd42c125cb19d955a1cb3f54a2d367cb79dc]] * Added blacklisting of unsafe HTML [[elements|https://github.com/Jermolene/TiddlyWiki5/commit/ba6edd42c125cb19d955a1cb3f54a2d367cb79dc]] and [[attributes|https://github.com/Jermolene/TiddlyWiki5/commit/d0caf21b2df9fda9800eb30489003a87cafb1277]]
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/baa8cf3dd098bab0a7a8c78b24747c69bd40889f]] a warning indicator to tiddlers in TiddlyWikiClassic format * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/baa8cf3dd098bab0a7a8c78b24747c69bd40889f]] a warning indicator to tiddlers in TiddlyWikiClassic format
* [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/42c67cfeb732fccb10b8ab574c84090dc2471352]] tiddler info ''Advanced'' panel with information about plugins and shadow tiddlers * [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/42c67cfeb732fccb10b8ab574c84090dc2471352]] tiddler info ''Advanced'' panel with information about plugins and shadow tiddlers
* [[Improved|https://github.com/Jermolene/TiddlyWiki5/commit/96457d801159958b897f98e22aa9af53b97f0e35]] layout of [[$:/ControlPanel]] ''Plugins'' tab * [[Improved|https://github.com/Jermolene/TiddlyWiki5/commit/96457d801159958b897f98e22aa9af53b97f0e35]] layout of [[$:/ControlPanel]] ''Plugins'' tab
@ -36,8 +41,7 @@ type: text/vnd.tiddlywiki
!! Hackability Improvements !! Hackability Improvements
* [[Updated|https://github.com/Jermolene/TiddlyWiki5/commit/bdbbf94326f70db0f8ef196270ab9e92bfde10fb]] [[Transclusion in WikiText]] syntax to allow translusion of a template without affecting the current tiddler * [[Updated|https://github.com/Jermolene/TiddlyWiki5/commit/bdbbf94326f70db0f8ef196270ab9e92bfde10fb]] [[Transclusion in WikiText]] syntax to allow translusion of a template without affecting the current tiddler
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/8a7d0f53d380e9ca93ee34d8ad05090d511e95c4]] `sourceURL` handling to `eval()` so that tiddler modules can be [[properly debugged|https://chromedevtools.googlecode.com/svn-history/r421/trunk/tutorials/b * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/8a7d0f53d380e9ca93ee34d8ad05090d511e95c4]] `sourceURL` handling to `eval()` so that tiddler modules can be [[properly debugged|https://chromedevtools.googlecode.com/svn-history/r421/trunk/tutorials/breapoints/index.html#regular]] in Chrome
reapoints/index.html#regular]] in Chrome
* New ScrollableWidget giving better control over scrollable regions * New ScrollableWidget giving better control over scrollable regions
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/d3c0296a87198296cff26aa7ce7bb8274cdcc3f7]] new CSS class `tw-site-title` for the site title * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/d3c0296a87198296cff26aa7ce7bb8274cdcc3f7]] new CSS class `tw-site-title` for the site title
* [[Disable|https://github.com/Jermolene/TiddlyWiki5/commit/e397e4d15951c1395c7752a7563f002ca459206e]] the TiddlyWeb sync adaptor unless the wiki is loaded over HTTP * [[Disable|https://github.com/Jermolene/TiddlyWiki5/commit/e397e4d15951c1395c7752a7563f002ca459206e]] the TiddlyWeb sync adaptor unless the wiki is loaded over HTTP
@ -49,7 +53,7 @@ reapoints/index.html#regular]] in Chrome
* [[Extend|https://github.com/Jermolene/TiddlyWiki5/commit/f649b5b037bfd2e7c48d1ba65ffa37064456523d]] the ButtonWidget to be able to set text references * [[Extend|https://github.com/Jermolene/TiddlyWiki5/commit/f649b5b037bfd2e7c48d1ba65ffa37064456523d]] the ButtonWidget to be able to set text references
* [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/afa677b9a0b1dff1239dc1ea08edd210b9736af9]] a class to tiddler frames in view mode * [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/afa677b9a0b1dff1239dc1ea08edd210b9736af9]] a class to tiddler frames in view mode
* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/50cf9678cb469e443e220b063e2355c844e417e7]] support for [[WidgetMessage: tw-home]] * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/50cf9678cb469e443e220b063e2355c844e417e7]] support for [[WidgetMessage: tw-home]]
* [[Hidden|https://github.com/Jermolene/TiddlyWiki5/commit/2608a323ebf3d8a8e925eda6d3a10ebb8f41d383]] system tags from the sidebar ''Tags' tab * [[Hidden|https://github.com/Jermolene/TiddlyWiki5/commit/2608a323ebf3d8a8e925eda6d3a10ebb8f41d383]] system tags from the sidebar ''Tags'' tab
* [[Allow|https://github.com/Jermolene/TiddlyWiki5/commit/98872bbe7c62faa4aa209fa421c2989aeef3aaf2]] pasting and import of HTML content * [[Allow|https://github.com/Jermolene/TiddlyWiki5/commit/98872bbe7c62faa4aa209fa421c2989aeef3aaf2]] pasting and import of HTML content
* [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/a5a2c718b1d5671652d01e3567dba1c6795b7521]] support for a tooltip on the LinkWidget * [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/a5a2c718b1d5671652d01e3567dba1c6795b7521]] support for a tooltip on the LinkWidget

View File

@ -1,11 +1,17 @@
created: 20131202102427114 created: 20131202102427114
modified: 20140126135354379 modified: 20140419133900452
tags: howto tags: howto
title: Upgrading title: Upgrading
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
There are several methods for upgrading an existing TiddlyWiki version 5 document to a new release. There is a [[different procedure|Upgrading TiddlyWiki on Node.js]] for upgrading [[TiddlyWiki on Node.js]]. There are several methods for upgrading an existing TiddlyWiki version 5 document to a new release. There is a [[different procedure|Upgrading TiddlyWiki on Node.js]] for upgrading [[TiddlyWiki on Node.js]].
<<<
Regardless of which method you use, remember the [[The First Rule of Using TiddlyWiki]]:
//You are responsible for looking after your own data; take care to make backups, especially when upgrading the ~TiddlyWiki core//
<<<
<div class="tw-message-box"> <div class="tw-message-box">
<a class="tw-message-icon" href="http://tiddlywiki.com/" target="_blank">{{TiddlyWiki Classic.png}}</a> <a class="tw-message-icon" href="http://tiddlywiki.com/" target="_blank">{{TiddlyWiki Classic.png}}</a>
@ -45,3 +51,7 @@ This will download a file called ''empty.html'' to your computer. This file is t
! Offline upgrading ! Offline upgrading
You can also download http://tiddlywiki.com/empty.html locally and perform the same drag-and-drop procedure to upgrade your files. You can also download http://tiddlywiki.com/empty.html locally and perform the same drag-and-drop procedure to upgrade your files.
! Problems with Upgrades
Particularly during the beta, it is possible for a customisation applied in a previous version to break when upgraded to the latest version. Use SafeMode to investigate and fix these problems.

View File

@ -0,0 +1,7 @@
created: 20140425085548209
modified: 20140425085738745
tags: command
title: BuildCommand
type: text/vnd.tiddlywiki
{{$:/language/Help/build}}

View File

@ -0,0 +1,4 @@
title: ClearPasswordCommand
tags: command
{{$:/language/Help/clearpassword}}

View File

@ -0,0 +1,7 @@
created: 20140425085548209
modified: 20140425085738745
tags: command
title: OutputCommand
type: text/vnd.tiddlywiki
{{$:/language/Help/output}}

View File

@ -22,4 +22,4 @@ System tags are used to give special behaviour to tiddlers:
These are the system tags in use in this wiki: These are the system tags in use in this wiki:
{{{ [all[tiddlers+shadows]tags[]prefix[$:/]] +[sort[title]] }}} {{{ [all[shadows+tiddlers]tags[]prefix[$:/]] +[sort[title]] }}}

View File

@ -1,43 +1,44 @@
created: 20130825213300000 created: 20130825213300000
modified: 20131212095204933 modified: 20140419151511111
tags: concepts tags: concepts
title: TiddlerFields title: TiddlerFields
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
\define lingo-base() $:/language/Docs/Fields/
TiddlerFields are name:value pairs that make up a [[tiddler|Tiddlers]]. Field names must be lowercase letters, digits or the characters `-` (dash), `_` (underscore) and `.` (period). TiddlerFields are name:value pairs that make up a [[tiddler|Tiddlers]]. Field names must be lowercase letters, digits or the characters `-` (dash), `_` (underscore) and `.` (period).
The standard fields are: The standard fields are:
|!Field Name |!Reference |!Description | |!Field Name |!Reference |!Description |
|`title` |TitleField |{{$:/docs/fields/title}} | |`title` |TitleField |<<lingo title>> |
|`text` |TextField |{{$:/docs/fields/text}} | |`text` |TextField |<<lingo text>> |
|`modified` |ModifiedField |{{$:/docs/fields/modified}} | |`modified` |ModifiedField |<<lingo modified>> |
|`modifier` |ModifierField |{{$:/docs/fields/modifier}} | |`modifier` |ModifierField |<<lingo modifier>> |
|`created` |CreatedField |{{$:/docs/fields/created}} | |`created` |CreatedField |<<lingo created>> |
|`creator` |CreatorField |{{$:/docs/fields/creator}} | |`creator` |CreatorField |<<lingo creator>> |
|`tags` |TagsField |{{$:/docs/fields/tags}} | |`tags` |TagsField |<<lingo tags>> |
|`type` |TypeField |{{$:/docs/fields/type}} | |`type` |TypeField |<<lingo type>> |
|`list` |ListField |{{$:/docs/fields/list}} | |`list` |ListField |<<lingo list>> |
Other fields used by the core are: Other fields used by the core are:
|!Field Name |!Reference |!Description | |!Field Name |!Reference |!Description |
|`color` |ColorField |{{$:/docs/fields/color}} | |`color` |ColorField |<<lingo color>> |
|`description` |DescriptionField |{{$:/docs/fields/description}} | |`description` |DescriptionField |<<lingo description>> |
|`draft.of` |DraftOfField |{{$:/docs/fields/draft.of}} | |`draft.of` |DraftOfField |<<lingo draft.of>> |
|`draft.title` |DraftTitleField |{{$:/docs/fields/draft.title}} | |`draft.title` |DraftTitleField |<<lingo draft.title>> |
|`footer` |FooterField |{{$:/docs/fields/footer}} | |`footer` |FooterField |<<lingo footer>> |
|`library` |LibraryField |{{$:/docs/fields/library}} | |`library` |LibraryField |<<lingo library>> |
|`name` |NameField |{{$:/docs/fields/name}} | |`name` |NameField |<<lingo name>> |
|`plugin-priority` |PluginPriorityField |{{$:/docs/fields/plugin-priority}} | |`plugin-priority` |PluginPriorityField |<<lingo plugin-priority>> |
|`plugin-type` |PluginTypeField |{{$:/docs/fields/plugin-type}} | |`plugin-type` |PluginTypeField |<<lingo plugin-type>> |
|`source` |SourceField |{{$:/docs/fields/source}} | |`source` |SourceField |<<lingo source>> |
|`subtitle` |SubtitleField |{{$:/docs/fields/subtitle}} | |`subtitle` |SubtitleField |<<lingo subtitle>> |
The TiddlyWebAdaptor uses a few more fields: The TiddlyWebAdaptor uses a few more fields:
|!Field Name |!Reference |!Description | |!Field Name |!Reference |!Description |
|`bag` |BagField |{{$:/docs/fields/bag}} | |`bag` |BagField |<<lingo bag>> |
|`revision` |RevisionField |{{$:/docs/fields/revision}} | |`revision` |RevisionField |<<lingo revision>> |
See the ''Advanced > TiddlerFields'' tab of the [[control panel|$:/ControlPanel]] for details of the fields used in this wiki. See the ''Advanced > TiddlerFields'' tab of the [[control panel|$:/ControlPanel]] for details of the fields used in this wiki.

View File

@ -24,6 +24,7 @@ The `tiddlywiki.info` file in a wiki folder contains a JSON object comprising th
* ''themes'' - an array of theme names to be included in the wiki * ''themes'' - an array of theme names to be included in the wiki
* ''languages'' - an array of language names to be included in the wiki * ''languages'' - an array of language names to be included in the wiki
* ''includeWikis'' - an array of relative paths to external wiki folders to be included in the wiki * ''includeWikis'' - an array of relative paths to external wiki folders to be included in the wiki
* ''build'' - a hashmap of named build targets, each defined by an array of command tokens (see BuildCommand)
* ''config'' - an optional hashmap of configuration options (see below) * ''config'' - an optional hashmap of configuration options (see below)
Configuration options include: Configuration options include:
@ -41,6 +42,13 @@ For example:
"includeWikis": [ "includeWikis": [
"../tw5.com" "../tw5.com"
], ],
"build": {
"index": [
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
"favicon": [
"--savetiddler","$:/favicon.ico","favicon.ico",
"--savetiddler","$:/green_favicon.ico","static/favicon.ico"]
},
"config": { "config": {
"retain-original-tiddler-path": true "retain-original-tiddler-path": true
} }

View File

@ -1,5 +1,5 @@
created: 20131211222303769 created: 20131211222303769
modified: 20140120130146763 modified: 20140424130146763
tags: dev tags: dev
title: JavaScript Macros title: JavaScript Macros
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
@ -25,3 +25,8 @@ There are several JavaScript macros built into the core which can serve as a jum
https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/macros https://github.com/Jermolene/TiddlyWiki5/tree/master/core/modules/macros
Note that JavaScript macros work on both the client and the server, and so do not have access to the browser DOM. Note that JavaScript macros work on both the client and the server, and so do not have access to the browser DOM.
!! Macro Behaviour
Macros are just used to return a chunk of wikitext for further processing. They should not make modifications to tiddlers in the wiki store. The reason is that you cannott control when the macro is called; it may be called repeatedly as part of refresh processing. So it is important that macros do not have any other side effects beyond generating their text.

View File

@ -0,0 +1,45 @@
created: 20140418142957325
modified: 20140418163615916
tags: features
title: DateFormat
type: text/vnd.tiddlywiki
The ViewWidget accepts a `template` attribute that allows the format of date values to be specified. The format string is processed with the following substitutions:
|!Token |!Substituted Value |
|`DDD` |Day of week in full (eg, "Monday") |
|`ddd` |Short day of week (eg, "Mon") |
|`DD` |Day of month |
|`0DD` |Adds a leading zero |
|`DDth` |Adds a suffix |
|`WW` |~ISO-8601 week number of year |
|`0WW` |Adds a leading zero |
|`MMM` |Month in full (eg, "July") |
|`mmm` |Short month (eg, "Jul") |
|`MM` |Month number |
|`0MM` |Adds leading zero |
|`YYYY` |Full year |
|`YY` |Two digit year |
|`wYYYY` |Full year with respect to week number |
|`wYY` |Two digit year with respect to week number |
|`hh` |Hours |
|`0hh` |Adds a leading zero |
|`hh12` |Hours in 12 hour clock |
|`0hh12` |Hours in 12 hour clock with leading zero |
|`mm` |Minutes |
|`0mm` |Minutes with leading zero |
|`ss` |Seconds |
|`0ss` |Seconds with leading zero |
|`am` or `pm` |Lower case AM/PM indicator |
|`AM` or `PM` |Upper case AM/PM indicator |
|`TZD` |Timezone offset |
|`\x` |Used to escape a character that would otherwise have special meaning |
Note that other text is passed through unchanged, allowing commas, colons or other separators to be used.
! Examples
|!Template |!Output |
|`DDth MMM YYYY` |16th February 2011 |
|`DDth MMM \M\M\M YYYY` |16th February MMM 2011 |
|`DDth mmm hh:mm:ss` |16th Feb 2011 11:38:42 |

View File

@ -0,0 +1,21 @@
created: 20140419082845576
modified: 20140419083436245
tags: features
title: SafeMode
type: text/vnd.tiddlywiki
! Introduction
Safe mode provides a way to disabling most customisations in TiddlyWiki. This is useful because if TiddlyWiki is customised incorrectly it can be rendered inoperable. A particular issue is that some customisations break when upgrading to a newer core version of TiddlyWiki (especially during the beta).
! Enabling Safe Mode
Safe mode is enabled in the browser by starting TiddlyWiki with the URL hash set to the string `#:safe`. For example:
http://tiddlywiki.com/#:safe
! How Safe Mode Works
In safe mode, any tiddlers that override shadow tiddlers are renamed to give them the prefix `SAFE: `, thus restoring the underlying shadow tiddler.
A report tiddler is displayed that allows you to inspect the tiddlers that were renamed.

View File

@ -1,5 +1,5 @@
created: 20140410103123179 created: 20140410103123179
modified: 20140410103123179 modified: 20140418103123179
tags: filters commonfilters tags: filters commonfilters
title: FilterOperator: is title: FilterOperator: is
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
@ -13,6 +13,7 @@ The ''is'' filter operator selects tiddlers from the current list according to t
* `[is[shadow]]` - tiddlers that are ShadowTiddlers * `[is[shadow]]` - tiddlers that are ShadowTiddlers
* `[is[system]]` - tiddlers that are SystemTiddlers * `[is[system]]` - tiddlers that are SystemTiddlers
* `[is[tiddler]]` - tiddlers that are not MissingTiddlers * `[is[tiddler]]` - tiddlers that are not MissingTiddlers
* `[is[tag]]` - tiddlers that are being used as tags
For example: For example:
@ -20,6 +21,8 @@ For example:
|`[tag[task]is[shadow]]` |Returns ShadowTiddlers tagged `task` | |`[tag[task]is[shadow]]` |Returns ShadowTiddlers tagged `task` |
|`[tag[task]!is[system]]` |Returns non-SystemTiddlers tagged `task` | |`[tag[task]!is[system]]` |Returns non-SystemTiddlers tagged `task` |
|`[is[shadow]]` |Returns ShadowTiddlers that have been overridden by a 'real' tiddler | |`[is[shadow]]` |Returns ShadowTiddlers that have been overridden by a 'real' tiddler |
|`[!is[shadow]]` |Returns ordinary tiddlers that are not shadow tiddlers |
|`[!is[tag]]` |Returns all tiddlers that are not being used as tags |
|`[is[missing]]` |Returns an empty list (see note below) | |`[is[missing]]` |Returns an empty list (see note below) |
Note that the ''is'' filter operator strictly filters the current list by choosing whether or not to include each one in the output. It never adds tiddlers to the results that are not already listed. This means that when used at the start of a run of filter operators the ''is'' operator will be choosing from the currently existing tiddlers, and so will never return missing tiddlers, or shadow tiddlers that haven't been overridden. Note that the ''is'' filter operator strictly filters the current list by choosing whether or not to include each one in the output. It never adds tiddlers to the results that are not already listed. This means that when used at the start of a run of filter operators the ''is'' operator will be choosing from the currently existing tiddlers, and so will never return missing tiddlers, or shadow tiddlers that haven't been overridden.

View File

@ -11,7 +11,7 @@ For example:
|!Filter String |!Description | |!Filter String |!Description |
|`[tag[mytag]]` |Returns all tiddlers tagged `mytag` | |`[tag[mytag]]` |Returns all tiddlers tagged `mytag` |
|`[all[shadows]tag[mytag]]` |Returns all ShadowTiddlers tagged `mytag` | |`[all[shadows]tag[mytag]]` |Returns all ShadowTiddlers tagged `mytag` |
|`[all[tiddlers+shadows]tag[mytag]]` |Returns all ShadowTiddlers and non-ShadowTiddlers tagged `mytag` | |`[all[shadows+tiddlers]tag[mytag]]` |Returns all ShadowTiddlers and non-ShadowTiddlers tagged `mytag` |
|`[!tag[mytag]]` |Returns all tiddlers not tagged `mytag` | |`[!tag[mytag]]` |Returns all tiddlers not tagged `mytag` |
|`[tag[mytag]!tag[exclude]]` |Returns all tiddlers tagged `mytag` that are not tagged `mytag` | |`[tag[mytag]!tag[exclude]]` |Returns all tiddlers tagged `mytag` that are not tagged `mytag` |

View File

@ -1,5 +1,5 @@
created: 20140213122133816 created: 2014013122133816
modified: 20140214124024493 modified: 20140415114024493
tags: howto tags: howto
title: How to create plugins in the browser title: How to create plugins in the browser
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
@ -19,7 +19,7 @@ To make a modified copy of a plugin, one edits the constituent shadow tiddlers (
!! 1. Setup your development environment !! 1. Setup your development environment
Start with a blank TiddlyWiki, and create a ''HelloThere'' tiddler that contains links to various tiddlers that you'll be visiting frequently: Start with a blank TiddlyWiki. It is useful to create a ''HelloThere'' tiddler that contains links to various tiddlers that you'll be opening frequently during plugin development:
* The plugin itself (eg `$:/plugins/yourname/pluginname`) * The plugin itself (eg `$:/plugins/yourname/pluginname`)
* The payload tiddlers that are to be packed into the plugin (eg `$:/plugins/yourname/pluginname/mywidget.js`) * The payload tiddlers that are to be packed into the plugin (eg `$:/plugins/yourname/pluginname/mywidget.js`)

View File

@ -1,12 +1,12 @@
created: 20140305091244145 created: 20140305091244145
modified: 20140305091258135 modified: 20140425121258135
tags: howto tags: howto
title: Using Stylesheets title: Using Stylesheets
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
The usual way of modifying the appearance of a TiddlyWiki is to use one of the available themes, or to modify the [[colour palette|ColourPalettes]]. The usual way of modifying the appearance of a TiddlyWiki is to use one of the available themes, or to modify the [[colour palette|ColourPalettes]].
You can also use custom CSS stylesheets by tagging tiddlers with `$:/tags/stylsheet`. For example, create a tiddler with the tag `$:/tags/stylsheet` and the following content in order to change the page background colour to red: You can also use custom CSS stylesheets by tagging tiddlers with `$:/tags/stylesheet`. For example, create a tiddler with the tag `$:/tags/stylesheet` and the following content in order to change the page background colour to red:
``` ```
html body.tw-body { html body.tw-body {

View File

@ -1,5 +1,5 @@
created: 20130823203800000 created: 20130823203800000
modified: 20140226202503234 modified: 20140419081726794
tags: planning tags: planning
title: RoadMap title: RoadMap
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
@ -18,15 +18,12 @@ The following additional features are planned or under consideration for impleme
** Improve upgrade process ** Improve upgrade process
** Establish plugin library ** Establish plugin library
** Proper use of ARIA roles ** Proper use of ARIA roles
* Features required by ~TiddlyWiki hackers
** Pretty-printed JSON (similar to http://marianoguerra.github.io/json.human.js/)
** A "safe mode" to disable customisations
* Fixing hangovers from TiddlyWikiClassic * Fixing hangovers from TiddlyWikiClassic
** ~TiddlyWiki file format (to avoid illegal attribute names) ** ~TiddlyWiki file format (to avoid illegal attribute names)
** Tiddler object format (to provide true polymorphism of field values) ** Tiddler object format (to provide true polymorphism of field values)
* Perfecting WikiText * Perfecting WikiText
** Global macros ** Global macros
** `[img[url]]` for remote image embedding, and `[ext[url]]` for explicit external links ** ~~`[img[url]]` for remote image embedding~~, and `[ext[url]]` for explicit external links
** Further ~WikiText features ** Further ~WikiText features
* Productivity features * Productivity features
** Import wizard allowing individual tiddlers to be selected for import ** Import wizard allowing individual tiddlers to be selected for import
@ -45,4 +42,4 @@ Also see the issues list on GitHub: https://github.com/Jermolene/TiddlyWiki5
! General Release ! General Release
TiddlyWiki will leave beta and become a full release early in 2014. That is the point at which it is declared stable enough for general use. It will continue to improve and evolve after this point, although constrained to remain backwards compatible so that plugins and content created for version 5.0 will continue to work into the indefinite future. TiddlyWiki will [[leave beta|TiddlyWiki5 Versioning]] and become a full release in the first half of 2014. That is the point at which it is declared stable enough for general use. It will continue to improve and evolve after this point, although constrained to remain backwards compatible so that plugins and content created for version 5.0 will continue to work into the indefinite future.

View File

@ -1,4 +1,4 @@
title: $:/editions/tw5.com/github-fork-ribbon title: $:/editions/tw5.com/github-fork-ribbon
tags: $:/tags/PageControls tags: $:/tags/PageControls
<div class="github-fork-ribbon-wrapper right" style><div class="github-fork-ribbon" style="background-color:#FFBB3D;"><$link to="ReleaseHistory"><<version>></$link></div></div> <div class="github-fork-ribbon-wrapper right" style><div class="github-fork-ribbon" style="background-color:#FF7685;"><$link to="ReleaseHistory"><<version>></$link></div></div>

View File

@ -1,30 +1,7 @@
created: 20140406210404245 created: 20140406210404245
modified: 20140406210649764 modified: 20140424113815434
tags: tips tags: tips
title: Editing Tiddlers with Emacs title: Editing Tiddlers with Emacs
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
This [[Emacs|http://www.gnu.org/software/emacs/]] function from Michael Fogleman simplifies editing tiddlers in `*.tid` files by automatically updating the `modified` field. Michael Fogleman has written an [[Emacs|http://www.gnu.org/software/emacs/]] major mode called [[tid-mode|https://github.com/mwfogleman/tid-mode]], which is for editing TiddlyWiki .tid files. It is derived from text-mode, uses the useful minor modes org-struct and subword, and updates the modified times when you save a .tid file.
If you have Emacs, you can save this function somewhere (such as in your init file). When you finish editing a tiddler, you can call the function, and it will update the modified time.
> Help Wanted: Even better would be a TiddlyWiki-mode that used this function as a save-hook
```
(defun tid-time ()
"If called in a tiddler file, this function updates the metadata to
reflect the modification time."
(interactive)
(when
(and
(> (length (buffer-file-name)) 4)
(string-equal (substring (buffer-file-name) -4) ".tid"))
(save-excursion
(goto-char (point-min))
(search-forward "modified: ")
(beginning-of-line)
(kill-line)
(insert (format-time-string "modified: %Y%m%d%H%M%S%3N")))))
```

View File

@ -0,0 +1,19 @@
created: 20140419132828051
modified: 20140419134201033
tags: howto tips
title: The First Rule of Using TiddlyWiki
type: text/vnd.tiddlywiki
!! The first rule of using TiddlyWiki is:
<p style="font-size:40pt;font-weight:700;color:red;">
Backup your data!
</p>
TiddlyWiki is a very flexible, customisable system that puts you firmly in charge of your own data. Every care is taken in TiddlyWiki's development to ensure that it is a safe place to preserve your most valuable data but the ultimate responsibility to reduce the risk of data loss falls to users.
The best way to make sure that your data is safe is to practice a rigorous system of backups:
* Consider using services like Dropbox to continuously back up your personal data to the cloud
* Retain backups before upgrading to a new version of TiddlyWiki

View File

@ -5,7 +5,7 @@ tags: widget
! Introduction ! Introduction
The button widget displays an HTML `<button>` element that can perform a combination optional actions when clicked: The button widget displays an HTML `<button>` element that can perform a combination of optional actions when clicked:
* Navigate to a specified tiddler * Navigate to a specified tiddler
* Dispatch a user defined [[widget message|WidgetMessages]] * Dispatch a user defined [[widget message|WidgetMessages]]

View File

@ -0,0 +1,20 @@
title: ImageWidget
created: 20140416160234142
modified: 20140416160234142
tags: widget
! Introduction
The image widget displays images that can be specified as a remote URL or the title of a local tiddler containing the image.
! Content and Attributes
Any content of the `<$image>` widget is ignored.
|!Attribute |!Description |
|source |The URL of the image, or the title of an image tiddler |
|width |The width of the image as a number |
|height |The height of the image |
|tooltip |The tooltip to be displayed over the image |
|class |CSS classes to be assigned to the `<img>` element |

View File

@ -1,10 +1,44 @@
created: 20131205160221762 created: 20131205160221762
modified: 20131205160234142 modified: 20140416160234142
tags: wikitext tags: wikitext
title: Images in WikiText title: Images in WikiText
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
To display an image stored in a tiddler just transclude that tiddler: ! Image Formatting
Images can be included in WikiText with the following syntax:
```
[img[Motovun Jack.jpg]]
[img[http://tiddlywiki.com/favicon.ico]]
```
If the image source is the title of an image tiddler then that tiddler is directly displayed. Otherwise it is interpreted as a URL and an HTML `<img>` tag is generated with the `src` attribute containing the URL.
A tooltip can also be specified:
```
[img[An explanatory tooltip|Motovun Jack.jpg]]
```
Attributes can be provided to specify CSS classes and the image width and height:
```
[img width=32 [Motovun Jack.jpg]]
[img width=32 class="tw-image" [Motovun Jack.jpg]]
```
Note that attributes can be specified as transclusions or variable references:
```
[img width={{!!mywidth}} class=<<image-classes>> [Motovun Jack.jpg]]
```
The image syntax is a shorthand for invoking the ImageWidget.
! Displaying Images via Transclusion
You can also display an image stored in a tiddler by transcluding that tiddler. The disadvantage of this approach is that there is no direct way to control the size of the image.
``` ```
{{Motovun Jack.jpg}} {{Motovun Jack.jpg}}
@ -13,3 +47,4 @@ To display an image stored in a tiddler just transclude that tiddler:
Renders as: Renders as:
{{Motovun Jack.jpg}} {{Motovun Jack.jpg}}

View File

@ -26,8 +26,30 @@
"zh-Hant", "zh-Hant",
"it-IT", "it-IT",
"ja-JP" "ja-JP"
] ],
, "build": {
"index": [
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
"encrypted": [
"--password", "password",
"--rendertiddler", "$:/core/save/all", "encrypted.html", "text/plain",
"--clearpassword"],
"favicon": [
"--savetiddler","$:/favicon.ico","favicon.ico",
"--savetiddler","$:/green_favicon.ico","static/favicon.ico"],
"readmes": [
"--rendertiddler","ReadMe","readme.md","text/html",
"--rendertiddler","ContributingTemplate","contributing.md","text/html",
"--rendertiddler","$:/core/copyright.txt","licenses/copyright.md","text/html"],
"empty": [
"--rendertiddler","$:/editions/tw5.com/download-empty","empty.html","text/plain",
"--rendertiddler","$:/editions/tw5.com/download-empty","empty.hta","text/plain"],
"static": [
"--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain",
"--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain",
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain",
"--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain"]
},
"config": { "config": {
"retain-original-tiddler-path": true "retain-original-tiddler-path": true
} }

View File

@ -152,3 +152,5 @@ Michael Fogleman, @mwfogleman, 2014/04/08
James W. Anderson, @welford, 2014/04/08 James W. Anderson, @welford, 2014/04/08
Tomohiro Miura, @pekopeko1, 2014/04/15 Tomohiro Miura, @pekopeko1, 2014/04/15
Devin Weaver, @sukima, 2014/05/21

View File

@ -1,7 +1,7 @@
{ {
"name": "tiddlywiki", "name": "tiddlywiki",
"preferGlobal": "true", "preferGlobal": "true",
"version": "5.0.9-prerelease", "version": "5.0.11-prerelease",
"author": "Jeremy Ruston <jeremy@jermolene.com>", "author": "Jeremy Ruston <jeremy@jermolene.com>",
"description": "a non-linear personal web notebook", "description": "a non-linear personal web notebook",
"contributors": [ "contributors": [

View File

@ -33,6 +33,18 @@ function transformNode(node) {
}); });
} }
widget.children = transformNodes(node.slice(p++)); widget.children = transformNodes(node.slice(p++));
// Massage images into the image widget
if(widget.tag === "img") {
widget.tag = "$image";
if(widget.attributes.alt) {
widget.attributes.tooltip = widget.attributes.alt;
delete widget.attributes.alt;
}
if(widget.attributes.src) {
widget.attributes.source = widget.attributes.src;
delete widget.attributes.src;
}
}
return widget; return widget;
} else { } else {
return {type: "text", text: node}; return {type: "text", text: node};

View File

@ -1,6 +1,6 @@
title: $:/editions/clientserver/download-offline title: $:/editions/clientserver/download-offline
\define saveTiddlerFilter() \define saveTiddlerFilter()
[all[tiddlers+shadows]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] +[sort[title]] [is[tiddler]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] +[sort[title]]
\end \end
{{$:/core/templates/tiddlywiki5.html}} {{$:/core/templates/tiddlywiki5.html}}

File diff suppressed because one or more lines are too long

View File

@ -61,15 +61,11 @@ Seamless modifications
@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics##storywidth}}) { @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics##storywidth}}) {
<<if-sidebar "
/* Drop the tiddler frame padding */ /* Drop the tiddler frame padding */
body.tw-body .tw-tiddler-frame { body.tw-body .tw-tiddler-frame {
padding: 0; padding: 0;
} }
">>
/* Move the sidebar up so that the title lines up */ /* Move the sidebar up so that the title lines up */
body.tw-body .tw-sidebar-scrollable { body.tw-body .tw-sidebar-scrollable {
padding: 43px 0 28px 42px; padding: 43px 0 28px 42px;

View File

@ -257,7 +257,7 @@ a.tw-tiddlylink-external:hover {
color: <<colour foreground>>; color: <<colour foreground>>;
} }
.tw-sidebar-lists button { .tw-sidebar-lists button.btn {
color: <<colour sidebar-button-foreground>>; color: <<colour sidebar-button-foreground>>;
} }
@ -330,13 +330,13 @@ a.tw-tiddlylink-external:hover {
} }
.tw-topbar-left { .tw-topbar-left {
left: 0; left: 29px;
top: 0; top: 5px;
} }
.tw-topbar-right { .tw-topbar-right {
top: 0; top: 5px;
right: 0; right: 29px;
} }
.tw-topbar button { .tw-topbar button {
@ -347,7 +347,7 @@ a.tw-tiddlylink-external:hover {
fill: <<colour muted-foreground>>; fill: <<colour muted-foreground>>;
} }
.tw-topbar svg:hover { .tw-topbar button:hover svg {
fill: <<colour foreground>>; fill: <<colour foreground>>;
} }
@ -472,7 +472,6 @@ a.tw-tiddlylink-external:hover {
.story-river { .story-river {
width: auto; width: auto;
padding: 0;
} }
">> ">>
@ -480,7 +479,7 @@ a.tw-tiddlylink-external:hover {
} }
@media print { @media print {
.sidebar-header { .sidebar-header, .tw-topbar {
display: none; display: none;
} }
@ -544,7 +543,6 @@ a.tw-tiddlylink-external:hover {
.tw-tiddler-frame { .tw-tiddler-frame {
width: 100%; width: 100%;
margin-bottom: 0;
} }
">> ">>