From 835b22c4b736219f1fac6c62fee7724fb228f587 Mon Sep 17 00:00:00 2001 From: vrugtehagel Date: Fri, 19 Dec 2025 10:15:55 +0100 Subject: [PATCH] Add `empty` filter I considered `isEmpty` (and `is_empty`) as well, but I went with the simpler `empty` because its use is mostly limited to `{{ if }}` statements. It's unlikely users are directly printing booleans, and the filter is more-or-less useless in tags like `{{ echo }}` or `{{ for }}`. Given the relatively narrow scope, I don't think there are readability issues with omitting the `is` from the name. Generally it'll be used in contexts where booleans are expected, like ```vto {{ if items |> empty }} {{ set isMissingTags = tags |> empty }} {{ /if }} ``` --- plugins/empty.ts | 16 ++++++++++ plugins/mod.ts | 2 ++ test/empty.test.ts | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 plugins/empty.ts create mode 100644 test/empty.test.ts diff --git a/plugins/empty.ts b/plugins/empty.ts new file mode 100644 index 0000000..e557cd1 --- /dev/null +++ b/plugins/empty.ts @@ -0,0 +1,16 @@ +import { SafeString } from "../core/environment.ts"; +import type { Environment, Plugin } from "../core/environment.ts"; + +export default function (): Plugin { + return (env: Environment) => { + env.filters.empty = (value: unknown): boolean => { + if (!value) return true; + if (typeof value == "string" || value instanceof SafeString) { + return value.toString().trim() == ""; + } + if (typeof value != "object") return false; + if (Array.isArray(value)) return value.length == 0; + return false; + }; + }; +} diff --git a/plugins/mod.ts b/plugins/mod.ts index 0701937..b1a378f 100644 --- a/plugins/mod.ts +++ b/plugins/mod.ts @@ -14,6 +14,7 @@ import echoTag from "./echo.ts"; import escape from "./escape.ts"; import unescape from "./unescape.ts"; import trim from "./trim.ts"; +import empty from "./empty.ts"; export default function (): Plugin { return (env: Environment) => { @@ -31,5 +32,6 @@ export default function (): Plugin { env.use(escape()); env.use(unescape()); env.use(trim()); + env.use(empty()); }; } diff --git a/test/empty.test.ts b/test/empty.test.ts new file mode 100644 index 0000000..05c94cb --- /dev/null +++ b/test/empty.test.ts @@ -0,0 +1,73 @@ +import { test } from "./utils.ts"; + +Deno.test("Escape filter", async () => { + await test({ + template: ` + NaN: {{ NaN |> empty }} + `, + expected: "NaN: true", + }); + + await test({ + template: ` + Zero: {{ 0 |> empty }} + `, + expected: "Zero: true", + }); + + await test({ + template: ` + One: {{ 1 |> empty }} + `, + expected: "One: false", + }); + + await test({ + template: ` + Null: {{ null |> empty }} + `, + expected: "Null: true", + }); + + await test({ + template: ` + Empty object: {{ {} |> empty }} + `, + expected: "Empty object: false", + }); + + await test({ + template: ` + Empty array: {{ [] |> empty }} + `, + expected: "Empty array: true", + }); + + await test({ + template: ` + Array with empty slot: {{ Array(1) |> empty }} + `, + expected: "Array with empty slot: false", + }); + + await test({ + template: ` + Empty string: {{ "" |> empty }} + `, + expected: "Empty string: true", + }); + + await test({ + template: String.raw` + Whitespace only: {{ " \n\t " |> empty }} + `, + expected: "Whitespace only: true", + }); + + await test({ + template: ` + String of zero: {{ "0" |> empty }} + `, + expected: "String of zero: false", + }); +});