This commit is contained in:
wycats
2010-12-04 22:26:23 -05:00
parent 4db1abcd74
commit 35b4d9fd01
8 changed files with 88 additions and 62 deletions
+5 -5
View File
@@ -14,13 +14,13 @@ Handlebars.Parser = handlebars;
Handlebars.parse = function(string) {
Handlebars.Parser.yy = Handlebars.AST;
Handlebars.Parser.lexer = new Handlebars.HandlebarsLexer;
Handlebars.Parser.lexer = new Handlebars.HandlebarsLexer();
return Handlebars.Parser.parse(string);
};
Handlebars.print = function(ast) {
return new Handlebars.PrintVisitor().accept(ast);
}
};
Handlebars.compile = function(string) {
var ast = Handlebars.parse(string);
@@ -29,8 +29,8 @@ Handlebars.compile = function(string) {
var runtime = new Handlebars.Runtime(context, fallback);
runtime.accept(ast);
return runtime.buffer;
}
}
};
};
// END(BROWSER)
exports.Handlebars = Handlebars
exports.Handlebars = Handlebars;
+8 -8
View File
@@ -29,7 +29,7 @@ Handlebars.Exception = require("handlebars/utils").Exception;
if(open.original !== close.original) {
throw new Handlebars.Exception(open.original + "doesn't match" + close.original);
}
}
};
Handlebars.AST.BlockNode = function(mustache, program, close) {
verifyMatch(mustache.id, close);
@@ -39,7 +39,7 @@ Handlebars.Exception = require("handlebars/utils").Exception;
};
Handlebars.AST.InverseNode = function(mustache, program, close) {
verifyMatch(mustache.id, close)
verifyMatch(mustache.id, close);
this.type = "inverse";
this.mustache = mustache;
this.program = program;
@@ -48,10 +48,10 @@ Handlebars.Exception = require("handlebars/utils").Exception;
Handlebars.AST.ContentNode = function(string) {
this.type = "content";
this.string = string;
}
};
Handlebars.AST.IdNode = function(parts) {
this.type = "ID"
this.type = "ID";
this.original = parts.join("/");
var dig = [], depth = 0;
@@ -61,22 +61,22 @@ Handlebars.Exception = require("handlebars/utils").Exception;
if(part === "..") { depth++; }
else if(part === "." || part === "this") { continue; }
else { dig.push(part) }
else { dig.push(part); }
}
this.parts = dig;
this.depth = depth;
}
};
Handlebars.AST.StringNode = function(string) {
this.type = "STRING";
this.string = string;
}
};
Handlebars.AST.CommentNode = function(comment) {
this.type = "comment";
this.comment = comment;
}
};
})();
// END(BROWSER)
+25
View File
@@ -0,0 +1,25 @@
(function() {
var classes = ["Lexer", "PrintVisitor", "Context", "Runtime", "Exception"];
var prop;
for(var i=0, l=classes.length; i<l; i++) {
var className = classes[i], klass = Handlebars[className];
klass.displayName = "new Handlebars." + className;
for(prop in klass) {
if(klass.hasOwnProperty(prop)) {
klass[prop].displayName = "Handlebars." + className + "#" + prop;
}
}
}
for(prop in Handlebars.Utils) {
if(Handlebars.Utils.hasOwnProperty(prop)) {
Handlebars.Utils[prop].displayName = "Handlebars.Utils." + prop;
}
}
Handlebars.parse.displayName = "Handlebars.parse";
Handlebars.print.displayName = "Handlebars.print";
Handlebars.compile.displayName = "Handlebars.compile";
})();
+18 -17
View File
@@ -1,11 +1,11 @@
var Handlebars = {};
Handlebars.Lexer = require("handlebars/jison_ext").Lexer
Handlebars.Lexer = require("handlebars/jison_ext").Lexer;
// BEGIN(BROWSER)
Handlebars.HandlebarsLexer = function() {
this.state = "CONTENT";
};
Handlebars.HandlebarsLexer.prototype = new Handlebars.Lexer;
Handlebars.HandlebarsLexer.prototype = new Handlebars.Lexer();
// The HandlebarsLexer uses a Lexer interface that is compatible
// with Jison.
@@ -22,14 +22,15 @@ Handlebars.HandlebarsLexer.prototype = new Handlebars.Lexer;
// pointer in the case of parse errors is in
// the right place.
Handlebars.HandlebarsLexer.prototype.lex = function() {
if(this.input === "") return;
if(this.input === "") { return; }
this.setupLex();
var lookahead = this.peek(2);
var result = '';
var peek;
if(lookahead === "") return;
if(lookahead === "") { return; }
if(this.state == "MUSTACHE") {
if(this.peek() === "/") {
@@ -40,20 +41,20 @@ Handlebars.HandlebarsLexer.prototype.lex = function() {
// chomp optional whitespace
while(this.peek() === " ") { this.ignorechar(); }
var lookahead = this.peek(2);
lookahead = this.peek(2);
// in a mustache, but less than 2 characters left => error
if(lookahead.length != 2) { return; }
// if the next characters are '}}', the mustache is done
if(lookahead === "}}") {
this.state = "CONTENT"
this.state = "CONTENT";
this.getchar(2);
// handle the case of {{{ foo }}} by always chomping
// a final }. TODO: Track escape state and handle the
// error condition here
if(this.peek() == "}") this.getchar();
if(this.peek() == "}") { this.getchar(); }
return "CLOSE";
// if the next character is a quote => enter a String
@@ -61,25 +62,25 @@ Handlebars.HandlebarsLexer.prototype.lex = function() {
this.readchar();
// scan the String until another quote is reached, skipping over escaped quotes
while(this.peek() !== '"') { if(this.peek(2) === '\\"') { this.readchar() }; this.getchar() }
while(this.peek() !== '"') { if(this.peek(2) === '\\"') { this.readchar(); } this.getchar(); }
this.readchar();
return "STRING";
// All other cases are IDs or errors
} else {
// grab alphanumeric characters
while(this.peek().match(/[_0-9A-Za-z\.]/)) { this.getchar() }
while(this.peek().match(/[_0-9A-Za-z\.]/)) { this.getchar(); }
var peek = this.peek();
peek = this.peek();
if(peek !== "}" && peek !== " " && peek !== "/") {
return
return;
}
// if any characters were grabbed => ID
if(this.yytext.length) { return "ID" }
if(this.yytext.length) { return "ID"; }
// Otherwise => Error
else return;
else { return; }
}
// Next chars are {{ => Open mustache
@@ -87,7 +88,7 @@ Handlebars.HandlebarsLexer.prototype.lex = function() {
this.state = "MUSTACHE";
this.getchar(2);
var peek = this.peek();
peek = this.peek();
if(peek === ">") {
this.getchar();
@@ -107,9 +108,9 @@ Handlebars.HandlebarsLexer.prototype.lex = function() {
} else if(peek === "!") {
this.readchar();
this.setupLex(); // reset the lexer state so the yytext is the comment only
while(this.peek(2) !== "}}") { this.getchar(); };
while(this.peek(2) !== "}}") { this.getchar(); }
this.readchar(2);
this.state = "CONTENT"
this.state = "CONTENT";
return "COMMENT";
} else {
return "OPEN";
@@ -118,7 +119,7 @@ Handlebars.HandlebarsLexer.prototype.lex = function() {
// Otherwise => content section
} else {
while(this.peek(2) !== "{{" && this.peek(2) !== "") { result = result + this.getchar(); }
return "CONTENT"
return "CONTENT";
}
};
// END(BROWSER)
+4 -4
View File
@@ -30,7 +30,7 @@ Handlebars.Lexer.prototype = {
this.matched += chr;
this.match += chr;
if(chr === "\n") this.yylineno++;
if(chr === "\n") { this.yylineno++; }
this.input = this.input.slice(1);
}
@@ -43,7 +43,7 @@ Handlebars.Lexer.prototype = {
for(var i=0; i<n; i++) {
chr = this.input[i];
if(chr === "\n") this.yylineno++;
if(chr === "\n") { this.yylineno++; }
this.matched += chr;
this.match += chr;
@@ -78,7 +78,7 @@ Handlebars.Lexer.prototype = {
var pre = this.pastInput();
var c = new Array(pre.length + 1 + this.readchars).join("-");
return pre + this.upcomingInput() + "\n" + c+"^";
},
}
};
Handlebars.Visitor = function() {};
@@ -87,7 +87,7 @@ Handlebars.Visitor.prototype = {
accept: function(object) {
return this[object.type](object);
}
}
};
// END(BROWSER)
exports.Lexer = Handlebars.Lexer;
+9 -8
View File
@@ -1,9 +1,9 @@
var Handlebars = {};
Handlebars.Visitor = require("handlebars/jison_ext").Visitor
Handlebars.Visitor = require("handlebars/jison_ext").Visitor;
// BEGIN(BROWSER)
Handlebars.PrintVisitor = function() { this.padding = 0; };
Handlebars.PrintVisitor.prototype = new Handlebars.Visitor;
Handlebars.PrintVisitor.prototype = new Handlebars.Visitor();
Handlebars.PrintVisitor.prototype.pad = function(string, newline) {
var out = "";
@@ -14,18 +14,19 @@ Handlebars.PrintVisitor.prototype.pad = function(string, newline) {
out = out + string;
if(newline !== false) { out = out + "\n" }
if(newline !== false) { out = out + "\n"; }
return out;
};
Handlebars.PrintVisitor.prototype.program = function(program) {
var out = this.pad("PROGRAM:"),
statements = program.statements,
inverse = program.inverse;
inverse = program.inverse,
i, l;
this.padding++;
for(var i=0, l=statements.length; i<l; i++) {
for(i=0, l=statements.length; i<l; i++) {
out = out + this.accept(statements[i]);
}
@@ -36,7 +37,7 @@ Handlebars.PrintVisitor.prototype.program = function(program) {
this.padding++;
for(var i=0, l=inverse.statements.length; i<l; i++) {
for(i=0, l=inverse.statements.length; i<l; i++) {
out = out + this.accept(inverse.statements[i]);
}
}
@@ -78,7 +79,7 @@ Handlebars.PrintVisitor.prototype.mustache = function(mustache) {
paramStrings.push(this.accept(params[i]));
}
var params = "[" + paramStrings.join(", ") + "]";
params = "[" + paramStrings.join(", ") + "]";
return this.pad("{{ " + this.accept(mustache.id) + " " + params + " }}");
};
@@ -107,7 +108,7 @@ Handlebars.PrintVisitor.prototype.content = function(content) {
Handlebars.PrintVisitor.prototype.comment = function(comment) {
return this.pad("{{! '" + comment.comment + "' }}");
}
};
// END(BROWSER)
exports.PrintVisitor = Handlebars.PrintVisitor;
+15 -12
View File
@@ -67,7 +67,7 @@ Handlebars.proxy = function(obj) {
var Proxy = this.K;
Proxy.prototype = obj;
return new Proxy();
}
};
Handlebars.Runtime = function(context, fallback, stack) {
this.stack = stack || [];
@@ -125,7 +125,7 @@ Handlebars.Runtime.prototype = {
if(buf && mustache.escaped) { buf = Handlebars.Utils.escapeExpression(buf); }
this.buffer = this.buffer + ((buf == null || buf === false) ? '' : buf);
this.buffer = this.buffer + ((!buf && buf !== 0) ? '' : buf);
},
block: function(block) {
@@ -135,6 +135,8 @@ Handlebars.Runtime.prototype = {
var idObj = this.ID(mustache.id),
data = idObj.data;
var result;
if(toString.call(data) !== "[object Function]") {
params = [data];
data = this.context.fallback.helperMissing;
@@ -143,13 +145,13 @@ Handlebars.Runtime.prototype = {
}
params.push(this.wrapProgram(block.program));
var result = data.apply(this.wrapContext(), params);
result = data.apply(this.wrapContext(), params);
this.buffer = this.buffer + result;
if(block.program.inverse) {
params.pop();
params.push(this.wrapProgram(block.program.inverse));
var result = data.not.apply(this.wrapContext(), params);
result = data.not.apply(this.wrapContext(), params);
this.buffer = this.buffer + result;
}
},
@@ -159,22 +161,23 @@ Handlebars.Runtime.prototype = {
var id = partial.id.original;
var partialBody = partials[partial.id.original];
var program, context;
if(!partialBody) {
throw new Handlebars.Exception("The partial " + partial.id.original + " does not exist");
}
if(typeof partialBody === "string") {
var program = Handlebars.parse(partialBody);
program = Handlebars.parse(partialBody);
partials[id] = program;
} else {
program = partialBody;
}
if(partial.context) {
var context = this.ID(partial.context);
context = this.ID(partial.context);
} else {
var context = this.context;
context = this.context;
}
var runtime = new Handlebars.Runtime(context, this.context.fallback, this.stack.slice(0));
this.buffer = this.buffer + runtime.program(program);
@@ -202,8 +205,8 @@ Handlebars.Runtime.prototype = {
id = id.parts.join("/");
data = data.apply(context, params);
if(Handlebars.Utils.isEmpty(data)) { isInverse = true }
if(data.not) { not = data.not } else { not = this.not }
if(Handlebars.Utils.isEmpty(data)) { isInverse = true; }
if(data.not) { not = data.not; } else { not = this.not; }
} else {
not = this.not;
}
@@ -239,7 +242,7 @@ Handlebars.Runtime.prototype = {
proxy.__get__ = function(path) {
path = new Handlebars.AST.IdNode(path.split("/"));
return context.evaluate(path, stack).data
return context.evaluate(path, stack).data;
};
proxy.isWrappedContext = true;
@@ -258,10 +261,10 @@ Handlebars.Runtime.prototype = {
var runtime = new Handlebars.Runtime(context, fallback, stack);
runtime.program(program);
return runtime.buffer;
}
};
}
}
};
// END(BROWSER)
exports.Runtime = Handlebars.Runtime;
+4 -8
View File
@@ -8,10 +8,10 @@ Handlebars.Exception = function(message) {
// Build out our basic SafeString type
Handlebars.SafeString = function(string) {
this.string = string;
}
};
Handlebars.SafeString.prototype.toString = function() {
return this.string.toString();
}
};
Handlebars.Utils = {
escapeExpression: function(string) {
@@ -27,18 +27,14 @@ Handlebars.Utils = {
switch(str) {
case "&":
return "&amp;";
break;
case '"':
return "\"";
case "\\":
return "\\\\";
break;
case "<":
return "&lt;";
break;
case ">":
return "&gt;";
break;
default:
return str;
}
@@ -51,13 +47,13 @@ Handlebars.Utils = {
return true;
} else if (value === false) {
return true;
} else if(Object.prototype.toString.call(value) === "[object Array]" && value.length == 0) {
} else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
return true;
} else {
return false;
}
}
}
};
// END(BROWSER)
exports.Utils = Handlebars.Utils;