From d17813ef5217264bd08f741b0e1f713bedf2d464 Mon Sep 17 00:00:00 2001 From: Jun Yang Date: Sat, 3 Dec 2022 00:14:47 +0800 Subject: [PATCH] fix: `case` should render multiple `when` statements --- src/tags/case.ts | 34 ++++++++++++++++++++-------------- test/e2e/issues.ts | 17 +++++++++++++++++ test/integration/tags/case.ts | 8 ++++++++ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/tags/case.ts b/src/tags/case.ts index a7608f6b56..191fddabec 100644 --- a/src/tags/case.ts +++ b/src/tags/case.ts @@ -2,7 +2,7 @@ import { ValueToken, Liquid, Tokenizer, toValue, evalToken, Value, Emitter, TagT export default class extends Tag { value: Value - branches: { value?: ValueToken, templates: Template[] }[] = [] + branches: { values: ValueToken[], templates: Template[] }[] = [] elseTemplates: Template[] = [] constructor (tagToken: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) { super(tagToken, remainTokens, liquid) @@ -15,15 +15,15 @@ export default class extends Tag { p = [] const tokenizer = new Tokenizer(token.args, this.liquid.options.operators) - + const values: ValueToken[] = [] while (!tokenizer.end()) { - const value = tokenizer.readValue() - this.branches.push({ - value: value, - templates: p - }) + values.push(tokenizer.readValueOrThrow()) tokenizer.readTo(',') } + this.branches.push({ + values, + templates: p + }) }) .on('tag:else', () => (p = this.elseTemplates)) .on('tag:endcase', () => stream.stop()) @@ -35,16 +35,22 @@ export default class extends Tag { stream.start() } - * render (ctx: Context, emitter: Emitter): Generator { + * render (ctx: Context, emitter: Emitter): Generator { const r = this.liquid.renderer - const value = toValue(yield this.value.value(ctx, ctx.opts.lenientIf)) + const target = toValue(yield this.value.value(ctx, ctx.opts.lenientIf)) + let branchHit = false for (const branch of this.branches) { - const target = yield evalToken(branch.value, ctx, ctx.opts.lenientIf) - if (target === value) { - yield r.renderTemplates(branch.templates, ctx, emitter) - return + for (const valueToken of branch.values) { + const value = yield evalToken(valueToken, ctx, ctx.opts.lenientIf) + if (target === value) { + yield r.renderTemplates(branch.templates, ctx, emitter) + branchHit = true + break + } } } - yield r.renderTemplates(this.elseTemplates, ctx, emitter) + if (!branchHit) { + yield r.renderTemplates(this.elseTemplates, ctx, emitter) + } } } diff --git a/test/e2e/issues.ts b/test/e2e/issues.ts index bc5a7421c1..734655fbd1 100644 --- a/test/e2e/issues.ts +++ b/test/e2e/issues.ts @@ -329,4 +329,21 @@ describe('Issues', function () { expect(await liquid.parseAndRender('{{i.i}}', context)).to.equal('1') expect(await liquid.parseAndRender('{{j.j}}', context)).to.equal('1') }) + it('#559 Case/When should evaluate multiple When statements', async () => { + const liquid = new Liquid() + const tpl = ` + {% assign tag = 'Love' %} + + {% case tag %} + {% when 'Love' or 'Luck' %} + This is a love or luck potion. + {% when 'Strength','Health', 'Love' %} + This is a strength or health or love potion. + {% else %} + This is a potion. + {% endcase %} + ` + const html = await liquid.parseAndRender(tpl) + expect(html).to.match(/^\s*This is a love or luck potion.\s+This is a strength or health or love potion.\s*$/) + }) }) diff --git a/test/integration/tags/case.ts b/test/integration/tags/case.ts index b085468255..f3eaf53174 100644 --- a/test/integration/tags/case.ts +++ b/test/integration/tags/case.ts @@ -71,4 +71,12 @@ describe('tags/case', function () { const html = await liquid.parseAndRender(src) return expect(html).to.equal('foo') }) + it('should render multiple matching branches', async function () { + const src = '{% case "b" %}' + + '{% when "a", "b" %}first' + + '{% when "b" %}second' + + '{%endcase%}' + const html = await liquid.parseAndRender(src) + return expect(html).to.equal('firstsecond') + }) })