1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-20 00:34:50 +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
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) {
var defaultVersion = {
@ -369,7 +369,8 @@ $tw.utils.checkVersions = function(versionStringA,versionStringB) {
];
return (diff[0] > 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],
src = (arg instanceof $tw.Tiddler) ? arg.fields : arg;
for(var t in src) {
if(src[t] === undefined) {
if(src[t] === undefined || src[t] === null) {
if(t in this.fields) {
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
*/
@ -1562,6 +1594,8 @@ readBrowserTiddlers: whether to read tiddlers from the HTML file we're executing
*/
$tw.boot.startup = function(options) {
options = options || {};
// Check for safe mode
$tw.safeMode = $tw.browser && location.hash === "#:safe";
// Initialise some more $tw properties
$tw.utils.deepDefaults($tw,{
modules: { // Information about each module
@ -1578,6 +1612,7 @@ $tw.boot.startup = function(options) {
wikiThemesSubDir: "./themes",
wikiLanguagesSubDir: "./languages",
wikiTiddlersSubDir: "./tiddlers",
wikiOutputSubDir: "./output",
jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)",
fileExtensionInfo: Object.create(null), // Map file extension to {type:}
contentTypeInfo: Object.create(null) // Map type to {encoding:,extension:}
@ -1645,6 +1680,10 @@ $tw.boot.startup = function(options) {
$tw.wiki.readPluginInfo();
$tw.wiki.registerPluginTiddlers("plugin");
$tw.wiki.unpackPluginTiddlers();
// Process "safe mode"
if($tw.safeMode) {
$tw.wiki.processSafeMode();
}
// Register typed modules from the tiddlers we've just loaded
$tw.wiki.defineTiddlerModules();
// 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>]
```
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
```
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>
```
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
*/
var Commander = function(commandTokens,callback,wiki,streams) {
var path = require("path");
this.commandTokens = commandTokens;
this.nextToken = 0;
this.callback = callback;
this.wiki = wiki;
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"),
path = require("path"),
title = this.params[0],
filename = this.params[1],
filename = path.resolve(this.commander.outputPath,this.params[1]),
type = this.params[2] || "text/html";
$tw.utils.createFileDirectories(filename);
fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) {
self.callback(err);
});

View File

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

View File

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

View File

@ -5,7 +5,7 @@ module-type: filteroperator
Filter operator for selecting tiddlers
[all[tiddlers+shadows]]
[all[shadows+tiddlers]]
\*/
(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 {
source(function(tiddler,title) {
if(tiddler) {
if(!tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
if(!tiddler || !tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
$tw.utils.pushTop(results,title);
}
}
});
}
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) {
this.tree = [{
type: "element",
tag: "pre",
children: [{
type: "text",
text: text
}]
tag: "$codeblock",
attributes: {
code: {type: "string", value: text},
language: {type: "string", value: type}
}
}];
};

View File

@ -48,7 +48,7 @@ exports.parse = function() {
// Advance the parser position to past the tag
this.parser.pos = tag.end;
// 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
tag.isBlock = this.is.block || hasLineBreak;
// 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:,}
*/
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:,}
Look for an HTML tag. Returns null if not found, otherwise returns {type: "element", name:, attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseTag = function(source,pos,options) {
options = options || {};
@ -321,45 +84,45 @@ exports.parseTag = function(source,pos,options) {
// Define our regexps
var reTagName = /([a-zA-Z0-9\-\$]+)/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a less than sign
token = this.parseTokenString(source,pos,"<");
token = $tw.utils.parseTokenString(source,pos,"<");
if(!token) {
return null;
}
pos = token.end;
// Get the tag name
token = this.parseTokenRegExp(source,pos,reTagName);
token = $tw.utils.parseTokenRegExp(source,pos,reTagName);
if(!token) {
return null;
}
node.tag = token.match[1];
pos = token.end;
// Process attributes
var attribute = this.parseAttribute(source,pos);
var attribute = $tw.utils.parseAttribute(source,pos);
while(attribute) {
node.attributes[attribute.name] = attribute;
pos = attribute.end;
// Get the next attribute
attribute = this.parseAttribute(source,pos);
attribute = $tw.utils.parseAttribute(source,pos);
}
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a closing slash
token = this.parseTokenString(source,pos,"/");
token = $tw.utils.parseTokenString(source,pos,"/");
if(token) {
pos = token.end;
node.isSelfClosing = true;
}
// Look for a greater than sign
token = this.parseTokenString(source,pos,">");
token = $tw.utils.parseTokenString(source,pos,">");
if(!token) {
return null;
}
pos = token.end;
// Check for a required line break
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) {
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");
if(messageBox) {
// Get the pathname of this document
var pathname = document.location.pathname;
// Test for a Windows path of the form /x:/blah/blah
if(/^\/[A-Z]\:\//i.test(pathname)) {
// Remove the leading slash
pathname = pathname.substr(1);
// Convert slashes to backslashes
pathname = pathname.replace(/\//g,"\\");
var pathname = document.location.toString();
// Replace file://localhost/ with file:///
if(pathname.indexOf("file://localhost/") == 0) {
pathname = "file://" + pathname.substr(16);
}
// Windows path file:///x:/blah/blah --> x:\blah\blah
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
var message = document.createElement("div");

View File

@ -87,9 +87,13 @@ exports.removeTrailingSeparator = function(dirPath) {
Recursively create a directory
*/
exports.createDirectory = function(dirPath) {
var parts = dirPath.split(path.sep);
for(var component=0; component<parts.length; component++) {
var subDirPath = parts.slice(0,component+1).join(path.sep);
if(dirPath.substr(dirPath.length-1,1) !== path.sep) {
dirPath = dirPath + 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)) {
try {
fs.mkdirSync(subDirPath);
@ -97,6 +101,33 @@ exports.createDirectory = function(dirPath) {
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;
};

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] || "";
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(typeof a === "string") {
a = a.toLowerCase();
}
if(typeof b === "string") {
b = b.toLowerCase();
}
}
}
else {
a-= 0;
b-= 0;
}
if(a < b) {
return isDescending ? +1 : -1;
} else {
if(a > b) {
return isDescending ? -1 : +1;
} else {
return 0;
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
}
});
};

View File

@ -1,5 +1,5 @@
title: $:/AdvancedSearch
<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>

View File

@ -12,7 +12,7 @@ caption: {{$:/language/Search/Filter/Caption}}
<div class="tw-block-dropdown-wrapper">
<$reveal state=<<qualify "$:/state/filterDropdown">> type="nomatch" text="" default="">
<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>
</div>
</$reveal>

View File

@ -1,5 +1,5 @@
title: $:/ControlPanel
<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>

View File

@ -5,5 +5,5 @@ caption: {{$:/language/ControlPanel/Advanced/Caption}}
{{$:/language/ControlPanel/Advanced/Hint}}
<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>

View File

@ -5,5 +5,5 @@ caption: {{$:/language/ControlPanel/Appearance/Caption}}
{{$:/language/ControlPanel/Appearance/Hint}}
<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>

View File

@ -6,7 +6,7 @@ tw-tiddler-frame tw-tiddler-edit-frame $(missingTiddlerClass)$ $(shadowTiddlerCl
<div class=<<frame-classes>>>
<$set name="storyTiddler" value=<<currentTiddler>>>
<$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>>/>
</$list>
</$keyboard>

View File

@ -1,4 +1,4 @@
title: $:/core/ui/EditTemplate/controls
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="">
<div class="tw-block-dropdown tw-edit-type-dropdown">
<$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>
</$linkcatcher>
</div>

View File

@ -1,5 +1,5 @@
title: $:/core/Filters/SystemTags
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}}

View File

@ -3,7 +3,7 @@ tags: $:/tags/MoreSideBar
caption: {{$:/language/SideBar/Tags/Caption}}
\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]]">

View File

@ -2,7 +2,7 @@ title: $:/core/ui/MoreSideBar/Types
tags: $:/tags/MoreSideBar
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">
<$view field="type"/>
<$list filter="[type{!!type}!is[system]sort[title]]">

View File

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

View File

@ -16,7 +16,7 @@ tw-page-container tw-page-view-$(themeTitle)$ tw-language-$(languageTitle)$
<$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>>/>

View File

@ -3,6 +3,6 @@ tags: $:/tags/PageTemplate
<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>

View File

@ -21,7 +21,7 @@ tags: $:/tags/PageTemplate
<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"/>

View File

@ -3,6 +3,10 @@ tags: $:/tags/PageTemplate
<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>

View File

@ -3,6 +3,10 @@ tags: $:/tags/PageTemplate
<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>

View File

@ -3,5 +3,5 @@ tags: $:/tags/SideBar
caption: {{$:/language/SideBar/More/Caption}}
<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>

View File

@ -18,6 +18,6 @@ title: $:/core/ui/SideBarLists
</div>
</$reveal>
<$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>
</div>

View File

@ -7,7 +7,7 @@ title: $:/TagManager
<$reveal state=<<qualify "$:/state/iconDropdown/$title$">> type="nomatch" text="" default="">
<$linkcatcher to="$title$!!icon">
<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}}>
<$view field="title"/>
</$link>

View File

@ -1,3 +1,3 @@
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
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>>/>
</$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()
tw-tiddler-frame tw-tiddler-view-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$
\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>
</$tiddler></$set></$set>

View File

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

View File

@ -7,7 +7,7 @@ fill:$(foregroundColor)$;
<div class="tw-tiddler-title">
<div class="titlebar">
<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>
<$set name="foregroundColor" value={{!!color}}>
<span style=<<title-styles>>>

View File

@ -4,7 +4,7 @@ title: $:/snippets/paletteswitcher
<<lingo Prompt>> <$view tiddler={{$:/palette}} field="name"/>
<$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>
</div>
</$linkcatcher>

View File

@ -1,6 +1,6 @@
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">
<$view field="modified" format="date" template={{$:/language/RecentChanges/DateFormat}}/>
<$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();
it("should parse whitespace", function() {
expect(parser.parseWhiteSpace("p ",0)).toEqual(
expect($tw.utils.parseWhiteSpace("p ",0)).toEqual(
null
);
expect(parser.parseWhiteSpace("p ",1)).toEqual(
expect($tw.utils.parseWhiteSpace("p ",1)).toEqual(
{ type : 'whitespace', start : 1, end : 3 }
);
});
it("should parse string tokens", function() {
expect(parser.parseTokenString("p= ",0,"=")).toEqual(
expect($tw.utils.parseTokenString("p= ",0,"=")).toEqual(
null
);
expect(parser.parseTokenString("p= ",1,"=")).toEqual(
expect($tw.utils.parseTokenString("p= ",1,"=")).toEqual(
{ type : 'token', value : '=', start : 1, end : 2 }
);
});
it("should parse regexp tokens", function() {
expect(parser.parseTokenRegExp("p=' ",0,/(=(?:'|"))/)).toEqual(
expect($tw.utils.parseTokenRegExp("p=' ",0,/(=(?:'|"))/)).toEqual(
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'
);
});
it("should parse string literals", function() {
expect(parser.parseStringLiteral("p='blah' ",0)).toEqual(
expect($tw.utils.parseStringLiteral("p='blah' ",0)).toEqual(
null
);
expect(parser.parseStringLiteral("p='blah' ",2)).toEqual(
expect($tw.utils.parseStringLiteral("p='blah' ",2)).toEqual(
{ 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 }
);
expect(parser.parseStringLiteral("p=\"blah' ",2)).toEqual(
expect($tw.utils.parseStringLiteral("p=\"blah' ",2)).toEqual(
null
);
expect(parser.parseStringLiteral("p=\"\" ",2)).toEqual(
expect($tw.utils.parseStringLiteral("p=\"\" ",2)).toEqual(
{ type : 'string', start : 2, value : '', end : 4 }
);
});
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 }
);
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 }
);
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 }
);
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 }
);
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 }
);
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 }
);
expect(parser.parseMacroParameter("myparam>",0)).toEqual(
expect($tw.utils.parseMacroParameter("myparam>",0)).toEqual(
{ type : 'macro-parameter', start : 0, value : 'myparam', end : 7 }
);
});
it("should parse macro invocations", function() {
expect(parser.parseMacroInvocation("<<mymacro",0)).toEqual(
expect($tw.utils.parseMacroInvocation("<<mymacro",0)).toEqual(
null
);
expect(parser.parseMacroInvocation("<<mymacro>>",0)).toEqual(
expect($tw.utils.parseMacroInvocation("<<mymacro>>",0)).toEqual(
{ 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 }
);
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 }
);
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 }
);
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 }
);
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 }
);
});
it("should parse HTML attributes", function() {
expect(parser.parseAttribute("p='blah' ",1)).toEqual(
expect($tw.utils.parseAttribute("p='blah' ",1)).toEqual(
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 }
);
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 }
);
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 }
);
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 }
);
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 }
);
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 }
);
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 }
);
expect(parser.parseAttribute(" attrib1>",0)).toEqual(
expect($tw.utils.parseAttribute(" attrib1>",0)).toEqual(
{ type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 }
);
});

View File

@ -83,7 +83,7 @@ describe("Tag tests", function() {
// Our tests
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:
```
[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.

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
title: Release 5.0.9-beta
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]]//
!! 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]]
* Initial implementation of CecilyView
* 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
* Improved and reorganised documentation for TiddlerFilters
* Demo of [[Making curved text with SVG]]
* [[Community]] links are now broken up into individual tiddlers
* [[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]]
* [[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
* [[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
@ -36,8 +41,7 @@ type: text/vnd.tiddlywiki
!! 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
* [[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
reapoints/index.html#regular]] in Chrome
* [[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
* 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
* [[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
* [[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]]
* [[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
* [[Add|https://github.com/Jermolene/TiddlyWiki5/commit/a5a2c718b1d5671652d01e3567dba1c6795b7521]] support for a tooltip on the LinkWidget

View File

@ -1,11 +1,17 @@
created: 20131202102427114
modified: 20140126135354379
modified: 20140419133900452
tags: howto
title: Upgrading
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]].
<<<
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">
<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
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:
{{{ [all[tiddlers+shadows]tags[]prefix[$:/]] +[sort[title]] }}}
{{{ [all[shadows+tiddlers]tags[]prefix[$:/]] +[sort[title]] }}}

View File

@ -1,43 +1,44 @@
created: 20130825213300000
modified: 20131212095204933
modified: 20140419151511111
tags: concepts
title: TiddlerFields
type: text/vnd.tiddlywiki
\define lingo-base() $:/language/Docs/Fields/
TiddlerFields are name:value pairs that make up a [[tiddler|Tiddlers]]. Field names must be lowercase letters, digits or the characters `-` (dash), `_` (underscore) and `.` (period).
The standard fields are:
|!Field Name |!Reference |!Description |
|`title` |TitleField |{{$:/docs/fields/title}} |
|`text` |TextField |{{$:/docs/fields/text}} |
|`modified` |ModifiedField |{{$:/docs/fields/modified}} |
|`modifier` |ModifierField |{{$:/docs/fields/modifier}} |
|`created` |CreatedField |{{$:/docs/fields/created}} |
|`creator` |CreatorField |{{$:/docs/fields/creator}} |
|`tags` |TagsField |{{$:/docs/fields/tags}} |
|`type` |TypeField |{{$:/docs/fields/type}} |
|`list` |ListField |{{$:/docs/fields/list}} |
|`title` |TitleField |<<lingo title>> |
|`text` |TextField |<<lingo text>> |
|`modified` |ModifiedField |<<lingo modified>> |
|`modifier` |ModifierField |<<lingo modifier>> |
|`created` |CreatedField |<<lingo created>> |
|`creator` |CreatorField |<<lingo creator>> |
|`tags` |TagsField |<<lingo tags>> |
|`type` |TypeField |<<lingo type>> |
|`list` |ListField |<<lingo list>> |
Other fields used by the core are:
|!Field Name |!Reference |!Description |
|`color` |ColorField |{{$:/docs/fields/color}} |
|`description` |DescriptionField |{{$:/docs/fields/description}} |
|`draft.of` |DraftOfField |{{$:/docs/fields/draft.of}} |
|`draft.title` |DraftTitleField |{{$:/docs/fields/draft.title}} |
|`footer` |FooterField |{{$:/docs/fields/footer}} |
|`library` |LibraryField |{{$:/docs/fields/library}} |
|`name` |NameField |{{$:/docs/fields/name}} |
|`plugin-priority` |PluginPriorityField |{{$:/docs/fields/plugin-priority}} |
|`plugin-type` |PluginTypeField |{{$:/docs/fields/plugin-type}} |
|`source` |SourceField |{{$:/docs/fields/source}} |
|`subtitle` |SubtitleField |{{$:/docs/fields/subtitle}} |
|`color` |ColorField |<<lingo color>> |
|`description` |DescriptionField |<<lingo description>> |
|`draft.of` |DraftOfField |<<lingo draft.of>> |
|`draft.title` |DraftTitleField |<<lingo draft.title>> |
|`footer` |FooterField |<<lingo footer>> |
|`library` |LibraryField |<<lingo library>> |
|`name` |NameField |<<lingo name>> |
|`plugin-priority` |PluginPriorityField |<<lingo plugin-priority>> |
|`plugin-type` |PluginTypeField |<<lingo plugin-type>> |
|`source` |SourceField |<<lingo source>> |
|`subtitle` |SubtitleField |<<lingo subtitle>> |
The TiddlyWebAdaptor uses a few more fields:
|!Field Name |!Reference |!Description |
|`bag` |BagField |{{$:/docs/fields/bag}} |
|`revision` |RevisionField |{{$:/docs/fields/revision}} |
|`bag` |BagField |<<lingo bag>> |
|`revision` |RevisionField |<<lingo revision>> |
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
* ''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
* ''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)
Configuration options include:
@ -41,6 +42,13 @@ For example:
"includeWikis": [
"../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": {
"retain-original-tiddler-path": true
}

View File

@ -1,5 +1,5 @@
created: 20131211222303769
modified: 20140120130146763
modified: 20140424130146763
tags: dev
title: JavaScript Macros
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
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
modified: 20140410103123179
modified: 20140418103123179
tags: filters commonfilters
title: FilterOperator: is
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[system]]` - tiddlers that are SystemTiddlers
* `[is[tiddler]]` - tiddlers that are not MissingTiddlers
* `[is[tag]]` - tiddlers that are being used as tags
For example:
@ -20,6 +21,8 @@ For example:
|`[tag[task]is[shadow]]` |Returns ShadowTiddlers 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 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) |
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 |
|`[tag[mytag]]` |Returns all tiddlers 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]!tag[exclude]]` |Returns all tiddlers tagged `mytag` that are not tagged `mytag` |

View File

@ -1,5 +1,5 @@
created: 20140213122133816
modified: 20140214124024493
created: 2014013122133816
modified: 20140415114024493
tags: howto
title: How to create plugins in the browser
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
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 payload tiddlers that are to be packed into the plugin (eg `$:/plugins/yourname/pluginname/mywidget.js`)

View File

@ -1,12 +1,12 @@
created: 20140305091244145
modified: 20140305091258135
modified: 20140425121258135
tags: howto
title: Using Stylesheets
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]].
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 {

View File

@ -1,5 +1,5 @@
created: 20130823203800000
modified: 20140226202503234
modified: 20140419081726794
tags: planning
title: RoadMap
type: text/vnd.tiddlywiki
@ -18,15 +18,12 @@ The following additional features are planned or under consideration for impleme
** Improve upgrade process
** Establish plugin library
** 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
** ~TiddlyWiki file format (to avoid illegal attribute names)
** Tiddler object format (to provide true polymorphism of field values)
* Perfecting WikiText
** 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
* Productivity features
** 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
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
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
modified: 20140406210649764
modified: 20140424113815434
tags: tips
title: Editing Tiddlers with Emacs
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.
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")))))
```
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.

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
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
* 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
modified: 20131205160234142
modified: 20140416160234142
tags: wikitext
title: Images in WikiText
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}}
@ -13,3 +47,4 @@ To display an image stored in a tiddler just transclude that tiddler:
Renders as:
{{Motovun Jack.jpg}}

View File

@ -26,8 +26,30 @@
"zh-Hant",
"it-IT",
"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": {
"retain-original-tiddler-path": true
}

View File

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

View File

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

View File

@ -33,6 +33,18 @@ function transformNode(node) {
});
}
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;
} else {
return {type: "text", text: node};

View File

@ -1,6 +1,6 @@
title: $:/editions/clientserver/download-offline
\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
{{$:/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}}) {
<<if-sidebar "
/* Drop the tiddler frame padding */
body.tw-body .tw-tiddler-frame {
padding: 0;
}
">>
/* Move the sidebar up so that the title lines up */
body.tw-body .tw-sidebar-scrollable {
padding: 43px 0 28px 42px;

View File

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