1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-09-27 22:58:19 +00:00

Allow for macros and classes at both run level and block level

Involving a bit of a refactoring of the parameters to the
$tw.Tree.Macro constructor
This commit is contained in:
Jeremy Ruston 2012-05-28 15:51:52 +01:00
parent aa4d435a67
commit 49a3cb8ede
18 changed files with 89 additions and 50 deletions

View File

@ -14,7 +14,6 @@ Zooming chooser macro
exports.info = { exports.info = {
name: "chooser", name: "chooser",
wrapperTag: "div",
params: { params: {
}, },
events: ["touchstart","touchmove","touchend","mouseover","mousemove","mouseup","mouseout"] events: ["touchstart","touchmove","touchend","mouseover","mousemove","mouseup","mouseout"]

View File

@ -79,11 +79,10 @@ exports.getSliderChildren = function() {
if(this.hasParameter("content")) { if(this.hasParameter("content")) {
return this.wiki.parseText("text/x-tiddlywiki",this.params.content).tree; return this.wiki.parseText("text/x-tiddlywiki",this.params.content).tree;
} else if(this.hasParameter("target")) { } else if(this.hasParameter("target")) {
return [$tw.Tree.Macro( return [$tw.Tree.Macro("tiddler",{
"tiddler", srcParams: {target: this.params.target},
{target: this.params.target}, wiki: this.wiki
null, })];
this.wiki)];
} else { } else {
return [$tw.Tree.errorNode("No content specified for slider")]; return [$tw.Tree.errorNode("No content specified for slider")];
} }

View File

@ -148,10 +148,10 @@ exports.executeMacro = function() {
var storyJson = JSON.parse(this.wiki.getTiddlerText(this.params.story)), var storyJson = JSON.parse(this.wiki.getTiddlerText(this.params.story)),
storyNode = $tw.Tree.Element("div",{},[]); storyNode = $tw.Tree.Element("div",{},[]);
for(var t=0; t<storyJson.tiddlers.length; t++) { for(var t=0; t<storyJson.tiddlers.length; t++) {
var m = $tw.Tree.Macro("tiddler", var m = $tw.Tree.Macro("tiddler",{
{target: storyJson.tiddlers[t].title,template: storyJson.tiddlers[t].template}, srcParams: {target: storyJson.tiddlers[t].title,template: storyJson.tiddlers[t].template},
null, wiki: this.wiki
this.wiki); });
m.execute(this.parents,this.tiddlerTitle); m.execute(this.parents,this.tiddlerTitle);
storyNode.children.push($tw.Tree.Element("div",{},[m])); storyNode.children.push($tw.Tree.Element("div",{},[m]));
} }
@ -199,10 +199,10 @@ exports.refreshInDom = function(changes) {
if(tiddlerNode === null) { if(tiddlerNode === null) {
// If not, render the tiddler // If not, render the tiddler
var m = $tw.Tree.Element("div",{},[ var m = $tw.Tree.Element("div",{},[
$tw.Tree.Macro("tiddler", $tw.Tree.Macro("tiddler",{
{target: story.tiddlers[t].title,template: story.tiddlers[t].template}, srcParams: {target: story.tiddlers[t].title,template: story.tiddlers[t].template},
null, wiki: this.wiki
this.wiki) })
]); ]);
m.execute(this.parents,this.tiddlerTitle); m.execute(this.parents,this.tiddlerTitle);
m.renderInDom(this.children[0].domNode,this.children[0].domNode.childNodes[t]); m.renderInDom(this.children[0].domNode,this.children[0].domNode.childNodes[t]);

View File

@ -54,10 +54,11 @@ exports.executeMacro = function() {
if(value === undefined) { if(value === undefined) {
return []; return [];
} else { } else {
var link = $tw.Tree.Macro("link", var link = $tw.Tree.Macro("link",{
{to: value}, srcParams: {to: value},
[$tw.Tree.Text(value)], content: [$tw.Tree.Text(value)],
this.wiki); wiki: this.wiki
});
link.execute(parents,this.tiddlerTitle); link.execute(parents,this.tiddlerTitle);
return [link]; return [link];
} }

View File

@ -14,7 +14,6 @@ Zooming navigator macro
exports.info = { exports.info = {
name: "zoomer", name: "zoomer",
wrapperTag: "div",
params: { params: {
}, },
events: ["touchstart","touchmove","touchend"] events: ["touchstart","touchmove","touchend"]

View File

@ -18,7 +18,7 @@ exports.blockParser = true;
exports.regExpString = "\\{\\{(?:[^\\{\\r\\n]+)\\{$"; exports.regExpString = "\\{\\{(?:[^\\{\\r\\n]+)\\{$";
exports.parse = function(match) { exports.parse = function(match,isBlock) {
var tree = [], var tree = [],
reStart = /\{\{([^\{\r\n]+){(?:\r?\n)?/mg, reStart = /\{\{([^\{\r\n]+){(?:\r?\n)?/mg,
reEnd = /(\}\}\}$(?:\r?\n)?)/mg, reEnd = /(\}\}\}$(?:\r?\n)?)/mg,

View File

@ -18,7 +18,7 @@ exports.blockParser = true;
exports.regExpString = "!{1,6}"; exports.regExpString = "!{1,6}";
exports.parse = function(match) { exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length; this.pos = match.index + match[0].length;
var classedRun = this.parseClassedRun(/(\r?\n)/mg); var classedRun = this.parseClassedRun(/(\r?\n)/mg);
return [$tw.Tree.Element("h1",{"class": classedRun["class"]},classedRun.tree)]; return [$tw.Tree.Element("h1",{"class": classedRun["class"]},classedRun.tree)];

View File

@ -19,7 +19,7 @@ exports.runParser = true;
exports.regExpString = "<[A-Za-z]+\\s*[^>]*>"; exports.regExpString = "<[A-Za-z]+\\s*[^>]*>";
exports.parse = function(match) { exports.parse = function(match,isBlock) {
var reStart = /<([A-Za-z]+)(\s*[^>]*)>/mg, var reStart = /<([A-Za-z]+)(\s*[^>]*)>/mg,
reAttr = /\s*([A-Za-z\-_]+)(?:\s*=\s*(?:("[^"]*")|('[^']*')|([^"'\s]+)))?/mg; reAttr = /\s*([A-Za-z\-_]+)(?:\s*=\s*(?:("[^"]*")|('[^']*')|([^"'\s]+)))?/mg;
reStart.lastIndex = this.pos; reStart.lastIndex = this.pos;

View File

@ -30,7 +30,7 @@ var listTypes = {
/* /*
*/ */
exports.parse = function(match) { exports.parse = function(match,isBlock) {
var listStack = [], // Array containing list elements for the previous row in the list var listStack = [], // Array containing list elements for the previous row in the list
t, listInfo, listElement, itemElement, previousRootListTag; t, listInfo, listElement, itemElement, previousRootListTag;
// Cycle through the rows in the list // Cycle through the rows in the list

View File

@ -18,7 +18,7 @@ exports.blockParser = true;
exports.regExpString = "-{3,}\r?\n"; exports.regExpString = "-{3,}\r?\n";
exports.parse = function(match) { exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length; this.pos = match.index + match[0].length;
return [$tw.Tree.Element("hr",{},[])]; return [$tw.Tree.Element("hr",{},[])];
}; };

View File

@ -54,7 +54,7 @@ WikiTextRenderer.prototype.parseBlock = function() {
rule = this.parser.blockRules[t]; rule = this.parser.blockRules[t];
} }
} }
return rule ? rule.parse.call(this,match) : []; return rule ? rule.parse.call(this,match,true) : [];
} else { } else {
// Treat it as a paragraph if we didn't find a block rule // Treat it as a paragraph if we didn't find a block rule
return [$tw.Tree.Element("p",{},this.parseRun())]; return [$tw.Tree.Element("p",{},this.parseRun())];
@ -111,7 +111,7 @@ WikiTextRenderer.prototype.parseRun = function(terminatorRegExp) {
} }
} }
if(rule) { if(rule) {
tree.push.apply(tree,rule.parse.call(this,runRuleMatch)); tree.push.apply(tree,rule.parse.call(this,runRuleMatch,false));
} }
// Look for the next run rule // Look for the next run rule
this.parser.runRegExp.lastIndex = this.pos; this.parser.runRegExp.lastIndex = this.pos;

View File

@ -19,13 +19,17 @@ exports.blockParser = true;
exports.regExpString = "<<"; exports.regExpString = "<<";
exports.parse = function(match) { exports.parse = function(match,isBlock) {
var regExp = /<<(?:([!@£\$%\^\&\*\(\)`\~'"\|\\\/;\:\.\,\+\=\-\_\{\}])|([^>\s]+))(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg; var regExp = /<<(?:([!@£\$%\^\&\*\(\)`\~'"\|\\\/;\:\.\,\+\=\-\_\{\}])|([^>\s]+))(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg;
regExp.lastIndex = this.pos; regExp.lastIndex = this.pos;
match = regExp.exec(this.source); match = regExp.exec(this.source);
if(match && match.index === this.pos) { if(match && match.index === this.pos) {
this.pos = match.index + match[0].length; this.pos = match.index + match[0].length;
var macroNode = $tw.Tree.Macro(match[1] || match[2],match[3],[],this.wiki); var macroNode = $tw.Tree.Macro(match[1] || match[2],{
srcParams: match[3],
isBlock: isBlock,
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies); this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode]; return [macroNode];
} }

View File

@ -18,7 +18,7 @@ exports.runParser = true;
exports.regExpString = "\\[\\["; exports.regExpString = "\\[\\[";
exports.parse = function(match) { exports.parse = function(match,isBlock) {
var regExp = /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg; var regExp = /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg;
regExp.lastIndex = this.pos; regExp.lastIndex = this.pos;
match = regExp.exec(this.source); match = regExp.exec(this.source);
@ -26,7 +26,11 @@ exports.parse = function(match) {
var text = match[1], var text = match[1],
link = match[3] || text; link = match[3] || text;
this.pos = match.index + match[0].length; this.pos = match.index + match[0].length;
var macroNode = $tw.Tree.Macro("link",{to: link},[$tw.Tree.Text(text)],this.wiki); var macroNode = $tw.Tree.Macro("link",{
srcParams: {to: link},
content: [$tw.Tree.Text(text)],
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies); this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode]; return [macroNode];
} }

View File

@ -33,7 +33,7 @@ textPrimitives.wikiLink = "(?:(?:" + textPrimitives.upperLetter + "+" +
exports.regExpString = textPrimitives.unWikiLink + "?" + textPrimitives.wikiLink; exports.regExpString = textPrimitives.unWikiLink + "?" + textPrimitives.wikiLink;
exports.parse = function(match) { exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length; this.pos = match.index + match[0].length;
// If the link starts with the unwikilink character then just output it as plain text // If the link starts with the unwikilink character then just output it as plain text
if(match[0].substr(0,1) === textPrimitives.unWikiLink) { if(match[0].substr(0,1) === textPrimitives.unWikiLink) {
@ -48,7 +48,11 @@ exports.parse = function(match) {
return [$tw.Tree.Text(match[0])]; return [$tw.Tree.Text(match[0])];
} }
} }
var macroNode = $tw.Tree.Macro("link",{to: match[0]},[$tw.Tree.Text(match[0])],this.wiki); var macroNode = $tw.Tree.Macro("link",{
srcParams: {to: match[0]},
content: [$tw.Tree.Text(match[0])],
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies); this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode]; return [macroNode];
}; };

View File

@ -38,10 +38,14 @@ TiddlyTextParser.prototype.parse = function(type,text) {
var macroName = match[2] || match[3]; var macroName = match[2] || match[3];
if(match[1]) { // Transclusion if(match[1]) { // Transclusion
macroNode = $tw.Tree.Macro("tiddler",{ macroNode = $tw.Tree.Macro("tiddler",{
target: match[1] srcParams: {target: match[1]},
},[],this.wiki); wiki: this.wiki
});
} else if(macroName) { // Macro call } else if(macroName) { // Macro call
macroNode = $tw.Tree.Macro(macroName,match[4],[],this.wiki); macroNode = $tw.Tree.Macro(macroName,{
srcParams: match[4],
wiki: this.wiki
});
} }
output.push(macroNode); output.push(macroNode);
dependencies.mergeDependencies(macroNode.dependencies); dependencies.mergeDependencies(macroNode.dependencies);

View File

@ -103,9 +103,13 @@ var enclosedTextHelper = function(w) {
} }
}; };
var insertMacroCall = function(w,output,name,params,children) { var insertMacroCall = function(w,output,name,params,content) {
if(name in w.wiki.macros) { if(name in w.wiki.macros) {
var macroNode = $tw.Tree.Macro(name,params,children,w.wiki); var macroNode = $tw.Tree.Macro(name,{
srcParams: params,
content: content,
wiki: w.wiki
});
w.dependencies.mergeDependencies(macroNode.dependencies); w.dependencies.mergeDependencies(macroNode.dependencies);
output.push(macroNode); output.push(macroNode);
} }

View File

@ -17,32 +17,39 @@ var Node = require("./node.js").Node;
/* /*
Construct a renderer node representing a macro invocation Construct a renderer node representing a macro invocation
macroName: name of the macro macroName: name of the macro
options: see below
The options available are:
srcParams: a string or a hashmap of parameters (each can be a string, or a fn(tiddler,wiki) for evaluated parameters) srcParams: a string or a hashmap of parameters (each can be a string, or a fn(tiddler,wiki) for evaluated parameters)
children: optional array of child nodes content: optional array of child nodes
store: reference to the WikiStore associated with this macro wiki: reference to the WikiStore associated with this macro
dependencies: optional Dependencies object representing the dependencies of this macro dependencies: optional Dependencies object representing the dependencies of this macro
isBlock: true if this macro is being used as an HTML block
Note that the dependencies will be evaluated if not provided. Note that the dependencies will be evaluated if not provided.
*/ */
var Macro = function(macroName,srcParams,content,wiki,dependencies) { var Macro = function(macroName,options) {
var MacroClass = wiki ? wiki.macros[macroName] : null; // Get the macro class options = options || {};
var MacroClass = options.wiki ? options.wiki.macros[macroName] : null; // Get the macro class
if(this instanceof Macro) { if(this instanceof Macro) {
// Save the details // Save the details
this.macroName = macroName; this.macroName = macroName;
this.srcParams = srcParams || {}; this.srcParams = options.srcParams || {};
this.content = content || []; this.content = options.content || [];
this.wiki = wiki; this.wiki = options.wiki;
this.dependencies = dependencies; this.dependencies = options.dependencies;
this.isBlock = options.isBlock;
// Parse the macro parameters if required // Parse the macro parameters if required
if(typeof this.srcParams === "string") { if(typeof this.srcParams === "string") {
this.srcParams = this.parseMacroParamString(srcParams); this.srcParams = this.parseMacroParamString(this.srcParams);
} }
// Evaluate the dependencies if required // Evaluate the dependencies if required
if(macroName && !this.dependencies) { if(macroName && !this.dependencies) {
this.dependencies = this.evaluateDependencies(); this.dependencies = this.evaluateDependencies();
} }
// Get a reference to the static information about this macro // Get a reference to the static information about this macro
if(wiki && wiki.macros[macroName]) { if(MacroClass) {
this.MacroClass = MacroClass; this.MacroClass = MacroClass;
this.info = MacroClass.prototype.info; this.info = MacroClass.prototype.info;
} }
@ -51,7 +58,7 @@ var Macro = function(macroName,srcParams,content,wiki,dependencies) {
if(!MacroClass) { if(!MacroClass) {
throw "Unknown macro '" + macroName + "'"; throw "Unknown macro '" + macroName + "'";
} }
return new MacroClass(macroName,srcParams,content,wiki,dependencies); return new MacroClass(macroName,options);
} }
}; };
@ -129,7 +136,13 @@ Macro.prototype.cloneContent = function() {
}; };
Macro.prototype.clone = function() { Macro.prototype.clone = function() {
return new this.MacroClass(this.macroName,this.srcParams,this.cloneContent(),this.wiki,this.dependencies); return new this.MacroClass(this.macroName,{
srcParams: this.srcParams,
content: this.cloneContent(),
wiki: this.wiki,
isBlock: this.isBlock,
dependencies: this.dependencies
});
}; };
Macro.prototype.execute = function(parents,tiddlerTitle) { Macro.prototype.execute = function(parents,tiddlerTitle) {
@ -164,7 +177,7 @@ Macro.prototype.render = function(type) {
Macro.prototype.renderInDom = function(parentDomNode,insertBefore) { Macro.prototype.renderInDom = function(parentDomNode,insertBefore) {
// Create the wrapper node for the macro // Create the wrapper node for the macro
var domNode = document.createElement(this.info.wrapperTag || "span"); var domNode = document.createElement(this.isBlock ? "div" : "span");
this.domNode = domNode; this.domNode = domNode;
if(insertBefore) { if(insertBefore) {
parentDomNode.insertBefore(domNode,insertBefore); parentDomNode.insertBefore(domNode,insertBefore);

View File

@ -82,3 +82,11 @@ This is my nice and simple block of text. HelloThere
And another: And another:
<article class="hello" mysignal data-thing='Nothing'><div class="another" mysignal2 data-thing='NothingElse'>This time the text is all squashed up, without line breaks</div></article> <article class="hello" mysignal data-thing='Nothing'><div class="another" mysignal2 data-thing='NothingElse'>This time the text is all squashed up, without line breaks</div></article>
---
Macro calls can be inline like this: <<version>>
Or, at paragraph block level:
<<version>>