Skip to content

Commit

Permalink
fix: elsif is not supported for unless, fixes #268
Browse files Browse the repository at this point in the history
  • Loading branch information
harttle committed Dec 7, 2020
1 parent a492d8e commit 2bbf501
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 8 deletions.
27 changes: 23 additions & 4 deletions src/builtin/tags/unless.ts
@@ -1,15 +1,22 @@
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)
.on('start', () => {
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))
Expand All @@ -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
5 changes: 2 additions & 3 deletions src/render/boolean.ts
Expand Up @@ -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
}
}
12 changes: 12 additions & 0 deletions test/e2e/issues.ts
Expand Up @@ -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 -%}
<div>X</div>
{%- elsif condition2 -%}
<div>Y</div>
{%- else %}
<div>Z</div>
{% endunless %}`
const engine = new Liquid()
const html = engine.parseAndRenderSync(template, { condition1: true, condition2: true })
expect(html).to.equal('<div>Y</div>')
})
})
6 changes: 5 additions & 1 deletion 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()
Expand Down
5 changes: 5 additions & 0 deletions test/integration/builtin/tags/unless.ts
Expand Up @@ -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)
Expand Down

0 comments on commit 2bbf501

Please sign in to comment.