summaryrefslogtreecommitdiffstats
path: root/lib/handlebars/compiler/helpers.js
diff options
context:
space:
mode:
authorkpdecker <kpdecker@gmail.com>2014-10-27 00:23:32 -0500
committerkpdecker <kpdecker@gmail.com>2014-10-27 19:17:16 -0500
commit4282668d47b90da0d00cf4c4a86977f18fc8cde4 (patch)
treea7254e549e27afb8043b03dd6ddd21e3afaae2e6 /lib/handlebars/compiler/helpers.js
parent8aa2a34a8d2453a45a3bc9d45e1fbed17e4d8bbc (diff)
downloadhandlebars.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.js33
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) {