ventojs 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [2.4.0] - 2026-07-09
8
+ ### Added
9
+ - Support for negative filters [#178].
10
+ Example: `{{ value |> !empty }}`
11
+
12
+ ### Changed
13
+ - `empty` filter returns true for empty objects.
14
+ Example: `{{ {} |> empty }}` returns `true`.
15
+
16
+ ### Fixed
17
+ - Updated benchmarks libraries and added `@11ty/nunjucks`.
18
+
7
19
  ## [2.3.1] - 2026-02-21
8
20
  ### Fixed
9
21
  - Types for Node [#174]
@@ -122,7 +134,9 @@ Vento 2.0 is now dependency-free and compatible with browsers without a build st
122
134
  [#166]: https://github.com/ventojs/vento/issues/166
123
135
  [#167]: https://github.com/ventojs/vento/issues/167
124
136
  [#174]: https://github.com/ventojs/vento/issues/174
137
+ [#178]: https://github.com/ventojs/vento/issues/178
125
138
 
139
+ [2.4.0]: https://github.com/ventojs/vento/compare/v2.3.1...v2.4.0
126
140
  [2.3.1]: https://github.com/ventojs/vento/compare/v2.3.0...v2.3.1
127
141
  [2.3.0]: https://github.com/ventojs/vento/compare/v2.2.0...v2.3.0
128
142
  [2.2.0]: https://github.com/ventojs/vento/compare/v2.1.1...v2.2.0
@@ -207,11 +207,11 @@ export class Environment {
207
207
  while (tokens.length > 0 && tokens[0][0] === "filter") {
208
208
  const token = tokens.shift();
209
209
  const [, code, position] = token;
210
- const match = code.match(/^(await\s+)?([\w.]+)(?:\((.*)\))?$/);
210
+ const match = code.match(/^(!)?(await\s+)?([\w.]+)(?:\((.*)\))?$/);
211
211
  if (!match) {
212
212
  throw new SourceError(`Invalid filter: ${code}`, position);
213
213
  }
214
- const [_, isAsync, name, args] = match;
214
+ const [_, isNegative, isAsync, name, args] = match;
215
215
  if (!Object.hasOwn(this.filters, name)) {
216
216
  if (name === "safe") {
217
217
  unescaped = true;
@@ -230,6 +230,10 @@ export class Environment {
230
230
  const { dataVarname } = this.options;
231
231
  output = `${(isAsync || checkAsync(this.filters[name])) ? "await " : ""}__env.filters.${name}.call({data:${dataVarname},env:__env}, ${output}${args ? `, ${args}` : ""})`;
232
232
  }
233
+ // Is negative
234
+ if (isNegative) {
235
+ output = `!${output}`;
236
+ }
233
237
  }
234
238
  // Escape by default
235
239
  if (autoescape && !unescaped) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ventojs",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "description": "🌬 A minimal but powerful template engine",
5
5
  "type": "module",
6
6
  "repository": {
package/plugins/empty.js CHANGED
@@ -5,13 +5,21 @@ export default function () {
5
5
  if (!value)
6
6
  return true;
7
7
  if (typeof value == "string" || value instanceof SafeString) {
8
- return value.toString().trim() == "";
8
+ return value.toString().trim() === "";
9
9
  }
10
10
  if (typeof value != "object")
11
11
  return false;
12
12
  if (Array.isArray(value))
13
- return value.length == 0;
13
+ return value.length === 0;
14
+ if (isPlainObject(value))
15
+ return Object.keys(value).length === 0;
14
16
  return false;
15
17
  };
16
18
  };
17
19
  }
20
+ const objectConstructor = {}.constructor;
21
+ /** Check if the argument passed is a plain object */
22
+ export function isPlainObject(obj) {
23
+ return typeof obj === "object" && obj !== null &&
24
+ (obj.constructor === objectConstructor || obj.constructor === undefined);
25
+ }
@@ -20,9 +20,9 @@ export declare class SourceError extends VentoError {
20
20
  getContext(): {
21
21
  type: string;
22
22
  message: string;
23
- position: number;
24
- file: string;
25
- source: string;
23
+ position: number | undefined;
24
+ file: string | undefined;
25
+ source: string | undefined;
26
26
  };
27
27
  }
28
28
  export declare class RuntimeError extends VentoError {
@@ -1,2 +1,4 @@
1
1
  import type { Plugin } from "../core/environment.d.ts";
2
2
  export default function (): Plugin;
3
+ /** Check if the argument passed is a plain object */
4
+ export declare function isPlainObject(obj: unknown): obj is Record<string, unknown>;