mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-24 17:10:29 +00:00
Switched over to using new Renderer class
This commit is contained in:
parent
fef0b9e4da
commit
0439f259b4
@ -13,6 +13,7 @@ var WikiStore = require("./WikiStore.js").WikiStore,
|
|||||||
Tiddler = require("./Tiddler.js").Tiddler,
|
Tiddler = require("./Tiddler.js").Tiddler,
|
||||||
tiddlerInput = require("./TiddlerInput.js"),
|
tiddlerInput = require("./TiddlerInput.js"),
|
||||||
tiddlerOutput = require("./TiddlerOutput.js"),
|
tiddlerOutput = require("./TiddlerOutput.js"),
|
||||||
|
Renderer = require("./Renderer.js").Renderer,
|
||||||
WikiTextParser = require("./WikiTextParser.js").WikiTextParser,
|
WikiTextParser = require("./WikiTextParser.js").WikiTextParser,
|
||||||
JSONParser = require("./JSONParser.js").JSONParser,
|
JSONParser = require("./JSONParser.js").JSONParser,
|
||||||
JavaScriptParser = require("./JavaScriptParser.js").JavaScriptParser,
|
JavaScriptParser = require("./JavaScriptParser.js").JavaScriptParser,
|
||||||
@ -99,9 +100,8 @@ var App = function() {
|
|||||||
// Set up navigation if we're in the browser
|
// Set up navigation if we're in the browser
|
||||||
if(this.isBrowser) {
|
if(this.isBrowser) {
|
||||||
// Open the PageTemplate
|
// Open the PageTemplate
|
||||||
var div = document.createElement("div");
|
var renderer = new Renderer("PageTemplate",null,this.store);
|
||||||
this.store.renderTiddlerInNode(div,"PageTemplate");
|
renderer.renderInDom(document.body);
|
||||||
document.body.appendChild(div);
|
|
||||||
// Set up a timer to change the value of a tiddler
|
// Set up a timer to change the value of a tiddler
|
||||||
var me = this;
|
var me = this;
|
||||||
window.setInterval(function() {
|
window.setInterval(function() {
|
||||||
@ -112,7 +112,7 @@ var App = function() {
|
|||||||
},3000);
|
},3000);
|
||||||
// Register an event handler to handle refreshing the DOM
|
// Register an event handler to handle refreshing the DOM
|
||||||
this.store.addEventListener("",function(changes) {
|
this.store.addEventListener("",function(changes) {
|
||||||
me.store.refreshDomNode(div,changes);
|
renderer.refreshInDom(changes);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
278
js/HTML.js
278
js/HTML.js
@ -1,278 +0,0 @@
|
|||||||
/*\
|
|
||||||
title: js/HTML.js
|
|
||||||
|
|
||||||
Represents a fragment of HTML as a JavaScript object tree structure. Helper methods are provided to simplify
|
|
||||||
constructing HTML trees and to render the tree as an HTML string.
|
|
||||||
|
|
||||||
The nodes in the tree have a `type` field that is the name of the node for HTML elements:
|
|
||||||
|
|
||||||
{type: "br", attributes: {name: "value"}}
|
|
||||||
|
|
||||||
Attributes values can be strings, arrays of strings or hashmaps. String arrays are
|
|
||||||
rendered by joining them together with a space. Hashmaps are rendered as `attr="name1:value1;name2:value2;"`.
|
|
||||||
|
|
||||||
Elements with child nodes are expressed as:
|
|
||||||
|
|
||||||
{type: "div", children: [<childnodes>]}
|
|
||||||
|
|
||||||
Text nodes are represented as:
|
|
||||||
|
|
||||||
{type: "text", value: "A string"}
|
|
||||||
|
|
||||||
HTML entities are represented as:
|
|
||||||
|
|
||||||
{type: "entity", value: "quot"}
|
|
||||||
|
|
||||||
It is sometimes useful to be able to mix raw strings of HTML too:
|
|
||||||
|
|
||||||
{type: "raw", value: "<div>Something</div>"}
|
|
||||||
|
|
||||||
Other types of node can also be placed in the tree, but they will be ignored by the built-in render function.
|
|
||||||
For example, nodes of type `"macro"` are used by the WikiTextParser.
|
|
||||||
|
|
||||||
\*/
|
|
||||||
(function(){
|
|
||||||
|
|
||||||
/*jslint node: true */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var utils = require("./Utils.js");
|
|
||||||
|
|
||||||
/*
|
|
||||||
Constructs an HTMLParseTree from a tree of nodes. A single node or an array of nodes can be passed.
|
|
||||||
|
|
||||||
As a shortcut, the constructor can be called as an ordinary function without the new keyword, in which case
|
|
||||||
it by default returns the `text/html` rendering of the tree.
|
|
||||||
*/
|
|
||||||
var HTML = function(tree,type) {
|
|
||||||
if(this instanceof HTML) {
|
|
||||||
// Called as a constructor
|
|
||||||
this.tree = tree;
|
|
||||||
} else {
|
|
||||||
// Called as a function
|
|
||||||
type = type || "text/html";
|
|
||||||
return (new HTML(tree)).render(type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to simplify constructing an HTML element node
|
|
||||||
type: element name
|
|
||||||
attributes: hashmap of element attributes to add
|
|
||||||
options: hashmap of options
|
|
||||||
The attributes hashmap can contain strings or hashmaps of strings, (they are processed to attr="name1:value1;name2:value2;")
|
|
||||||
The options include:
|
|
||||||
content: a string to include as content in the element (also generates closing tag)
|
|
||||||
classes: an array of classnames to apply to the element
|
|
||||||
selfClosing: causes the element to be rendered with a trailing /, as in <br />
|
|
||||||
insertAfterAttributes: a string to insert after the attribute section of the element
|
|
||||||
*/
|
|
||||||
HTML.elem = function(type,attributes,children) {
|
|
||||||
var e = {type: type};
|
|
||||||
if(attributes) {
|
|
||||||
e.attributes = attributes;
|
|
||||||
}
|
|
||||||
if(children) {
|
|
||||||
e.children = children;
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct a text node
|
|
||||||
*/
|
|
||||||
HTML.text = function(value) {
|
|
||||||
return {type: "text", value: value};
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct an entity
|
|
||||||
*/
|
|
||||||
HTML.entity = function(value) {
|
|
||||||
return {type: "entity", value: value};
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct a raw HTML node
|
|
||||||
*/
|
|
||||||
HTML.raw = function(value) {
|
|
||||||
return {type: "raw", value: value};
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct a macro call
|
|
||||||
*/
|
|
||||||
HTML.macro = function(name,params,children,dependencies) {
|
|
||||||
var m = {type: "macro", name: name, params: params, dependencies: dependencies};
|
|
||||||
if(children) {
|
|
||||||
m.children = children;
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct a label
|
|
||||||
*/
|
|
||||||
HTML.label = function(type,value,classes) {
|
|
||||||
classes = (classes || []).slice(0);
|
|
||||||
classes.push("label");
|
|
||||||
return HTML.elem("span",{
|
|
||||||
"class": classes,
|
|
||||||
"data-tw-label-type": type
|
|
||||||
},value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct a split label
|
|
||||||
*/
|
|
||||||
HTML.splitLabel = function(type,left,right,classes) {
|
|
||||||
classes = (classes || []).slice(0);
|
|
||||||
classes.push("splitLabel");
|
|
||||||
return HTML.elem("span",{
|
|
||||||
"class": classes
|
|
||||||
},[
|
|
||||||
HTML.elem("span",{
|
|
||||||
"class": ["splitLabelLeft"],
|
|
||||||
"data-tw-label-type": type
|
|
||||||
},left),
|
|
||||||
HTML.elem("span",{
|
|
||||||
"class": ["splitLabelRight"]
|
|
||||||
},right)
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Static method to construct a slider
|
|
||||||
*/
|
|
||||||
HTML.slider = function(type,label,tooltip,body) {
|
|
||||||
var attributes = {
|
|
||||||
"class": "tw-slider",
|
|
||||||
"data-tw-slider-type": type
|
|
||||||
};
|
|
||||||
if(tooltip) {
|
|
||||||
attributes.alt = tooltip;
|
|
||||||
attributes.title = tooltip;
|
|
||||||
}
|
|
||||||
return HTML.elem("div",
|
|
||||||
attributes,
|
|
||||||
[
|
|
||||||
HTML.elem("a",
|
|
||||||
{
|
|
||||||
"class": ["tw-slider-label"]
|
|
||||||
},[
|
|
||||||
HTML.text(label)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
HTML.elem("div",
|
|
||||||
{
|
|
||||||
"class": ["tw-slider-body"],
|
|
||||||
"style": {"display": "none"}
|
|
||||||
},
|
|
||||||
body
|
|
||||||
)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Render the HTML tree to a string, either of "text/html" or "text/plain"
|
|
||||||
*/
|
|
||||||
HTML.prototype.render = function(targetType) {
|
|
||||||
if(targetType == "text/plain") {
|
|
||||||
return this.renderPlain().join("");
|
|
||||||
} else if(targetType == "text/html") {
|
|
||||||
return this.renderHtml().join("");
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Render the HTML tree to a "text/html" string, returned as a string array
|
|
||||||
*/
|
|
||||||
HTML.prototype.renderHtml = function(output,node) {
|
|
||||||
output = output || [];
|
|
||||||
node = node || this.tree;
|
|
||||||
if(node instanceof Array) {
|
|
||||||
for(var t=0; t<node.length; t++) {
|
|
||||||
this.renderHtml(output,node[t]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch(node.type) {
|
|
||||||
case "text":
|
|
||||||
output.push(utils.htmlEncode(node.value));
|
|
||||||
break;
|
|
||||||
case "entity":
|
|
||||||
output.push(node.value);
|
|
||||||
break;
|
|
||||||
case "raw":
|
|
||||||
output.push(node.value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
output.push("<",node.type);
|
|
||||||
if(node.attributes) {
|
|
||||||
for(var a in node.attributes) {
|
|
||||||
var v = node.attributes[a];
|
|
||||||
if(v !== undefined) {
|
|
||||||
if(v instanceof Array) {
|
|
||||||
v = v.join(" ");
|
|
||||||
} else if(typeof v === "object") {
|
|
||||||
var s = [];
|
|
||||||
for(var p in v) {
|
|
||||||
s.push(p + ":" + v[p] + ";");
|
|
||||||
}
|
|
||||||
v = s.join("");
|
|
||||||
}
|
|
||||||
output.push(" ");
|
|
||||||
output.push(a);
|
|
||||||
output.push("='");
|
|
||||||
output.push(utils.htmlEncode(v));
|
|
||||||
output.push("'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output.push(">");
|
|
||||||
if(node.children) {
|
|
||||||
this.renderHtml(output,node.children);
|
|
||||||
output.push("</",node.type,">");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Render the HTML tree to a "text/plain" string, returned as a string array
|
|
||||||
*/
|
|
||||||
HTML.prototype.renderPlain = function(output,node) {
|
|
||||||
output = output || [];
|
|
||||||
node = node || this.tree;
|
|
||||||
if(node instanceof Array) {
|
|
||||||
for(var t=0; t<node.length; t++) {
|
|
||||||
this.renderPlain(output,node[t]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch(node.type) {
|
|
||||||
case "text":
|
|
||||||
output.push(node.value);
|
|
||||||
break;
|
|
||||||
case "entity":
|
|
||||||
output.push(utils.entityDecode(node.value));
|
|
||||||
break;
|
|
||||||
case "raw":
|
|
||||||
output.push(node.value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if(node.children) {
|
|
||||||
this.renderPlain(output,node.children);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.HTML = HTML;
|
|
||||||
|
|
||||||
})();
|
|
@ -10,7 +10,7 @@ Compiles images into JavaScript functions that render them in HTML
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
var WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
||||||
HTML = require("./HTML.js").HTML,
|
Renderer = require("./Renderer.js").Renderer,
|
||||||
utils = require("./Utils.js");
|
utils = require("./Utils.js");
|
||||||
|
|
||||||
var ImageParser = function(options) {
|
var ImageParser = function(options) {
|
||||||
@ -19,12 +19,12 @@ var ImageParser = function(options) {
|
|||||||
|
|
||||||
ImageParser.prototype.parse = function(type,text) {
|
ImageParser.prototype.parse = function(type,text) {
|
||||||
var src;
|
var src;
|
||||||
if(this.type === "image/svg+xml") {
|
if(type === "image/svg+xml") {
|
||||||
src = "data:" + type + "," + encodeURIComponent(text);
|
src = "data:" + type + "," + encodeURIComponent(text);
|
||||||
} else {
|
} else {
|
||||||
src = "data:" + type + ";base64," + text;
|
src = "data:" + type + ";base64," + text;
|
||||||
}
|
}
|
||||||
return new WikiTextParseTree([HTML.elem("img",{src: src})],{},this.store);
|
return new WikiTextParseTree([Renderer.ElementNode("img",{src: src})],{},this.store);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.ImageParser = ImageParser;
|
exports.ImageParser = ImageParser;
|
||||||
|
@ -10,31 +10,31 @@ Compiles JSON objects into JavaScript functions that render them in HTML and pla
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
var WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
||||||
HTML = require("./HTML.js").HTML,
|
Renderer = require("./Renderer.js").Renderer,
|
||||||
utils = require("./Utils.js");
|
utils = require("./Utils.js");
|
||||||
|
|
||||||
var renderObject = function(obj) {
|
var renderObject = function(obj) {
|
||||||
var children = [],t;
|
var children = [],t;
|
||||||
if(obj instanceof Array) {
|
if(obj instanceof Array) {
|
||||||
for(t=0; t<obj.length; t++) {
|
for(t=0; t<obj.length; t++) {
|
||||||
children.push(HTML.elem("li",{
|
children.push(Renderer.ElementNode("li",{
|
||||||
"class": ["jsonArrayMember"]
|
"class": ["jsonArrayMember"]
|
||||||
},[renderObject(obj[t])]));
|
},[renderObject(obj[t])]));
|
||||||
}
|
}
|
||||||
return HTML.elem("ul",{
|
return Renderer.ElementNode("ul",{
|
||||||
"class": ["jsonArray"]
|
"class": ["jsonArray"]
|
||||||
},children);
|
},children);
|
||||||
} else if(typeof obj === "object") {
|
} else if(typeof obj === "object") {
|
||||||
for(t in obj) {
|
for(t in obj) {
|
||||||
children.push(HTML.elem("li",{
|
children.push(Renderer.ElementNode("li",{
|
||||||
"class": ["jsonObjectMember"]
|
"class": ["jsonObjectMember"]
|
||||||
},[HTML.splitLabel("JSON",[HTML.text(t)],[renderObject(obj[t])])]));
|
},[Renderer.SplitLabelNode("JSON",[Renderer.TextNode(t)],[renderObject(obj[t])])]));
|
||||||
}
|
}
|
||||||
return HTML.elem("ul",{
|
return Renderer.ElementNode("ul",{
|
||||||
"class": ["jsonObject"]
|
"class": ["jsonObject"]
|
||||||
},children);
|
},children);
|
||||||
} else {
|
} else {
|
||||||
return HTML.label("JSON" + (typeof obj),[HTML.text(JSON.stringify(obj))],["jsonValue"]);
|
return Renderer.LabelNode("JSON" + (typeof obj),[Renderer.TextNode(JSON.stringify(obj))],["jsonValue"]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ utils.entityDecode = function(s) {
|
|||||||
if(c) {
|
if(c) {
|
||||||
return String.fromCharCode(c);
|
return String.fromCharCode(c);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return s; // Couldn't convert it as an entity, just return it raw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
218
js/WikiStore.js
218
js/WikiStore.js
@ -13,18 +13,16 @@ WikiStore uses the .cache member of tiddlers to store the following information:
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Tiddler = require("./Tiddler.js").Tiddler,
|
var Tiddler = require("./Tiddler.js").Tiddler,
|
||||||
HTML = require("./HTML.js").HTML,
|
Renderer = require("./Renderer.js").Renderer,
|
||||||
utils = require("./Utils.js");
|
utils = require("./Utils.js");
|
||||||
|
|
||||||
/* Creates a new WikiStore object
|
/* Creates a new WikiStore object
|
||||||
|
|
||||||
Available options are:
|
Available options are:
|
||||||
shadowStore: An existing WikiStore to use for shadow tiddler storage. Pass null to prevent a default shadow store from being created
|
shadowStore: An existing WikiStore to use for shadow tiddler storage. Pass null to prevent a default shadow store from being created
|
||||||
disableHtmlWrapperNodes: If true will suppress the generation of the wrapper nodes used by the refresh and diagnostic machinery
|
|
||||||
*/
|
*/
|
||||||
var WikiStore = function WikiStore(options) {
|
var WikiStore = function WikiStore(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
this.disableHtmlWrapperNodes = !!options.disableHtmlWrapperNodes;
|
|
||||||
this.tiddlers = {}; // Hashmap of tiddlers by title
|
this.tiddlers = {}; // Hashmap of tiddlers by title
|
||||||
this.parsers = {}; // Hashmap of parsers by accepted MIME type
|
this.parsers = {}; // Hashmap of parsers by accepted MIME type
|
||||||
this.macros = {}; // Hashmap of macros by macro name
|
this.macros = {}; // Hashmap of macros by macro name
|
||||||
@ -265,229 +263,21 @@ WikiStore.prototype.parseTiddler = function(title) {
|
|||||||
return parseTree;
|
return parseTree;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
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) {
|
|
||||||
var tree = this.parseText(type,text);
|
|
||||||
return tree.compile(targetType);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Compiles a JavaScript function that renders a tiddler in a particular MIME type
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.compileTiddler = function(title,type) {
|
|
||||||
var tiddler = this.getTiddler(title),
|
|
||||||
renderers = this.getCacheForTiddler(title,"renderers",function() {
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
if(tiddler) {
|
|
||||||
if(!renderers[type]) {
|
|
||||||
var tree = this.parseTiddler(title);
|
|
||||||
renderers[type] = tree.compile(type);
|
|
||||||
}
|
|
||||||
return renderers[type];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Render a block of text of a specified type into a particular MIME type
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.renderText = function(type,text,targetType,asTitle,options) {
|
|
||||||
options = options || {};
|
|
||||||
var noWrap = options.noWrap || this.disableHtmlWrapperNodes,
|
|
||||||
tiddler = this.getTiddler(asTitle),
|
|
||||||
renderer = this.compileText(type,text,targetType),
|
|
||||||
content = renderer.render(tiddler,this);
|
|
||||||
return noWrap ? content : HTML(HTML.elem("div",{
|
|
||||||
"data-tw-render-text": true,
|
|
||||||
"data-tw-render-as": asTitle
|
|
||||||
},[HTML.raw(content)]),targetType);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Render a tiddler to a particular MIME type
|
Render a tiddler to a particular MIME type
|
||||||
targetType: target MIME type
|
targetType: target MIME type
|
||||||
title: title of the tiddler to render
|
title: title of the tiddler to render
|
||||||
template: optional title of the tiddler to use as a template
|
template: optional title of the tiddler to use as a template
|
||||||
options: see below
|
|
||||||
|
|
||||||
Options include:
|
|
||||||
noWrap: Suppress the outer refresh wrapper nodes
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
WikiStore.prototype.renderTiddler = function(targetType,title,templateTitle,options) {
|
WikiStore.prototype.renderTiddler = function(targetType,title,templateTitle) {
|
||||||
options = options || {};
|
var r = new Renderer(title,templateTitle,this);
|
||||||
if(typeof templateTitle !== "string") {
|
return r.render(targetType);
|
||||||
templateTitle = title;
|
|
||||||
}
|
|
||||||
var noWrap = options.noWrap || this.disableHtmlWrapperNodes,
|
|
||||||
tiddler = this.getTiddler(title),
|
|
||||||
renderer = this.compileTiddler(templateTitle,targetType),
|
|
||||||
template,
|
|
||||||
content;
|
|
||||||
if(tiddler) {
|
|
||||||
content = renderer.render(tiddler,this);
|
|
||||||
if(title !== templateTitle) {
|
|
||||||
template = this.getTiddler(templateTitle);
|
|
||||||
return noWrap ? content : HTML(HTML.elem("div",{
|
|
||||||
"data-tw-render-tiddler": title,
|
|
||||||
"data-tw-render-template": templateTitle
|
|
||||||
},[HTML.raw(content)]),targetType);
|
|
||||||
} else {
|
|
||||||
return noWrap ? content : HTML(HTML.elem("div",{
|
|
||||||
"data-tw-render-tiddler": title
|
|
||||||
},[HTML.raw(content)]),targetType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Renders a tiddler and inserts the HTML into a DOM node, and then attaches the event handlers needed by macros
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.renderTiddlerInNode = function(node,title,templateTitle,options) {
|
|
||||||
node.innerHTML = this.renderTiddler("text/html",title,templateTitle,options);
|
|
||||||
this.attachEventHandlers(node,title,templateTitle);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Recursively attach macro event handlers for a node and its children
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.attachEventHandlers = function(node,renderTiddler,renderTemplate) {
|
|
||||||
var me = this,
|
|
||||||
dispatchMacroEvent = function(event) {
|
|
||||||
var renderer = me.compileTiddler(renderTemplate ? renderTemplate : renderTiddler,"text/html"),
|
|
||||||
macroName = node.getAttribute("data-tw-macro"),
|
|
||||||
macro = me.macros[macroName],
|
|
||||||
step = node.getAttribute("data-tw-render-step");
|
|
||||||
return macro.events[event.type](event,node,renderTiddler,me,renderer.renderSteps[step].params(renderTiddler,renderer,me,utils));
|
|
||||||
};
|
|
||||||
if(node.getAttribute) {
|
|
||||||
var macroName = node.getAttribute("data-tw-macro");
|
|
||||||
if(typeof macroName === "string") {
|
|
||||||
var macro = this.macros[macroName];
|
|
||||||
if(macro.events) {
|
|
||||||
for(var e in macro.events) {
|
|
||||||
node.addEventListener(e,dispatchMacroEvent,false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(node.hasAttribute("data-tw-render-tiddler")) {
|
|
||||||
renderTiddler = node.getAttribute("data-tw-render-tiddler");
|
|
||||||
renderTemplate = node.getAttribute("data-tw-render-template");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(node.hasChildNodes) {
|
|
||||||
for(var t=0; t<node.childNodes.length; t++) {
|
|
||||||
this.attachEventHandlers(node.childNodes[t],renderTiddler,renderTemplate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
WikiStore.prototype.installMacro = function(macro) {
|
WikiStore.prototype.installMacro = function(macro) {
|
||||||
this.macros[macro.name] = macro;
|
this.macros[macro.name] = macro;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Executes a macro and returns the result
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.renderMacro = function(macroName,targetType,tiddler,params,content) {
|
|
||||||
var macro = this.macros[macroName];
|
|
||||||
if(macro) {
|
|
||||||
return macro.render(targetType,tiddler,this,params,content);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Re-renders a macro into a node
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.rerenderMacro = function(node,changes,macroName,targetType,tiddler,params,content) {
|
|
||||||
var macro = this.macros[macroName];
|
|
||||||
if(macro) {
|
|
||||||
if(macro.rerender) {
|
|
||||||
macro.rerender(node,changes,targetType,tiddler,this,params,content);
|
|
||||||
} else {
|
|
||||||
node.innerHTML = macro.render(targetType,tiddler,this,params,content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Refresh a DOM node and it's children so that it reflects the current state of the store
|
|
||||||
node: reference to the DOM node to be refreshed
|
|
||||||
changes: hashmap of {title: "created|modified|deleted"}
|
|
||||||
renderer: the renderer to use to refresh the node (usually pass null)
|
|
||||||
tiddler: the tiddler to use as the context for executing the renderer
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.refreshDomNode = function(node,changes,renderer,tiddler) {
|
|
||||||
var me = this,
|
|
||||||
refreshChildNodes = function(node,renderer,tiddler) {
|
|
||||||
if(node.hasChildNodes()) {
|
|
||||||
for(var c=0; c<node.childNodes.length; c++) {
|
|
||||||
me.refreshDomNode(node.childNodes[c],changes,renderer,tiddler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Get all the various attributes we need
|
|
||||||
var renderTiddler = node.getAttribute ? node.getAttribute("data-tw-render-tiddler") : null,
|
|
||||||
renderTemplate = node.getAttribute ? node.getAttribute("data-tw-render-template") : null,
|
|
||||||
macro = node.getAttribute ? node.getAttribute("data-tw-macro") : null,
|
|
||||||
renderStep = node.getAttribute ? node.getAttribute("data-tw-render-step") : null;
|
|
||||||
// Is this node the rendering of a tiddler?
|
|
||||||
if(renderTiddler !== null) {
|
|
||||||
// Rerender the content of the node if the tiddler being rendered or its template has changed
|
|
||||||
if(changes.hasOwnProperty(renderTiddler) || (renderTemplate && changes.hasOwnProperty(renderTemplate))) {
|
|
||||||
this.renderTiddlerInNode(node,renderTiddler,renderTemplate,{noWrap: true});
|
|
||||||
} else {
|
|
||||||
// If it hasn't changed, just refresh the child nodes
|
|
||||||
if(typeof renderTemplate !== "string") {
|
|
||||||
renderTemplate = renderTiddler;
|
|
||||||
}
|
|
||||||
refreshChildNodes(node,this.compileTiddler(renderTemplate,"text/html"),this.getTiddler(renderTiddler));
|
|
||||||
}
|
|
||||||
// Is this node a macro
|
|
||||||
} else if(macro !== null) {
|
|
||||||
// Get the render step
|
|
||||||
var r = renderer.renderSteps[renderStep];
|
|
||||||
// Refresh if a dependency has changed
|
|
||||||
if(this.hasDependencyChanged(r.dependencies,changes)) {
|
|
||||||
renderer.rerender(node,changes,tiddler,this,renderStep);
|
|
||||||
} else {
|
|
||||||
// If no change, just refresh the children
|
|
||||||
refreshChildNodes(node,renderer,tiddler);
|
|
||||||
}
|
|
||||||
// If it's not a macro or a tiddler rendering, just process any child nodes
|
|
||||||
} else {
|
|
||||||
refreshChildNodes(node,renderer,tiddler);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if the specified dependencies are impacted by the specified changes
|
|
||||||
dependencies: a dependencies tree
|
|
||||||
changes: an array of titles of changed tiddlers
|
|
||||||
*/
|
|
||||||
WikiStore.prototype.hasDependencyChanged = function(dependencies,changes) {
|
|
||||||
if(dependencies.dependentAll) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for(var rel in dependencies) {
|
|
||||||
if(rel !== "dependentAll") {
|
|
||||||
for(var t in dependencies[rel]) {
|
|
||||||
if(changes.hasOwnProperty(t)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.WikiStore = WikiStore;
|
exports.WikiStore = WikiStore;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -9,8 +9,7 @@ A container for the parse tree generated by parsing wikitext
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var WikiTextRenderer = require("./WikiTextRenderer.js").WikiTextRenderer,
|
var Renderer = require("./Renderer.js").Renderer,
|
||||||
HTML = require("./HTML.js").HTML,
|
|
||||||
ArgParser = require("./ArgParser.js").ArgParser,
|
ArgParser = require("./ArgParser.js").ArgParser,
|
||||||
utils = require("./Utils.js");
|
utils = require("./Utils.js");
|
||||||
|
|
||||||
@ -21,373 +20,6 @@ var WikiTextParseTree = function(tree,dependencies,store) {
|
|||||||
this.store = store;
|
this.store = 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 renderer = new WikiTextRenderer(),
|
|
||||||
renderStep = {},
|
|
||||||
renderStepIndex = renderer.addRenderStep(renderStep),
|
|
||||||
output = [];
|
|
||||||
if(type === "text/html") {
|
|
||||||
this.compileSubTreeHtml(output,renderer,treenode);
|
|
||||||
} else if(type === "text/plain") {
|
|
||||||
this.compileSubTreePlain(output,renderer,treenode);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Create the parse tree for the rendering step function definition
|
|
||||||
var parseTree = this.store.jsParser.createTree(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
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: {
|
|
||||||
type: "PropertyAccess",
|
|
||||||
base: {
|
|
||||||
type: "ArrayLiteral",
|
|
||||||
elements: output
|
|
||||||
},
|
|
||||||
name: "join"
|
|
||||||
},
|
|
||||||
"arguments": [ {
|
|
||||||
type: "StringLiteral",
|
|
||||||
value: ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
renderStep.type = "main";
|
|
||||||
renderStep.step = renderStepIndex;
|
|
||||||
renderStep.dependencies = {};
|
|
||||||
renderStep.handler = parseTree.compile("application/javascript").render;
|
|
||||||
return renderer;
|
|
||||||
};
|
|
||||||
|
|
||||||
var pushString = function(output,s) {
|
|
||||||
var last = output[output.length-1];
|
|
||||||
if(output.length > 0 && last.type === "StringLiterals") {
|
|
||||||
last.value.push(s);
|
|
||||||
} else if (output.length > 0 && last.type === "StringLiteral") {
|
|
||||||
last.type = "StringLiterals";
|
|
||||||
last.value = [last.value,s];
|
|
||||||
} else {
|
|
||||||
output.push({type: "StringLiteral", value: s});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
|
||||||
renderStep = {},
|
|
||||||
renderStepIndex = renderer.addRenderStep(renderStep);
|
|
||||||
// Check for errors
|
|
||||||
if(!macro) {
|
|
||||||
pushString(output,"{{** Unknown macro '" + name + "' **}}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(macro.types.indexOf(type) === -1) {
|
|
||||||
pushString(output,"{{** Macro '" + name + "' cannot render to MIME type '" + type + "'**}}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
renderStep.type = "macro";
|
|
||||||
renderStep.macro = name;
|
|
||||||
renderStep.renderType = type;
|
|
||||||
renderStep.step = renderStepIndex;
|
|
||||||
renderStep.dependencies = node.dependencies;
|
|
||||||
// Slot the parameters into the macro call
|
|
||||||
var properties = [];
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
properties.push({
|
|
||||||
type: "PropertyAssignment",
|
|
||||||
name: p,
|
|
||||||
value: n
|
|
||||||
});
|
|
||||||
}
|
|
||||||
renderStep.params = this.store.jsParser.createTree([
|
|
||||||
{
|
|
||||||
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: "ObjectLiteral",
|
|
||||||
properties: properties
|
|
||||||
}
|
|
||||||
} ]
|
|
||||||
}
|
|
||||||
]).compile("application/javascript").render;
|
|
||||||
// Compile any child nodes
|
|
||||||
var subOutput = [];
|
|
||||||
if(node.children) {
|
|
||||||
this.compileSubTreeHtml(subOutput,renderer,node.children);
|
|
||||||
}
|
|
||||||
renderStep.content = this.store.jsParser.createTree([
|
|
||||||
{
|
|
||||||
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: {
|
|
||||||
type: "PropertyAccess",
|
|
||||||
base: {
|
|
||||||
type: "ArrayLiteral",
|
|
||||||
elements: subOutput
|
|
||||||
},
|
|
||||||
name: "join"
|
|
||||||
},
|
|
||||||
"arguments": [ {
|
|
||||||
type: "StringLiteral",
|
|
||||||
value: ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]).compile("application/javascript").render;
|
|
||||||
// Add the wrapper node
|
|
||||||
var wrapperTag = macro.wrapperTag || "div";
|
|
||||||
if(type === "text/html" && !this.store.disableHtmlWrapperNodes) {
|
|
||||||
pushString(output,HTML(HTML.elem(wrapperTag,{
|
|
||||||
"data-tw-macro": name,
|
|
||||||
"data-tw-render-step": renderStepIndex
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
// Output the macro call
|
|
||||||
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.store.disableHtmlWrapperNodes) {
|
|
||||||
pushString(output,"</" + wrapperTag + ">");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WikiTextParseTree.prototype.compileElementHtml = function(output,renderer,element,options) {
|
|
||||||
options = options || {};
|
|
||||||
pushString(output,HTML(HTML.elem(element.type,element.attributes)));
|
|
||||||
if(!options.selfClosing) {
|
|
||||||
if(element.children) {
|
|
||||||
this.compileSubTreeHtml(output,renderer,element.children);
|
|
||||||
}
|
|
||||||
pushString(output,"</" + element.type + ">");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WikiTextParseTree.prototype.compileSubTreeHtml = function(output,renderer,tree) {
|
|
||||||
for(var t=0; t<tree.length; t++) {
|
|
||||||
switch(tree[t].type) {
|
|
||||||
case "text":
|
|
||||||
pushString(output,utils.htmlEncode(tree[t].value));
|
|
||||||
break;
|
|
||||||
case "entity":
|
|
||||||
pushString(output,tree[t].value);
|
|
||||||
break;
|
|
||||||
case "br":
|
|
||||||
case "img":
|
|
||||||
this.compileElementHtml(output,renderer,tree[t],{selfClosing: true}); // Self closing elements
|
|
||||||
break;
|
|
||||||
case "macro":
|
|
||||||
this.compileMacroCall(output,renderer,"text/html",tree[t]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.compileElementHtml(output,renderer,tree[t]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WikiTextParseTree.prototype.compileElementPlain = function(output,renderer,element,options) {
|
|
||||||
options = options || {};
|
|
||||||
if(!options.selfClosing) {
|
|
||||||
if(element.children) {
|
|
||||||
this.compileSubTreePlain(output,renderer,element.children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WikiTextParseTree.prototype.compileSubTreePlain = function(output,renderer,tree) {
|
|
||||||
for(var t=0; t<tree.length; t++) {
|
|
||||||
switch(tree[t].type) {
|
|
||||||
case "text":
|
|
||||||
pushString(output,tree[t].value);
|
|
||||||
break;
|
|
||||||
case "entity":
|
|
||||||
var c = utils.entityDecode(tree[t].value);
|
|
||||||
if(c) {
|
|
||||||
pushString(output,c);
|
|
||||||
} else {
|
|
||||||
pushString(output,tree[t].value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "br":
|
|
||||||
case "img":
|
|
||||||
this.compileElementPlain(output,renderer,tree[t],{selfClosing: true}); // Self closing elements
|
|
||||||
break;
|
|
||||||
case "macro":
|
|
||||||
this.compileMacroCall(output,renderer,"text/plain",tree[t]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.compileElementPlain(output,renderer,tree[t]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Render the parse tree to a debugging string of the specified MIME type
|
|
||||||
WikiTextParseTree.prototype.toString = function(type) {
|
|
||||||
var renderNode,
|
|
||||||
renderArray = function(tree) {
|
|
||||||
var children = [];
|
|
||||||
for(var t=0; t<tree.length; t++) {
|
|
||||||
children.push(HTML.elem("li",{
|
|
||||||
"class": ["nodeWikiText"]
|
|
||||||
},renderNode(tree[t])));
|
|
||||||
}
|
|
||||||
return HTML.elem("ul",{
|
|
||||||
"class": ["treeWikiText"]
|
|
||||||
},children);
|
|
||||||
},
|
|
||||||
renderTextNode = function(node) {
|
|
||||||
return [HTML.splitLabel(
|
|
||||||
node.type,
|
|
||||||
[HTML.text(node.type)],
|
|
||||||
[HTML.raw(utils.htmlEncode(node.value).replace(/\n/g,"<br>"))],
|
|
||||||
["treeNode"]
|
|
||||||
)];
|
|
||||||
},
|
|
||||||
renderDependencies = function(dependencies) {
|
|
||||||
var output = [];
|
|
||||||
for(var d in dependencies) {
|
|
||||||
if(d === "dependentAll") {
|
|
||||||
output.push(HTML.splitLabel("dependency",[HTML.text(d)],[HTML.text(dependencies[d])]));
|
|
||||||
} else {
|
|
||||||
var dependents = [];
|
|
||||||
for(var t in dependencies[d]) {
|
|
||||||
dependents.push(t);
|
|
||||||
}
|
|
||||||
output.push(HTML.splitLabel("dependency",[HTML.text(d)],[HTML.text(dependents.join(", "))]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return HTML.splitLabel(
|
|
||||||
"dependencies",
|
|
||||||
[HTML.text("Dependencies")],
|
|
||||||
output
|
|
||||||
);
|
|
||||||
},
|
|
||||||
renderMacroNode = function(node) {
|
|
||||||
var params = [],
|
|
||||||
ret = [];
|
|
||||||
for(var p in node.params) {
|
|
||||||
var v = node.params[p].value;
|
|
||||||
if(node.params[p].type === "eval") {
|
|
||||||
v = "{{" + v + "}}";
|
|
||||||
}
|
|
||||||
params.push(HTML.splitLabel(
|
|
||||||
"param",
|
|
||||||
[HTML.text(p)],
|
|
||||||
[HTML.text(v)]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"macro",
|
|
||||||
[HTML.text(node.name)],
|
|
||||||
params,
|
|
||||||
["treeNode"]
|
|
||||||
));
|
|
||||||
if(node.dependencies) {
|
|
||||||
ret.push(renderDependencies(node.dependencies));
|
|
||||||
}
|
|
||||||
if(node.children) {
|
|
||||||
ret.push(renderArray(node.children));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
renderHtmlNode = function(node) {
|
|
||||||
var attributes = [],
|
|
||||||
ret = [];
|
|
||||||
for(var a in node.attributes) {
|
|
||||||
var v = node.attributes[a];
|
|
||||||
if(typeof v === "string") {
|
|
||||||
v = v;
|
|
||||||
} else if(v instanceof Array) {
|
|
||||||
v = v.join("; ");
|
|
||||||
} else if(typeof v === "object") {
|
|
||||||
var o = [];
|
|
||||||
for(var n in v) {
|
|
||||||
o.push(n,":",v[n],";");
|
|
||||||
}
|
|
||||||
v = o.join("");
|
|
||||||
}
|
|
||||||
attributes.push(HTML.splitLabel(
|
|
||||||
"attribute",
|
|
||||||
[HTML.text(a)],
|
|
||||||
[HTML.text(v)]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"html",
|
|
||||||
[HTML.text(node.type)],
|
|
||||||
attributes,
|
|
||||||
["treeNode"]
|
|
||||||
));
|
|
||||||
if(node.children) {
|
|
||||||
ret.push(renderArray(node.children));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
renderNode = function(node) {
|
|
||||||
if(node.type === "text") {
|
|
||||||
return renderTextNode(node);
|
|
||||||
} else if(node.type === "macro") {
|
|
||||||
return renderMacroNode(node);
|
|
||||||
} else {
|
|
||||||
return renderHtmlNode(node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return HTML(renderDependencies(this.dependencies),type) + HTML(renderArray(this.tree),type);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.WikiTextParseTree = WikiTextParseTree;
|
exports.WikiTextParseTree = WikiTextParseTree;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -33,7 +33,7 @@ HTML nodes look like this:
|
|||||||
|
|
||||||
var WikiTextRules = require("./WikiTextRules.js"),
|
var WikiTextRules = require("./WikiTextRules.js"),
|
||||||
WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
||||||
HTML = require("./HTML.js").HTML,
|
Renderer = require("./Renderer.js").Renderer,
|
||||||
utils = require("./Utils.js"),
|
utils = require("./Utils.js"),
|
||||||
util = require("util");
|
util = require("util");
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ WikiTextParser.prototype.mergeDependencies = function(newDependencies) {
|
|||||||
|
|
||||||
WikiTextParser.prototype.outputText = function(place,startPos,endPos) {
|
WikiTextParser.prototype.outputText = function(place,startPos,endPos) {
|
||||||
if(startPos < endPos) {
|
if(startPos < endPos) {
|
||||||
place.push(HTML.text(this.source.substring(startPos,endPos)));
|
place.push(Renderer.TextNode(this.source.substring(startPos,endPos)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
/*\
|
|
||||||
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 HTML = require("./HTML.js").HTML,
|
|
||||||
utils = require("./Utils.js");
|
|
||||||
|
|
||||||
var WikiTextRenderer = function() {
|
|
||||||
this.renderSteps = []; // Array of {step: n, renderType: "main"|"macro", 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;
|
|
||||||
var step = this.renderSteps[renderStep];
|
|
||||||
if(renderStep < this.renderSteps.length) {
|
|
||||||
switch(step.type) {
|
|
||||||
case "main":
|
|
||||||
return step.handler(tiddler,this,store,utils);
|
|
||||||
case "macro":
|
|
||||||
return store.renderMacro(step.macro,
|
|
||||||
step.renderType,
|
|
||||||
tiddler,
|
|
||||||
step.params(tiddler,this,store,utils),
|
|
||||||
step.content(tiddler,this,store,utils));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WikiTextRenderer.prototype.rerender = function(node,changes,tiddler,store,renderStep) {
|
|
||||||
renderStep = renderStep || 0;
|
|
||||||
var step = this.renderSteps[renderStep];
|
|
||||||
if(renderStep < this.renderSteps.length) {
|
|
||||||
switch(step.type) {
|
|
||||||
case "main":
|
|
||||||
node.innerHTML = step.handler(tiddler,this,store,utils);
|
|
||||||
break;
|
|
||||||
case "macro":
|
|
||||||
store.rerenderMacro(node,changes,step.macro,
|
|
||||||
step.renderType,
|
|
||||||
tiddler,
|
|
||||||
step.params(tiddler,this,store,utils),
|
|
||||||
step.content(tiddler,this,store,utils));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WikiTextRenderer.prototype.toString = function(type) {
|
|
||||||
var renderNode,
|
|
||||||
renderArray = function(tree) {
|
|
||||||
var children = [];
|
|
||||||
for(var t=0; t<tree.length; t++) {
|
|
||||||
children.push(HTML.elem("li",{
|
|
||||||
"class": ["nodeWikiTextRenderer"]
|
|
||||||
},renderNode(tree[t])));
|
|
||||||
}
|
|
||||||
return HTML.elem("ul",{
|
|
||||||
"class": ["treeWikiTextRenderer"]
|
|
||||||
},children);
|
|
||||||
};
|
|
||||||
renderNode = function(node) {
|
|
||||||
var ret = [];
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"rendererStep",
|
|
||||||
[HTML.text(node.step.toString())],
|
|
||||||
[HTML.text(node.type.toString())]
|
|
||||||
));
|
|
||||||
if(node.macro) {
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"macro",
|
|
||||||
[HTML.text("macro")],
|
|
||||||
[HTML.text(node.macro)]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if(node.params) {
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"params",
|
|
||||||
[HTML.text("params")],
|
|
||||||
[HTML.raw(utils.htmlEncode(node.params.toString()).replace(/\n/g,"<br>"))]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if(node.dependencies) {
|
|
||||||
var dependencies = [];
|
|
||||||
for(var d in node.dependencies) {
|
|
||||||
if(d === "dependentAll") {
|
|
||||||
dependencies.push(HTML.splitLabel("dependency",[HTML.text(d)],[HTML.text(node.dependencies[d])]));
|
|
||||||
} else {
|
|
||||||
var dependents = [];
|
|
||||||
for(var t in node.dependencies[d]) {
|
|
||||||
dependents.push(t);
|
|
||||||
}
|
|
||||||
dependencies.push(HTML.splitLabel("dependency",[HTML.text(d)],[HTML.text(dependents.join(","))]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"dependencies",
|
|
||||||
[HTML.text("Dependencies")],
|
|
||||||
dependencies
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if(node.content) {
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"content",
|
|
||||||
[HTML.text("content")],
|
|
||||||
[HTML.raw(utils.htmlEncode(node.content.toString()).replace(/\n/g,"<br>"))]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if(node.handler) {
|
|
||||||
ret.push(HTML.splitLabel(
|
|
||||||
"handler",
|
|
||||||
[HTML.text("handler")],
|
|
||||||
[HTML.raw(utils.htmlEncode(node.handler.toString()).replace(/\n/g,"<br>"))]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
return HTML(renderArray(this.renderSteps),type);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.WikiTextRenderer = WikiTextRenderer;
|
|
||||||
|
|
||||||
})();
|
|
@ -8,7 +8,7 @@ title: js/WikiTextRules.js
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var ArgParser = require("./ArgParser.js").ArgParser,
|
var ArgParser = require("./ArgParser.js").ArgParser,
|
||||||
HTML = require("./HTML.js").HTML,
|
Renderer = require("./Renderer.js").Renderer,
|
||||||
util = require("util");
|
util = require("util");
|
||||||
|
|
||||||
var textPrimitives = {
|
var textPrimitives = {
|
||||||
@ -97,11 +97,38 @@ var enclosedTextHelper = function(w) {
|
|||||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||||
var text = lookaheadMatch[1];
|
var text = lookaheadMatch[1];
|
||||||
w.output.push(HTML.elem(this.element,null,[HTML.text(text)]));
|
w.output.push(Renderer.ElementNode(this.element,null,[Renderer.TextNode(text)]));
|
||||||
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
|
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var compileMacroParams = function(w,params) {
|
||||||
|
// Slot the parameters into the macro call
|
||||||
|
var properties = [],n;
|
||||||
|
for(var p in params) {
|
||||||
|
if(params[p].type === "string") {
|
||||||
|
n = {type: "StringLiteral", value: params[p].value};
|
||||||
|
} else {
|
||||||
|
n = w.store.jsParser.parse(params[p].value).tree.elements[0];
|
||||||
|
}
|
||||||
|
properties.push({type: "PropertyAssignment",name: p,value: n});
|
||||||
|
}
|
||||||
|
return w.store.jsParser.createTree([
|
||||||
|
{
|
||||||
|
type: "Function",
|
||||||
|
name: null,
|
||||||
|
params: ["tiddler","store","utils"], // These are the parameters passed to the parameter expressions
|
||||||
|
elements: [ {
|
||||||
|
type: "ReturnStatement",
|
||||||
|
value: {
|
||||||
|
type: "ObjectLiteral",
|
||||||
|
properties: properties
|
||||||
|
}
|
||||||
|
} ]
|
||||||
|
}
|
||||||
|
]).compile("application/javascript").render;
|
||||||
|
};
|
||||||
|
|
||||||
var insertMacroCall = function(w,output,name,params,children) {
|
var insertMacroCall = function(w,output,name,params,children) {
|
||||||
var macro = w.store.macros[name],
|
var macro = w.store.macros[name],
|
||||||
dependencies = {};
|
dependencies = {};
|
||||||
@ -131,7 +158,7 @@ var insertMacroCall = function(w,output,name,params,children) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.mergeDependencies(dependencies);
|
w.mergeDependencies(dependencies);
|
||||||
output.push(HTML.macro(name,params,children,dependencies));
|
output.push(Renderer.MacroNode(name,compileMacroParams(w,params),children,dependencies,w.store));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,7 +201,7 @@ var rules = [
|
|||||||
rowTypes: {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
|
rowTypes: {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
|
||||||
handler: function(w)
|
handler: function(w)
|
||||||
{
|
{
|
||||||
var table = HTML.elem("table",{"class": "twtable"},[]);
|
var table = Renderer.ElementNode("table",{"class": "twtable"},[]);
|
||||||
w.output.push(table);
|
w.output.push(table);
|
||||||
var prevColumns = [];
|
var prevColumns = [];
|
||||||
var currRowType = null;
|
var currRowType = null;
|
||||||
@ -190,7 +217,7 @@ var rules = [
|
|||||||
w.nextMatch += lookaheadMatch[0].length+1;
|
w.nextMatch += lookaheadMatch[0].length+1;
|
||||||
} else {
|
} else {
|
||||||
if(nextRowType != currRowType) {
|
if(nextRowType != currRowType) {
|
||||||
rowContainer = HTML.elem(this.rowTypes[nextRowType],{},[]);
|
rowContainer = Renderer.ElementNode(this.rowTypes[nextRowType],{},[]);
|
||||||
table.children.push(rowContainer);
|
table.children.push(rowContainer);
|
||||||
currRowType = nextRowType;
|
currRowType = nextRowType;
|
||||||
}
|
}
|
||||||
@ -205,7 +232,7 @@ var rules = [
|
|||||||
rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
|
rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
|
||||||
w.subWikifyTerm(rowContainer.children,this.rowTermRegExp);
|
w.subWikifyTerm(rowContainer.children,this.rowTermRegExp);
|
||||||
} else {
|
} else {
|
||||||
var theRow = HTML.elem("tr",{},[]);
|
var theRow = Renderer.ElementNode("tr",{},[]);
|
||||||
theRow.attributes["class"] = rowCount%2 ? "oddRow" : "evenRow";
|
theRow.attributes["class"] = rowCount%2 ? "oddRow" : "evenRow";
|
||||||
rowContainer.children.push(theRow);
|
rowContainer.children.push(theRow);
|
||||||
this.rowHandler(w,theRow.children,prevColumns);
|
this.rowHandler(w,theRow.children,prevColumns);
|
||||||
@ -261,11 +288,11 @@ var rules = [
|
|||||||
}
|
}
|
||||||
var cell;
|
var cell;
|
||||||
if(chr == "!") {
|
if(chr == "!") {
|
||||||
cell = HTML.elem("th",{},[]);
|
cell = Renderer.ElementNode("th",{},[]);
|
||||||
e.push(cell);
|
e.push(cell);
|
||||||
w.nextMatch++;
|
w.nextMatch++;
|
||||||
} else {
|
} else {
|
||||||
cell = HTML.elem("td",{},[]);
|
cell = Renderer.ElementNode("td",{},[]);
|
||||||
e.push(cell);
|
e.push(cell);
|
||||||
}
|
}
|
||||||
prevCell = cell;
|
prevCell = cell;
|
||||||
@ -295,7 +322,7 @@ var rules = [
|
|||||||
termRegExp: /(\n)/mg,
|
termRegExp: /(\n)/mg,
|
||||||
handler: function(w)
|
handler: function(w)
|
||||||
{
|
{
|
||||||
var e = HTML.elem("h" + w.matchLength,{},[]);
|
var e = Renderer.ElementNode("h" + w.matchLength,{},[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,this.termRegExp);
|
w.subWikifyTerm(e.children,this.termRegExp);
|
||||||
}
|
}
|
||||||
@ -339,7 +366,7 @@ var rules = [
|
|||||||
if(currLevel !== 0 && target.children) {
|
if(currLevel !== 0 && target.children) {
|
||||||
target = target.children[target.children.length-1];
|
target = target.children[target.children.length-1];
|
||||||
}
|
}
|
||||||
e = HTML.elem(listType,{},[]);
|
e = Renderer.ElementNode(listType,{},[]);
|
||||||
target.push(e);
|
target.push(e);
|
||||||
stack.push(e.children);
|
stack.push(e.children);
|
||||||
}
|
}
|
||||||
@ -351,13 +378,13 @@ var rules = [
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
} else if(listLevel == currLevel && listType != currType) {
|
} else if(listLevel == currLevel && listType != currType) {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
e = HTML.elem(listType,{},[]);
|
e = Renderer.ElementNode(listType,{},[]);
|
||||||
stack[stack.length-1].push(e);
|
stack[stack.length-1].push(e);
|
||||||
stack.push(e.children);
|
stack.push(e.children);
|
||||||
}
|
}
|
||||||
currLevel = listLevel;
|
currLevel = listLevel;
|
||||||
currType = listType;
|
currType = listType;
|
||||||
e = HTML.elem(itemType,{},[]);
|
e = Renderer.ElementNode(itemType,{},[]);
|
||||||
stack[stack.length-1].push(e);
|
stack[stack.length-1].push(e);
|
||||||
w.subWikifyTerm(e.children,this.termRegExp);
|
w.subWikifyTerm(e.children,this.termRegExp);
|
||||||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||||||
@ -372,7 +399,7 @@ var rules = [
|
|||||||
termRegExp: /(^<<<(\n|$))/mg,
|
termRegExp: /(^<<<(\n|$))/mg,
|
||||||
element: "blockquote",
|
element: "blockquote",
|
||||||
handler: function(w) {
|
handler: function(w) {
|
||||||
var e = HTML.elem(this.element,{},[]);
|
var e = Renderer.ElementNode(this.element,{},[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,this.termRegExp);
|
w.subWikifyTerm(e.children,this.termRegExp);
|
||||||
}
|
}
|
||||||
@ -393,7 +420,7 @@ var rules = [
|
|||||||
do {
|
do {
|
||||||
if(newLevel > currLevel) {
|
if(newLevel > currLevel) {
|
||||||
for(t=currLevel; t<newLevel; t++) {
|
for(t=currLevel; t<newLevel; t++) {
|
||||||
e = HTML.elem(this.element,{},[]);
|
e = Renderer.ElementNode(this.element,{},[]);
|
||||||
stack[stack.length-1].push(e);
|
stack[stack.length-1].push(e);
|
||||||
}
|
}
|
||||||
} else if(newLevel < currLevel) {
|
} else if(newLevel < currLevel) {
|
||||||
@ -402,7 +429,7 @@ var rules = [
|
|||||||
}
|
}
|
||||||
currLevel = newLevel;
|
currLevel = newLevel;
|
||||||
w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
|
w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
|
||||||
stack[stack.length-1].push(HTML.elem("br"));
|
stack[stack.length-1].push(Renderer.ElementNode("br"));
|
||||||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||||
matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
|
matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
|
||||||
@ -419,7 +446,7 @@ var rules = [
|
|||||||
match: "^----+$\\n?|<hr ?/?>\\n?",
|
match: "^----+$\\n?|<hr ?/?>\\n?",
|
||||||
handler: function(w)
|
handler: function(w)
|
||||||
{
|
{
|
||||||
w.output.push(HTML.elem("hr"));
|
w.output.push(Renderer.ElementNode("hr"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -492,7 +519,7 @@ var rules = [
|
|||||||
}
|
}
|
||||||
insertMacroCall(w,w.output,"link",{
|
insertMacroCall(w,w.output,"link",{
|
||||||
target: {type: "string", value: link}
|
target: {type: "string", value: link}
|
||||||
},[HTML.text(text)]);
|
},[Renderer.TextNode(text)]);
|
||||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -519,7 +546,7 @@ var rules = [
|
|||||||
if(w.autoLinkWikiWords) {
|
if(w.autoLinkWikiWords) {
|
||||||
insertMacroCall(w,w.output,"link",{
|
insertMacroCall(w,w.output,"link",{
|
||||||
target: {type: "string", value: w.matchText}
|
target: {type: "string", value: w.matchText}
|
||||||
},[HTML.text(w.source.substring(w.matchStart,w.nextMatch))]);
|
},[Renderer.TextNode(w.source.substring(w.matchStart,w.nextMatch))]);
|
||||||
} else {
|
} else {
|
||||||
w.outputText(w.output,w.matchStart,w.nextMatch);
|
w.outputText(w.output,w.matchStart,w.nextMatch);
|
||||||
}
|
}
|
||||||
@ -533,7 +560,7 @@ var rules = [
|
|||||||
{
|
{
|
||||||
insertMacroCall(w,w.output,"link",{
|
insertMacroCall(w,w.output,"link",{
|
||||||
target: {type: "string", value: w.matchText}
|
target: {type: "string", value: w.matchText}
|
||||||
},[HTML.text(w.source.substring(w.matchStart,w.nextMatch))]);
|
},[Renderer.TextNode(w.source.substring(w.matchStart,w.nextMatch))]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -584,7 +611,7 @@ var rules = [
|
|||||||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||||
w.output.push(HTML.elem("html",{},[HTML.raw(lookaheadMatch[1])]));
|
w.output.push(Renderer.ElementNode("html",{},[Renderer.RawNode(lookaheadMatch[1])]));
|
||||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,32 +638,32 @@ var rules = [
|
|||||||
var e,lookaheadRegExp,lookaheadMatch;
|
var e,lookaheadRegExp,lookaheadMatch;
|
||||||
switch(w.matchText) {
|
switch(w.matchText) {
|
||||||
case "''":
|
case "''":
|
||||||
e = HTML.elem("strong",null,[]);
|
e = Renderer.ElementNode("strong",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,/('')/mg);
|
w.subWikifyTerm(e.children,/('')/mg);
|
||||||
break;
|
break;
|
||||||
case "//":
|
case "//":
|
||||||
e = HTML.elem("em",null,[]);
|
e = Renderer.ElementNode("em",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,/(\/\/)/mg);
|
w.subWikifyTerm(e.children,/(\/\/)/mg);
|
||||||
break;
|
break;
|
||||||
case "__":
|
case "__":
|
||||||
e = HTML.elem("u",null,[]);
|
e = Renderer.ElementNode("u",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,/(__)/mg);
|
w.subWikifyTerm(e.children,/(__)/mg);
|
||||||
break;
|
break;
|
||||||
case "^^":
|
case "^^":
|
||||||
e = HTML.elem("sup",null,[]);
|
e = Renderer.ElementNode("sup",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,/(\^\^)/mg);
|
w.subWikifyTerm(e.children,/(\^\^)/mg);
|
||||||
break;
|
break;
|
||||||
case "~~":
|
case "~~":
|
||||||
e = HTML.elem("sub",null,[]);
|
e = Renderer.ElementNode("sub",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,/(~~)/mg);
|
w.subWikifyTerm(e.children,/(~~)/mg);
|
||||||
break;
|
break;
|
||||||
case "--":
|
case "--":
|
||||||
e = HTML.elem("strike",null,[]);
|
e = Renderer.ElementNode("strike",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
w.subWikifyTerm(e.children,/(--)/mg);
|
w.subWikifyTerm(e.children,/(--)/mg);
|
||||||
break;
|
break;
|
||||||
@ -645,7 +672,7 @@ var rules = [
|
|||||||
lookaheadRegExp.lastIndex = w.matchStart;
|
lookaheadRegExp.lastIndex = w.matchStart;
|
||||||
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||||
w.output.push(HTML.elem("code",null,[HTML.text(lookaheadMatch[1])]));
|
w.output.push(Renderer.ElementNode("code",null,[Renderer.TextNode(lookaheadMatch[1])]));
|
||||||
w.nextMatch = lookaheadRegExp.lastIndex;
|
w.nextMatch = lookaheadRegExp.lastIndex;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -654,7 +681,7 @@ var rules = [
|
|||||||
lookaheadRegExp.lastIndex = w.matchStart;
|
lookaheadRegExp.lastIndex = w.matchStart;
|
||||||
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||||
w.output.push(HTML.elem("code",null,[HTML.text(lookaheadMatch[1])]));
|
w.output.push(Renderer.ElementNode("code",null,[Renderer.TextNode(lookaheadMatch[1])]));
|
||||||
w.nextMatch = lookaheadRegExp.lastIndex;
|
w.nextMatch = lookaheadRegExp.lastIndex;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -669,7 +696,7 @@ var rules = [
|
|||||||
{
|
{
|
||||||
switch(w.matchText) {
|
switch(w.matchText) {
|
||||||
case "@@":
|
case "@@":
|
||||||
var e = HTML.elem("span",null,[]);
|
var e = Renderer.ElementNode("span",null,[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
var styles = inlineCssHelper(w);
|
var styles = inlineCssHelper(w);
|
||||||
if(styles.length === 0)
|
if(styles.length === 0)
|
||||||
@ -684,7 +711,7 @@ var rules = [
|
|||||||
var lookaheadMatch = lookaheadRegExp.exec(w.source);
|
var lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||||
if(lookaheadMatch) {
|
if(lookaheadMatch) {
|
||||||
w.nextMatch = lookaheadRegExp.lastIndex;
|
w.nextMatch = lookaheadRegExp.lastIndex;
|
||||||
e = HTML.elem(lookaheadMatch[2] == "\n" ? "div" : "span",{
|
e = Renderer.ElementNode(lookaheadMatch[2] == "\n" ? "div" : "span",{
|
||||||
"class": lookaheadMatch[1]
|
"class": lookaheadMatch[1]
|
||||||
},[]);
|
},[]);
|
||||||
w.output.push(e);
|
w.output.push(e);
|
||||||
@ -700,7 +727,7 @@ var rules = [
|
|||||||
match: "--",
|
match: "--",
|
||||||
handler: function(w)
|
handler: function(w)
|
||||||
{
|
{
|
||||||
w.output.push(HTML.entity("—"));
|
w.output.push(Renderer.EntityNode("—"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -709,7 +736,7 @@ var rules = [
|
|||||||
match: "\\n|<br ?/?>",
|
match: "\\n|<br ?/?>",
|
||||||
handler: function(w)
|
handler: function(w)
|
||||||
{
|
{
|
||||||
w.output.push(HTML.elem("br"));
|
w.output.push(Renderer.ElementNode("br"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -722,7 +749,7 @@ var rules = [
|
|||||||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||||
w.output.push(HTML.text(lookaheadMatch[1]));
|
w.output.push(Renderer.TextNode(lookaheadMatch[1]));
|
||||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -733,7 +760,7 @@ var rules = [
|
|||||||
match: "&#?[a-zA-Z0-9]{2,8};",
|
match: "&#?[a-zA-Z0-9]{2,8};",
|
||||||
handler: function(w)
|
handler: function(w)
|
||||||
{
|
{
|
||||||
w.output.push(HTML.entity(w.matchText));
|
w.output.push(Renderer.EntityNode(w.matchText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ title: js/macros/echo.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("../Utils.js");
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "echo",
|
name: "echo",
|
||||||
@ -15,12 +15,8 @@ exports.macro = {
|
|||||||
params: {
|
params: {
|
||||||
text: {byPos: 0, type: "text", optional: false}
|
text: {byPos: 0, type: "text", optional: false}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
if(type === "text/html") {
|
return [Renderer.TextNode(macroNode.params.text)];
|
||||||
return utils.htmlEncode(params.text);
|
|
||||||
} else {
|
|
||||||
return params.text;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@ title: js/macros/image.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var HTML = require("../HTML.js").HTML,
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
utils = require("../Utils.js");
|
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "image",
|
name: "image",
|
||||||
@ -18,28 +17,27 @@ exports.macro = {
|
|||||||
text: {byName: true, type: "text", optional: true},
|
text: {byName: true, type: "text", optional: true},
|
||||||
alignment: {byName: true, type: "text", optional: true}
|
alignment: {byName: true, type: "text", optional: true}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
if(type === "text/html") {
|
if(store.tiddlerExists(macroNode.params.src)) {
|
||||||
if(store.tiddlerExists(params.src)) {
|
var imageTree = store.parseTiddler(macroNode.params.src).tree,
|
||||||
if(params.text) {
|
cloneImage = [];
|
||||||
return HTML(HTML.elem("div",{
|
for(var t=0; t<imageTree.length; t++) {
|
||||||
alt: params.text,
|
cloneImage.push(imageTree[t].clone());
|
||||||
title: params.text
|
|
||||||
},[
|
|
||||||
HTML.raw(store.renderTiddler(type,params.src))
|
|
||||||
]));
|
|
||||||
} else {
|
|
||||||
return store.renderTiddler(type,params.src);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return HTML(HTML.elem("img",{
|
|
||||||
href: params.src,
|
|
||||||
alt: params.text,
|
|
||||||
title: params.text
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
} else if (type === "text/plain") {
|
if(macroNode.params.text) {
|
||||||
return params.text ? params.text : "";
|
return [Renderer.ElementNode("div",{
|
||||||
|
alt: macroNode.params.text,
|
||||||
|
title: macroNode.params.text
|
||||||
|
},cloneImage)];
|
||||||
|
} else {
|
||||||
|
return cloneImage;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return [Renderer.ElementNode("img",{
|
||||||
|
href: macroNode.params.src,
|
||||||
|
alt: macroNode.params.text,
|
||||||
|
title: macroNode.params.text
|
||||||
|
})];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ title: js/macros/info.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var HTML = require("../HTML.js").HTML,
|
var Renderer = require("../Renderer.js").Renderer,
|
||||||
utils = require("../Utils.js");
|
utils = require("../Utils.js");
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
@ -31,16 +31,16 @@ exports.macro = {
|
|||||||
var parseTree = store.parseTiddler(tiddler.title);
|
var parseTree = store.parseTiddler(tiddler.title);
|
||||||
switch(info) {
|
switch(info) {
|
||||||
case "parsetree":
|
case "parsetree":
|
||||||
return HTML(HTML.slider("parsetree",
|
return [Renderer.SliderNode("parsetree",
|
||||||
"Parse tree",
|
"Parse tree",
|
||||||
"The parse tree for this tiddler",
|
"The parse tree for this tiddler",
|
||||||
HTML.raw(parseTree.toString(type))),type);
|
(parseTree.toString(type)))];
|
||||||
//break;
|
//break;
|
||||||
case "compiled":
|
case "compiled":
|
||||||
return HTML(HTML.slider("compiled",
|
return [Renderer.SliderNode("compiled",
|
||||||
"Render functions",
|
"Render functions",
|
||||||
"The render functions for this tiddler",
|
"The render functions for this tiddler",
|
||||||
HTML.raw(parseTree.compile(type).toString(type))),type);
|
(parseTree.compile(type).toString(type)))];
|
||||||
//break;
|
//break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ title: js/macros/link.js
|
|||||||
/*jslint node: true, browser: true */
|
/*jslint node: true, browser: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var HTML = require("../HTML.js").HTML,
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
utils = require("../Utils.js");
|
|
||||||
|
|
||||||
var isLinkExternal = function(target) {
|
var isLinkExternal = function(target) {
|
||||||
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
|
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
|
||||||
@ -23,42 +22,43 @@ exports.macro = {
|
|||||||
target: {byName: "default", type: "tiddler", rel: "link", optional: false}
|
target: {byName: "default", type: "tiddler", rel: "link", optional: false}
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
click: function(event,node,tiddler,store,params) {
|
click: function(event,macroNode) {
|
||||||
if(isLinkExternal(params.target)) {
|
if(isLinkExternal(macroNode.params.target)) {
|
||||||
event.target.setAttribute("target","_blank");
|
event.target.setAttribute("target","_blank");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
var navEvent = document.createEvent("Event");
|
var navEvent = document.createEvent("Event");
|
||||||
navEvent.initEvent("tw-navigate",true,true);
|
navEvent.initEvent("tw-navigate",true,true);
|
||||||
navEvent.navigateTo = params.target;
|
navEvent.navigateTo = macroNode.params.target;
|
||||||
node.dispatchEvent(navEvent);
|
event.target.dispatchEvent(navEvent);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params,content) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
var classes = ["tw-tiddlylink"],
|
var classes = ["tw-tiddlylink"],
|
||||||
target = params.target;
|
target = macroNode.params.target;
|
||||||
if(isLinkExternal(params.target)) {
|
if(isLinkExternal(target)) {
|
||||||
classes.push("tw-tiddlylink-external");
|
classes.push("tw-tiddlylink-external");
|
||||||
} else {
|
} else {
|
||||||
classes.push("tw-tiddlylink-internal");
|
classes.push("tw-tiddlylink-internal");
|
||||||
if(store.tiddlerExists(params.target)) {
|
if(store.tiddlerExists(target)) {
|
||||||
classes.push("tw-tiddlylink-resolves");
|
classes.push("tw-tiddlylink-resolves");
|
||||||
} else {
|
} else {
|
||||||
classes.push("tw-tiddlylink-missing");
|
classes.push("tw-tiddlylink-missing");
|
||||||
}
|
}
|
||||||
target = encodeURIComponent(target);
|
target = encodeURIComponent(target);
|
||||||
}
|
}
|
||||||
return HTML(HTML.elem(
|
var content = [Renderer.ElementNode(
|
||||||
"a",{
|
"a",{
|
||||||
href: target,
|
href: target,
|
||||||
"class": classes
|
"class": classes
|
||||||
},[
|
},macroNode.cloneChildren())];
|
||||||
HTML.raw(content)
|
for(var t=0; t<content.length; t++) {
|
||||||
]
|
content[t].execute(tiddler);
|
||||||
),type);
|
}
|
||||||
|
return content;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ title: js/macros/list.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("../Utils.js");
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
|
|
||||||
var handlers = {
|
var handlers = {
|
||||||
all: function(store) {
|
all: function(store) {
|
||||||
@ -41,35 +41,33 @@ exports.macro = {
|
|||||||
template: {byName: true, type: "tiddler", optional: true},
|
template: {byName: true, type: "tiddler", optional: true},
|
||||||
emptyMessage: {byName: true, type: "text", optional: true}
|
emptyMessage: {byName: true, type: "text", optional: true}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
var templateType = "text/x-tiddlywiki",
|
var templateType = "text/x-tiddlywiki",
|
||||||
templateText = "<<view title link>>",
|
templateText = "<<view title link>>",
|
||||||
template = params.template ? store.getTiddler(params.template) : null,
|
template = macroNode.params.template ? store.getTiddler(macroNode.params.template) : null,
|
||||||
output = [],
|
content = [],
|
||||||
isHtml = type === "text/html",
|
|
||||||
encoder = isHtml ? utils.htmlEncode : function(x) {return x;},
|
|
||||||
pushTag = isHtml ? function(x) {output.push(x);} : function(x) {},
|
|
||||||
handler,
|
|
||||||
t;
|
t;
|
||||||
if(template) {
|
if(template) {
|
||||||
templateType = template.type;
|
templateType = template.type;
|
||||||
templateText = template.text;
|
templateText = template.text;
|
||||||
}
|
}
|
||||||
handler = handlers[params.type];
|
var handler = handlers[macroNode.params.type];
|
||||||
handler = handler || handlers.all;
|
handler = handler || handlers.all;
|
||||||
var tiddlers = handler(store);
|
var tiddlers = handler(store);
|
||||||
if(tiddlers.length === 0) {
|
if(tiddlers.length === 0) {
|
||||||
return params.emptyMessage ? encoder(params.emptyMessage) : "";
|
return [Renderer.TextNode(macroNode.params.emptyMessage || "")];
|
||||||
} else {
|
} else {
|
||||||
var renderer = store.compileText(templateType,templateText,type);
|
var templateTree = store.parseText(templateType,templateText).tree;
|
||||||
pushTag("<ul>");
|
|
||||||
for(t=0; t<tiddlers.length; t++) {
|
for(t=0; t<tiddlers.length; t++) {
|
||||||
pushTag("<li>");
|
var cloneTemplate = [];
|
||||||
output.push(renderer.render(store.getTiddler(tiddlers[t]),store));
|
for(var c=0; c<templateTree.length; c++) {
|
||||||
pushTag("</li>");
|
cloneTemplate.push(templateTree[c].clone());
|
||||||
|
}
|
||||||
|
var listNode = Renderer.ElementNode("li",null,cloneTemplate);
|
||||||
|
listNode.execute(store.getTiddler(tiddlers[t]));
|
||||||
|
content.push(listNode);
|
||||||
}
|
}
|
||||||
pushTag("</ul>");
|
return [Renderer.ElementNode("ul",null,content)];
|
||||||
return output.join("");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ title: js/macros/slider.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var HTML = require("../HTML.js").HTML,
|
var Renderer = require("../Renderer.js").Renderer,
|
||||||
utils = require("../Utils.js");
|
utils = require("../Utils.js");
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
@ -20,23 +20,25 @@ exports.macro = {
|
|||||||
tooltip: {byPos: 3, type: "text", optional: true}
|
tooltip: {byPos: 3, type: "text", optional: true}
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
click: function(event,node,tiddler,store,params) {
|
click: function(event,macroNode) {
|
||||||
var el = node.firstChild.firstChild.nextSibling;
|
var el = event.currentTarget.firstChild.firstChild.nextSibling;
|
||||||
el.style.display = el.style.display === "block" ? "none" : "block";
|
el.style.display = el.style.display === "block" ? "none" : "block";
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
if(type === "text/html") {
|
var target = macroNode.params.targetTiddler,
|
||||||
return HTML(HTML.slider(params.name,
|
dependencies = {include: {}};
|
||||||
params.label,
|
dependencies.include[target] = 1;
|
||||||
params.tooltip,
|
var content = Renderer.SliderNode(macroNode.params.name,
|
||||||
HTML.raw(store.renderTiddler(type,params.targetTiddler))),type);
|
macroNode.params.label,
|
||||||
} else if(type === "text/plain") {
|
macroNode.params.tooltip,
|
||||||
return store.renderTiddler(type,params.target);
|
[
|
||||||
}
|
Renderer.MacroNode("tiddler",{target: target},null,dependencies,store)
|
||||||
return null;
|
]);
|
||||||
|
content.execute(tiddler);
|
||||||
|
return [content];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ title: js/macros/story.js
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Tiddler = require("../Tiddler.js").Tiddler,
|
var Tiddler = require("../Tiddler.js").Tiddler,
|
||||||
|
Renderer = require("../Renderer.js").Renderer,
|
||||||
utils = require("../Utils.js");
|
utils = require("../Utils.js");
|
||||||
|
|
||||||
// Parse the text of a story tiddler into an array of tiddler titles
|
// Parse the text of a story tiddler into an array of tiddler titles
|
||||||
@ -23,19 +24,6 @@ var parseStory = function(storyText) {
|
|||||||
return tiddlers;
|
return tiddlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Search the children of a node looking for the required tiddler rendering
|
|
||||||
var searchTiddlerNode = function(node,renderTiddler,renderTemplate) {
|
|
||||||
while(node !== null) {
|
|
||||||
if(node.getAttribute && node.getAttribute("data-tw-render-tiddler") === renderTiddler) {
|
|
||||||
if(!renderTemplate || (renderTemplate && node.getAttribute("data-tw-render-template") == renderTemplate)) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node = node.nextSibling;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "story",
|
name: "story",
|
||||||
types: ["text/html","text/plain"],
|
types: ["text/html","text/plain"],
|
||||||
@ -44,9 +32,9 @@ exports.macro = {
|
|||||||
template: {byName: true, type: "tiddler", optional: true}
|
template: {byName: true, type: "tiddler", optional: true}
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
"tw-navigate": function(event,node,tiddler,store,params) {
|
"tw-navigate": function(event,macroNode) {
|
||||||
var storyTiddler = store.getTiddler(params.story);
|
var storyTiddler = macroNode.store.getTiddler(macroNode.params.story);
|
||||||
store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
|
macroNode.store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
|
||||||
$("html,body").animate({
|
$("html,body").animate({
|
||||||
scrollTop: 0
|
scrollTop: 0
|
||||||
}, 400);
|
}, 400);
|
||||||
@ -54,53 +42,77 @@ exports.macro = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
var tiddlers = parseStory(store.getTiddlerText(params.story)),
|
var tiddlers = parseStory(store.getTiddlerText(macroNode.params.story)),
|
||||||
output = [];
|
content = [];
|
||||||
for(var t=0; t<tiddlers.length; t++) {
|
for(var t=0; t<tiddlers.length; t++) {
|
||||||
if(params.template) {
|
var paramFn = {target: tiddlers[t],template: macroNode.params.template},
|
||||||
output.push(store.renderTiddler(type,tiddlers[t],params.template));
|
dependencies = {include: {}};
|
||||||
} else {
|
dependencies.include[tiddlers[t]] = 1;
|
||||||
output.push(store.renderTiddler(type,tiddlers[t]));
|
if(macroNode.params.template) {
|
||||||
|
dependencies.include[macroNode.params.template] = 1;
|
||||||
}
|
}
|
||||||
|
var m = Renderer.MacroNode("tiddler",paramFn,null,dependencies,store);
|
||||||
|
m.execute(tiddler);
|
||||||
|
content.push(m);
|
||||||
}
|
}
|
||||||
return output.join("\n");
|
return content;
|
||||||
},
|
},
|
||||||
rerender: function(node,changes,type,tiddler,store,params) {
|
refresh: function(macroNode,tiddler,store) {
|
||||||
/*jslint browser: true */
|
/*jslint browser: true */
|
||||||
// Get the tiddlers we're supposed to be displaying
|
// Get the tiddlers we're supposed to be displaying
|
||||||
var targetTiddlers = parseStory(store.getTiddlerText(params.story)),
|
var targetTiddlers = parseStory(store.getTiddlerText(macroNode.params.story)),
|
||||||
currNode = node.firstChild,
|
template = macroNode.params.template,
|
||||||
nextNode;
|
t,n,domNode,
|
||||||
for(var t=0; t<targetTiddlers.length; t++) {
|
findTiddler = function (childIndex,tiddlerTitle,templateTitle) {
|
||||||
|
while(childIndex < macroNode.content.length) {
|
||||||
|
var params = macroNode.content[childIndex].params;
|
||||||
|
if(params.target === tiddlerTitle) {
|
||||||
|
if(!templateTitle || params.template === templateTitle) {
|
||||||
|
return childIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
childIndex++;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
for(t=0; t<targetTiddlers.length; t++) {
|
||||||
// See if the node we want is already there
|
// See if the node we want is already there
|
||||||
var tiddlerNode = searchTiddlerNode(currNode,targetTiddlers[t],params.template);
|
var tiddlerNode = findTiddler(t,targetTiddlers[t],template);
|
||||||
if(tiddlerNode === null) {
|
if(tiddlerNode === null) {
|
||||||
// If not, render the tiddler
|
// If not, render the tiddler
|
||||||
var tmpNode = document.createElement("div");
|
var paramFn = {target: targetTiddlers[t],template: template},
|
||||||
store.renderTiddlerInNode(tmpNode,targetTiddlers[t],params.template);
|
dependencies = {include: {}};
|
||||||
tiddlerNode = tmpNode.firstChild;
|
dependencies.include[targetTiddlers[t]] = 1;
|
||||||
node.insertBefore(tiddlerNode,currNode);
|
if(template) {
|
||||||
|
dependencies.include[template] = 1;
|
||||||
|
}
|
||||||
|
var m = Renderer.MacroNode("tiddler",paramFn,null,dependencies,store);
|
||||||
|
m.execute(store.getTiddler(targetTiddlers[t]));
|
||||||
|
m.renderInDom(macroNode.domNode,macroNode.domNode.childNodes[t]);
|
||||||
|
macroNode.content.splice(t,0,m);
|
||||||
} else {
|
} else {
|
||||||
// Delete any nodes preceding the one we want
|
// Delete any nodes preceding the one we want
|
||||||
while(currNode !== tiddlerNode) {
|
if(tiddlerNode > t) {
|
||||||
nextNode = currNode.nextSibling;
|
// First delete the DOM nodes
|
||||||
node.removeChild(currNode);
|
for(n=t; n<tiddlerNode; n++) {
|
||||||
currNode = nextNode;
|
domNode = macroNode.content[n].domNode;
|
||||||
|
domNode.parentNode.removeChild(domNode);
|
||||||
|
}
|
||||||
|
// Then delete the actual renderer nodes
|
||||||
|
macroNode.content.splice(t,tiddlerNode-t);
|
||||||
}
|
}
|
||||||
// Refresh it
|
|
||||||
store.refreshDomNode(tiddlerNode,changes);
|
|
||||||
currNode = currNode.nextSibling;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove any unused nodes
|
// Remove any left over nodes
|
||||||
while(currNode !== null) {
|
if(macroNode.content.length > targetTiddlers.length) {
|
||||||
nextNode = currNode.nextSibling;
|
for(t=targetTiddlers.length; t<macroNode.content.length; t++) {
|
||||||
node.removeChild(currNode);
|
domNode = macroNode.content[t].domNode;
|
||||||
currNode = nextNode;
|
domNode.parentNode.removeChild(domNode);
|
||||||
|
}
|
||||||
|
macroNode.content.splice(targetTiddlers.length,macroNode.content.length-targetTiddlers.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ the `template` parameter or, if that parameter is missing, the tiddler named in
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("../Utils.js");
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "tiddler",
|
name: "tiddler",
|
||||||
@ -53,29 +53,39 @@ exports.macro = {
|
|||||||
template: {byName: true, type: "tiddler", optional: true},
|
template: {byName: true, type: "tiddler", optional: true},
|
||||||
"with": {byName: true, type: "text", optional: true, dependentAll: true}
|
"with": {byName: true, type: "text", optional: true, dependentAll: true}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
var renderTitle = params.target,
|
var renderTitle = macroNode.params.target,
|
||||||
renderTemplate = params.template;
|
renderTemplate = macroNode.params.template,
|
||||||
|
content,
|
||||||
|
contentClone = [],
|
||||||
|
t;
|
||||||
if(typeof renderTitle !== "string") {
|
if(typeof renderTitle !== "string") {
|
||||||
renderTitle = tiddler.title;
|
renderTitle = tiddler.title;
|
||||||
}
|
}
|
||||||
if(typeof renderTemplate !== "string") {
|
if(typeof renderTemplate !== "string") {
|
||||||
renderTemplate = renderTitle;
|
renderTemplate = renderTitle;
|
||||||
}
|
}
|
||||||
if(params["with"]) {
|
if("with" in macroNode.params) {
|
||||||
// Parameterised transclusion
|
// Parameterised transclusion
|
||||||
var targetTiddler = store.getTiddler(renderTemplate),
|
var targetTiddler = store.getTiddler(renderTemplate),
|
||||||
text = targetTiddler.text;
|
text = targetTiddler.text;
|
||||||
var withTokens = [params["with"]];
|
var withTokens = [macroNode.params["with"]];
|
||||||
for(var t=0; t<withTokens.length; t++) {
|
for(t=0; t<withTokens.length; t++) {
|
||||||
var placeholderRegExp = new RegExp("\\$"+(t+1),"mg");
|
var placeholderRegExp = new RegExp("\\$"+(t+1),"mg");
|
||||||
text = text.replace(placeholderRegExp,withTokens[t]);
|
text = text.replace(placeholderRegExp,withTokens[t]);
|
||||||
}
|
}
|
||||||
return store.renderText(targetTiddler.type,text,type,renderTitle);
|
content = store.parseText(targetTiddler.type,text).tree;
|
||||||
} else {
|
} else {
|
||||||
// There's no parameterisation, so we can just render the target tiddler directly
|
// There's no parameterisation, so we can just render the target tiddler directly
|
||||||
return store.renderTiddler(type,renderTitle,renderTemplate);
|
content = store.parseTiddler(renderTemplate).tree;
|
||||||
}
|
}
|
||||||
|
for(t=0; t<content.length; t++) {
|
||||||
|
contentClone.push(content[t].clone());
|
||||||
|
}
|
||||||
|
for(t=0; t<contentClone.length; t++) {
|
||||||
|
contentClone[t].execute(store.getTiddler(renderTitle));
|
||||||
|
}
|
||||||
|
return contentClone;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,15 +7,15 @@ title: js/macros/version.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("../Utils.js");
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "version",
|
name: "version",
|
||||||
types: ["text/html","text/plain"],
|
types: ["text/html","text/plain"],
|
||||||
params: {
|
params: {
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
return "5.0.0";
|
return [Renderer.TextNode("5.0.0")];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ title: js/macros/video.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("../Utils.js");
|
var Renderer = require("../Renderer.js").Renderer;
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "video",
|
name: "video",
|
||||||
@ -18,21 +18,36 @@ exports.macro = {
|
|||||||
width: {byName: true, type: "text", optional: true},
|
width: {byName: true, type: "text", optional: true},
|
||||||
height: {byName: true, type: "text", optional: true}
|
height: {byName: true, type: "text", optional: true}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
var videoType = params.type || "vimeo",
|
var src = macroNode.params.src,
|
||||||
videoWidth = params.width || 640,
|
videoType = macroNode.params.type || "vimeo",
|
||||||
videoHeight = params.height || 360;
|
videoWidth = macroNode.params.width || 640,
|
||||||
if(type === "text/html") {
|
videoHeight = macroNode.params.height || 360;
|
||||||
switch(videoType) {
|
switch(videoType) {
|
||||||
case "vimeo":
|
case "vimeo":
|
||||||
return "<iframe src='http://player.vimeo.com/video/" + params.src + "?autoplay=0' width='" + videoWidth + "' height='" + videoHeight + "' frameborder='0'></iframe>";
|
return [Renderer.ElementNode("iframe",{
|
||||||
case "youtube":
|
src: "http://player.vimeo.com/video/" + src + "?autoplay=0",
|
||||||
return "<iframe type='text/html' width='" + videoWidth + "' height='" + videoHeight + "' src='http://www.youtube.com/embed/" + params.src + "' frameborder='0'></iframe>";
|
width: videoWidth,
|
||||||
case "archiveorg":
|
height: videoHeight,
|
||||||
return "<iframe src='http://www.archive.org/embed/" + params.src + "' width='" + videoWidth + "' height='" + videoHeight + "' frameborder='0'></iframe>";
|
frameborder: 0
|
||||||
}
|
})];
|
||||||
} else if (type === "text/plain") {
|
case "youtube":
|
||||||
return ""; // Not really sure how to render a video into plain text...
|
return [Renderer.ElementNode("iframe",{
|
||||||
|
type: "text/html",
|
||||||
|
src: "http://www.youtube.com/embed/" + src,
|
||||||
|
width: videoWidth,
|
||||||
|
height: videoHeight,
|
||||||
|
frameborder: 0
|
||||||
|
})];
|
||||||
|
case "archiveorg":
|
||||||
|
return [Renderer.ElementNode("iframe",{
|
||||||
|
src: "http://www.archive.org/embed/" + src,
|
||||||
|
width: videoWidth,
|
||||||
|
height: videoHeight,
|
||||||
|
frameborder: 0
|
||||||
|
})];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,8 @@ title: js/macros/view.js
|
|||||||
/*jslint node: true */
|
/*jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var utils = require("../Utils.js");
|
var Renderer = require("../Renderer.js").Renderer,
|
||||||
|
utils = require("../Utils.js");
|
||||||
|
|
||||||
exports.macro = {
|
exports.macro = {
|
||||||
name: "view",
|
name: "view",
|
||||||
@ -17,28 +18,44 @@ exports.macro = {
|
|||||||
format: {byPos: 1, type: "text", optional: true},
|
format: {byPos: 1, type: "text", optional: true},
|
||||||
template: {byPos: 2, type: "text", optional: true}
|
template: {byPos: 2, type: "text", optional: true}
|
||||||
},
|
},
|
||||||
render: function(type,tiddler,store,params) {
|
execute: function(macroNode,tiddler,store) {
|
||||||
var encoder = type === "text/html" ? utils.htmlEncode : function(x) {return x;};
|
|
||||||
if(!tiddler) {
|
if(!tiddler) {
|
||||||
return "{{** Missing tiddler **}}";
|
return Renderer.TextNode("{{** Missing tiddler **}}");
|
||||||
} else {
|
} else {
|
||||||
var v = tiddler[params.field];
|
var v = tiddler[macroNode.params.field],
|
||||||
|
content,
|
||||||
|
t,
|
||||||
|
contentClone = [];
|
||||||
if(v !== undefined) {
|
if(v !== undefined) {
|
||||||
switch(params.format) {
|
switch(macroNode.params.format) {
|
||||||
case "link":
|
case "link":
|
||||||
return store.renderMacro("link",type,tiddler,{target: v},encoder(v));
|
var dependencies = {link: {}};
|
||||||
|
dependencies.link[v] = 1;
|
||||||
|
var link = Renderer.MacroNode("link",
|
||||||
|
{target: v},
|
||||||
|
[Renderer.TextNode(v)],
|
||||||
|
dependencies,
|
||||||
|
store);
|
||||||
|
link.execute(tiddler);
|
||||||
|
return [link];
|
||||||
case "wikified":
|
case "wikified":
|
||||||
if(params.field === "text") {
|
if(macroNode.params.field === "text") {
|
||||||
return store.renderTiddler(type,tiddler.title);
|
content = store.parseTiddler(tiddler.title).tree;
|
||||||
} else {
|
} else {
|
||||||
return store.renderText("text/x-tiddlywiki",v,type,tiddler.title);
|
content = store.parseText("text/x-tiddlywiki",v).tree;
|
||||||
}
|
}
|
||||||
break;
|
for(t=0; t<content.length; t++) {
|
||||||
|
contentClone.push(content[t].clone());
|
||||||
|
}
|
||||||
|
for(t=0; t<contentClone.length; t++) {
|
||||||
|
contentClone[t].execute(tiddler);
|
||||||
|
}
|
||||||
|
return contentClone;
|
||||||
case "date":
|
case "date":
|
||||||
var template = params.template || "DD MMM YYYY";
|
var template = macroNode.params.template || "DD MMM YYYY";
|
||||||
return encoder(utils.formatDateString(v,template));
|
return [Renderer.TextNode(utils.formatDateString(v,template))];
|
||||||
default: // "text"
|
default: // "text"
|
||||||
return encoder(v);
|
return [Renderer.TextNode(v)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user