diff options
Diffstat (limited to 'lib/handlebars/compiler')
-rw-r--r-- | lib/handlebars/compiler/ast.js | 7 | ||||
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 7 | ||||
-rw-r--r-- | lib/handlebars/compiler/helpers.js | 8 | ||||
-rw-r--r-- | lib/handlebars/compiler/javascript-compiler.js | 77 | ||||
-rw-r--r-- | lib/handlebars/compiler/visitor.js | 60 |
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; |