ventojs 0.8.0 → 0.9.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.
Files changed (136) hide show
  1. package/README.md +7 -61
  2. package/esm/deps/deno.land/std@0.201.0/html/entities.d.ts +38 -0
  3. package/esm/deps/deno.land/std@0.201.0/html/entities.js +76 -0
  4. package/esm/deps/deno.land/std@0.201.0/html/mod.d.ts +6 -0
  5. package/esm/deps/deno.land/std@0.201.0/html/mod.js +8 -0
  6. package/esm/deps.d.ts +1 -0
  7. package/esm/deps.js +1 -0
  8. package/esm/mod.d.ts +1 -0
  9. package/esm/mod.js +1 -0
  10. package/esm/plugins/escape.js +2 -12
  11. package/esm/plugins/export.js +5 -4
  12. package/esm/plugins/import.js +4 -11
  13. package/esm/plugins/include.js +3 -2
  14. package/esm/plugins/layout.js +4 -3
  15. package/esm/plugins/set.js +5 -4
  16. package/esm/plugins/unescape.js +2 -12
  17. package/esm/src/environment.d.ts +1 -0
  18. package/esm/src/environment.js +9 -12
  19. package/package.json +4 -2
  20. package/script/_dnt.shims.d.ts +5 -0
  21. package/script/_dnt.shims.js +65 -0
  22. package/script/deps/deno.land/std@0.201.0/assert/assert.d.ts +2 -0
  23. package/script/deps/deno.land/std@0.201.0/assert/assert.js +12 -0
  24. package/script/deps/deno.land/std@0.201.0/assert/assertion_error.d.ts +4 -0
  25. package/script/deps/deno.land/std@0.201.0/assert/assertion_error.js +11 -0
  26. package/script/deps/deno.land/std@0.201.0/html/entities.d.ts +38 -0
  27. package/script/deps/deno.land/std@0.201.0/html/entities.js +81 -0
  28. package/script/deps/deno.land/std@0.201.0/html/mod.d.ts +6 -0
  29. package/script/deps/deno.land/std@0.201.0/html/mod.js +24 -0
  30. package/script/deps/deno.land/std@0.201.0/path/_basename.d.ts +16 -0
  31. package/script/deps/deno.land/std@0.201.0/path/_basename.js +83 -0
  32. package/script/deps/deno.land/std@0.201.0/path/_constants.d.ts +39 -0
  33. package/script/deps/deno.land/std@0.201.0/path/_constants.js +49 -0
  34. package/script/deps/deno.land/std@0.201.0/path/_dirname.d.ts +10 -0
  35. package/script/deps/deno.land/std@0.201.0/path/_dirname.js +137 -0
  36. package/script/deps/deno.land/std@0.201.0/path/_extname.d.ts +12 -0
  37. package/script/deps/deno.land/std@0.201.0/path/_extname.js +126 -0
  38. package/script/deps/deno.land/std@0.201.0/path/_format.d.ts +11 -0
  39. package/script/deps/deno.land/std@0.201.0/path/_format.js +40 -0
  40. package/script/deps/deno.land/std@0.201.0/path/_from_file_url.d.ts +25 -0
  41. package/script/deps/deno.land/std@0.201.0/path/_from_file_url.js +51 -0
  42. package/script/deps/deno.land/std@0.201.0/path/_interface.d.ts +26 -0
  43. package/script/deps/deno.land/std@0.201.0/path/_interface.js +4 -0
  44. package/script/deps/deno.land/std@0.201.0/path/_is_absolute.d.ts +10 -0
  45. package/script/deps/deno.land/std@0.201.0/path/_is_absolute.js +39 -0
  46. package/script/deps/deno.land/std@0.201.0/path/_join.d.ts +10 -0
  47. package/script/deps/deno.land/std@0.201.0/path/_join.js +98 -0
  48. package/script/deps/deno.land/std@0.201.0/path/_normalize.d.ts +14 -0
  49. package/script/deps/deno.land/std@0.201.0/path/_normalize.js +158 -0
  50. package/script/deps/deno.land/std@0.201.0/path/_os.d.ts +4 -0
  51. package/script/deps/deno.land/std@0.201.0/path/_os.js +44 -0
  52. package/script/deps/deno.land/std@0.201.0/path/_parse.d.ts +11 -0
  53. package/script/deps/deno.land/std@0.201.0/path/_parse.js +255 -0
  54. package/script/deps/deno.land/std@0.201.0/path/_relative.d.ts +19 -0
  55. package/script/deps/deno.land/std@0.201.0/path/_relative.js +221 -0
  56. package/script/deps/deno.land/std@0.201.0/path/_resolve.d.ts +10 -0
  57. package/script/deps/deno.land/std@0.201.0/path/_resolve.js +211 -0
  58. package/script/deps/deno.land/std@0.201.0/path/_to_file_url.d.ts +25 -0
  59. package/script/deps/deno.land/std@0.201.0/path/_to_file_url.js +66 -0
  60. package/script/deps/deno.land/std@0.201.0/path/_to_namespaced_path.d.ts +10 -0
  61. package/script/deps/deno.land/std@0.201.0/path/_to_namespaced_path.js +51 -0
  62. package/script/deps/deno.land/std@0.201.0/path/_util.d.ts +6 -0
  63. package/script/deps/deno.land/std@0.201.0/path/_util.js +116 -0
  64. package/script/deps/deno.land/std@0.201.0/path/basename.d.ts +8 -0
  65. package/script/deps/deno.land/std@0.201.0/path/basename.js +20 -0
  66. package/script/deps/deno.land/std@0.201.0/path/common.d.ts +13 -0
  67. package/script/deps/deno.land/std@0.201.0/path/common.js +40 -0
  68. package/script/deps/deno.land/std@0.201.0/path/dirname.d.ts +5 -0
  69. package/script/deps/deno.land/std@0.201.0/path/dirname.js +15 -0
  70. package/script/deps/deno.land/std@0.201.0/path/extname.d.ts +6 -0
  71. package/script/deps/deno.land/std@0.201.0/path/extname.js +16 -0
  72. package/script/deps/deno.land/std@0.201.0/path/format.d.ts +6 -0
  73. package/script/deps/deno.land/std@0.201.0/path/format.js +15 -0
  74. package/script/deps/deno.land/std@0.201.0/path/from_file_url.d.ts +18 -0
  75. package/script/deps/deno.land/std@0.201.0/path/from_file_url.js +27 -0
  76. package/script/deps/deno.land/std@0.201.0/path/glob.d.ts +83 -0
  77. package/script/deps/deno.land/std@0.201.0/path/glob.js +391 -0
  78. package/script/deps/deno.land/std@0.201.0/path/is_absolute.d.ts +5 -0
  79. package/script/deps/deno.land/std@0.201.0/path/is_absolute.js +15 -0
  80. package/script/deps/deno.land/std@0.201.0/path/join.d.ts +5 -0
  81. package/script/deps/deno.land/std@0.201.0/path/join.js +15 -0
  82. package/script/deps/deno.land/std@0.201.0/path/mod.d.ts +22 -0
  83. package/script/deps/deno.land/std@0.201.0/path/mod.js +74 -0
  84. package/script/deps/deno.land/std@0.201.0/path/normalize.d.ts +7 -0
  85. package/script/deps/deno.land/std@0.201.0/path/normalize.js +17 -0
  86. package/script/deps/deno.land/std@0.201.0/path/parse.d.ts +6 -0
  87. package/script/deps/deno.land/std@0.201.0/path/parse.js +15 -0
  88. package/script/deps/deno.land/std@0.201.0/path/posix.d.ts +15 -0
  89. package/script/deps/deno.land/std@0.201.0/path/posix.js +35 -0
  90. package/script/deps/deno.land/std@0.201.0/path/relative.d.ts +12 -0
  91. package/script/deps/deno.land/std@0.201.0/path/relative.js +22 -0
  92. package/script/deps/deno.land/std@0.201.0/path/resolve.d.ts +5 -0
  93. package/script/deps/deno.land/std@0.201.0/path/resolve.js +17 -0
  94. package/script/deps/deno.land/std@0.201.0/path/separator.d.ts +2 -0
  95. package/script/deps/deno.land/std@0.201.0/path/separator.js +8 -0
  96. package/script/deps/deno.land/std@0.201.0/path/to_file_url.d.ts +18 -0
  97. package/script/deps/deno.land/std@0.201.0/path/to_file_url.js +27 -0
  98. package/script/deps/deno.land/std@0.201.0/path/to_namespaced_path.d.ts +5 -0
  99. package/script/deps/deno.land/std@0.201.0/path/to_namespaced_path.js +17 -0
  100. package/script/deps/deno.land/std@0.201.0/path/win32.d.ts +15 -0
  101. package/script/deps/deno.land/std@0.201.0/path/win32.js +35 -0
  102. package/script/deps.d.ts +2 -0
  103. package/script/deps.js +28 -0
  104. package/script/mod.d.ts +9 -0
  105. package/script/mod.js +69 -0
  106. package/script/package.json +3 -0
  107. package/script/plugins/echo.d.ts +2 -0
  108. package/script/plugins/echo.js +16 -0
  109. package/script/plugins/escape.d.ts +2 -0
  110. package/script/plugins/escape.js +9 -0
  111. package/script/plugins/export.d.ts +2 -0
  112. package/script/plugins/export.js +50 -0
  113. package/script/plugins/for.d.ts +2 -0
  114. package/script/plugins/for.js +51 -0
  115. package/script/plugins/function.d.ts +2 -0
  116. package/script/plugins/function.js +40 -0
  117. package/script/plugins/if.d.ts +2 -0
  118. package/script/plugins/if.js +35 -0
  119. package/script/plugins/import.d.ts +2 -0
  120. package/script/plugins/import.js +20 -0
  121. package/script/plugins/include.d.ts +2 -0
  122. package/script/plugins/include.js +26 -0
  123. package/script/plugins/js.d.ts +2 -0
  124. package/script/plugins/js.js +14 -0
  125. package/script/plugins/layout.d.ts +2 -0
  126. package/script/plugins/layout.js +37 -0
  127. package/script/plugins/set.d.ts +2 -0
  128. package/script/plugins/set.js +48 -0
  129. package/script/plugins/unescape.d.ts +2 -0
  130. package/script/plugins/unescape.js +9 -0
  131. package/script/src/environment.d.ts +42 -0
  132. package/script/src/environment.js +176 -0
  133. package/script/src/loader.d.ts +14 -0
  134. package/script/src/loader.js +46 -0
  135. package/script/src/tokenizer.d.ts +8 -0
  136. package/script/src/tokenizer.js +190 -0
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # VENTO
1
+ # Vento
2
2
 
3
3
  This is a minimal template engine inspired by other great engines like Nunjucks,
4
- Liquid, Mustache or EJS.
4
+ Liquid, Mustache, and EJS.
5
5
 
6
6
  ## Why another template engine?
7
7
 
@@ -32,6 +32,7 @@ neither is). The issues I found in existing template engines:
32
32
  ### Liquid
33
33
 
34
34
  - I like:
35
+
35
36
  - The support for async evaluation is less hacky than Nunjucks.
36
37
  - The variables are not escaped by default, there's an `escape` filter for
37
38
  that.
@@ -91,64 +92,9 @@ First, let's take a look at this syntax example:
91
92
 
92
93
  ## Getting started
93
94
 
94
- This is a library for Deno. ~~I'm planning to release an NPM version in the
95
- future.~~
96
- [There's already an NPM version](https://www.npmjs.com/package/ventojs) that you
97
- can install with `npm install ventojs`.
98
-
99
- Import the library and create an instance:
100
-
101
- ```ts
102
- import vento from "https://deno.land/x/vento/mod.ts";
103
-
104
- const vto = vento({
105
- // Resolve the non-relative includes paths
106
- includes: "./path/to/includes",
107
- });
108
- ```
109
-
110
- Or in Node:
111
-
112
- ```ts
113
- import vento from "ventojs";
114
-
115
- const vto = vento({
116
- // Resolve the non-relative includes paths
117
- includes: "./path/to/includes",
118
- });
119
- ```
120
-
121
- There are different ways to load, compile and run a template. For example, you
122
- can use `load` to load and compile a template file and return it.
123
-
124
- ```ts
125
- // Load and return a template
126
- const template = vto.load("my-template.vto");
127
-
128
- // Now you can use it passing the data
129
- const result = template({ title: "Hello world" });
130
- console.log(result.content);
131
- ```
132
-
133
- Alternatively, you can load and run the template file in a single call:
134
-
135
- ```ts
136
- const result = vto.run("my-template.vto", { title: "Hello world" });
137
- console.log(result.content);
138
- ```
139
-
140
- If the template code is not a file, you can run it directly:
141
-
142
- ```ts
143
- const result = vto.runString("<h1>{{ title }}</h1>", { title: "Hello world" });
144
- console.log(result.content);
145
- ```
146
-
147
- ## Visual Studio Code Support
148
-
149
- [The Vento extension for VS Code](https://marketplace.visualstudio.com/items?itemName=oscarotero.vento-syntax)
150
- enables syntax highlight and provides some useful snippets.
95
+ See [Getting started](https://vento.js.org/getting-started/) on the docs.
151
96
 
152
- ## API
97
+ ## Editor support
153
98
 
154
- [Read the docs](https://oscarotero.github.io/vento/)
99
+ See [Editor integrations](https://vento.js.org/editor-integrations/) on the
100
+ docs.
@@ -0,0 +1,38 @@
1
+ export type EntityList = Record<string, string>;
2
+ /**
3
+ * Escapes text for safe interpolation into HTML text content and quoted attributes
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { escape } from "https://deno.land/std@$STD_VERSION/html/entities.ts";
8
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts";
9
+ *
10
+ * assertEquals(escape("<>'&AA"), "&lt;&gt;&#39;&amp;AA");
11
+ *
12
+ * // characters that don't need to be escaped will be left alone,
13
+ * // even if named HTML entities exist for them
14
+ * assertEquals(escape("þð"), "þð");
15
+ * ```
16
+ */
17
+ export declare function escape(str: string): string;
18
+ export type UnescapeOptions = {
19
+ entityList: EntityList;
20
+ };
21
+ /**
22
+ * Unescapes HTML entities in text
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { unescape } from "https://deno.land/std@$STD_VERSION/html/entities.ts";
27
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts";
28
+ *
29
+ * // default options (only handles &<>'" and numeric entities)
30
+ * assertEquals(unescape("&lt;&gt;&apos;&amp;&#65;&#x41;"), "<>'&AA");
31
+ * assertEquals(unescape("&thorn;&eth;"), "&thorn;&eth;");
32
+ *
33
+ * // using the full named entity list from the HTML spec (~47K unminified)
34
+ * import entityList from "https://deno.land/std@$STD_VERSION/html/named_entity_list.json" assert { type: "json" };
35
+ * assertEquals(unescape("&thorn;&eth;", { entityList }), "þð");
36
+ * ```
37
+ */
38
+ export declare function unescape(str: string, options?: Partial<UnescapeOptions>): string;
@@ -0,0 +1,76 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ // This module is browser compatible.
3
+ const rawToEntityEntries = [
4
+ ["&", "&amp;"],
5
+ ["<", "&lt;"],
6
+ [">", "&gt;"],
7
+ ['"', "&quot;"],
8
+ ["'", "&#39;"],
9
+ ];
10
+ const defaultEntityList = Object.fromEntries([
11
+ ...rawToEntityEntries.map(([raw, entity]) => [entity, raw]),
12
+ ["&apos;", "'"],
13
+ ["&nbsp;", "\xa0"],
14
+ ]);
15
+ const rawToEntity = new Map(rawToEntityEntries);
16
+ const rawRe = new RegExp(`[${[...rawToEntity.keys()].join("")}]`, "g");
17
+ /**
18
+ * Escapes text for safe interpolation into HTML text content and quoted attributes
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { escape } from "https://deno.land/std@$STD_VERSION/html/entities.ts";
23
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts";
24
+ *
25
+ * assertEquals(escape("<>'&AA"), "&lt;&gt;&#39;&amp;AA");
26
+ *
27
+ * // characters that don't need to be escaped will be left alone,
28
+ * // even if named HTML entities exist for them
29
+ * assertEquals(escape("þð"), "þð");
30
+ * ```
31
+ */
32
+ export function escape(str) {
33
+ return str.replaceAll(rawRe, (m) => rawToEntity.get(m));
34
+ }
35
+ const defaultUnescapeOptions = {
36
+ entityList: defaultEntityList,
37
+ };
38
+ const MAX_CODE_POINT = 0x10ffff;
39
+ const RX_DEC_ENTITY = /&#([0-9]+);/g;
40
+ const RX_HEX_ENTITY = /&#x(\p{AHex}+);/gu;
41
+ const entityListRegexCache = new WeakMap();
42
+ /**
43
+ * Unescapes HTML entities in text
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { unescape } from "https://deno.land/std@$STD_VERSION/html/entities.ts";
48
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts";
49
+ *
50
+ * // default options (only handles &<>'" and numeric entities)
51
+ * assertEquals(unescape("&lt;&gt;&apos;&amp;&#65;&#x41;"), "<>'&AA");
52
+ * assertEquals(unescape("&thorn;&eth;"), "&thorn;&eth;");
53
+ *
54
+ * // using the full named entity list from the HTML spec (~47K unminified)
55
+ * import entityList from "https://deno.land/std@$STD_VERSION/html/named_entity_list.json" assert { type: "json" };
56
+ * assertEquals(unescape("&thorn;&eth;", { entityList }), "þð");
57
+ * ```
58
+ */
59
+ export function unescape(str, options = {}) {
60
+ const { entityList } = { ...defaultUnescapeOptions, ...options };
61
+ let entityRe = entityListRegexCache.get(entityList);
62
+ if (!entityRe) {
63
+ entityRe = new RegExp(`(${Object.keys(entityList)
64
+ .sort((a, b) => b.length - a.length)
65
+ .join("|")})`, "g");
66
+ entityListRegexCache.set(entityList, entityRe);
67
+ }
68
+ return str
69
+ .replaceAll(entityRe, (m) => entityList[m])
70
+ .replaceAll(RX_DEC_ENTITY, (_, dec) => codePointStrToChar(dec, 10))
71
+ .replaceAll(RX_HEX_ENTITY, (_, hex) => codePointStrToChar(hex, 16));
72
+ }
73
+ function codePointStrToChar(codePointStr, radix) {
74
+ const codePoint = parseInt(codePointStr, radix);
75
+ return codePoint > MAX_CODE_POINT ? "�" : String.fromCodePoint(codePoint);
76
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Functions for HTML tasks such as escaping or unescaping HTML entities
3
+ *
4
+ * @module
5
+ */
6
+ export * from "./entities.js";
@@ -0,0 +1,8 @@
1
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
2
+ // This module is browser compatible.
3
+ /**
4
+ * Functions for HTML tasks such as escaping or unescaping HTML entities
5
+ *
6
+ * @module
7
+ */
8
+ export * from "./entities.js";
package/esm/deps.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * as path from "./deps/deno.land/std@0.201.0/path/mod.js";
2
+ export * as html from "./deps/deno.land/std@0.201.0/html/mod.js";
package/esm/deps.js CHANGED
@@ -1 +1,2 @@
1
1
  export * as path from "./deps/deno.land/std@0.201.0/path/mod.js";
2
+ export * as html from "./deps/deno.land/std@0.201.0/html/mod.js";
package/esm/mod.d.ts CHANGED
@@ -2,6 +2,7 @@ import { Environment } from "./src/environment.js";
2
2
  import { Loader } from "./src/loader.js";
3
3
  export interface Options {
4
4
  includes?: string | Loader;
5
+ useWith?: boolean;
5
6
  dataVarname?: string;
6
7
  autoescape?: boolean;
7
8
  }
package/esm/mod.js CHANGED
@@ -21,6 +21,7 @@ export default function (options = {}) {
21
21
  loader,
22
22
  dataVarname: options.dataVarname || "it",
23
23
  autoescape: options.autoescape || false,
24
+ useWith: options.useWith || true,
24
25
  });
25
26
  // Register basic plugins
26
27
  env.use(ifTag());
@@ -1,16 +1,6 @@
1
+ import { html } from "../deps.js";
1
2
  export default function () {
2
3
  return (env) => {
3
- env.filters.escape = escape;
4
+ env.filters.escape = html.escape;
4
5
  };
5
6
  }
6
- const escapeMap = {
7
- "&": "&amp;",
8
- "<": "&lt;",
9
- ">": "&gt;",
10
- '"': "&quot;",
11
- "'": "&#39;",
12
- "`": "&#x60;",
13
- };
14
- function escape(str) {
15
- return str.replace(/[&<>"'`]/g, (match) => escapeMap[match]);
16
- }
@@ -8,6 +8,7 @@ function exportTag(env, code, _output, tokens) {
8
8
  return;
9
9
  }
10
10
  const expression = code.replace(/^export\s+/, "");
11
+ const { dataVarname } = env.options;
11
12
  // Value is set (e.g. {{ export foo = "bar" }})
12
13
  if (expression.includes("=")) {
13
14
  const match = code.match(/^export\s+([\w]+)\s*=\s*([\s\S]+)$/);
@@ -16,19 +17,19 @@ function exportTag(env, code, _output, tokens) {
16
17
  }
17
18
  const [, variable, value] = match;
18
19
  const val = env.compileFilters(tokens, value);
19
- return `if (__data.hasOwnProperty("${variable}")) {
20
+ return `if (${dataVarname}.hasOwnProperty("${variable}")) {
20
21
  ${variable} = ${val};
21
22
  } else {
22
23
  var ${variable} = ${val};
23
24
  }
24
- __data["${variable}"] = ${variable};
25
+ ${dataVarname}["${variable}"] = ${variable};
25
26
  __exports["${variable}"] = ${variable};
26
27
  `;
27
28
  }
28
29
  // Value is captured (eg: {{ export foo }}bar{{ /export }})
29
30
  const compiled = [];
30
31
  const compiledFilters = env.compileFilters(tokens, expression);
31
- compiled.push(`if (__data.hasOwnProperty("${expression}")) {
32
+ compiled.push(`if (${dataVarname}.hasOwnProperty("${expression}")) {
32
33
  ${expression} = "";
33
34
  } else {
34
35
  var ${expression} = "";
@@ -40,7 +41,7 @@ function exportTag(env, code, _output, tokens) {
40
41
  }
41
42
  tokens.shift();
42
43
  compiled.push(`${expression} = ${compiledFilters};`);
43
- compiled.push(`__data["${expression.trim()}"] = ${expression};`);
44
+ compiled.push(`${dataVarname}["${expression.trim()}"] = ${expression};`);
44
45
  compiled.push(`__exports["${expression.trim()}"] = ${expression};`);
45
46
  return compiled.join("\n");
46
47
  }
@@ -3,7 +3,7 @@ export default function () {
3
3
  env.tags.push(importTag);
4
4
  };
5
5
  }
6
- function importTag(_env, code) {
6
+ function importTag(env, code) {
7
7
  if (!code.startsWith("import ")) {
8
8
  return;
9
9
  }
@@ -11,14 +11,7 @@ function importTag(_env, code) {
11
11
  if (!match) {
12
12
  throw new Error(`Invalid import: ${code}`);
13
13
  }
14
- const [_, vars, file] = match;
15
- const compiled = [];
16
- compiled.push(`__tmp = await __env.run(${file}, {...__data}, __file);`);
17
- if (vars.startsWith("{")) {
18
- compiled.push(`let ${vars} = __tmp;`);
19
- }
20
- else {
21
- compiled.push(`let ${vars} = __tmp;`);
22
- }
23
- return compiled.join("\n");
14
+ const [, vars, file] = match;
15
+ const { dataVarname } = env.options;
16
+ return `let ${vars} = await __env.run(${file}, {...${dataVarname}}, __file);`;
24
17
  }
@@ -12,9 +12,10 @@ function includeTag(env, code, output, tokens) {
12
12
  throw new Error(`Invalid include: ${code}`);
13
13
  }
14
14
  const [_, file, data] = match;
15
+ const { dataVarname } = env.options;
15
16
  return `{
16
- __tmp = await __env.run(${file},
17
- {...__data${data ? `, ${data}` : ""}},
17
+ const __tmp = await __env.run(${file},
18
+ {...${dataVarname}${data ? `, ${data}` : ""}},
18
19
  __file
19
20
  );
20
21
  ${output} += ${env.compileFilters(tokens, "__tmp.content")};
@@ -16,15 +16,16 @@ function layoutTag(env, code, output, tokens) {
16
16
  const compiled = [];
17
17
  const compiledFilters = env.compileFilters(tokens, varname);
18
18
  compiled.push("{");
19
- compiled.push(`var ${varname} = "";`);
19
+ compiled.push(`let ${varname} = "";`);
20
20
  compiled.push(...env.compileTokens(tokens, varname, ["/layout"]));
21
21
  if (tokens.length && (tokens[0][0] !== "tag" || tokens[0][1] !== "/layout")) {
22
22
  throw new Error(`Missing closing tag for layout tag: ${code}`);
23
23
  }
24
24
  tokens.shift();
25
25
  compiled.push(`${varname} = ${compiledFilters};`);
26
- compiled.push(`__tmp = await __env.run(${file},
27
- {...__data${data ? `, ${data}` : ""}, content: ${env.compileFilters(tokens, varname)}},
26
+ const { dataVarname } = env.options;
27
+ compiled.push(`const __tmp = await __env.run(${file},
28
+ {...${dataVarname}${data ? `, ${data}` : ""}, content: ${env.compileFilters(tokens, varname)}},
28
29
  __file
29
30
  );
30
31
  ${output} += __tmp.content;`);
@@ -8,6 +8,7 @@ function setTag(env, code, _output, tokens) {
8
8
  return;
9
9
  }
10
10
  const expression = code.replace(/^set\s+/, "");
11
+ const { dataVarname } = env.options;
11
12
  // Value is set (e.g. {{ set foo = "bar" }})
12
13
  if (expression.includes("=")) {
13
14
  const match = code.match(/^set\s+([\w]+)\s*=\s*([\s\S]+)$/);
@@ -16,18 +17,18 @@ function setTag(env, code, _output, tokens) {
16
17
  }
17
18
  const [, variable, value] = match;
18
19
  const val = env.compileFilters(tokens, value);
19
- return `if (__data.hasOwnProperty("${variable}")) {
20
+ return `if (${dataVarname}.hasOwnProperty("${variable}")) {
20
21
  ${variable} = ${val};
21
22
  } else {
22
23
  var ${variable} = ${val};
23
24
  }
24
- __data["${variable}"] = ${variable};
25
+ ${dataVarname}["${variable}"] = ${variable};
25
26
  `;
26
27
  }
27
28
  // Value is captured (eg: {{ set foo }}bar{{ /set }})
28
29
  const compiled = [];
29
30
  const compiledFilters = env.compileFilters(tokens, expression);
30
- compiled.push(`if (__data.hasOwnProperty("${expression}")) {
31
+ compiled.push(`if (${dataVarname}.hasOwnProperty("${expression}")) {
31
32
  ${expression} = "";
32
33
  } else {
33
34
  var ${expression} = "";
@@ -39,6 +40,6 @@ function setTag(env, code, _output, tokens) {
39
40
  }
40
41
  tokens.shift();
41
42
  compiled.push(`${expression} = ${compiledFilters};`);
42
- compiled.push(`__data["${expression.trim()}"] = ${expression};`);
43
+ compiled.push(`${dataVarname}["${expression.trim()}"] = ${expression};`);
43
44
  return compiled.join("\n");
44
45
  }
@@ -1,16 +1,6 @@
1
+ import { html } from "../deps.js";
1
2
  export default function () {
2
3
  return (env) => {
3
- env.filters.unescape = unescape;
4
+ env.filters.unescape = html.unescape;
4
5
  };
5
6
  }
6
- const unescapeMap = {
7
- "&amp;": "&",
8
- "&lt;": "<",
9
- "&gt;": ">",
10
- "&quot;": '"',
11
- "&#39;": "'",
12
- "&#x60;": "`",
13
- };
14
- function unescape(str) {
15
- return str.replace(/(&amp;|&lt;|&gt;|&quot;|&#39;|&#x60;)/g, (match) => unescapeMap[match]);
16
- }
@@ -21,6 +21,7 @@ export interface Options {
21
21
  loader: Loader;
22
22
  dataVarname: string;
23
23
  autoescape: boolean;
24
+ useWith: boolean;
24
25
  }
25
26
  export declare class Environment {
26
27
  cache: Map<string, Template>;
@@ -37,15 +37,12 @@ export class Environment {
37
37
  try {
38
38
  const tokens = tokenize(source);
39
39
  const code = this.compileTokens(tokens).join("\n");
40
- const constructor = new Function("__file", "__env", "__defaults", `return${sync ? "" : " async"} function (__data) {
40
+ const { dataVarname, useWith } = this.options;
41
+ const constructor = new Function("__file", "__env", "__defaults", `return${sync ? "" : " async"} function (${dataVarname}) {
41
42
  try {
42
- __data = Object.assign({}, __defaults, __data);
43
- const ${this.options.dataVarname} = __data;
44
- let __tmp;
43
+ ${dataVarname} = Object.assign({}, __defaults, ${dataVarname});
45
44
  const __exports = { content: "" };
46
- with (__data) {
47
- ${code}
48
- }
45
+ ${useWith ? `with (${dataVarname}) {${code}}` : code}
49
46
  return __exports;
50
47
  } catch (cause) {
51
48
  throw new Error(\`Error rendering template: \${__file}\`, { cause });
@@ -112,8 +109,11 @@ export class Environment {
112
109
  }
113
110
  const [_, isAsync, name, args] = match;
114
111
  if (!this.filters[name]) {
115
- // If a global function
116
- if (isGlobal(name)) {
112
+ if (name === "safe") {
113
+ unescaped = true;
114
+ }
115
+ else if (isGlobal(name)) {
116
+ // If a global function
117
117
  output = `${isAsync ? "await " : ""}${name}(${output}${args ? `, ${args}` : ""})`;
118
118
  }
119
119
  else {
@@ -122,9 +122,6 @@ export class Environment {
122
122
  }
123
123
  }
124
124
  else {
125
- if (name === "unescape") {
126
- unescaped = true;
127
- }
128
125
  // It's a filter (e.g. filters.upper())
129
126
  output = `${isAsync ? "await " : ""}__env.filters.${name}(${output}${args ? `, ${args}` : ""})`;
130
127
  }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "module": "./esm/mod.js",
3
+ "main": "./script/mod.js",
3
4
  "name": "ventojs",
4
- "version": "0.8.0",
5
+ "version": "0.9.0",
5
6
  "description": "🌬 A minimal but powerful template engine",
6
7
  "license": "MIT",
7
8
  "repository": "github:oscarotero/vento",
@@ -9,7 +10,8 @@
9
10
  "bugs": "https://github.com/oscarotero/vento/issues",
10
11
  "exports": {
11
12
  ".": {
12
- "import": "./esm/mod.js"
13
+ "import": "./esm/mod.js",
14
+ "require": "./script/mod.js"
13
15
  }
14
16
  },
15
17
  "scripts": {
@@ -0,0 +1,5 @@
1
+ import { Deno } from "@deno/shim-deno";
2
+ export { Deno } from "@deno/shim-deno";
3
+ export declare const dntGlobalThis: Omit<typeof globalThis, "Deno"> & {
4
+ Deno: typeof Deno;
5
+ };
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dntGlobalThis = exports.Deno = void 0;
4
+ const shim_deno_1 = require("@deno/shim-deno");
5
+ var shim_deno_2 = require("@deno/shim-deno");
6
+ Object.defineProperty(exports, "Deno", { enumerable: true, get: function () { return shim_deno_2.Deno; } });
7
+ const dntGlobals = {
8
+ Deno: shim_deno_1.Deno,
9
+ };
10
+ exports.dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
11
+ function createMergeProxy(baseObj, extObj) {
12
+ return new Proxy(baseObj, {
13
+ get(_target, prop, _receiver) {
14
+ if (prop in extObj) {
15
+ return extObj[prop];
16
+ }
17
+ else {
18
+ return baseObj[prop];
19
+ }
20
+ },
21
+ set(_target, prop, value) {
22
+ if (prop in extObj) {
23
+ delete extObj[prop];
24
+ }
25
+ baseObj[prop] = value;
26
+ return true;
27
+ },
28
+ deleteProperty(_target, prop) {
29
+ let success = false;
30
+ if (prop in extObj) {
31
+ delete extObj[prop];
32
+ success = true;
33
+ }
34
+ if (prop in baseObj) {
35
+ delete baseObj[prop];
36
+ success = true;
37
+ }
38
+ return success;
39
+ },
40
+ ownKeys(_target) {
41
+ const baseKeys = Reflect.ownKeys(baseObj);
42
+ const extKeys = Reflect.ownKeys(extObj);
43
+ const extKeysSet = new Set(extKeys);
44
+ return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
45
+ },
46
+ defineProperty(_target, prop, desc) {
47
+ if (prop in extObj) {
48
+ delete extObj[prop];
49
+ }
50
+ Reflect.defineProperty(baseObj, prop, desc);
51
+ return true;
52
+ },
53
+ getOwnPropertyDescriptor(_target, prop) {
54
+ if (prop in extObj) {
55
+ return Reflect.getOwnPropertyDescriptor(extObj, prop);
56
+ }
57
+ else {
58
+ return Reflect.getOwnPropertyDescriptor(baseObj, prop);
59
+ }
60
+ },
61
+ has(_target, prop) {
62
+ return prop in extObj || prop in baseObj;
63
+ },
64
+ });
65
+ }
@@ -0,0 +1,2 @@
1
+ /** Make an assertion, error will be thrown if `expr` does not have truthy value. */
2
+ export declare function assert(expr: unknown, msg?: string): asserts expr;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assert = void 0;
4
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
5
+ const assertion_error_js_1 = require("./assertion_error.js");
6
+ /** Make an assertion, error will be thrown if `expr` does not have truthy value. */
7
+ function assert(expr, msg = "") {
8
+ if (!expr) {
9
+ throw new assertion_error_js_1.AssertionError(msg);
10
+ }
11
+ }
12
+ exports.assert = assert;
@@ -0,0 +1,4 @@
1
+ export declare class AssertionError extends Error {
2
+ name: string;
3
+ constructor(message: string);
4
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AssertionError = void 0;
4
+ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
5
+ class AssertionError extends Error {
6
+ name = "AssertionError";
7
+ constructor(message) {
8
+ super(message);
9
+ }
10
+ }
11
+ exports.AssertionError = AssertionError;
@@ -0,0 +1,38 @@
1
+ export type EntityList = Record<string, string>;
2
+ /**
3
+ * Escapes text for safe interpolation into HTML text content and quoted attributes
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { escape } from "https://deno.land/std@$STD_VERSION/html/entities.ts";
8
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts";
9
+ *
10
+ * assertEquals(escape("<>'&AA"), "&lt;&gt;&#39;&amp;AA");
11
+ *
12
+ * // characters that don't need to be escaped will be left alone,
13
+ * // even if named HTML entities exist for them
14
+ * assertEquals(escape("þð"), "þð");
15
+ * ```
16
+ */
17
+ export declare function escape(str: string): string;
18
+ export type UnescapeOptions = {
19
+ entityList: EntityList;
20
+ };
21
+ /**
22
+ * Unescapes HTML entities in text
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { unescape } from "https://deno.land/std@$STD_VERSION/html/entities.ts";
27
+ * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts";
28
+ *
29
+ * // default options (only handles &<>'" and numeric entities)
30
+ * assertEquals(unescape("&lt;&gt;&apos;&amp;&#65;&#x41;"), "<>'&AA");
31
+ * assertEquals(unescape("&thorn;&eth;"), "&thorn;&eth;");
32
+ *
33
+ * // using the full named entity list from the HTML spec (~47K unminified)
34
+ * import entityList from "https://deno.land/std@$STD_VERSION/html/named_entity_list.json" assert { type: "json" };
35
+ * assertEquals(unescape("&thorn;&eth;", { entityList }), "þð");
36
+ * ```
37
+ */
38
+ export declare function unescape(str: string, options?: Partial<UnescapeOptions>): string;