1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-06-25 23:03:15 +00:00

Refactored wikitext parser to deal better with terminated blocks

This commit is contained in:
Jeremy Ruston 2012-06-10 17:26:54 +01:00
parent 7a2bbc7fb2
commit e0b630686e
7 changed files with 59 additions and 27 deletions

View File

@ -16,7 +16,6 @@ exports.info = {
name: "button",
params: {
name: {byName: "default", type: "text"},
label: {byName: true, type: "text"},
"class": {byName: true, type: "text"}
},
events: ["click"]
@ -43,7 +42,10 @@ exports.executeMacro = function() {
if(this.classes) {
$tw.utils.pushTop(attributes["class"],this.classes);
}
return $tw.Tree.Element("button",attributes,[$tw.Tree.Text(this.params.label)]);
for(var t=0; t<this.content.length; t++) {
this.content[t].execute(this.parents,this.tiddlerTitle);
}
return $tw.Tree.Element("button",attributes,this.content);
};
})();

View File

@ -23,13 +23,11 @@ var WikiTextRenderer = function(text,options) {
this.parser = options.parser;
this.tree = [];
this.dependencies = new $tw.Dependencies();
// Parse the text into runs or blocks
if(options.isRun) {
this.tree.push.apply(this.tree,this.parseRun(null));
this.tree.push.apply(this.tree,this.parseRun());
} else {
// Parse the text into blocks
while(this.pos < this.sourceLength) {
this.tree.push.apply(this.tree,this.parseBlock());
}
this.tree.push.apply(this.tree,this.parseBlocks());
}
};
@ -41,9 +39,14 @@ WikiTextRenderer.prototype = new Renderer();
WikiTextRenderer.constructor = WikiTextRenderer;
/*
Parse a block of text at the current position
Parse a block from the current position
terminatorRegExpString: optional regular expression string that identifies the end of plain paragraphs. Must not include capturing parenthesis
options: see below
Options are:
leaveTerminator: True if the terminator shouldn't be consumed
*/
WikiTextRenderer.prototype.parseBlock = function() {
WikiTextRenderer.prototype.parseBlock = function(terminatorRegExpString,options) {
var terminatorRegExp = terminatorRegExpString ? new RegExp("(" + terminatorRegExpString + "|\\r?\\n\\r?\\n)","mg") : /(\r?\n\r?\n)/mg;
this.skipWhitespace();
if(this.pos >= this.sourceLength) {
return [];
@ -61,17 +64,44 @@ WikiTextRenderer.prototype.parseBlock = function() {
return rule ? rule.parse.call(this,match,true) : [];
} else {
// 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(terminatorRegExp,options))];
}
};
/*
Parse blocks of text until a terminating regexp is encountered
terminatorRegExp: terminating regular expression
Parse blocks of text until a terminating regexp is encountered or the end of the text
terminatorRegExpString: terminating regular expression
options: see below
Options are:
addClass: optional CSS class to add to each block
*/
WikiTextRenderer.prototype.parseBlockTerminated = function(terminatorRegExp,className) {
WikiTextRenderer.prototype.parseBlocks = function(terminatorRegExpString,options) {
if(terminatorRegExpString) {
return this.parseBlocksTerminated(terminatorRegExpString,options);
} else {
return this.parseBlocksUnterminated(options);
}
};
/*
Parse a block from the current position to the end of the text
*/
WikiTextRenderer.prototype.parseBlocksUnterminated = function(options) {
var tree = [];
while(this.pos < this.sourceLength) {
tree.push.apply(tree,this.parseBlock());
}
return tree;
};
/*
Parse blocks of text until a terminating regexp is encountered. See parseBlocks() for details
*/
WikiTextRenderer.prototype.parseBlocksTerminated = function(terminatorRegExpString,options) {
options = options || {};
var terminatorRegExp = new RegExp("(" + terminatorRegExpString + ")","mg"),
tree = [];
// Skip any whitespace
this.skipWhitespace();
// Check if we've got the end marker
@ -79,10 +109,10 @@ WikiTextRenderer.prototype.parseBlockTerminated = function(terminatorRegExp,clas
var match = terminatorRegExp.exec(this.source);
// Parse the text into blocks
while(this.pos < this.sourceLength && !(match && match.index === this.pos)) {
var blocks = this.parseBlock();
var blocks = this.parseBlock(terminatorRegExpString,{leaveTerminator: true});
for(var t=0; t<blocks.length; t++) {
if(className) {
blocks[t].addClass(className);
if(options.addClass) {
blocks[t].addClass(options.addClass);
}
tree.push(blocks[t]);
}
@ -117,10 +147,10 @@ Options are:
Returns an array of tree nodes
*/
WikiTextRenderer.prototype.parseRun = function(terminatorRegExp,options) {
if(terminatorRegExp === null) {
return this.parseRunUnterminated(options);
} else {
if(terminatorRegExp) {
return this.parseRunTerminated(terminatorRegExp,options);
} else {
return this.parseRunUnterminated(options);
}
};
@ -163,7 +193,6 @@ WikiTextRenderer.prototype.parseRunTerminated = function(terminatorRegExp,option
options = options || {};
var tree = [];
// Find the next occurrence of the terminator
terminatorRegExp = terminatorRegExp || /(\r?\n\r?\n)/mg;
terminatorRegExp.lastIndex = this.pos;
var terminatorMatch = terminatorRegExp.exec(this.source);
// Find the next occurrence of a runrule

View File

@ -33,13 +33,13 @@ exports.regExpString = "\\{\\{(?:[^\\{\\r\\n]+)\\{$\\r?\\n";
exports.parse = function(match,isBlock) {
var tree = [],
reStart = /\{\{([^\{\r\n]+){\r?\n/mg,
reEnd = /(\}\}\}$(?:\r?\n)?)/mg,
reEndString = "(\\}\\}\\}$(?:\\r?\\n)?)",
endMatch;
reStart.lastIndex = this.pos;
match = reStart.exec(this.source);
if(match) {
this.pos = match.index + match[0].length;
tree = this.parseBlockTerminated(reEnd,match[1]);
tree = this.parseBlocks(reEndString,{addClass: match[1]});
}
return tree;
};

View File

@ -49,10 +49,11 @@ exports.parse = function(match,isBlock) {
attrMatch = reAttr.exec(startMatch[2]);
}
this.pos = startMatch.index + startMatch[0].length;
var reEnd = new RegExp("(</" + startMatch[1] + ">)","mg"),
var reEndString = "(</" + startMatch[1] + ">)",
reEnd = new RegExp(reEndString,"mg"),
content;
if(isBlock) {
content = this.parseBlockTerminated(reEnd);
content = this.parseBlocks(reEndString);
} else {
content = this.parseRun(reEnd);
}

View File

@ -37,7 +37,7 @@ exports.parse = function(match,isBlock) {
if(match[5]) {
// If the macro has content then parse it as a block or run
if(isBlock) {
content = this.parseBlockTerminated(/(^>>$)/mg);
content = this.parseBlocks(">>");
} else {
content = this.parseRun(/(>>)/mg);
}

View File

@ -1,7 +1,7 @@
title: $:/templates/EditTemplate
modifier: JeremyRuston
<<view title>> <<button SaveTiddler label:"done" class:"btn btn-mini btn-success">>
<<view title>> <<button SaveTiddler class:"btn btn-mini btn-success"><Done>>
{{title{
<<edit draft.title>>
}}}

View File

@ -2,7 +2,7 @@ title: $:/templates/ViewTemplate
modifier: JeremyRuston
{{title{
<div><span><<view title>></span><<button EditTiddler label:"edit" class:"btn btn-mini btn-primary">></div>
<div><span><<view title>></span><<button EditTiddler class:"btn btn-mini btn-primary"><Edit>></div>
}}}
{{small{
<div><<view modifier link>> <<view modified date>> <<view tags>> </div>