Undefined variables
At render time, if a template variable or path to a variable can not be resolved to a value, an instance of Undefined is used in its place. We can control undefined variable rendering behavior through the undefinedType option when constructing a new Liquid environment.
Default undefined
The default Undefined type is silent. It renders to the empty string, is falsy when tested for truthiness, and yields an empty iterable when looped over with the {% for %} tag.
Hello {{ nosuchthing }}
{% for thing in nosuchthing %}
{{ thing }}
{% endfor %}
Hello
Strict undefined
The StrictUndefined type throws an UndefinedVariableError in all contexts, even when tested for truthiness with the {% if %} tag.
import { Environment, StrictUndefined } from "liquidscript";
const liquid = new Environment({ undefinedType: StrictUndefined });
const template = liquid.parse("{{ nosuchthing }}");
template.render().then(console.log);
// UndefinedVariableError: 'nosuchthing' is undefined
Note that UndefinedVariableError inherits from DetailedLiquidError, giving us the opportunity to capture or output useful diagnostic information.
import {
DetailedLiquidError,
Environment,
StrictUndefined,
} from "liquidscript";
const liquid = new Environment({ undefinedType: StrictUndefined });
const template = liquid.parse(
"{% if nosuchthing %}TRUE{% else %}FALSE{% endif %}",
);
(async () => {
try {
await template.render();
} catch (err) {
if (err instanceof DetailedLiquidError) {
console.error(err.render());
} else {
throw err;
}
}
})();
name error: 'nosuchthing' is undefined
-> 1:6
|
1 | {% if nosuchthing %}TRUE{% else %}FALSE{% endif %}
| ^^^^^^^^^^^ 'nosuchthing' is undefined
Falsy strict undefined
The FalsyStrictUndefined type is similar to StrictUndefined, but can be tested for truthiness and equality without throwing an exception.
import {
DetailedLiquidError,
Environment,
FalsyStrictUndefined,
} from "liquidscript";
const liquid = new Environment({ undefinedType: FalsyStrictUndefined });
const template = liquid.parse(
"{% if nosuchthing %}TRUE{% else %}FALSE{% endif %}",
);
(async () => {
try {
console.log(await template.render());
} catch (err) {
if (err instanceof DetailedLiquidError) {
console.error(err.render());
} else {
throw err;
}
}
})();
FALSE
Customizing undefined variable behavior
All of the built-in Undefined types are implemented as drops and are accessed exclusively through the drop API. This means you can inherit from Undefined and override any drop methods to customize undefined variable behavior.