Update statement node ASTs
This commit is contained in:
@@ -28,6 +28,41 @@ var AST = {
|
||||
this.strip = strip;
|
||||
},
|
||||
|
||||
BlockNode: function(sexpr, program, inverse, strip, locInfo) {
|
||||
this.loc = locInfo;
|
||||
|
||||
this.type = 'BlockStatement';
|
||||
this.sexpr = sexpr;
|
||||
this.program = program;
|
||||
this.inverse = inverse;
|
||||
this.strip = strip;
|
||||
},
|
||||
|
||||
PartialNode: function(sexpr, strip, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = 'PartialStatement';
|
||||
this.sexpr = sexpr;
|
||||
this.indent = '';
|
||||
|
||||
this.strip = strip;
|
||||
this.strip.inlineStandalone = true;
|
||||
},
|
||||
|
||||
ContentNode: function(string, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = 'ContentStatement';
|
||||
this.original = this.value = string;
|
||||
},
|
||||
|
||||
CommentNode: function(comment, strip, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = 'CommentStatement';
|
||||
this.value = comment;
|
||||
|
||||
this.strip = strip;
|
||||
strip.inlineStandalone = true;
|
||||
},
|
||||
|
||||
SexprNode: function(rawParams, hash, locInfo) {
|
||||
this.loc = locInfo;
|
||||
|
||||
@@ -51,37 +86,6 @@ var AST = {
|
||||
// pass or at runtime.
|
||||
},
|
||||
|
||||
PartialNode: function(partialName, context, hash, strip, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = "partial";
|
||||
this.partialName = partialName;
|
||||
this.context = context;
|
||||
this.hash = hash;
|
||||
this.strip = strip;
|
||||
|
||||
this.strip.inlineStandalone = true;
|
||||
},
|
||||
|
||||
BlockNode: function(sexpr, program, inverse, strip, locInfo) {
|
||||
this.loc = locInfo;
|
||||
|
||||
this.type = 'block';
|
||||
this.sexpr = sexpr;
|
||||
this.program = program;
|
||||
this.inverse = inverse;
|
||||
this.strip = strip;
|
||||
|
||||
if (inverse && !program) {
|
||||
this.isInverse = true;
|
||||
}
|
||||
},
|
||||
|
||||
ContentNode: function(string, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = "content";
|
||||
this.original = this.string = string;
|
||||
},
|
||||
|
||||
HashNode: function(pairs, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = "hash";
|
||||
@@ -128,12 +132,6 @@ var AST = {
|
||||
this.stringModeValue = this.string;
|
||||
},
|
||||
|
||||
PartialNameNode: function(name, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = "PARTIAL_NAME";
|
||||
this.name = name.original;
|
||||
},
|
||||
|
||||
DataNode: function(id, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = "DATA";
|
||||
@@ -163,15 +161,6 @@ var AST = {
|
||||
this.type = "BOOLEAN";
|
||||
this.bool = bool;
|
||||
this.stringModeValue = bool === "true";
|
||||
},
|
||||
|
||||
CommentNode: function(comment, strip, locInfo) {
|
||||
this.loc = locInfo;
|
||||
this.type = "comment";
|
||||
this.comment = comment;
|
||||
|
||||
this.strip = strip;
|
||||
strip.inlineStandalone = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -107,24 +107,19 @@ Compiler.prototype = {
|
||||
return guid;
|
||||
},
|
||||
|
||||
block: function(block) {
|
||||
BlockStatement: function(block) {
|
||||
var sexpr = block.sexpr,
|
||||
program = block.program,
|
||||
inverse = block.inverse;
|
||||
|
||||
if (program) {
|
||||
program = this.compileProgram(program);
|
||||
}
|
||||
|
||||
if (inverse) {
|
||||
inverse = this.compileProgram(inverse);
|
||||
}
|
||||
program = program && this.compileProgram(program);
|
||||
inverse = inverse && this.compileProgram(inverse);
|
||||
|
||||
var type = this.classifySexpr(sexpr);
|
||||
|
||||
if (type === "helper") {
|
||||
if (type === 'helper') {
|
||||
this.helperSexpr(sexpr, program, inverse);
|
||||
} else if (type === "simple") {
|
||||
} else if (type === 'simple') {
|
||||
this.simpleSexpr(sexpr);
|
||||
|
||||
// now that the simple mustache is resolved, we need to
|
||||
@@ -147,32 +142,23 @@ Compiler.prototype = {
|
||||
this.opcode('append', block);
|
||||
},
|
||||
|
||||
hash: function(hash) {
|
||||
var pairs = hash.pairs, i, l;
|
||||
|
||||
this.opcode('pushHash', hash);
|
||||
|
||||
for(i=0, l=pairs.length; i<l; i++) {
|
||||
this.pushParam(pairs[i][1]);
|
||||
}
|
||||
while(i--) {
|
||||
this.opcode('assignToHash', hash, pairs[i][0]);
|
||||
}
|
||||
this.opcode('popHash', hash);
|
||||
},
|
||||
|
||||
partial: function(partial) {
|
||||
var partialName = partial.partialName;
|
||||
PartialStatement: function(partial) {
|
||||
var partialName = partial.sexpr.id.original;
|
||||
this.usePartial = true;
|
||||
|
||||
if (partial.hash) {
|
||||
this.accept(partial.hash);
|
||||
if (partial.sexpr.hash) {
|
||||
this.accept(partial.sexpr.hash);
|
||||
} else {
|
||||
this.opcode('pushLiteral', partial, 'undefined');
|
||||
}
|
||||
|
||||
if (partial.context) {
|
||||
this.accept(partial.context);
|
||||
var params = partial.sexpr.params;
|
||||
if (params.length) {
|
||||
if (params.length > 1) {
|
||||
throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
|
||||
}
|
||||
|
||||
this.pushParam(params[0]);
|
||||
} else {
|
||||
this.opcode('getContext', partial, 0);
|
||||
this.opcode('pushContext', partial);
|
||||
@@ -183,16 +169,10 @@ Compiler.prototype = {
|
||||
this.opcode('appendContent', partial, indent);
|
||||
indent = '';
|
||||
}
|
||||
this.opcode('invokePartial', partial, partialName.name, indent);
|
||||
this.opcode('invokePartial', partial, partialName, indent);
|
||||
this.opcode('append', partial);
|
||||
},
|
||||
|
||||
content: function(content) {
|
||||
if (content.string) {
|
||||
this.opcode('appendContent', content, content.string);
|
||||
}
|
||||
},
|
||||
|
||||
MustacheStatement: function(mustache) {
|
||||
this.sexpr(mustache.sexpr);
|
||||
|
||||
@@ -203,6 +183,25 @@ Compiler.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
ContentStatement: function(content) {
|
||||
if (content.value) {
|
||||
this.opcode('appendContent', content, content.value);
|
||||
}
|
||||
},
|
||||
|
||||
CommentStatement: function() {},
|
||||
|
||||
sexpr: function(sexpr) {
|
||||
var type = this.classifySexpr(sexpr);
|
||||
|
||||
if (type === "simple") {
|
||||
this.simpleSexpr(sexpr);
|
||||
} else if (type === "helper") {
|
||||
this.helperSexpr(sexpr);
|
||||
} else {
|
||||
this.ambiguousSexpr(sexpr);
|
||||
}
|
||||
},
|
||||
ambiguousSexpr: function(sexpr, program, inverse) {
|
||||
var id = sexpr.id,
|
||||
name = id.parts[0],
|
||||
@@ -252,16 +251,18 @@ Compiler.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
sexpr: function(sexpr) {
|
||||
var type = this.classifySexpr(sexpr);
|
||||
hash: function(hash) {
|
||||
var pairs = hash.pairs, i, l;
|
||||
|
||||
if (type === "simple") {
|
||||
this.simpleSexpr(sexpr);
|
||||
} else if (type === "helper") {
|
||||
this.helperSexpr(sexpr);
|
||||
} else {
|
||||
this.ambiguousSexpr(sexpr);
|
||||
this.opcode('pushHash', hash);
|
||||
|
||||
for(i=0, l=pairs.length; i<l; i++) {
|
||||
this.pushParam(pairs[i][1]);
|
||||
}
|
||||
while(i--) {
|
||||
this.opcode('assignToHash', hash, pairs[i][0]);
|
||||
}
|
||||
this.opcode('popHash', hash);
|
||||
},
|
||||
|
||||
ID: function(id) {
|
||||
@@ -294,8 +295,6 @@ Compiler.prototype = {
|
||||
this.opcode('pushLiteral', bool, bool.bool);
|
||||
},
|
||||
|
||||
comment: function() {},
|
||||
|
||||
// HELPERS
|
||||
opcode: function(name, node) {
|
||||
this.opcodes.push({ opcode: name, args: slice.call(arguments, 2), loc: node.loc });
|
||||
@@ -339,12 +338,14 @@ Compiler.prototype = {
|
||||
},
|
||||
|
||||
pushParam: function(val) {
|
||||
var stringModeValue = val.stringModeValue != null ? val.stringModeValue : '';
|
||||
|
||||
if (this.stringParams) {
|
||||
if(val.depth) {
|
||||
this.addDepth(val.depth);
|
||||
}
|
||||
this.opcode('getContext', val, val.depth || 0);
|
||||
this.opcode('pushStringParam', val, val.stringModeValue, val.type);
|
||||
this.opcode('pushStringParam', val, stringModeValue, val.type);
|
||||
|
||||
if (val.type === 'sexpr') {
|
||||
// Subexpressions get evaluated and passed in
|
||||
@@ -353,7 +354,7 @@ Compiler.prototype = {
|
||||
}
|
||||
} else {
|
||||
if (this.trackIds) {
|
||||
this.opcode('pushId', val, val.type, val.idName || val.stringModeValue);
|
||||
this.opcode('pushId', val, val.type, val.idName || stringModeValue);
|
||||
}
|
||||
this.accept(val);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ export function prepareProgram(body, isRoot) {
|
||||
|
||||
if (omitLeft(body, i)) {
|
||||
// If we are on a standalone node, save the indent info for partials
|
||||
if (current.type === 'partial') {
|
||||
if (current.type === 'PartialStatement') {
|
||||
// Pull out the whitespace from the final line
|
||||
current.indent = (/([ \t]+$)/).exec(body[i-1].original)[1];
|
||||
}
|
||||
@@ -180,7 +180,7 @@ function isPrevWhitespace(body, i, isRoot) {
|
||||
return isRoot;
|
||||
}
|
||||
|
||||
if (prev.type === 'content') {
|
||||
if (prev.type === 'ContentStatement') {
|
||||
return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ function isNextWhitespace(body, i, isRoot) {
|
||||
return isRoot;
|
||||
}
|
||||
|
||||
if (next.type === 'content') {
|
||||
if (next.type === 'ContentStatement') {
|
||||
return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original);
|
||||
}
|
||||
}
|
||||
@@ -209,13 +209,13 @@ function isNextWhitespace(body, i, isRoot) {
|
||||
// content is met.
|
||||
function omitRight(body, i, multiple) {
|
||||
var current = body[i == null ? 0 : i + 1];
|
||||
if (!current || current.type !== 'content' || (!multiple && current.rightStripped)) {
|
||||
if (!current || current.type !== 'ContentStatement' || (!multiple && current.rightStripped)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var original = current.string;
|
||||
current.string = current.string.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), '');
|
||||
current.rightStripped = current.string !== original;
|
||||
var original = current.value;
|
||||
current.value = current.value.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), '');
|
||||
current.rightStripped = current.value !== original;
|
||||
}
|
||||
|
||||
// Marks the node to the left of the position as omitted.
|
||||
@@ -227,13 +227,13 @@ function omitRight(body, i, multiple) {
|
||||
// content is met.
|
||||
function omitLeft(body, i, multiple) {
|
||||
var current = body[i == null ? body.length - 1 : i - 1];
|
||||
if (!current || current.type !== 'content' || (!multiple && current.leftStripped)) {
|
||||
if (!current || current.type !== 'ContentStatement' || (!multiple && current.leftStripped)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We omit the last node if it's whitespace only and not preceeded by a non-content node.
|
||||
var original = current.string;
|
||||
current.string = current.string.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
|
||||
current.leftStripped = current.string !== original;
|
||||
var original = current.value;
|
||||
current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
|
||||
current.leftStripped = current.value !== original;
|
||||
return current.leftStripped;
|
||||
}
|
||||
|
||||
@@ -48,21 +48,21 @@ PrintVisitor.prototype.MustacheStatement = function(mustache) {
|
||||
return this.pad('{{ ' + this.accept(mustache.sexpr) + ' }}');
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.block = function(block) {
|
||||
PrintVisitor.prototype.BlockStatement = function(block) {
|
||||
var out = "";
|
||||
|
||||
out = out + this.pad("BLOCK:");
|
||||
out = out + this.pad('BLOCK:');
|
||||
this.padding++;
|
||||
out = out + this.pad(this.accept(block.sexpr));
|
||||
if (block.program) {
|
||||
out = out + this.pad("PROGRAM:");
|
||||
out = out + this.pad('PROGRAM:');
|
||||
this.padding++;
|
||||
out = out + this.accept(block.program);
|
||||
this.padding--;
|
||||
}
|
||||
if (block.inverse) {
|
||||
if (block.program) { this.padding++; }
|
||||
out = out + this.pad("{{^}}");
|
||||
out = out + this.pad('{{^}}');
|
||||
this.padding++;
|
||||
out = out + this.accept(block.inverse);
|
||||
this.padding--;
|
||||
@@ -73,6 +73,26 @@ PrintVisitor.prototype.block = function(block) {
|
||||
return out;
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.PartialStatement = function(partial) {
|
||||
var sexpr = partial.sexpr,
|
||||
content = 'PARTIAL:' + sexpr.id.original;
|
||||
if(sexpr.params[0]) {
|
||||
content += ' ' + this.accept(sexpr.params[0]);
|
||||
}
|
||||
if (sexpr.hash) {
|
||||
content += ' ' + this.accept(sexpr.hash);
|
||||
}
|
||||
return this.pad('{{> ' + content + ' }}');
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.ContentStatement = function(content) {
|
||||
return this.pad("CONTENT[ '" + content.value + "' ]");
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.CommentStatement = function(comment) {
|
||||
return this.pad("{{! '" + comment.value + "' }}");
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.sexpr = function(sexpr) {
|
||||
var params = sexpr.params, paramStrings = [], hash;
|
||||
|
||||
@@ -87,17 +107,6 @@ PrintVisitor.prototype.sexpr = function(sexpr) {
|
||||
return this.accept(sexpr.id) + " " + params + hash;
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.partial = function(partial) {
|
||||
var content = this.accept(partial.partialName);
|
||||
if(partial.context) {
|
||||
content += " " + this.accept(partial.context);
|
||||
}
|
||||
if (partial.hash) {
|
||||
content += " " + this.accept(partial.hash);
|
||||
}
|
||||
return this.pad("{{> " + content + " }}");
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.hash = function(hash) {
|
||||
var pairs = hash.pairs;
|
||||
var joinedPairs = [], left, right;
|
||||
@@ -132,19 +141,7 @@ PrintVisitor.prototype.ID = function(id) {
|
||||
}
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.PARTIAL_NAME = function(partialName) {
|
||||
return "PARTIAL:" + partialName.name;
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.DATA = function(data) {
|
||||
return "@" + this.accept(data.id);
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.content = function(content) {
|
||||
return this.pad("CONTENT[ '" + content.string + "' ]");
|
||||
};
|
||||
|
||||
PrintVisitor.prototype.comment = function(comment) {
|
||||
return this.pad("{{! '" + comment.comment + "' }}");
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Visitor.prototype = {
|
||||
constructor: Visitor,
|
||||
|
||||
accept: function(object) {
|
||||
return object && this[object.type] && this[object.type](object);
|
||||
return object && this[object.type](object);
|
||||
},
|
||||
|
||||
Program: function(program) {
|
||||
@@ -20,12 +20,21 @@ Visitor.prototype = {
|
||||
this.accept(mustache.sexpr);
|
||||
},
|
||||
|
||||
block: function(block) {
|
||||
this.accept(block.mustache);
|
||||
BlockStatement: function(block) {
|
||||
this.accept(block.sexpr);
|
||||
this.accept(block.program);
|
||||
this.accept(block.inverse);
|
||||
},
|
||||
|
||||
PartialStatement: function(partial) {
|
||||
this.accept(partial.partialName);
|
||||
this.accept(partial.context);
|
||||
this.accept(partial.hash);
|
||||
},
|
||||
|
||||
ContentStatement: function(content) {},
|
||||
CommentStatement: function(comment) {},
|
||||
|
||||
sexpr: function(sexpr) {
|
||||
var params = sexpr.params, paramStrings = [], hash;
|
||||
|
||||
@@ -44,13 +53,6 @@ Visitor.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
partial: function(partial) {
|
||||
this.accept(partial.partialName);
|
||||
this.accept(partial.context);
|
||||
this.accept(partial.hash);
|
||||
},
|
||||
PARTIAL_NAME: function(partialName) {},
|
||||
|
||||
DATA: function(data) {
|
||||
this.accept(data.id);
|
||||
},
|
||||
@@ -58,10 +60,7 @@ Visitor.prototype = {
|
||||
STRING: function(string) {},
|
||||
NUMBER: function(number) {},
|
||||
BOOLEAN: function(bool) {},
|
||||
ID: function(id) {},
|
||||
|
||||
content: function(content) {},
|
||||
comment: function(comment) {}
|
||||
ID: function(id) {}
|
||||
};
|
||||
|
||||
export default Visitor;
|
||||
|
||||
+27
-36
@@ -168,18 +168,9 @@ describe('ast', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("PartialNameNode", function(){
|
||||
|
||||
it('stores location info', function(){
|
||||
var pnn = new handlebarsEnv.AST.PartialNameNode({original: "YES"}, LOCATION_INFO);
|
||||
testLocationInfoStorage(pnn);
|
||||
});
|
||||
});
|
||||
|
||||
describe("PartialNode", function(){
|
||||
|
||||
it('stores location info', function(){
|
||||
var pn = new handlebarsEnv.AST.PartialNode("so_partial", {}, {}, {}, LOCATION_INFO);
|
||||
var pn = new handlebarsEnv.AST.PartialNode('so_partial', {}, LOCATION_INFO);
|
||||
testLocationInfoStorage(pn);
|
||||
});
|
||||
});
|
||||
@@ -248,8 +239,8 @@ describe('ast', function() {
|
||||
describe('mustache', function() {
|
||||
it('does not mark mustaches as standalone', function() {
|
||||
var ast = Handlebars.parse(' {{comment}} ');
|
||||
equals(!!ast.body[0].string, true);
|
||||
equals(!!ast.body[2].string, true);
|
||||
equals(!!ast.body[0].value, true);
|
||||
equals(!!ast.body[2].value, true);
|
||||
});
|
||||
});
|
||||
describe('blocks', function() {
|
||||
@@ -257,38 +248,38 @@ describe('ast', function() {
|
||||
var ast = Handlebars.parse(' {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '),
|
||||
block = ast.body[1];
|
||||
|
||||
equals(ast.body[0].string, '');
|
||||
equals(ast.body[0].value, '');
|
||||
|
||||
equals(block.program.body[0].string, 'foo\n');
|
||||
equals(block.inverse.body[0].string, ' bar \n');
|
||||
equals(block.program.body[0].value, 'foo\n');
|
||||
equals(block.inverse.body[0].value, ' bar \n');
|
||||
|
||||
equals(ast.body[2].string, '');
|
||||
equals(ast.body[2].value, '');
|
||||
});
|
||||
it('marks initial block mustaches as standalone', function() {
|
||||
var ast = Handlebars.parse('{{# comment}} \nfoo\n {{/comment}}'),
|
||||
block = ast.body[0];
|
||||
|
||||
equals(block.program.body[0].string, 'foo\n');
|
||||
equals(block.program.body[0].value, 'foo\n');
|
||||
});
|
||||
it('marks mustaches with children as standalone', function() {
|
||||
var ast = Handlebars.parse('{{# comment}} \n{{foo}}\n {{/comment}}'),
|
||||
block = ast.body[0];
|
||||
|
||||
equals(block.program.body[0].string, '');
|
||||
equals(block.program.body[0].value, '');
|
||||
equals(block.program.body[1].sexpr.id.original, 'foo');
|
||||
equals(block.program.body[2].string, '\n');
|
||||
equals(block.program.body[2].value, '\n');
|
||||
});
|
||||
it('marks nested block mustaches as standalone', function() {
|
||||
var ast = Handlebars.parse('{{#foo}} \n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} \n{{/foo}}'),
|
||||
body = ast.body[0].program.body,
|
||||
block = body[1];
|
||||
|
||||
equals(body[0].string, '');
|
||||
equals(body[0].value, '');
|
||||
|
||||
equals(block.program.body[0].string, 'foo\n');
|
||||
equals(block.inverse.body[0].string, ' bar \n');
|
||||
equals(block.program.body[0].value, 'foo\n');
|
||||
equals(block.inverse.body[0].value, ' bar \n');
|
||||
|
||||
equals(body[0].string, '');
|
||||
equals(body[0].value, '');
|
||||
});
|
||||
it('does not mark nested block mustaches as standalone', function() {
|
||||
var ast = Handlebars.parse('{{#foo}} {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} {{/foo}}'),
|
||||
@@ -297,8 +288,8 @@ describe('ast', function() {
|
||||
|
||||
equals(body[0].omit, undefined);
|
||||
|
||||
equals(block.program.body[0].string, ' \nfoo\n');
|
||||
equals(block.inverse.body[0].string, ' bar \n ');
|
||||
equals(block.program.body[0].value, ' \nfoo\n');
|
||||
equals(block.inverse.body[0].value, ' bar \n ');
|
||||
|
||||
equals(body[0].omit, undefined);
|
||||
});
|
||||
@@ -307,8 +298,8 @@ describe('ast', function() {
|
||||
body = ast.body[0].program.body,
|
||||
block = body[0];
|
||||
|
||||
equals(block.program.body[0].string, ' \nfoo\n');
|
||||
equals(block.inverse.body[0].string, ' bar \n ');
|
||||
equals(block.program.body[0].value, ' \nfoo\n');
|
||||
equals(block.inverse.body[0].value, ' bar \n ');
|
||||
|
||||
equals(body[0].omit, undefined);
|
||||
});
|
||||
@@ -319,22 +310,22 @@ describe('ast', function() {
|
||||
|
||||
equals(ast.body[0].omit, undefined);
|
||||
|
||||
equals(block.program.body[0].string, 'foo\n');
|
||||
equals(block.inverse.body[0].string, ' bar \n');
|
||||
equals(block.program.body[0].value, 'foo\n');
|
||||
equals(block.inverse.body[0].value, ' bar \n');
|
||||
|
||||
equals(ast.body[2].string, '');
|
||||
equals(ast.body[2].value, '');
|
||||
});
|
||||
});
|
||||
describe('partials', function() {
|
||||
it('marks partial as standalone', function() {
|
||||
var ast = Handlebars.parse('{{> partial }} ');
|
||||
equals(ast.body[1].string, '');
|
||||
equals(ast.body[1].value, '');
|
||||
});
|
||||
it('marks indented partial as standalone', function() {
|
||||
var ast = Handlebars.parse(' {{> partial }} ');
|
||||
equals(ast.body[0].string, '');
|
||||
equals(ast.body[0].value, '');
|
||||
equals(ast.body[1].indent, ' ');
|
||||
equals(ast.body[2].string, '');
|
||||
equals(ast.body[2].value, '');
|
||||
});
|
||||
it('marks those around content as not standalone', function() {
|
||||
var ast = Handlebars.parse('a{{> partial }}');
|
||||
@@ -347,12 +338,12 @@ describe('ast', function() {
|
||||
describe('comments', function() {
|
||||
it('marks comment as standalone', function() {
|
||||
var ast = Handlebars.parse('{{! comment }} ');
|
||||
equals(ast.body[1].string, '');
|
||||
equals(ast.body[1].value, '');
|
||||
});
|
||||
it('marks indented comment as standalone', function() {
|
||||
var ast = Handlebars.parse(' {{! comment }} ');
|
||||
equals(ast.body[0].string, '');
|
||||
equals(ast.body[2].string, '');
|
||||
equals(ast.body[0].value, '');
|
||||
equals(ast.body[2].value, '');
|
||||
});
|
||||
it('marks those around content as not standalone', function() {
|
||||
var ast = Handlebars.parse('a{{! comment }}');
|
||||
|
||||
@@ -82,6 +82,8 @@ describe('parser', function() {
|
||||
|
||||
it('parses a partial', function() {
|
||||
equals(ast_for("{{> foo }}"), "{{> PARTIAL:foo }}\n");
|
||||
equals(ast_for("{{> 'foo' }}"), "{{> PARTIAL:foo }}\n");
|
||||
equals(ast_for("{{> 1 }}"), "{{> PARTIAL:1 }}\n");
|
||||
});
|
||||
|
||||
it('parses a partial with context', function() {
|
||||
|
||||
@@ -23,6 +23,12 @@ describe('partials', function() {
|
||||
shouldCompileToWithPartials(string, [hash, {}, {dude: partial}], true, "Dudes: Empty");
|
||||
});
|
||||
|
||||
it('partials with duplicate parameters', function() {
|
||||
shouldThrow(function() {
|
||||
CompilerContext.compile('Dudes: {{>dude dudes foo bar=baz}}');
|
||||
}, Error, 'Unsupported number of partial arguments: 2 - 1:7');
|
||||
});
|
||||
|
||||
it("partials with parameters", function() {
|
||||
var string = "Dudes: {{#dudes}}{{> dude others=..}}{{/dudes}}";
|
||||
var partial = "{{others.foo}}{{name}} ({{url}}) ";
|
||||
|
||||
+5
-9
@@ -14,16 +14,12 @@ describe('Visitor', function() {
|
||||
// Simply run the thing and make sure it does not fail and that all of the
|
||||
// stub methods are executed
|
||||
var visitor = new Handlebars.Visitor();
|
||||
visitor.accept(Handlebars.parse('{{#foo (bar 1 "1" true) foo=@data}}{{!comment}}{{> bar }} {{/foo}}'));
|
||||
visitor.accept(Handlebars.parse('{{foo}}{{#foo (bar 1 "1" true) foo=@data}}{{!comment}}{{> bar }} {{/foo}}'));
|
||||
});
|
||||
|
||||
it('should traverse to stubs', function() {
|
||||
var visitor = new Handlebars.Visitor();
|
||||
|
||||
visitor.PARTIAL_NAME = function(partialName) {
|
||||
equal(partialName.name, 'bar');
|
||||
};
|
||||
|
||||
visitor.STRING = function(string) {
|
||||
equal(string.string, '2');
|
||||
};
|
||||
@@ -36,11 +32,11 @@ describe('Visitor', function() {
|
||||
visitor.ID = function(id) {
|
||||
equal(id.original, 'foo.bar');
|
||||
};
|
||||
visitor.content = function(content) {
|
||||
equal(content.string, ' ');
|
||||
visitor.ContentStatement = function(content) {
|
||||
equal(content.value, ' ');
|
||||
};
|
||||
visitor.comment = function(comment) {
|
||||
equal(comment.comment, 'comment');
|
||||
visitor.CommentStatement = function(comment) {
|
||||
equal(comment.value, 'comment');
|
||||
};
|
||||
|
||||
visitor.accept(Handlebars.parse('{{#foo.bar (foo.bar 1 "2" true) foo=@foo.bar}}{{!comment}}{{> bar }} {{/foo.bar}}'));
|
||||
|
||||
+6
-7
@@ -78,12 +78,11 @@ mustache
|
||||
;
|
||||
|
||||
partial
|
||||
: OPEN_PARTIAL partialName param hash? CLOSE -> new yy.PartialNode($2, $3, $4, yy.stripFlags($1, $5), yy.locInfo(@$))
|
||||
| OPEN_PARTIAL partialName hash? CLOSE -> new yy.PartialNode($2, undefined, $3, yy.stripFlags($1, $4), yy.locInfo(@$))
|
||||
: OPEN_PARTIAL sexpr CLOSE -> new yy.PartialNode($2, yy.stripFlags($1, $3), yy.locInfo(@$))
|
||||
;
|
||||
|
||||
sexpr
|
||||
: path param* hash? -> new yy.SexprNode([$1].concat($2), $3, yy.locInfo(@$))
|
||||
: helperName param* hash? -> new yy.SexprNode([$1].concat($2), $3, yy.locInfo(@$))
|
||||
| dataName -> new yy.SexprNode([$1], null, yy.locInfo(@$))
|
||||
;
|
||||
|
||||
@@ -108,10 +107,10 @@ blockParams
|
||||
: OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> $2
|
||||
;
|
||||
|
||||
partialName
|
||||
: path -> new yy.PartialNameNode($1, yy.locInfo(@$))
|
||||
| STRING -> new yy.PartialNameNode(new yy.StringNode($1, yy.locInfo(@$)), yy.locInfo(@$))
|
||||
| NUMBER -> new yy.PartialNameNode(new yy.NumberNode($1, yy.locInfo(@$)))
|
||||
helperName
|
||||
: path -> $1
|
||||
| STRING -> new yy.StringNode($1, yy.locInfo(@$)), yy.locInfo(@$)
|
||||
| NUMBER -> new yy.NumberNode($1, yy.locInfo(@$))
|
||||
;
|
||||
|
||||
dataName
|
||||
|
||||
Reference in New Issue
Block a user