From 6f2b24f7ca6772872bbfd0046e1db7b290e99a50 Mon Sep 17 00:00:00 2001 From: sschuldenzucker Date: Sun, 29 Nov 2020 22:55:40 +0100 Subject: [PATCH] implement lenientIf for the `unless` tag, too --- docs/source/tutorials/options.md | 2 +- src/builtin/tags/unless.ts | 2 +- src/liquid-options.ts | 2 +- test/integration/liquid/strict.ts | 7 ++++++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/source/tutorials/options.md b/docs/source/tutorials/options.md index 50ca213af..4c1a0dda9 100644 --- a/docs/source/tutorials/options.md +++ b/docs/source/tutorials/options.md @@ -89,7 +89,7 @@ it defaults to false. For example, when set to true, a blank string would evalu **strictVariables** is used to assert variable existence. If set to `false`, undefined variables will be rendered as empty string. Otherwise, undefined variables will cause a render exception. Defaults to `false`. -**lenientIf** modifies the behavior of `strictVariables` to allow handling optional variables. If set to `true`, an undefined variable will *not* cause an exception in the following two situations: a) it is the condition to an `if` or `elsif` tag; b) it occurs right before a `default` filter. Irrelevant if `strictVariables` is not set. Defaults to `false`. +**lenientIf** modifies the behavior of `strictVariables` to allow handling optional variables. If set to `true`, an undefined variable will *not* cause an exception in the following two situations: a) it is the condition to an `if`, `elsif`, or `unless` tag; b) it occurs right before a `default` filter. Irrelevant if `strictVariables` is not set. Defaults to `false`. {% note info Non-existent Tags %} Non-existent tags always throw errors during pasrsing and this behaviour can not be customized. diff --git a/src/builtin/tags/unless.ts b/src/builtin/tags/unless.ts index 3bae42612..af48e2642 100644 --- a/src/builtin/tags/unless.ts +++ b/src/builtin/tags/unless.ts @@ -22,7 +22,7 @@ export default { render: function * (ctx: Context, emitter: Emitter) { const r = this.liquid.renderer - const cond = yield new Expression(this.cond).value(ctx) + 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)) diff --git a/src/liquid-options.ts b/src/liquid-options.ts index 9e868fb4f..0c066ef13 100644 --- a/src/liquid-options.ts +++ b/src/liquid-options.ts @@ -19,7 +19,7 @@ export interface LiquidOptions { strictFilters?: boolean; /** Whether or not to assert variable existence. If set to `false`, undefined variables will be rendered as empty string. Otherwise, undefined variables will cause an exception. Defaults to `false`. */ strictVariables?: boolean; - /** Modifies the behavior of `strictVariables`. If set, a single undefined variable will *not* cause an exception in the context of the `if` tag and the `default` filter. Instead, it will evaluate to `false` and `null`, respectively. Irrelevant if `strictVariables` is not set. Defaults to `false`. **/ + /** Modifies the behavior of `strictVariables`. If set, a single undefined variable will *not* cause an exception in the context of the `if`/`elsif`/`unless` tag and the `default` filter. Instead, it will evaluate to `false` and `null`, respectively. Irrelevant if `strictVariables` is not set. Defaults to `false`. **/ lenientIf?: boolean; /** Strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`. */ trimTagRight?: boolean; diff --git a/test/integration/liquid/strict.ts b/test/integration/liquid/strict.ts index 0f4040672..b8ff24a9e 100644 --- a/test/integration/liquid/strict.ts +++ b/test/integration/liquid/strict.ts @@ -45,7 +45,12 @@ describe('LiquidOptions#strict*', function () { const html = await engine.render(tpl, {'defined3': 'bla'}, strictLenientOpts) return expect(html).to.equal('bla') }) - it('should still throw with an undefined variable in an expression', function () { + it('should not throw in `unless` with a single variable', async function () { + const tpl = engine.parse('before{% unless notdefined %}X{% else %}{{notdefined}}{% endunless %}after') + const html = await engine.render(tpl, ctx, strictLenientOpts) + return expect(html).to.equal('beforeXafter') + }) + it('should still throw with an undefined variable in a compound `if` expression', function () { const tpl = engine.parse('{% if notdefined == 15 %}a{% endif %}') const fhtml = engine.render(tpl, ctx, strictLenientOpts) return expect(fhtml).to.be.rejectedWith(/undefined variable: notdefined/)