1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-06-26 07:13:15 +00:00

Major reorganisation of wikitext rendering

Getting ready to support selective refresh of DOM elements
This commit is contained in:
Jeremy Ruston 2012-01-24 16:26:37 +00:00
parent 870529f76b
commit 398831b0d9
13 changed files with 286 additions and 104 deletions

View File

@ -9,6 +9,17 @@ Compiles bitmap images into JavaScript functions that render them in HTML
/*jslint node: true */
"use strict";
var utils = require("./Utils.js");
var BitmapRenderer = function(handlerCode) {
/*jslint evil: true */
this.handler = eval(handlerCode);
};
BitmapRenderer.prototype.render = function(tiddler,store) {
return this.handler(tiddler,store,utils);
};
// The parse tree is degenerate
var BitmapParseTree = function() {
this.dependencies = [];
@ -16,7 +27,7 @@ var BitmapParseTree = function() {
BitmapParseTree.prototype.compile = function(type) {
if(type === "text/html") {
return "(function (tiddler,store,utils) {return '<img src=\"data:' + tiddler.type + ';base64,' + tiddler.text + '\">';})";
return new BitmapRenderer("(function (tiddler,store,utils) {return '<img src=\"data:' + tiddler.type + ';base64,' + tiddler.text + '\">';})");
} else {
return null;
}

View File

@ -28,7 +28,11 @@ var JavaScriptParseTree = function(tree) {
// Render the entire JavaScript tree object to JavaScript source code
JavaScriptParseTree.prototype.render = function() {
var output = [];
this.renderSubTree(output,this.tree);
if(this.tree instanceof Array) {
this.renderSubTree(output,this.tree);
} else {
this.renderNode(output,this.tree);
}
var r = output.join("");
return r;
};

View File

@ -9,6 +9,17 @@ Compiles SVG images into JavaScript functions that render them in HTML
/*jslint node: true */
"use strict";
var utils = require("./Utils.js");
var SVGRenderer = function(handlerCode) {
/*jslint evil: true */
this.handler = eval(handlerCode);
};
SVGRenderer.prototype.render = function(tiddler,store) {
return this.handler(tiddler,store,utils);
};
// The parse tree is degenerate
var SVGParseTree = function() {
this.dependencies = [];
@ -16,7 +27,7 @@ var SVGParseTree = function() {
SVGParseTree.prototype.compile = function(type) {
if(type === "text/html") {
return "(function (tiddler,store,utils) {return '<img src=\"data:' + tiddler.type + ',' + encodeURIComponent(tiddler.text) + '\">';})";
return new SVGRenderer("(function (tiddler,store,utils) {return '<img src=\"data:' + tiddler.type + ',' + encodeURIComponent(tiddler.text) + '\">';})");
} else {
return null;
}

View File

@ -301,30 +301,25 @@ WikiStore.prototype.parseTiddler = function(title) {
};
/*
Compiles a block of text of a specified type into a JavaScript function that renders the text in a particular MIME type
Compiles a block of text of a specified type into a renderer that renders the text in a particular MIME type
*/
WikiStore.prototype.compileText = function(type,text,targetType) {
/*jslint evil: true */
var tree = this.parseText(type,text);
return eval(tree.compile(targetType));
return tree.compile(targetType);
};
/*
Compiles a JavaScript function that renders a tiddler in a particular MIME type
*/
WikiStore.prototype.compileTiddler = function(title,type) {
/*jslint evil: true */
var tiddler = this.getTiddler(title),
renderers = this.getCacheForTiddler(title,"renderers",function() {
return {};
});
if(tiddler) {
if(!renderers[type]) {
var tree = this.parseTiddler(title),
text = tree.compile(type);
// Add a source URL to help debugging (see http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/)
text += "//@ sourceURL=" + encodeURIComponent(title) + "-" + type;
renderers[type] = eval(text);
var tree = this.parseTiddler(title);
renderers[type] = tree.compile(type);
}
return renderers[type];
} else {
@ -337,8 +332,8 @@ Render a block of text of a specified type into a particular MIME type
*/
WikiStore.prototype.renderText = function(type,text,targetType,asTitle) {
var tiddler = this.getTiddler(asTitle),
fn = this.compileText(type,text,targetType);
return fn(tiddler,this,utils);
renderer = this.compileText(type,text,targetType);
return renderer.render(tiddler,this);
};
/*
@ -348,17 +343,17 @@ store.renderTiddler("text/html",templateTitle,tiddlerTitle)
*/
WikiStore.prototype.renderTiddler = function(targetType,title,asTitle) {
var tiddler = this.getTiddler(title),
fn = this.compileTiddler(title,targetType),
renderer = this.compileTiddler(title,targetType),
renditions = this.getCacheForTiddler(title,"renditions",function() {
return {};
});
if(tiddler) {
if(asTitle) {
var asTiddler = this.getTiddler(asTitle);
return fn(asTiddler,this,utils);
return renderer.render(asTiddler,this);
} else {
if(!renditions[targetType]) {
renditions[targetType] = fn(tiddler,this,utils);
renditions[targetType] = renderer.render(tiddler,this);
}
return renditions[targetType];
}

View File

@ -9,7 +9,8 @@ A container for the parse tree generated by parsing wikitext
/*jslint node: true */
"use strict";
var ArgParser = require("./ArgParser.js").ArgParser,
var WikiTextRenderer = require("./WikiTextRenderer.js").WikiTextRenderer,
ArgParser = require("./ArgParser.js").ArgParser,
utils = require("./Utils.js");
// Intialise the parse tree object
@ -22,22 +23,26 @@ var WikiTextParseTree = function(tree,dependencies,store) {
// Compile the parse tree into a JavaScript function that returns the required
// representation of the tree
WikiTextParseTree.prototype.compile = function(type,treenode) {
/*jslint evil: true */
treenode = treenode || this.tree;
var output = [];
var renderer = new WikiTextRenderer(),
renderStep = {},
renderStepIndex = renderer.addRenderStep(renderStep),
output = [];
if(type === "text/html") {
this.compileSubTreeHtml(output,treenode);
this.compileSubTreeHtml(output,renderer,treenode);
} else if(type === "text/plain") {
this.compileSubTreePlain(output,treenode);
this.compileSubTreePlain(output,renderer,treenode);
} else {
return null;
}
// And then wrap the javascript tree and render it back into JavaScript code
// Create the parse tree for the rendering step function definition
var parseTree = this.store.jsParser.createTree(
[
{
type: "Function",
name: null,
params: ["tiddler","store","utils"], // These are the parameters passed to the tiddler function; must match the invocation in WikiStore.renderTiddler()
params: ["tiddler","renderer","store","utils"], // These are the parameters passed to the tiddler function; must match the invocation in WikiStore.renderTiddler()
elements: [
{
type: "ReturnStatement",
@ -61,11 +66,13 @@ WikiTextParseTree.prototype.compile = function(type,treenode) {
]
}
]);
var r = parseTree.render();
return r;
renderStep.step = renderStepIndex;
renderStep.dependencies = [];
renderStep.handler = eval(parseTree.render());
return renderer;
};
WikiTextParseTree.prototype.pushString = function(output,s) {
var pushString = function(output,s) {
var last = output[output.length-1];
if(output.length > 0 && last.type === "StringLiterals") {
last.value.push(s);
@ -77,66 +84,80 @@ WikiTextParseTree.prototype.pushString = function(output,s) {
}
};
WikiTextParseTree.prototype.compileMacroCall = function(output,type,node) {
WikiTextParseTree.prototype.compileMacroCall = function(output,renderer,type,node) {
/*jslint evil: true */
var name = node.name,
params = node.params,
macro = this.store.macros[name],
p,
n;
n,
renderStep = {},
renderStepIndex = renderer.addRenderStep(renderStep);
// Check for errors
if(!macro) {
this.pushString(output,"{{** Unknown macro '" + name + "' **}}");
pushString(output,"{{** Unknown macro '" + name + "' **}}");
return;
}
if(macro.types.indexOf(type) === -1) {
this.pushString(output,"{{** Macro '" + name + "' cannot render to MIME type '" + type + "'**}}");
pushString(output,"{{** Macro '" + name + "' cannot render to MIME type '" + type + "'**}}");
return;
}
// Compose the macro call as a render function
var macroCall = {
type: "FunctionCall",
name: {
base: {
base: {
base: {
name: "store",
type: "Variable"},
name: "macros",
type: "PropertyAccess"},
type: "Function",
name: null,
params: ["tiddler","renderer","store","utils"], // These are the parameters passed to the tiddler function; must match the invocation in WikiStore.renderTiddler()
elements: [ {
type: "ReturnStatement",
value: {
type: "FunctionCall",
name: {
base: {
base: {
base: {
name: "store",
type: "Variable"},
name: "macros",
type: "PropertyAccess"},
name: {
type: "StringLiteral",
value: name},
type: "PropertyAccess"},
name: "handler",
type: "PropertyAccess"},
"arguments": [ {
type: "StringLiteral",
value: name},
type: "PropertyAccess"},
name: "handler",
type: "PropertyAccess"},
"arguments": [ {
type: "StringLiteral",
value: type
},{
type: "Variable",
name: "tiddler"
},{
type: "Variable",
name: "store"
},{
type: "ObjectLiteral",
properties: []
}]
value: type
},{
type: "Variable",
name: "tiddler"
},{
type: "Variable",
name: "store"
},{
type: "ObjectLiteral",
properties: []
}]
}}]
};
// Slot the parameters into the macro call
for(p in params) {
if(params[p].type === "string") {
n = {type: "StringLiteral", value: params[p].value};
} else {
n = this.store.jsParser.parse(params[p].value).tree.elements[0];
}
macroCall["arguments"][3].properties.push({
macroCall.elements[0].value["arguments"][3].properties.push({
type: "PropertyAssignment",
name: p,
value: n
});
}
// Compile any child nodes
if(node.children) {
var subOutput = [];
this.compileSubTreeHtml(subOutput,node.children);
macroCall["arguments"].push({
this.compileSubTreeHtml(subOutput,renderer,node.children);
macroCall.elements[0].value["arguments"].push({
type: "FunctionCall",
name: {
type: "PropertyAccess",
@ -152,86 +173,108 @@ WikiTextParseTree.prototype.compileMacroCall = function(output,type,node) {
}]
});
}
renderStep.step = renderStepIndex;
renderStep.dependencies = node.dependencies;
renderStep.handler = eval(this.store.jsParser.createTree(macroCall).render());
var wrapperTag = macro.wrapperTag || "div";
if(type === "text/html") {
this.pushString(output,utils.stitchElement(wrapperTag,{
"data-tw-macro": name
pushString(output,utils.stitchElement(wrapperTag,{
"data-tw-macro": name,
"data-tw-render-step": renderStepIndex
}));
}
output.push(macroCall);
output.push({
type: "FunctionCall",
name: {
base: {
name: "renderer",
type: "Variable"},
name: "render",
type: "PropertyAccess"},
"arguments": [ {
type: "Variable",
name: "tiddler"
},{
type: "Variable",
name: "store"
},{
type: "NumericLiteral",
value: renderStepIndex
}]
});
if(type === "text/html") {
this.pushString(output,"</" + wrapperTag + ">");
pushString(output,"</" + wrapperTag + ">");
}
};
WikiTextParseTree.prototype.compileElementHtml = function(output,element,options) {
WikiTextParseTree.prototype.compileElementHtml = function(output,renderer,element,options) {
options = options || {};
this.pushString(output,utils.stitchElement(element.type,element.attributes,{
pushString(output,utils.stitchElement(element.type,element.attributes,{
selfClosing: options.selfClosing
}));
if(!options.selfClosing) {
if(element.children) {
this.compileSubTreeHtml(output,element.children);
this.compileSubTreeHtml(output,renderer,element.children);
}
this.pushString(output,"</" + element.type + ">");
pushString(output,"</" + element.type + ">");
}
};
WikiTextParseTree.prototype.compileSubTreeHtml = function(output,tree) {
WikiTextParseTree.prototype.compileSubTreeHtml = function(output,renderer,tree) {
for(var t=0; t<tree.length; t++) {
switch(tree[t].type) {
case "text":
this.pushString(output,utils.htmlEncode(tree[t].value));
pushString(output,utils.htmlEncode(tree[t].value));
break;
case "entity":
this.pushString(output,tree[t].value);
pushString(output,tree[t].value);
break;
case "br":
case "img":
this.compileElementHtml(output,tree[t],{selfClosing: true}); // Self closing elements
this.compileElementHtml(output,renderer,tree[t],{selfClosing: true}); // Self closing elements
break;
case "macro":
this.compileMacroCall(output,"text/html",tree[t]);
this.compileMacroCall(output,renderer,"text/html",tree[t]);
break;
default:
this.compileElementHtml(output,tree[t]);
this.compileElementHtml(output,renderer,tree[t]);
break;
}
}
};
WikiTextParseTree.prototype.compileElementPlain = function(output,element, options) {
WikiTextParseTree.prototype.compileElementPlain = function(output,renderer,element,options) {
options = options || {};
if(!options.selfClosing) {
if(element.children) {
this.compileSubTreePlain(output,element.children);
this.compileSubTreePlain(output,renderer,element.children);
}
}
};
WikiTextParseTree.prototype.compileSubTreePlain = function(output,tree) {
WikiTextParseTree.prototype.compileSubTreePlain = function(output,renderer,tree) {
for(var t=0; t<tree.length; t++) {
switch(tree[t].type) {
case "text":
this.pushString(output,tree[t].value);
pushString(output,tree[t].value);
break;
case "entity":
var c = utils.entityDecode(tree[t].value);
if(c) {
this.pushString(output,c);
pushString(output,c);
} else {
this.pushString(output,tree[t].value);
pushString(output,tree[t].value);
}
break;
case "br":
case "img":
this.compileElementPlain(output,tree[t],{selfClosing: true}); // Self closing elements
this.compileElementPlain(output,renderer,tree[t],{selfClosing: true}); // Self closing elements
break;
case "macro":
this.compileMacroCall(output,"text/plain",tree[t]);
this.compileMacroCall(output,renderer,"text/plain",tree[t]);
break;
default:
this.compileElementPlain(output,tree[t]);
this.compileElementPlain(output,renderer,tree[t]);
break;
}
}
@ -286,6 +329,17 @@ WikiTextParseTree.prototype.toString = function(type) {
}));
output.push("</span>");
}
output.push(utils.stitchElement("span",null,
{classNames: ["treeNode","splitLabel"]}));
output.push(utils.stitchElement("span",{"data-tw-treenode-type": "renderStepDependencies"},{
content: "dependencies",
classNames: ["splitLabelLeft"]
}));
output.push(utils.stitchElement("span",null,{
content: utils.htmlEncode(node.dependencies === null ? "*" : node.dependencies.join(", ")),
classNames: ["splitLabelRight"]
}));
output.push("</span>");
if(node.children) {
utils.renderObject(output,type,node.children,customTemplates);
}

View File

@ -83,6 +83,18 @@ WikiTextParser.prototype.addDependency = function(dependency) {
}
};
WikiTextParser.prototype.addDependencies = function(dependencies) {
if(dependencies === null) {
this.dependencies = null;
} else if(this.dependencies !== null){
for(var t=0; t<dependencies.length; t++) {
if(this.dependencies.indexOf(dependencies[t]) === -1) {
this.dependencies.push(dependencies[t]);
}
}
}
};
WikiTextParser.prototype.outputText = function(place,startPos,endPos) {
if(startPos < endPos) {
place.push({type: "text", value: this.source.substring(startPos,endPos)});

79
js/WikiTextRenderer.js Normal file
View File

@ -0,0 +1,79 @@
/*\
title: js/WikiTextRenderer.js
An array of JavaScript functions that generate a specified representation of a parse tree
\*/
(function(){
/*jslint node: true */
"use strict";
var utils = require("./Utils.js");
var WikiTextRenderer = function() {
this.renderSteps = []; // Array of {step: n, dependencies: [],handler: function(tiddler,renderer,store,utils) {}}
};
WikiTextRenderer.prototype.addRenderStep = function(renderStep) {
this.renderSteps.push(renderStep);
return this.renderSteps.length - 1;
};
WikiTextRenderer.prototype.render = function(tiddler,store,renderStep) {
renderStep = renderStep || 0;
if(renderStep < this.renderSteps.length) {
return this.renderSteps[renderStep].handler(tiddler,this,store,utils);
} else {
return null;
}
};
WikiTextRenderer.prototype.refreshDom = function(node,tiddler,store) {
};
WikiTextRenderer.prototype.toString = function(type) {
var output = [],
customTemplates = [
function(output,type,node) { // Rendering step
if(node.step !== undefined) {
output.push(utils.stitchElement("span",
{"data-tw-treenode-type": "renderStep"},{
content: node.step.toString(),
classNames: ["treeNode","label"]
}));
output.push(utils.stitchElement("span",null,
{classNames: ["treeNode","splitLabel"]}));
output.push(utils.stitchElement("span",{"data-tw-treenode-type": "renderStepDependencies"},{
content: "dependencies",
classNames: ["splitLabelLeft"]
}));
output.push(utils.stitchElement("span",null,{
content: utils.htmlEncode(node.dependencies === null ? "*" : node.dependencies.join(", ")),
classNames: ["splitLabelRight"]
}));
output.push("</span>");
output.push(utils.stitchElement("span",null,
{classNames: ["treeNode","splitLabel"]}));
output.push(utils.stitchElement("span",{"data-tw-treenode-type": "renderStepHandler"},{
content: "handler",
classNames: ["splitLabelLeft"]
}));
output.push(utils.stitchElement("code",null,{
content: utils.htmlEncode(node.handler.toString()).replace(/\n/g,"<br>"),
classNames: ["splitLabelRight"]
}));
output.push("</span>");
return true;
}
return false;
}
];
utils.renderObject(output,type,this.renderSteps,customTemplates);
return output.join("");
};
exports.WikiTextRenderer = WikiTextRenderer;
})();

View File

@ -105,24 +105,29 @@ var enclosedTextHelper = function(w) {
var parseMacroCall = function(w,name,paramString) {
var macro = w.store.macros[name],
params = {};
params = {},
dependencies = [];
if(macro) {
if(macro.dependentAll) {
w.addDependency(null);
dependencies = null;
}
var args = new ArgParser(paramString,{defaultName: "anon"}),
insertParam = function(param,name,arg) {
if(param.dependentAll) {
dependencies = null;
}
if(param.type === "tiddler") {
w.addDependency(arg.evaluated ? null : arg.string);
if(arg.evaluated) {
dependencies = null;
} else if(dependencies !== null) {
dependencies.push(arg.string);
}
}
params[name] = {type: arg.evaluated ? "eval" : "string", value: arg.string};
};
for(var m in macro.params) {
var param = macro.params[m],
arg;
if(param.dependentAll) {
w.addDependency(null);
}
if("byPos" in param && args.byPos[param.byPos]) {
arg = args.byPos[param.byPos].v;
insertParam(param,m,arg);
@ -137,7 +142,8 @@ var parseMacroCall = function(w,name,paramString) {
}
}
}
return {type: "macro", name: name, params: params};
w.addDependencies(dependencies);
return {type: "macro", name: name, params: params, dependencies: dependencies};
};
var rules = [
@ -467,16 +473,19 @@ var rules = [
children: [{
type: "text",
value: ""
}]},
}],
dependencies: []},
text = lookaheadMatch[1];
if(lookaheadMatch[3]) {
// Pretty bracketted link
var link = lookaheadMatch[3];
e.params.target.value = link;
e.dependencies.push(link);
w.addDependency(link);
} else {
// Simple bracketted link
e.params.target.value = text;
e.dependencies.push(text);
w.addDependency(text);
}
e.children[0].value = text;
@ -511,7 +520,10 @@ var rules = [
children: [{
type: "text",
value: w.source.substring(w.matchStart,w.nextMatch)
}]};
}],
dependencies: [
w.matchText
]};
w.addDependency(w.matchText);
w.output.push(link);
} else {
@ -531,7 +543,10 @@ var rules = [
children: [{
type: "text",
value: w.source.substring(w.matchStart,w.nextMatch)
}]};
}],
dependencies: [
w.matchText
]};
w.addDependency(w.matchText);
w.output.push(e);
}
@ -562,8 +577,10 @@ var rules = [
image.params.text = {type: "string", value: lookaheadMatch[3]};
}
image.params.src.value = lookaheadMatch[4];
image.dependencies = [lookaheadMatch[4]];
if(lookaheadMatch[5]) {
link.params.target.value = lookaheadMatch[5];
link.dependencies = [lookaheadMatch[5]];
w.output.push(link);
} else {
w.output.push(image);

View File

@ -25,9 +25,7 @@ exports.macro = {
return "Parse tree: " + parseTree.toString(type);
//break;
case "compiled":
return "Compiled as: " + utils.stitchElement("pre",null,{
content: encoder(parseTree.compile(type))
});
return "Compiled as: " + parseTree.compile(type).toString(type);
//break;
case "dependencies":
if(parseTree.dependencies === null) {

View File

@ -61,11 +61,11 @@ exports.macro = {
if(tiddlers.length === 0) {
return params.emptyMessage ? encoder(params.emptyMessage) : "";
} else {
var fn = store.compileText(templateType,templateText,type);
var renderer = store.compileText(templateType,templateText,type);
pushTag("<ul>");
for(t=0; t<tiddlers.length; t++) {
pushTag("<li>");
output.push(fn(store.getTiddler(tiddlers[t]),store,utils));
output.push(renderer.render(store.getTiddler(tiddlers[t]),store));
pushTag("</li>");
}
pushTag("</ul>");

View File

@ -1,12 +1,12 @@
<h1>Welcome to <span data-tw-macro='link'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span></h1><div data-tw-macro='tiddler'>Welcome to <span data-tw-macro='link'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span>, an interactive wiki written in <span data-tw-macro='link'><a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a></span> to run in the browser or under node.js. It is a reboot of <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> (<span data-tw-macro='link'><a href='http://www.tiddlywiki.com/' class='tw-tiddlylink tw-tiddlylink-external'>http://www.tiddlywiki.com/</a></span>), the now venerable, reusable non-linear personal web notebook first released in 2004.<br /><br /><span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> is based on the idea of making information more useful by modelling it in the smallest meaningful semantic units, referred to as &quot;tiddlers&quot;. Structure comes from links, tags, and stories (sequences of tiddlers). Tiddlers use a wikitext notation that concisely represents a wide range of text formatting and hypertext features.<br /><br /><span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> has earned an enduring place as a tool that people <span data-tw-macro='link'><a href='Raves' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>love using</a></span> for its rich, interactive interface to <span data-tw-macro='link'><a href='TiddlyWikiConcepts' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>manipulate complex data</a></span> with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors. Because people can use it without needing any complicated server infrastructure, and because it is <span data-tw-macro='link'><a href='OpenSourceLicense' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>open source</a></span>, it has bought unprecedented freedom to people to keep their precious information under their own control. <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> was originally created by <span data-tw-macro='link'><a href='JeremyRuston' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JeremyRuston</a></span> and is now a thriving <span data-tw-macro='link'><a href='OpenSourceLicense' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>open source</a></span> project with a busy <span data-tw-macro='link'><a href='Community' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>Community</a></span> of independent developers.<br /></div><br /><h1>Usage</h1><div data-tw-macro='tiddler'><span data-tw-macro='link'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span> can be used on the command line to perform an extensive set of operations based on <span data-tw-macro='link'><a href='RecipeFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>RecipeFiles</a></span>, <span data-tw-macro='link'><a href='TiddlerFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlerFiles</a></span> and <span data-tw-macro='link'><a href='TiddlyWikiFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWikiFiles</a></span>.<br /><br />Usage:<br /><code>
<h1>Welcome to <span data-tw-macro='link' data-tw-render-step='1'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span></h1><div data-tw-macro='tiddler' data-tw-render-step='2'>Welcome to <span data-tw-macro='link' data-tw-render-step='1'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span>, an interactive wiki written in <span data-tw-macro='link' data-tw-render-step='2'><a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a></span> to run in the browser or under node.js. It is a reboot of <span data-tw-macro='link' data-tw-render-step='3'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> (<span data-tw-macro='link' data-tw-render-step='4'><a href='http://www.tiddlywiki.com/' class='tw-tiddlylink tw-tiddlylink-external'>http://www.tiddlywiki.com/</a></span>), the now venerable, reusable non-linear personal web notebook first released in 2004.<br /><br /><span data-tw-macro='link' data-tw-render-step='5'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> is based on the idea of making information more useful by modelling it in the smallest meaningful semantic units, referred to as &quot;tiddlers&quot;. Structure comes from links, tags, and stories (sequences of tiddlers). Tiddlers use a wikitext notation that concisely represents a wide range of text formatting and hypertext features.<br /><br /><span data-tw-macro='link' data-tw-render-step='6'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> has earned an enduring place as a tool that people <span data-tw-macro='link' data-tw-render-step='7'><a href='Raves' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>love using</a></span> for its rich, interactive interface to <span data-tw-macro='link' data-tw-render-step='8'><a href='TiddlyWikiConcepts' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>manipulate complex data</a></span> with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors. Because people can use it without needing any complicated server infrastructure, and because it is <span data-tw-macro='link' data-tw-render-step='9'><a href='OpenSourceLicense' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>open source</a></span>, it has bought unprecedented freedom to people to keep their precious information under their own control. <span data-tw-macro='link' data-tw-render-step='10'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> was originally created by <span data-tw-macro='link' data-tw-render-step='11'><a href='JeremyRuston' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JeremyRuston</a></span> and is now a thriving <span data-tw-macro='link' data-tw-render-step='12'><a href='OpenSourceLicense' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>open source</a></span> project with a busy <span data-tw-macro='link' data-tw-render-step='13'><a href='Community' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>Community</a></span> of independent developers.<br /></div><br /><h1>Usage</h1><div data-tw-macro='tiddler' data-tw-render-step='3'><span data-tw-macro='link' data-tw-render-step='1'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span> can be used on the command line to perform an extensive set of operations based on <span data-tw-macro='link' data-tw-render-step='2'><a href='RecipeFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>RecipeFiles</a></span>, <span data-tw-macro='link' data-tw-render-step='3'><a href='TiddlerFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>TiddlerFiles</a></span> and <span data-tw-macro='link' data-tw-render-step='4'><a href='TiddlyWikiFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWikiFiles</a></span>.<br /><br />Usage:<br /><code>
node tiddlywiki.js &lt;options&gt;
</code><br />The command line options are processed sequentially from left to right. Processing pauses during long operations, like loading a <span data-tw-macro='link'><a href='RecipeFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>recipe file</a></span> and all the subrecipes and <span data-tw-macro='link'><a href='TiddlerFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>tiddlers</a></span> that it references. The following options are available:<br /><table class='twtable'><tbody><tr class='evenRow'><td align='left'><code>--recipe &lt;filepath&gt;</code></td><td align='left'>Loads a specfied <code>.recipe</code> file</td></tr><tr class='oddRow'><td align='left'><code>--load &lt;filepath&gt;</code></td><td align='left'>Load additional tiddlers from 2.x.x <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> files (<code>.html</code>), <code>.tiddler</code>, <code>.tid</code>, <code>.json</code> or other files</td></tr><tr class='evenRow'><td align='left'><code>--savewiki &lt;dirpath&gt;</code></td><td align='left'>Saves all the loaded tiddlers as a single file <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> called <code>index.html</code> and an RSS feed called <code>index.xml</code> in a new directory of the specified name</td></tr><tr class='oddRow'><td align='left'><code>--savetiddler &lt;title&gt; &lt;filename&gt; [&lt;type&gt;]</code></td><td align='left'>Save an individual tiddler as a specified MIME type, defaults to <code>text/html</code></td></tr><tr class='evenRow'><td align='left'><code>--savetiddlers &lt;outdir&gt;</code></td><td align='left'>Saves all the loaded tiddlers as <code>.tid</code> files in the specified directory</td></tr><tr class='oddRow'><td align='left'><code>--servewiki &lt;port&gt;</code></td><td align='left'>Serve the cooked <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> over HTTP at <code>/</code></td></tr><tr class='evenRow'><td align='left'><code>--servetiddlers &lt;port&gt;</code></td><td align='left'>Serve individual tiddlers over HTTP at <code>/tiddlertitle</code></td></tr><tr class='oddRow'><td align='left'><code>--wikitest &lt;dir&gt;</code></td><td align='left'>Run wikification tests against the tiddlers in the given directory</td></tr><tr class='evenRow'><td align='left'><code>--dumpstore</code></td><td align='left'>Dump the <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> store in JSON format</td></tr><tr class='oddRow'><td align='left'><code>--dumprecipe</code></td><td align='left'>Dump the current recipe in JSON format</td></tr><tr class='evenRow'><td align='left'><code>--verbose</code></td><td align='left'>verbose output, useful for debugging</td></tr></tbody></table><h2> Examples</h2>This example loads the tiddlers from a <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> HTML file and makes them available over HTTP:<br /><code>
</code><br />The command line options are processed sequentially from left to right. Processing pauses during long operations, like loading a <span data-tw-macro='link' data-tw-render-step='5'><a href='RecipeFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>recipe file</a></span> and all the subrecipes and <span data-tw-macro='link' data-tw-render-step='6'><a href='TiddlerFiles' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-resolves'>tiddlers</a></span> that it references. The following options are available:<br /><table class='twtable'><tbody><tr class='evenRow'><td align='left'><code>--recipe &lt;filepath&gt;</code></td><td align='left'>Loads a specfied <code>.recipe</code> file</td></tr><tr class='oddRow'><td align='left'><code>--load &lt;filepath&gt;</code></td><td align='left'>Load additional tiddlers from 2.x.x <span data-tw-macro='link' data-tw-render-step='7'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> files (<code>.html</code>), <code>.tiddler</code>, <code>.tid</code>, <code>.json</code> or other files</td></tr><tr class='evenRow'><td align='left'><code>--savewiki &lt;dirpath&gt;</code></td><td align='left'>Saves all the loaded tiddlers as a single file <span data-tw-macro='link' data-tw-render-step='8'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> called <code>index.html</code> and an RSS feed called <code>index.xml</code> in a new directory of the specified name</td></tr><tr class='oddRow'><td align='left'><code>--savetiddler &lt;title&gt; &lt;filename&gt; [&lt;type&gt;]</code></td><td align='left'>Save an individual tiddler as a specified MIME type, defaults to <code>text/html</code></td></tr><tr class='evenRow'><td align='left'><code>--savetiddlers &lt;outdir&gt;</code></td><td align='left'>Saves all the loaded tiddlers as <code>.tid</code> files in the specified directory</td></tr><tr class='oddRow'><td align='left'><code>--servewiki &lt;port&gt;</code></td><td align='left'>Serve the cooked <span data-tw-macro='link' data-tw-render-step='9'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> over HTTP at <code>/</code></td></tr><tr class='evenRow'><td align='left'><code>--servetiddlers &lt;port&gt;</code></td><td align='left'>Serve individual tiddlers over HTTP at <code>/tiddlertitle</code></td></tr><tr class='oddRow'><td align='left'><code>--wikitest &lt;dir&gt;</code></td><td align='left'>Run wikification tests against the tiddlers in the given directory</td></tr><tr class='evenRow'><td align='left'><code>--dumpstore</code></td><td align='left'>Dump the <span data-tw-macro='link' data-tw-render-step='10'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> store in JSON format</td></tr><tr class='oddRow'><td align='left'><code>--dumprecipe</code></td><td align='left'>Dump the current recipe in JSON format</td></tr><tr class='evenRow'><td align='left'><code>--verbose</code></td><td align='left'>verbose output, useful for debugging</td></tr></tbody></table><h2> Examples</h2>This example loads the tiddlers from a <span data-tw-macro='link' data-tw-render-step='11'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> HTML file and makes them available over HTTP:<br /><code>
node tiddlywiki.js --load mywiki.html --servewiki 127.0.0.1:8000
</code><br />This example cooks a <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> from a recipe:<br /><code>
</code><br />This example cooks a <span data-tw-macro='link' data-tw-render-step='12'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> from a recipe:<br /><code>
node tiddlywiki.js --recipe tiddlywiki.com/index.recipe --savewiki tmp/
</code><br />This example ginsus a <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> into its constituent tiddlers:<br /><code>
</code><br />This example ginsus a <span data-tw-macro='link' data-tw-render-step='13'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> into its constituent tiddlers:<br /><code>
node tiddlywiki.js --load mywiki.html --savetiddlers tmp/tiddlers
</code><br /><h2> Notes</h2><code>--servewiki</code> and <code>--servertiddlers</code> are for different purposes and should not be used together. The former is for <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> core developers who want to be able to edit the <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> source files in a text editor and view the results in the browser by clicking refresh; it is slow because it reloads all the <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> <span data-tw-macro='link'><a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a></span> files each time the page is loaded. The latter is for experimenting with the new wikification engine.<br /><br /><code>--wikitest</code> looks for <code>*.tid</code> files in the specified folder. It then wikifies the tiddlers to both &quot;text/plain&quot; and &quot;text/html&quot; format and checks the results against the content of the <code>*.html</code> and <code>*.txt</code> files in the same directory.</div><br /><h1>Testing</h1><div data-tw-macro='tiddler'><code>test.sh</code> contains a simple test script that cooks the main tiddlywiki.com recipe and compares it with the results of the old build process (ie, running cook.rb and then opening the file in a browser and performing a 'save changes' operation). It also runs a series of wikifications tests that work off the data in <code>test/wikitests/</code>.</div><br /><h1>Planned <span data-tw-macro='link'><a href='WikiText' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiText</a></span> Features</h1><div data-tw-macro='tiddler'>It is proposed to extend the existing <span data-tw-macro='link'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> wikitext syntax with the following extensions<br /><br /><ol><li> Addition of <code>**bold**</code> character formatting</li><li> Addition of <code>`backtick for code`</code> character formatting</li><li> Addition of <span data-tw-macro='link'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> forced line break, e.g. <code>force\\linebreak</code></li><li> Addition of <span data-tw-macro='link'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> headings, e.g. <code>==Heading</code></li><li> Addition of <span data-tw-macro='link'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> headings in tables, e.g. <code>|=|=table|=header|</code></li><li> Addition of white-listed HTML tags intermixed with wikitext</li><li> Addition of <span data-tw-macro='link'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> pretty links, e.g. <code>[[description -&gt; link]]</code></li><li> Addition of multiline macros, e.g.</li></ol><pre>&lt;&lt;myMacro
</code><br /><h2> Notes</h2><code>--servewiki</code> and <code>--servertiddlers</code> are for different purposes and should not be used together. The former is for <span data-tw-macro='link' data-tw-render-step='14'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> core developers who want to be able to edit the <span data-tw-macro='link' data-tw-render-step='15'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> source files in a text editor and view the results in the browser by clicking refresh; it is slow because it reloads all the <span data-tw-macro='link' data-tw-render-step='16'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> <span data-tw-macro='link' data-tw-render-step='17'><a href='JavaScript' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>JavaScript</a></span> files each time the page is loaded. The latter is for experimenting with the new wikification engine.<br /><br /><code>--wikitest</code> looks for <code>*.tid</code> files in the specified folder. It then wikifies the tiddlers to both &quot;text/plain&quot; and &quot;text/html&quot; format and checks the results against the content of the <code>*.html</code> and <code>*.txt</code> files in the same directory.</div><br /><h1>Testing</h1><div data-tw-macro='tiddler' data-tw-render-step='4'><code>test.sh</code> contains a simple test script that cooks the main tiddlywiki.com recipe and compares it with the results of the old build process (ie, running cook.rb and then opening the file in a browser and performing a 'save changes' operation). It also runs a series of wikifications tests that work off the data in <code>test/wikitests/</code>.</div><br /><h1>Planned <span data-tw-macro='link' data-tw-render-step='5'><a href='WikiText' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiText</a></span> Features</h1><div data-tw-macro='tiddler' data-tw-render-step='6'>It is proposed to extend the existing <span data-tw-macro='link' data-tw-render-step='1'><a href='TiddlyWiki' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki</a></span> wikitext syntax with the following extensions<br /><br /><ol><li> Addition of <code>**bold**</code> character formatting</li><li> Addition of <code>`backtick for code`</code> character formatting</li><li> Addition of <span data-tw-macro='link' data-tw-render-step='2'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> forced line break, e.g. <code>force\\linebreak</code></li><li> Addition of <span data-tw-macro='link' data-tw-render-step='3'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> headings, e.g. <code>==Heading</code></li><li> Addition of <span data-tw-macro='link' data-tw-render-step='4'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> headings in tables, e.g. <code>|=|=table|=header|</code></li><li> Addition of white-listed HTML tags intermixed with wikitext</li><li> Addition of <span data-tw-macro='link' data-tw-render-step='5'><a href='WikiCreole-style' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>WikiCreole-style</a></span> pretty links, e.g. <code>[[description -&gt; link]]</code></li><li> Addition of multiline macros, e.g.</li></ol><pre>&lt;&lt;myMacro
param1: Parameter value
param2: value
&quot;unnamed parameter&quot;
@ -15,4 +15,4 @@ A multiline parameter that can go on for as long as it likes
and contain linebreaks.
))
&gt;&gt;
</pre></div><br /><br /><em>This <code>readme</code> file was automatically generated by <span data-tw-macro='link'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span></em><br />
</pre></div><br /><br /><em>This <code>readme</code> file was automatically generated by <span data-tw-macro='link' data-tw-render-step='7'><a href='TiddlyWiki5' class='tw-tiddlylink tw-tiddlylink-internal tw-tiddlylink-missing'>TiddlyWiki5</a></span></em><br />

View File

@ -102,7 +102,7 @@ a.tw-tiddlylink-missing {
margin-right: 5px;
padding: 3px 5px 3px;
border-radius: 3px;
background-color: #cca;
background-color: #fcf;
}
.splitLabel {

View File

@ -7,4 +7,5 @@ modifier: JeremyRuston
<<view modifier link>> <<view modified date>>}}}
{{body{
<<view text wikified>>}}}
<<info parsetree>>
<<info compiled>>