diff --git a/src/builtin/tags/unless.ts b/src/builtin/tags/unless.ts index af48e2642c..61e28c6dcc 100644 --- a/src/builtin/tags/unless.ts +++ b/src/builtin/tags/unless.ts @@ -1,8 +1,9 @@ -import { TopLevelToken, Template, Emitter, Expression, isFalsy, ParseStream, Context, TagImplOptions, Token, TagToken } from '../../types' +import { TopLevelToken, Template, Emitter, Expression, isTruthy, isFalsy, ParseStream, Context, TagImplOptions, TagToken } from '../../types' export default { parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) { this.templates = [] + this.branches = [] this.elseTemplates = [] let p const stream: ParseStream = this.liquid.parser.parseStream(remainTokens) @@ -10,6 +11,12 @@ export default { p = this.templates this.cond = tagToken.args }) + .on('tag:elsif', (token: TagToken) => { + this.branches.push({ + cond: token.args, + templates: p = [] + }) + }) .on('tag:else', () => (p = this.elseTemplates)) .on('tag:endunless', () => stream.stop()) .on('template', (tpl: Template) => p.push(tpl)) @@ -23,8 +30,20 @@ export default { render: function * (ctx: Context, emitter: Emitter) { const r = this.liquid.renderer const cond = yield new Expression(this.cond, ctx.opts.lenientIf).value(ctx) - yield (isFalsy(cond, ctx) - ? r.renderTemplates(this.templates, ctx, emitter) - : r.renderTemplates(this.elseTemplates, ctx, emitter)) + + if (isFalsy(cond, ctx)) { + yield r.renderTemplates(this.templates, ctx, emitter) + return + } + + for (const branch of this.branches) { + const cond = yield new Expression(branch.cond, ctx.opts.lenientIf).value(ctx) + if (isTruthy(cond, ctx)) { + yield r.renderTemplates(branch.templates, ctx, emitter) + return + } + } + + yield r.renderTemplates(this.elseTemplates, ctx, emitter) } } as TagImplOptions diff --git a/src/render/boolean.ts b/src/render/boolean.ts index 6c51d63bf6..d91c8f7f18 100644 --- a/src/render/boolean.ts +++ b/src/render/boolean.ts @@ -5,10 +5,9 @@ export function isTruthy (val: any, ctx: Context): boolean { } export function isFalsy (val: any, ctx: Context): boolean { - if(ctx.opts.jsTruthy) { + if (ctx.opts.jsTruthy) { return !val - } - else { + } else { return val === false || undefined === val || val === null } } diff --git a/test/e2e/issues.ts b/test/e2e/issues.ts index 11be1b8e9b..6e6917892c 100644 --- a/test/e2e/issues.ts +++ b/test/e2e/issues.ts @@ -42,4 +42,16 @@ describe('Issues', function () { const html = engine.parseAndRenderSync(template) expect(html).to.equal('This is a code snippet showing how {% breaks the raw block.') }) + it('#268 elsif is not supported for unless', () => { + const template = `{%- unless condition1 -%} +
X
+ {%- elsif condition2 -%} +
Y
+ {%- else %} +
Z
+ {% endunless %}` + const engine = new Liquid() + const html = engine.parseAndRenderSync(template, { condition1: true, condition2: true }) + expect(html).to.equal('
Y
') + }) }) diff --git a/test/integration/builtin/tags/if.ts b/test/integration/builtin/tags/if.ts index 66f2c251e9..2930ba17f4 100644 --- a/test/integration/builtin/tags/if.ts +++ b/test/integration/builtin/tags/if.ts @@ -1,5 +1,9 @@ import { Liquid } from '../../../../src/liquid' -import { expect } from 'chai' +import * as chai from 'chai' +import * as chaiAsPromised from 'chai-as-promised' + +const expect = chai.expect +chai.use(chaiAsPromised) describe('tags/if', function () { const liquid = new Liquid() diff --git a/test/integration/builtin/tags/unless.ts b/test/integration/builtin/tags/unless.ts index 823411ef34..7d5fc6fe71 100644 --- a/test/integration/builtin/tags/unless.ts +++ b/test/integration/builtin/tags/unless.ts @@ -14,6 +14,11 @@ describe('tags/unless', function () { const html = await liquid.parseAndRender(src) return expect(html).to.equal('no') }) + it('should support elsif', async function () { + const src = '{% unless true %}1{%elsif true%}2{%else%}3{%endunless%}' + const html = await liquid.parseAndRender(src) + return expect(html).to.equal('2') + }) it('should render unless when predicate yields false', async function () { const src = '{% unless false %}yes{%else%}no{%endunless%}' const html = await liquid.parseAndRender(src)