diff options
author | kpdecker <kpdecker@gmail.com> | 2014-10-27 00:23:32 -0500 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2014-10-27 19:17:16 -0500 |
commit | 4282668d47b90da0d00cf4c4a86977f18fc8cde4 (patch) | |
tree | a7254e549e27afb8043b03dd6ddd21e3afaae2e6 /lib/handlebars/compiler/helpers.js | |
parent | 8aa2a34a8d2453a45a3bc9d45e1fbed17e4d8bbc (diff) | |
download | handlebars.js-4282668d47b90da0d00cf4c4a86977f18fc8cde4.zip handlebars.js-4282668d47b90da0d00cf4c4a86977f18fc8cde4.tar.gz handlebars.js-4282668d47b90da0d00cf4c4a86977f18fc8cde4.tar.bz2 |
Implement parser for else chaining of helpers
Allows users to chain multiple helpers together using their inverse callbacks. I.e.
```
{{#if foo}}
{{else if bar}}
{{else}}
{{/if}}
```
The control flow here effectively causes the helpers to be nested. The above is actually syntactic sugar for this:
```
{{#if foo}}
{{else}}
{{#if bar}}
{{else}}
{{/if}}
{{/if}}
```
Any helper may be used in this manner, the only requirement is they support normal calls and inverse calls.
Introduces a breaking change in that `{{else foo}}` may no longer be used as a root level operator. Instead `{{^foo}}` must be used.
Fixes #72.
Diffstat (limited to 'lib/handlebars/compiler/helpers.js')
-rw-r--r-- | lib/handlebars/compiler/helpers.js | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js index 758c740..b375479 100644 --- a/lib/handlebars/compiler/helpers.js +++ b/lib/handlebars/compiler/helpers.js @@ -10,11 +10,29 @@ export function stripFlags(open, close) { export function prepareBlock(mustache, program, inverseAndProgram, close, inverted, locInfo) { /*jshint -W040 */ - if (mustache.sexpr.id.original !== close.path.original) { + // When we are chaining inverse calls, we will not have a close path + if (close && close.path && (mustache.sexpr.id.original !== close.path.original)) { throw new Exception(mustache.sexpr.id.original + ' doesn\'t match ' + close.path.original, mustache); } - var inverse = inverseAndProgram && inverseAndProgram.program; + // Safely handle a chained inverse that does not have a non-conditional inverse + // (i.e. both inverseAndProgram AND close are undefined) + if (!close) { + close = {strip: {}}; + } + + // Find the inverse program that is involed with whitespace stripping. + var inverse = inverseAndProgram && inverseAndProgram.program, + firstInverse = inverse, + lastInverse = inverse; + if (inverse && inverse.inverse) { + firstInverse = inverse.statements[0].program; + + // Walk the inverse chain to find the last inverse that is actually in the chain. + while (lastInverse.inverse) { + lastInverse = lastInverse.statements[lastInverse.statements.length-1].program; + } + } var strip = { left: mustache.strip.left, @@ -23,7 +41,7 @@ export function prepareBlock(mustache, program, inverseAndProgram, close, invert // Determine the standalone candiacy. Basically flag our content as being possibly standalone // so our parent can determine if we actually are standalone openStandalone: isNextWhitespace(program.statements), - closeStandalone: isPrevWhitespace((inverse || program).statements) + closeStandalone: isPrevWhitespace((firstInverse || program).statements) }; if (mustache.strip.right) { @@ -36,19 +54,20 @@ export function prepareBlock(mustache, program, inverseAndProgram, close, invert if (inverseStrip.left) { omitLeft(program.statements, null, true); } + if (inverseStrip.right) { - omitRight(inverse.statements, null, true); + omitRight(firstInverse.statements, null, true); } if (close.strip.left) { - omitLeft(inverse.statements, null, true); + omitLeft(lastInverse.statements, null, true); } // Find standalone else statments if (isPrevWhitespace(program.statements) - && isNextWhitespace(inverse.statements)) { + && isNextWhitespace(firstInverse.statements)) { omitLeft(program.statements); - omitRight(inverse.statements); + omitRight(firstInverse.statements); } } else { if (close.strip.left) { |