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:
commit
37c50bae61
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
.DS_Store
|
||||
tmp/
|
||||
output/
|
||||
|
45
boot/boot.js
45
boot/boot.js
@ -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
|
||||
|
11
core/language/en-GB/Help/build.tid
Normal file
11
core/language/en-GB/Help/build.tid
Normal 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.
|
||||
|
8
core/language/en-GB/Help/clearpassword.tid
Normal file
8
core/language/en-GB/Help/clearpassword.tid
Normal 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
|
||||
```
|
10
core/language/en-GB/Help/output.tid
Normal file
10
core/language/en-GB/Help/output.tid
Normal 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.
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/*
|
||||
|
52
core/modules/commands/build.js
Normal file
52
core/modules/commands/build.js
Normal 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;
|
||||
|
||||
})();
|
33
core/modules/commands/clearpassword.js
Normal file
33
core/modules/commands/clearpassword.js
Normal 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;
|
||||
|
||||
})();
|
38
core/modules/commands/output.js
Normal file
38
core/modules/commands/output.js
Normal 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;
|
||||
|
||||
})();
|
@ -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);
|
||||
});
|
||||
|
@ -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}});
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ module-type: filteroperator
|
||||
|
||||
Filter operator for selecting tiddlers
|
||||
|
||||
[all[tiddlers+shadows]]
|
||||
[all[shadows+tiddlers]]
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
37
core/modules/filters/is/tag.js
Normal file
37
core/modules/filters/is/tag.js
Normal 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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
268
core/modules/parsers/parseutils.js
Normal file
268
core/modules/parsers/parseutils.js
Normal 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;
|
||||
};
|
||||
|
||||
})();
|
@ -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}
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
137
core/modules/parsers/wikiparser/rules/image.js
Normal file
137
core/modules/parsers/wikiparser/rules/image.js
Normal 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;
|
||||
};
|
||||
|
||||
})();
|
@ -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");
|
||||
|
@ -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;
|
||||
};
|
||||
|
123
core/modules/widgets/image.js
Normal file
123
core/modules/widgets/image.js
Normal 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;
|
||||
|
||||
})();
|
@ -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);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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}}
|
||||
|
||||
|
@ -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]]">
|
||||
|
||||
|
@ -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]]">
|
||||
|
@ -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>
|
||||
|
@ -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>>/>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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"/>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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">>
|
||||
|
@ -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>
|
||||
|
@ -1,4 +0,0 @@
|
||||
title: $:/core/ui/TopBar/home
|
||||
tags: $:/tags/TopLeftBar
|
||||
|
||||
<$button message="tw-home" class="btn-invisible">{{$:/core/images/home-button}}</$button>
|
@ -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>
|
||||
|
@ -1,7 +1,6 @@
|
||||
title: $:/core/ui/ViewTemplate/body
|
||||
tags: $:/tags/ViewTemplate
|
||||
|
||||
\define lingo-base() $:/language/MissingTiddler/
|
||||
<div class="body">
|
||||
|
||||
<$transclude>
|
||||
|
@ -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>>>
|
||||
|
@ -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}}>•</$reveal><$reveal state="$:/palette" type="nomatch" text={{!!title}}> </$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}}>•</$reveal><$reveal state="$:/palette" type="nomatch" text={{!!title}}> </$reveal> ''<$view field="name" format="text"/>'' - <$view field="description" format="text"/></div><$transclude tiddler="$:/snippets/currpalettepreview"/></$link></div>
|
||||
</$list>
|
||||
</div>
|
||||
</$linkcatcher>
|
@ -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]]">
|
||||
|
@ -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 }
|
||||
);
|
||||
});
|
||||
|
@ -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");
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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.
|
||||
|
40
editions/tw5.com/tiddlers/Release 5.0.10beta.tid
Normal file
40
editions/tw5.com/tiddlers/Release 5.0.10beta.tid
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
7
editions/tw5.com/tiddlers/commands/BuildCommand.tid
Normal file
7
editions/tw5.com/tiddlers/commands/BuildCommand.tid
Normal file
@ -0,0 +1,7 @@
|
||||
created: 20140425085548209
|
||||
modified: 20140425085738745
|
||||
tags: command
|
||||
title: BuildCommand
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
{{$:/language/Help/build}}
|
@ -0,0 +1,4 @@
|
||||
title: ClearPasswordCommand
|
||||
tags: command
|
||||
|
||||
{{$:/language/Help/clearpassword}}
|
7
editions/tw5.com/tiddlers/commands/OutputCommand.tid
Normal file
7
editions/tw5.com/tiddlers/commands/OutputCommand.tid
Normal file
@ -0,0 +1,7 @@
|
||||
created: 20140425085548209
|
||||
modified: 20140425085738745
|
||||
tags: command
|
||||
title: OutputCommand
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
{{$:/language/Help/output}}
|
@ -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]] }}}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
45
editions/tw5.com/tiddlers/features/DateFormat.tid
Normal file
45
editions/tw5.com/tiddlers/features/DateFormat.tid
Normal 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 |
|
21
editions/tw5.com/tiddlers/features/SafeMode.tid
Normal file
21
editions/tw5.com/tiddlers/features/SafeMode.tid
Normal 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.
|
@ -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.
|
||||
|
@ -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` |
|
||||
|
||||
|
@ -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`)
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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>
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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]]
|
||||
|
20
editions/tw5.com/tiddlers/widgets/ImageWidget.tid
Normal file
20
editions/tw5.com/tiddlers/widgets/ImageWidget.tid
Normal 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 |
|
||||
|
@ -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}}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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": [
|
||||
|
@ -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};
|
||||
|
@ -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}}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
">>
|
||||
|
Loading…
Reference in New Issue
Block a user