Skip to content

Commit

Permalink
fix: case should render multiple when statements
Browse files Browse the repository at this point in the history
  • Loading branch information
harttle committed Dec 2, 2022
1 parent 46ffe03 commit d17813e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 14 deletions.
34 changes: 20 additions & 14 deletions src/tags/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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())
Expand All @@ -35,16 +35,22 @@ export default class extends Tag {
stream.start()
}

* render (ctx: Context, emitter: Emitter): Generator<unknown, unknown, unknown> {
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
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)
}
}
}
17 changes: 17 additions & 0 deletions test/e2e/issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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*$/)
})
})
8 changes: 8 additions & 0 deletions test/integration/tags/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
})

0 comments on commit d17813e

Please sign in to comment.