summaryrefslogtreecommitdiffstats
path: root/lib/handlebars/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/handlebars/compiler')
-rw-r--r--lib/handlebars/compiler/ast.js7
-rw-r--r--lib/handlebars/compiler/compiler.js7
-rw-r--r--lib/handlebars/compiler/helpers.js8
-rw-r--r--lib/handlebars/compiler/javascript-compiler.js77
-rw-r--r--lib/handlebars/compiler/visitor.js60
5 files changed, 104 insertions, 55 deletions
diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js
index 49bdc33..e05ceec 100644
--- a/lib/handlebars/compiler/ast.js
+++ b/lib/handlebars/compiler/ast.js
@@ -196,14 +196,13 @@ var AST = {
this.stringModeValue = bool === "true";
},
- CommentNode: function(comment, locInfo) {
+ CommentNode: function(comment, strip, locInfo) {
LocationInfo.call(this, locInfo);
this.type = "comment";
this.comment = comment;
- this.strip = {
- inlineStandalone: true
- };
+ this.strip = strip;
+ strip.inlineStandalone = true;
}
};
diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js
index 1aba34b..1303d8f 100644
--- a/lib/handlebars/compiler/compiler.js
+++ b/lib/handlebars/compiler/compiler.js
@@ -179,7 +179,12 @@ Compiler.prototype = {
this.opcode('pushContext');
}
- this.opcode('invokePartial', partialName.name, partial.indent || '');
+ var indent = partial.indent || '';
+ if (this.options.preventIndent && indent) {
+ this.opcode('appendContent', indent);
+ indent = '';
+ }
+ this.opcode('invokePartial', partialName.name, indent);
this.opcode('append');
},
diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js
index b375479..d236f7f 100644
--- a/lib/handlebars/compiler/helpers.js
+++ b/lib/handlebars/compiler/helpers.js
@@ -7,6 +7,11 @@ export function stripFlags(open, close) {
};
}
+export function stripComment(comment) {
+ return comment.replace(/^\{\{~?\!-?-?/, '')
+ .replace(/-?-?~?\}\}$/, '');
+}
+
export function prepareBlock(mustache, program, inverseAndProgram, close, inverted, locInfo) {
/*jshint -W040 */
@@ -112,7 +117,8 @@ export function prepareProgram(statements, isRoot) {
if (omitLeft(statements, i)) {
// If we are on a standalone node, save the indent info for partials
if (current.type === 'partial') {
- current.indent = (/([ \t]+$)/).exec(statements[i-1].original) ? RegExp.$1 : '';
+ // Pull out the whitespace from the final line
+ current.indent = (/([ \t]+$)/).exec(statements[i-1].original)[1];
}
}
}
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js
index d41cacd..4e414e5 100644
--- a/lib/handlebars/compiler/javascript-compiler.js
+++ b/lib/handlebars/compiler/javascript-compiler.js
@@ -289,13 +289,18 @@ JavaScriptCompiler.prototype = {
// If `value` is truthy, or 0, it is coerced into a string and appended
// Otherwise, the empty string is appended
append: function() {
- // Force anything that is inlined onto the stack so we don't have duplication
- // when we examine local
- this.flushInline();
- var local = this.popStack();
- this.pushSource('if (' + local + ' != null) { ' + this.appendToBuffer(local) + ' }');
- if (this.environment.isSimple) {
- this.pushSource("else { " + this.appendToBuffer("''") + " }");
+ if (this.isInline()) {
+ this.replaceStack(function(current) {
+ return ' != null ? ' + current + ' : ""';
+ });
+
+ this.pushSource(this.appendToBuffer(this.popStack()));
+ } else {
+ var local = this.popStack();
+ this.pushSource('if (' + local + ' != null) { ' + this.appendToBuffer(local) + ' }');
+ if (this.environment.isSimple) {
+ this.pushSource("else { " + this.appendToBuffer("''") + " }");
+ }
}
},
@@ -692,7 +697,7 @@ JavaScriptCompiler.prototype = {
},
pushStackLiteral: function(item) {
- return this.push(new Literal(item));
+ this.push(new Literal(item));
},
pushSource: function(source) {
@@ -706,15 +711,6 @@ JavaScriptCompiler.prototype = {
}
},
- pushStack: function(item) {
- this.flushInline();
-
- var stack = this.incrStack();
- this.pushSource(stack + " = " + item + ";");
- this.compileStack.push(stack);
- return stack;
- },
-
replaceStack: function(callback) {
var prefix = '',
inline = this.isInline(),
@@ -736,8 +732,8 @@ JavaScriptCompiler.prototype = {
usedLiteral = true;
} else {
// Get or create the current stack name for use by the inline
- createdStack = !this.stackSlot;
- var name = !createdStack ? this.topStackName() : this.incrStack();
+ createdStack = true;
+ var name = this.incrStack();
prefix = '(' + this.push(name) + ' = ' + top + ')';
stack = this.topStack();
@@ -764,15 +760,16 @@ JavaScriptCompiler.prototype = {
},
flushInline: function() {
var inlineStack = this.inlineStack;
- if (inlineStack.length) {
- this.inlineStack = [];
- for (var i = 0, len = inlineStack.length; i < len; i++) {
- var entry = inlineStack[i];
- if (entry instanceof Literal) {
- this.compileStack.push(entry);
- } else {
- this.pushStack(entry);
- }
+ this.inlineStack = [];
+ for (var i = 0, len = inlineStack.length; i < len; i++) {
+ var entry = inlineStack[i];
+ /* istanbul ignore if */
+ if (entry instanceof Literal) {
+ this.compileStack.push(entry);
+ } else {
+ var stack = this.incrStack();
+ this.pushSource(stack + " = " + entry + ";");
+ this.compileStack.push(stack);
}
}
},
@@ -802,6 +799,7 @@ JavaScriptCompiler.prototype = {
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
item = stack[stack.length - 1];
+ /* istanbul ignore if */
if (item instanceof Literal) {
return item.value;
} else {
@@ -852,7 +850,7 @@ JavaScriptCompiler.prototype = {
};
},
- setupOptions: function(helper, paramSize, params) {
+ setupParams: function(helper, paramSize, params, useRegister) {
var options = {}, contexts = [], types = [], ids = [], param, inverse, program;
options.name = this.quotedString(helper);
@@ -872,16 +870,8 @@ JavaScriptCompiler.prototype = {
// Avoid setting fn and inverse if neither are set. This allows
// helpers to do a check for `if (options.fn)`
if (program || inverse) {
- if (!program) {
- program = 'this.noop';
- }
-
- if (!inverse) {
- inverse = 'this.noop';
- }
-
- options.fn = program;
- options.inverse = inverse;
+ options.fn = program || 'this.noop';
+ options.inverse = inverse || 'this.noop';
}
// The parameters go on to the stack in order (making sure that they are evaluated in order)
@@ -912,14 +902,7 @@ JavaScriptCompiler.prototype = {
options.data = "data";
}
- return options;
- },
-
- // the params and contexts arguments are passed in arrays
- // to fill in
- setupParams: function(helperName, paramSize, params, useRegister) {
- var options = this.objectLiteral(this.setupOptions(helperName, paramSize, params));
-
+ options = this.objectLiteral(options);
if (useRegister) {
this.useRegister('options');
params.push('options');
diff --git a/lib/handlebars/compiler/visitor.js b/lib/handlebars/compiler/visitor.js
index 6a0373e..a4eb2b4 100644
--- a/lib/handlebars/compiler/visitor.js
+++ b/lib/handlebars/compiler/visitor.js
@@ -4,8 +4,64 @@ Visitor.prototype = {
constructor: Visitor,
accept: function(object) {
- return this[object.type](object);
- }
+ return object && this[object.type] && this[object.type](object);
+ },
+
+ program: function(program) {
+ var statements = program.statements,
+ i, l;
+
+ for(i=0, l=statements.length; i<l; i++) {
+ this.accept(statements[i]);
+ }
+ },
+
+ block: function(block) {
+ this.accept(block.mustache);
+ this.accept(block.program);
+ this.accept(block.inverse);
+ },
+
+ mustache: function(mustache) {
+ this.accept(mustache.sexpr);
+ },
+
+ sexpr: function(sexpr) {
+ var params = sexpr.params, paramStrings = [], hash;
+
+ this.accept(sexpr.id);
+ for(var i=0, l=params.length; i<l; i++) {
+ this.accept(params[i]);
+ }
+ this.accept(sexpr.hash);
+ },
+
+ hash: function(hash) {
+ var pairs = hash.pairs;
+
+ for(var i=0, l=pairs.length; i<l; i++) {
+ this.accept(pairs[i][1]);
+ }
+ },
+
+ 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);
+ },
+
+ STRING: function(string) {},
+ NUMBER: function(number) {},
+ BOOLEAN: function(bool) {},
+ ID: function(id) {},
+
+ content: function(content) {},
+ comment: function(comment) {}
};
export default Visitor;