mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-24 00:50:28 +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,
|
||||
tiddlerInput = require("./TiddlerInput.js"),
|
||||
tiddlerOutput = require("./TiddlerOutput.js"),
|
||||
Renderer = require("./Renderer.js").Renderer,
|
||||
WikiTextParser = require("./WikiTextParser.js").WikiTextParser,
|
||||
JSONParser = require("./JSONParser.js").JSONParser,
|
||||
JavaScriptParser = require("./JavaScriptParser.js").JavaScriptParser,
|
||||
@ -99,9 +100,8 @@ var App = function() {
|
||||
// Set up navigation if we're in the browser
|
||||
if(this.isBrowser) {
|
||||
// Open the PageTemplate
|
||||
var div = document.createElement("div");
|
||||
this.store.renderTiddlerInNode(div,"PageTemplate");
|
||||
document.body.appendChild(div);
|
||||
var renderer = new Renderer("PageTemplate",null,this.store);
|
||||
renderer.renderInDom(document.body);
|
||||
// Set up a timer to change the value of a tiddler
|
||||
var me = this;
|
||||
window.setInterval(function() {
|
||||
@ -112,7 +112,7 @@ var App = function() {
|
||||
},3000);
|
||||
// Register an event handler to handle refreshing the DOM
|
||||
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";
|
||||
|
||||
var WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
||||
HTML = require("./HTML.js").HTML,
|
||||
Renderer = require("./Renderer.js").Renderer,
|
||||
utils = require("./Utils.js");
|
||||
|
||||
var ImageParser = function(options) {
|
||||
@ -19,12 +19,12 @@ var ImageParser = function(options) {
|
||||
|
||||
ImageParser.prototype.parse = function(type,text) {
|
||||
var src;
|
||||
if(this.type === "image/svg+xml") {
|
||||
if(type === "image/svg+xml") {
|
||||
src = "data:" + type + "," + encodeURIComponent(text);
|
||||
} else {
|
||||
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;
|
||||
|
@ -10,31 +10,31 @@ Compiles JSON objects into JavaScript functions that render them in HTML and pla
|
||||
"use strict";
|
||||
|
||||
var WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
||||
HTML = require("./HTML.js").HTML,
|
||||
Renderer = require("./Renderer.js").Renderer,
|
||||
utils = require("./Utils.js");
|
||||
|
||||
var renderObject = function(obj) {
|
||||
var children = [],t;
|
||||
if(obj instanceof Array) {
|
||||
for(t=0; t<obj.length; t++) {
|
||||
children.push(HTML.elem("li",{
|
||||
children.push(Renderer.ElementNode("li",{
|
||||
"class": ["jsonArrayMember"]
|
||||
},[renderObject(obj[t])]));
|
||||
}
|
||||
return HTML.elem("ul",{
|
||||
return Renderer.ElementNode("ul",{
|
||||
"class": ["jsonArray"]
|
||||
},children);
|
||||
} else if(typeof obj === "object") {
|
||||
for(t in obj) {
|
||||
children.push(HTML.elem("li",{
|
||||
children.push(Renderer.ElementNode("li",{
|
||||
"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"]
|
||||
},children);
|
||||
} 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) {
|
||||
return String.fromCharCode(c);
|
||||
} 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";
|
||||
|
||||
var Tiddler = require("./Tiddler.js").Tiddler,
|
||||
HTML = require("./HTML.js").HTML,
|
||||
Renderer = require("./Renderer.js").Renderer,
|
||||
utils = require("./Utils.js");
|
||||
|
||||
/* Creates a new WikiStore object
|
||||
|
||||
Available options are:
|
||||
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) {
|
||||
options = options || {};
|
||||
this.disableHtmlWrapperNodes = !!options.disableHtmlWrapperNodes;
|
||||
this.tiddlers = {}; // Hashmap of tiddlers by title
|
||||
this.parsers = {}; // Hashmap of parsers by accepted MIME type
|
||||
this.macros = {}; // Hashmap of macros by macro name
|
||||
@ -265,229 +263,21 @@ WikiStore.prototype.parseTiddler = function(title) {
|
||||
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
|
||||
targetType: target MIME type
|
||||
title: title of the tiddler to render
|
||||
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) {
|
||||
options = options || {};
|
||||
if(typeof templateTitle !== "string") {
|
||||
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.renderTiddler = function(targetType,title,templateTitle) {
|
||||
var r = new Renderer(title,templateTitle,this);
|
||||
return r.render(targetType);
|
||||
};
|
||||
|
||||
WikiStore.prototype.installMacro = function(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;
|
||||
|
||||
})();
|
||||
|
@ -9,8 +9,7 @@ A container for the parse tree generated by parsing wikitext
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var WikiTextRenderer = require("./WikiTextRenderer.js").WikiTextRenderer,
|
||||
HTML = require("./HTML.js").HTML,
|
||||
var Renderer = require("./Renderer.js").Renderer,
|
||||
ArgParser = require("./ArgParser.js").ArgParser,
|
||||
utils = require("./Utils.js");
|
||||
|
||||
@ -21,373 +20,6 @@ var WikiTextParseTree = function(tree,dependencies,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;
|
||||
|
||||
})();
|
||||
|
@ -33,7 +33,7 @@ HTML nodes look like this:
|
||||
|
||||
var WikiTextRules = require("./WikiTextRules.js"),
|
||||
WikiTextParseTree = require("./WikiTextParseTree.js").WikiTextParseTree,
|
||||
HTML = require("./HTML.js").HTML,
|
||||
Renderer = require("./Renderer.js").Renderer,
|
||||
utils = require("./Utils.js"),
|
||||
util = require("util");
|
||||
|
||||
@ -97,7 +97,7 @@ WikiTextParser.prototype.mergeDependencies = function(newDependencies) {
|
||||
|
||||
WikiTextParser.prototype.outputText = function(place,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";
|
||||
|
||||
var ArgParser = require("./ArgParser.js").ArgParser,
|
||||
HTML = require("./HTML.js").HTML,
|
||||
Renderer = require("./Renderer.js").Renderer,
|
||||
util = require("util");
|
||||
|
||||
var textPrimitives = {
|
||||
@ -97,11 +97,38 @@ var enclosedTextHelper = function(w) {
|
||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
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 macro = w.store.macros[name],
|
||||
dependencies = {};
|
||||
@ -131,7 +158,7 @@ var insertMacroCall = function(w,output,name,params,children) {
|
||||
}
|
||||
}
|
||||
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"},
|
||||
handler: function(w)
|
||||
{
|
||||
var table = HTML.elem("table",{"class": "twtable"},[]);
|
||||
var table = Renderer.ElementNode("table",{"class": "twtable"},[]);
|
||||
w.output.push(table);
|
||||
var prevColumns = [];
|
||||
var currRowType = null;
|
||||
@ -190,7 +217,7 @@ var rules = [
|
||||
w.nextMatch += lookaheadMatch[0].length+1;
|
||||
} else {
|
||||
if(nextRowType != currRowType) {
|
||||
rowContainer = HTML.elem(this.rowTypes[nextRowType],{},[]);
|
||||
rowContainer = Renderer.ElementNode(this.rowTypes[nextRowType],{},[]);
|
||||
table.children.push(rowContainer);
|
||||
currRowType = nextRowType;
|
||||
}
|
||||
@ -205,7 +232,7 @@ var rules = [
|
||||
rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
|
||||
w.subWikifyTerm(rowContainer.children,this.rowTermRegExp);
|
||||
} else {
|
||||
var theRow = HTML.elem("tr",{},[]);
|
||||
var theRow = Renderer.ElementNode("tr",{},[]);
|
||||
theRow.attributes["class"] = rowCount%2 ? "oddRow" : "evenRow";
|
||||
rowContainer.children.push(theRow);
|
||||
this.rowHandler(w,theRow.children,prevColumns);
|
||||
@ -261,11 +288,11 @@ var rules = [
|
||||
}
|
||||
var cell;
|
||||
if(chr == "!") {
|
||||
cell = HTML.elem("th",{},[]);
|
||||
cell = Renderer.ElementNode("th",{},[]);
|
||||
e.push(cell);
|
||||
w.nextMatch++;
|
||||
} else {
|
||||
cell = HTML.elem("td",{},[]);
|
||||
cell = Renderer.ElementNode("td",{},[]);
|
||||
e.push(cell);
|
||||
}
|
||||
prevCell = cell;
|
||||
@ -295,7 +322,7 @@ var rules = [
|
||||
termRegExp: /(\n)/mg,
|
||||
handler: function(w)
|
||||
{
|
||||
var e = HTML.elem("h" + w.matchLength,{},[]);
|
||||
var e = Renderer.ElementNode("h" + w.matchLength,{},[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,this.termRegExp);
|
||||
}
|
||||
@ -339,7 +366,7 @@ var rules = [
|
||||
if(currLevel !== 0 && target.children) {
|
||||
target = target.children[target.children.length-1];
|
||||
}
|
||||
e = HTML.elem(listType,{},[]);
|
||||
e = Renderer.ElementNode(listType,{},[]);
|
||||
target.push(e);
|
||||
stack.push(e.children);
|
||||
}
|
||||
@ -351,13 +378,13 @@ var rules = [
|
||||
stack.pop();
|
||||
} else if(listLevel == currLevel && listType != currType) {
|
||||
stack.pop();
|
||||
e = HTML.elem(listType,{},[]);
|
||||
e = Renderer.ElementNode(listType,{},[]);
|
||||
stack[stack.length-1].push(e);
|
||||
stack.push(e.children);
|
||||
}
|
||||
currLevel = listLevel;
|
||||
currType = listType;
|
||||
e = HTML.elem(itemType,{},[]);
|
||||
e = Renderer.ElementNode(itemType,{},[]);
|
||||
stack[stack.length-1].push(e);
|
||||
w.subWikifyTerm(e.children,this.termRegExp);
|
||||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||||
@ -372,7 +399,7 @@ var rules = [
|
||||
termRegExp: /(^<<<(\n|$))/mg,
|
||||
element: "blockquote",
|
||||
handler: function(w) {
|
||||
var e = HTML.elem(this.element,{},[]);
|
||||
var e = Renderer.ElementNode(this.element,{},[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,this.termRegExp);
|
||||
}
|
||||
@ -393,7 +420,7 @@ var rules = [
|
||||
do {
|
||||
if(newLevel > currLevel) {
|
||||
for(t=currLevel; t<newLevel; t++) {
|
||||
e = HTML.elem(this.element,{},[]);
|
||||
e = Renderer.ElementNode(this.element,{},[]);
|
||||
stack[stack.length-1].push(e);
|
||||
}
|
||||
} else if(newLevel < currLevel) {
|
||||
@ -402,7 +429,7 @@ var rules = [
|
||||
}
|
||||
currLevel = newLevel;
|
||||
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;
|
||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||
matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
|
||||
@ -419,7 +446,7 @@ var rules = [
|
||||
match: "^----+$\\n?|<hr ?/?>\\n?",
|
||||
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",{
|
||||
target: {type: "string", value: link}
|
||||
},[HTML.text(text)]);
|
||||
},[Renderer.TextNode(text)]);
|
||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||
}
|
||||
}
|
||||
@ -519,7 +546,7 @@ var rules = [
|
||||
if(w.autoLinkWikiWords) {
|
||||
insertMacroCall(w,w.output,"link",{
|
||||
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 {
|
||||
w.outputText(w.output,w.matchStart,w.nextMatch);
|
||||
}
|
||||
@ -533,7 +560,7 @@ var rules = [
|
||||
{
|
||||
insertMacroCall(w,w.output,"link",{
|
||||
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;
|
||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -611,32 +638,32 @@ var rules = [
|
||||
var e,lookaheadRegExp,lookaheadMatch;
|
||||
switch(w.matchText) {
|
||||
case "''":
|
||||
e = HTML.elem("strong",null,[]);
|
||||
e = Renderer.ElementNode("strong",null,[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/('')/mg);
|
||||
break;
|
||||
case "//":
|
||||
e = HTML.elem("em",null,[]);
|
||||
e = Renderer.ElementNode("em",null,[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(\/\/)/mg);
|
||||
break;
|
||||
case "__":
|
||||
e = HTML.elem("u",null,[]);
|
||||
e = Renderer.ElementNode("u",null,[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(__)/mg);
|
||||
break;
|
||||
case "^^":
|
||||
e = HTML.elem("sup",null,[]);
|
||||
e = Renderer.ElementNode("sup",null,[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(\^\^)/mg);
|
||||
break;
|
||||
case "~~":
|
||||
e = HTML.elem("sub",null,[]);
|
||||
e = Renderer.ElementNode("sub",null,[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(~~)/mg);
|
||||
break;
|
||||
case "--":
|
||||
e = HTML.elem("strike",null,[]);
|
||||
e = Renderer.ElementNode("strike",null,[]);
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(--)/mg);
|
||||
break;
|
||||
@ -645,7 +672,7 @@ var rules = [
|
||||
lookaheadRegExp.lastIndex = w.matchStart;
|
||||
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
@ -654,7 +681,7 @@ var rules = [
|
||||
lookaheadRegExp.lastIndex = w.matchStart;
|
||||
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
@ -669,7 +696,7 @@ var rules = [
|
||||
{
|
||||
switch(w.matchText) {
|
||||
case "@@":
|
||||
var e = HTML.elem("span",null,[]);
|
||||
var e = Renderer.ElementNode("span",null,[]);
|
||||
w.output.push(e);
|
||||
var styles = inlineCssHelper(w);
|
||||
if(styles.length === 0)
|
||||
@ -684,7 +711,7 @@ var rules = [
|
||||
var lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||
if(lookaheadMatch) {
|
||||
w.nextMatch = lookaheadRegExp.lastIndex;
|
||||
e = HTML.elem(lookaheadMatch[2] == "\n" ? "div" : "span",{
|
||||
e = Renderer.ElementNode(lookaheadMatch[2] == "\n" ? "div" : "span",{
|
||||
"class": lookaheadMatch[1]
|
||||
},[]);
|
||||
w.output.push(e);
|
||||
@ -700,7 +727,7 @@ var rules = [
|
||||
match: "--",
|
||||
handler: function(w)
|
||||
{
|
||||
w.output.push(HTML.entity("—"));
|
||||
w.output.push(Renderer.EntityNode("—"));
|
||||
}
|
||||
},
|
||||
|
||||
@ -709,7 +736,7 @@ var rules = [
|
||||
match: "\\n|<br ?/?>",
|
||||
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;
|
||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -733,7 +760,7 @@ var rules = [
|
||||
match: "&#?[a-zA-Z0-9]{2,8};",
|
||||
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 */
|
||||
"use strict";
|
||||
|
||||
var utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
exports.macro = {
|
||||
name: "echo",
|
||||
@ -15,12 +15,8 @@ exports.macro = {
|
||||
params: {
|
||||
text: {byPos: 0, type: "text", optional: false}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
if(type === "text/html") {
|
||||
return utils.htmlEncode(params.text);
|
||||
} else {
|
||||
return params.text;
|
||||
}
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
return [Renderer.TextNode(macroNode.params.text)];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,8 +7,7 @@ title: js/macros/image.js
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var HTML = require("../HTML.js").HTML,
|
||||
utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
exports.macro = {
|
||||
name: "image",
|
||||
@ -18,28 +17,27 @@ exports.macro = {
|
||||
text: {byName: true, type: "text", optional: true},
|
||||
alignment: {byName: true, type: "text", optional: true}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
if(type === "text/html") {
|
||||
if(store.tiddlerExists(params.src)) {
|
||||
if(params.text) {
|
||||
return HTML(HTML.elem("div",{
|
||||
alt: params.text,
|
||||
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
|
||||
}));
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
if(store.tiddlerExists(macroNode.params.src)) {
|
||||
var imageTree = store.parseTiddler(macroNode.params.src).tree,
|
||||
cloneImage = [];
|
||||
for(var t=0; t<imageTree.length; t++) {
|
||||
cloneImage.push(imageTree[t].clone());
|
||||
}
|
||||
} else if (type === "text/plain") {
|
||||
return params.text ? params.text : "";
|
||||
if(macroNode.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 */
|
||||
"use strict";
|
||||
|
||||
var HTML = require("../HTML.js").HTML,
|
||||
var Renderer = require("../Renderer.js").Renderer,
|
||||
utils = require("../Utils.js");
|
||||
|
||||
exports.macro = {
|
||||
@ -31,16 +31,16 @@ exports.macro = {
|
||||
var parseTree = store.parseTiddler(tiddler.title);
|
||||
switch(info) {
|
||||
case "parsetree":
|
||||
return HTML(HTML.slider("parsetree",
|
||||
return [Renderer.SliderNode("parsetree",
|
||||
"Parse tree",
|
||||
"The parse tree for this tiddler",
|
||||
HTML.raw(parseTree.toString(type))),type);
|
||||
(parseTree.toString(type)))];
|
||||
//break;
|
||||
case "compiled":
|
||||
return HTML(HTML.slider("compiled",
|
||||
return [Renderer.SliderNode("compiled",
|
||||
"Render functions",
|
||||
"The render functions for this tiddler",
|
||||
HTML.raw(parseTree.compile(type).toString(type))),type);
|
||||
(parseTree.compile(type).toString(type)))];
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ title: js/macros/link.js
|
||||
/*jslint node: true, browser: true */
|
||||
"use strict";
|
||||
|
||||
var HTML = require("../HTML.js").HTML,
|
||||
utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
var isLinkExternal = function(target) {
|
||||
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}
|
||||
},
|
||||
events: {
|
||||
click: function(event,node,tiddler,store,params) {
|
||||
if(isLinkExternal(params.target)) {
|
||||
click: function(event,macroNode) {
|
||||
if(isLinkExternal(macroNode.params.target)) {
|
||||
event.target.setAttribute("target","_blank");
|
||||
return true;
|
||||
} else {
|
||||
var navEvent = document.createEvent("Event");
|
||||
navEvent.initEvent("tw-navigate",true,true);
|
||||
navEvent.navigateTo = params.target;
|
||||
node.dispatchEvent(navEvent);
|
||||
navEvent.navigateTo = macroNode.params.target;
|
||||
event.target.dispatchEvent(navEvent);
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
render: function(type,tiddler,store,params,content) {
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
var classes = ["tw-tiddlylink"],
|
||||
target = params.target;
|
||||
if(isLinkExternal(params.target)) {
|
||||
target = macroNode.params.target;
|
||||
if(isLinkExternal(target)) {
|
||||
classes.push("tw-tiddlylink-external");
|
||||
} else {
|
||||
classes.push("tw-tiddlylink-internal");
|
||||
if(store.tiddlerExists(params.target)) {
|
||||
if(store.tiddlerExists(target)) {
|
||||
classes.push("tw-tiddlylink-resolves");
|
||||
} else {
|
||||
classes.push("tw-tiddlylink-missing");
|
||||
}
|
||||
target = encodeURIComponent(target);
|
||||
}
|
||||
return HTML(HTML.elem(
|
||||
var content = [Renderer.ElementNode(
|
||||
"a",{
|
||||
href: target,
|
||||
"class": classes
|
||||
},[
|
||||
HTML.raw(content)
|
||||
]
|
||||
),type);
|
||||
},macroNode.cloneChildren())];
|
||||
for(var t=0; t<content.length; t++) {
|
||||
content[t].execute(tiddler);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@ title: js/macros/list.js
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
var handlers = {
|
||||
all: function(store) {
|
||||
@ -41,35 +41,33 @@ exports.macro = {
|
||||
template: {byName: true, type: "tiddler", 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",
|
||||
templateText = "<<view title link>>",
|
||||
template = params.template ? store.getTiddler(params.template) : null,
|
||||
output = [],
|
||||
isHtml = type === "text/html",
|
||||
encoder = isHtml ? utils.htmlEncode : function(x) {return x;},
|
||||
pushTag = isHtml ? function(x) {output.push(x);} : function(x) {},
|
||||
handler,
|
||||
template = macroNode.params.template ? store.getTiddler(macroNode.params.template) : null,
|
||||
content = [],
|
||||
t;
|
||||
if(template) {
|
||||
templateType = template.type;
|
||||
templateText = template.text;
|
||||
}
|
||||
handler = handlers[params.type];
|
||||
var handler = handlers[macroNode.params.type];
|
||||
handler = handler || handlers.all;
|
||||
var tiddlers = handler(store);
|
||||
if(tiddlers.length === 0) {
|
||||
return params.emptyMessage ? encoder(params.emptyMessage) : "";
|
||||
return [Renderer.TextNode(macroNode.params.emptyMessage || "")];
|
||||
} else {
|
||||
var renderer = store.compileText(templateType,templateText,type);
|
||||
pushTag("<ul>");
|
||||
var templateTree = store.parseText(templateType,templateText).tree;
|
||||
for(t=0; t<tiddlers.length; t++) {
|
||||
pushTag("<li>");
|
||||
output.push(renderer.render(store.getTiddler(tiddlers[t]),store));
|
||||
pushTag("</li>");
|
||||
var cloneTemplate = [];
|
||||
for(var c=0; c<templateTree.length; c++) {
|
||||
cloneTemplate.push(templateTree[c].clone());
|
||||
}
|
||||
var listNode = Renderer.ElementNode("li",null,cloneTemplate);
|
||||
listNode.execute(store.getTiddler(tiddlers[t]));
|
||||
content.push(listNode);
|
||||
}
|
||||
pushTag("</ul>");
|
||||
return output.join("");
|
||||
return [Renderer.ElementNode("ul",null,content)];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ title: js/macros/slider.js
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var HTML = require("../HTML.js").HTML,
|
||||
var Renderer = require("../Renderer.js").Renderer,
|
||||
utils = require("../Utils.js");
|
||||
|
||||
exports.macro = {
|
||||
@ -20,23 +20,25 @@ exports.macro = {
|
||||
tooltip: {byPos: 3, type: "text", optional: true}
|
||||
},
|
||||
events: {
|
||||
click: function(event,node,tiddler,store,params) {
|
||||
var el = node.firstChild.firstChild.nextSibling;
|
||||
click: function(event,macroNode) {
|
||||
var el = event.currentTarget.firstChild.firstChild.nextSibling;
|
||||
el.style.display = el.style.display === "block" ? "none" : "block";
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
if(type === "text/html") {
|
||||
return HTML(HTML.slider(params.name,
|
||||
params.label,
|
||||
params.tooltip,
|
||||
HTML.raw(store.renderTiddler(type,params.targetTiddler))),type);
|
||||
} else if(type === "text/plain") {
|
||||
return store.renderTiddler(type,params.target);
|
||||
}
|
||||
return null;
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
var target = macroNode.params.targetTiddler,
|
||||
dependencies = {include: {}};
|
||||
dependencies.include[target] = 1;
|
||||
var content = Renderer.SliderNode(macroNode.params.name,
|
||||
macroNode.params.label,
|
||||
macroNode.params.tooltip,
|
||||
[
|
||||
Renderer.MacroNode("tiddler",{target: target},null,dependencies,store)
|
||||
]);
|
||||
content.execute(tiddler);
|
||||
return [content];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@ title: js/macros/story.js
|
||||
"use strict";
|
||||
|
||||
var Tiddler = require("../Tiddler.js").Tiddler,
|
||||
Renderer = require("../Renderer.js").Renderer,
|
||||
utils = require("../Utils.js");
|
||||
|
||||
// Parse the text of a story tiddler into an array of tiddler titles
|
||||
@ -23,19 +24,6 @@ var parseStory = function(storyText) {
|
||||
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 = {
|
||||
name: "story",
|
||||
types: ["text/html","text/plain"],
|
||||
@ -44,9 +32,9 @@ exports.macro = {
|
||||
template: {byName: true, type: "tiddler", optional: true}
|
||||
},
|
||||
events: {
|
||||
"tw-navigate": function(event,node,tiddler,store,params) {
|
||||
var storyTiddler = store.getTiddler(params.story);
|
||||
store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
|
||||
"tw-navigate": function(event,macroNode) {
|
||||
var storyTiddler = macroNode.store.getTiddler(macroNode.params.story);
|
||||
macroNode.store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
|
||||
$("html,body").animate({
|
||||
scrollTop: 0
|
||||
}, 400);
|
||||
@ -54,53 +42,77 @@ exports.macro = {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
var tiddlers = parseStory(store.getTiddlerText(params.story)),
|
||||
output = [];
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
var tiddlers = parseStory(store.getTiddlerText(macroNode.params.story)),
|
||||
content = [];
|
||||
for(var t=0; t<tiddlers.length; t++) {
|
||||
if(params.template) {
|
||||
output.push(store.renderTiddler(type,tiddlers[t],params.template));
|
||||
} else {
|
||||
output.push(store.renderTiddler(type,tiddlers[t]));
|
||||
var paramFn = {target: tiddlers[t],template: macroNode.params.template},
|
||||
dependencies = {include: {}};
|
||||
dependencies.include[tiddlers[t]] = 1;
|
||||
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 */
|
||||
// Get the tiddlers we're supposed to be displaying
|
||||
var targetTiddlers = parseStory(store.getTiddlerText(params.story)),
|
||||
currNode = node.firstChild,
|
||||
nextNode;
|
||||
for(var t=0; t<targetTiddlers.length; t++) {
|
||||
var targetTiddlers = parseStory(store.getTiddlerText(macroNode.params.story)),
|
||||
template = macroNode.params.template,
|
||||
t,n,domNode,
|
||||
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
|
||||
var tiddlerNode = searchTiddlerNode(currNode,targetTiddlers[t],params.template);
|
||||
var tiddlerNode = findTiddler(t,targetTiddlers[t],template);
|
||||
if(tiddlerNode === null) {
|
||||
// If not, render the tiddler
|
||||
var tmpNode = document.createElement("div");
|
||||
store.renderTiddlerInNode(tmpNode,targetTiddlers[t],params.template);
|
||||
tiddlerNode = tmpNode.firstChild;
|
||||
node.insertBefore(tiddlerNode,currNode);
|
||||
var paramFn = {target: targetTiddlers[t],template: template},
|
||||
dependencies = {include: {}};
|
||||
dependencies.include[targetTiddlers[t]] = 1;
|
||||
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 {
|
||||
// Delete any nodes preceding the one we want
|
||||
while(currNode !== tiddlerNode) {
|
||||
nextNode = currNode.nextSibling;
|
||||
node.removeChild(currNode);
|
||||
currNode = nextNode;
|
||||
if(tiddlerNode > t) {
|
||||
// First delete the DOM nodes
|
||||
for(n=t; n<tiddlerNode; n++) {
|
||||
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
|
||||
while(currNode !== null) {
|
||||
nextNode = currNode.nextSibling;
|
||||
node.removeChild(currNode);
|
||||
currNode = nextNode;
|
||||
// Remove any left over nodes
|
||||
if(macroNode.content.length > targetTiddlers.length) {
|
||||
for(t=targetTiddlers.length; t<macroNode.content.length; t++) {
|
||||
domNode = macroNode.content[t].domNode;
|
||||
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 */
|
||||
"use strict";
|
||||
|
||||
var utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
exports.macro = {
|
||||
name: "tiddler",
|
||||
@ -53,29 +53,39 @@ exports.macro = {
|
||||
template: {byName: true, type: "tiddler", optional: true},
|
||||
"with": {byName: true, type: "text", optional: true, dependentAll: true}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
var renderTitle = params.target,
|
||||
renderTemplate = params.template;
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
var renderTitle = macroNode.params.target,
|
||||
renderTemplate = macroNode.params.template,
|
||||
content,
|
||||
contentClone = [],
|
||||
t;
|
||||
if(typeof renderTitle !== "string") {
|
||||
renderTitle = tiddler.title;
|
||||
}
|
||||
if(typeof renderTemplate !== "string") {
|
||||
renderTemplate = renderTitle;
|
||||
}
|
||||
if(params["with"]) {
|
||||
if("with" in macroNode.params) {
|
||||
// Parameterised transclusion
|
||||
var targetTiddler = store.getTiddler(renderTemplate),
|
||||
text = targetTiddler.text;
|
||||
var withTokens = [params["with"]];
|
||||
for(var t=0; t<withTokens.length; t++) {
|
||||
var withTokens = [macroNode.params["with"]];
|
||||
for(t=0; t<withTokens.length; t++) {
|
||||
var placeholderRegExp = new RegExp("\\$"+(t+1),"mg");
|
||||
text = text.replace(placeholderRegExp,withTokens[t]);
|
||||
}
|
||||
return store.renderText(targetTiddler.type,text,type,renderTitle);
|
||||
content = store.parseText(targetTiddler.type,text).tree;
|
||||
} else {
|
||||
// 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 */
|
||||
"use strict";
|
||||
|
||||
var utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
exports.macro = {
|
||||
name: "version",
|
||||
types: ["text/html","text/plain"],
|
||||
params: {
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
return "5.0.0";
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
return [Renderer.TextNode("5.0.0")];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@ title: js/macros/video.js
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer;
|
||||
|
||||
exports.macro = {
|
||||
name: "video",
|
||||
@ -18,21 +18,36 @@ exports.macro = {
|
||||
width: {byName: true, type: "text", optional: true},
|
||||
height: {byName: true, type: "text", optional: true}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
var videoType = params.type || "vimeo",
|
||||
videoWidth = params.width || 640,
|
||||
videoHeight = params.height || 360;
|
||||
if(type === "text/html") {
|
||||
switch(videoType) {
|
||||
case "vimeo":
|
||||
return "<iframe src='http://player.vimeo.com/video/" + params.src + "?autoplay=0' width='" + videoWidth + "' height='" + videoHeight + "' frameborder='0'></iframe>";
|
||||
case "youtube":
|
||||
return "<iframe type='text/html' width='" + videoWidth + "' height='" + videoHeight + "' src='http://www.youtube.com/embed/" + params.src + "' frameborder='0'></iframe>";
|
||||
case "archiveorg":
|
||||
return "<iframe src='http://www.archive.org/embed/" + params.src + "' width='" + videoWidth + "' height='" + videoHeight + "' frameborder='0'></iframe>";
|
||||
}
|
||||
} else if (type === "text/plain") {
|
||||
return ""; // Not really sure how to render a video into plain text...
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
var src = macroNode.params.src,
|
||||
videoType = macroNode.params.type || "vimeo",
|
||||
videoWidth = macroNode.params.width || 640,
|
||||
videoHeight = macroNode.params.height || 360;
|
||||
switch(videoType) {
|
||||
case "vimeo":
|
||||
return [Renderer.ElementNode("iframe",{
|
||||
src: "http://player.vimeo.com/video/" + src + "?autoplay=0",
|
||||
width: videoWidth,
|
||||
height: videoHeight,
|
||||
frameborder: 0
|
||||
})];
|
||||
case "youtube":
|
||||
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 */
|
||||
"use strict";
|
||||
|
||||
var utils = require("../Utils.js");
|
||||
var Renderer = require("../Renderer.js").Renderer,
|
||||
utils = require("../Utils.js");
|
||||
|
||||
exports.macro = {
|
||||
name: "view",
|
||||
@ -17,28 +18,44 @@ exports.macro = {
|
||||
format: {byPos: 1, type: "text", optional: true},
|
||||
template: {byPos: 2, type: "text", optional: true}
|
||||
},
|
||||
render: function(type,tiddler,store,params) {
|
||||
var encoder = type === "text/html" ? utils.htmlEncode : function(x) {return x;};
|
||||
execute: function(macroNode,tiddler,store) {
|
||||
if(!tiddler) {
|
||||
return "{{** Missing tiddler **}}";
|
||||
return Renderer.TextNode("{{** Missing tiddler **}}");
|
||||
} else {
|
||||
var v = tiddler[params.field];
|
||||
var v = tiddler[macroNode.params.field],
|
||||
content,
|
||||
t,
|
||||
contentClone = [];
|
||||
if(v !== undefined) {
|
||||
switch(params.format) {
|
||||
switch(macroNode.params.format) {
|
||||
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":
|
||||
if(params.field === "text") {
|
||||
return store.renderTiddler(type,tiddler.title);
|
||||
if(macroNode.params.field === "text") {
|
||||
content = store.parseTiddler(tiddler.title).tree;
|
||||
} 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":
|
||||
var template = params.template || "DD MMM YYYY";
|
||||
return encoder(utils.formatDateString(v,template));
|
||||
var template = macroNode.params.template || "DD MMM YYYY";
|
||||
return [Renderer.TextNode(utils.formatDateString(v,template))];
|
||||
default: // "text"
|
||||
return encoder(v);
|
||||
return [Renderer.TextNode(v)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user