diff options
author | kpdecker <kpdecker@gmail.com> | 2015-08-14 15:18:52 -0500 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2015-08-22 10:59:08 -0700 |
commit | 91ffd32cad32b2d1cd310ff94f65b28c428206ac (patch) | |
tree | 13cb346dfb0e6dc72dc6dddbcdf3ed8e61ebaeff /lib/handlebars/compiler | |
parent | 2571dd8e8e43fd320672763564b16a5b3ae33966 (diff) | |
download | handlebars.js-91ffd32cad32b2d1cd310ff94f65b28c428206ac.zip handlebars.js-91ffd32cad32b2d1cd310ff94f65b28c428206ac.tar.gz handlebars.js-91ffd32cad32b2d1cd310ff94f65b28c428206ac.tar.bz2 |
Implement partial blocks
This allows for failover for missing partials as well as limited templating ability through the `{{> @partial-block }}` partial special case.
Partial fix for #1018
Diffstat (limited to 'lib/handlebars/compiler')
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 14 | ||||
-rw-r--r-- | lib/handlebars/compiler/helpers.js | 19 | ||||
-rw-r--r-- | lib/handlebars/compiler/printer.js | 16 | ||||
-rw-r--r-- | lib/handlebars/compiler/visitor.js | 45 |
4 files changed, 71 insertions, 23 deletions
diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index ad6b861..a689e7d 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -1,3 +1,5 @@ +/* eslint-disable new-cap */ + import Exception from '../exception'; import {isArray, indexOf} from '../utils'; import AST from './ast'; @@ -157,6 +159,11 @@ Compiler.prototype = { PartialStatement: function(partial) { this.usePartial = true; + let program = partial.program; + if (program) { + program = this.compileProgram(partial.program); + } + let params = partial.params; if (params.length > 1) { throw new Exception('Unsupported number of partial arguments: ' + params.length, partial); @@ -170,7 +177,7 @@ Compiler.prototype = { this.accept(partial.name); } - this.setupFullMustacheParams(partial, undefined, undefined, true); + this.setupFullMustacheParams(partial, program, undefined, true); let indent = partial.indent || ''; if (this.options.preventIndent && indent) { @@ -181,9 +188,12 @@ Compiler.prototype = { this.opcode('invokePartial', isDynamic, partialName, indent); this.opcode('append'); }, + PartialBlockStatement: function(partialBlock) { + this.PartialStatement(partialBlock); + }, MustacheStatement: function(mustache) { - this.SubExpression(mustache); // eslint-disable-line new-cap + this.SubExpression(mustache); if (mustache.escaped && !this.options.noEscape) { this.opcode('appendEscaped'); diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js index bf72034..e04f4dd 100644 --- a/lib/handlebars/compiler/helpers.js +++ b/lib/handlebars/compiler/helpers.js @@ -185,3 +185,22 @@ export function prepareProgram(statements, loc) { } +export function preparePartialBlock(openPartialBlock, program, close, locInfo) { + if (openPartialBlock.name.original !== close.path.original) { + let errorNode = {loc: openPartialBlock.name.loc}; + + throw new Exception(openPartialBlock.name.original + " doesn't match " + close.path.original, errorNode); + } + + return { + type: 'PartialBlockStatement', + path: openPartialBlock.name, + params: openPartialBlock.params, + hash: openPartialBlock.hash, + program, + openStrip: openPartialBlock.strip, + closeStrip: close && close.strip, + loc: this.locInfo(locInfo) + }; +} + diff --git a/lib/handlebars/compiler/printer.js b/lib/handlebars/compiler/printer.js index 107d4b6..cf7aa48 100644 --- a/lib/handlebars/compiler/printer.js +++ b/lib/handlebars/compiler/printer.js @@ -84,6 +84,22 @@ PrintVisitor.prototype.PartialStatement = function(partial) { } return this.pad('{{> ' + content + ' }}'); }; +PrintVisitor.prototype.PartialBlockStatement = function(partial) { + let content = 'PARTIAL BLOCK:' + partial.name.original; + if (partial.params[0]) { + content += ' ' + this.accept(partial.params[0]); + } + if (partial.hash) { + content += ' ' + this.accept(partial.hash); + } + + content += ' ' + this.pad('PROGRAM:'); + this.padding++; + content += this.accept(partial.program); + this.padding--; + + return this.pad('{{> ' + content + ' }}'); +}; PrintVisitor.prototype.ContentStatement = function(content) { return this.pad("CONTENT[ '" + content.value + "' ]"); diff --git a/lib/handlebars/compiler/visitor.js b/lib/handlebars/compiler/visitor.js index 89dd632..cc54c53 100644 --- a/lib/handlebars/compiler/visitor.js +++ b/lib/handlebars/compiler/visitor.js @@ -75,35 +75,21 @@ Visitor.prototype = { this.acceptArray(program.body); }, - MustacheStatement: function(mustache) { - this.acceptRequired(mustache, 'path'); - this.acceptArray(mustache.params); - this.acceptKey(mustache, 'hash'); - }, + MustacheStatement: visitSubExpression, - BlockStatement: function(block) { - this.acceptRequired(block, 'path'); - this.acceptArray(block.params); - this.acceptKey(block, 'hash'); + BlockStatement: visitBlock, - this.acceptKey(block, 'program'); - this.acceptKey(block, 'inverse'); - }, + PartialStatement: visitPartial, + PartialBlockStatement: function(partial) { + visitPartial.call(this, partial); - PartialStatement: function(partial) { - this.acceptRequired(partial, 'name'); - this.acceptArray(partial.params); - this.acceptKey(partial, 'hash'); + this.acceptKey(partial, 'program'); }, ContentStatement: function(/* content */) {}, CommentStatement: function(/* comment */) {}, - SubExpression: function(sexpr) { - this.acceptRequired(sexpr, 'path'); - this.acceptArray(sexpr.params); - this.acceptKey(sexpr, 'hash'); - }, + SubExpression: visitSubExpression, PathExpression: function(/* path */) {}, @@ -121,4 +107,21 @@ Visitor.prototype = { } }; +function visitSubExpression(mustache) { + this.acceptRequired(mustache, 'path'); + this.acceptArray(mustache.params); + this.acceptKey(mustache, 'hash'); +} +function visitBlock(block) { + visitSubExpression.call(this, block); + + this.acceptKey(block, 'program'); + this.acceptKey(block, 'inverse'); +} +function visitPartial(partial) { + this.acceptRequired(partial, 'name'); + this.acceptArray(partial.params); + this.acceptKey(partial, 'hash'); +} + export default Visitor; |