sjabloon 0.7.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.
- package/README.md +83 -43
- package/lib/core.js +632 -0
- package/{dist → lib}/html.d.ts +2 -2
- package/lib/html.js +21 -0
- package/{dist → lib}/index.d.ts +2 -2
- package/lib/index.js +44 -0
- package/{dist → lib}/text.d.ts +2 -2
- package/lib/text.js +19 -0
- package/{dist → lib}/types.d.ts +36 -23
- package/package.json +108 -106
- package/dist/core.js +0 -1
- package/dist/html.js +0 -1
- package/dist/index.js +0 -1
- package/dist/text.js +0 -1
package/lib/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The token edition, and the engine proper: a template renders to a stream of
|
|
3
|
+
* literal and value tokens. Escaping belongs to whoever consumes the stream,
|
|
4
|
+
* so nothing here is HTML-aware and `{{{ }}}` has no meaning — `{{ }}` is
|
|
5
|
+
* already raw.
|
|
6
|
+
*/
|
|
7
|
+
import { make } from "./core.js";
|
|
8
|
+
|
|
9
|
+
export { isDiagnostic, relocate } from "./core.js";
|
|
10
|
+
|
|
11
|
+
export const { template, render } = make([
|
|
12
|
+
// Static text is a compile-time constant: hoist and freeze one token per
|
|
13
|
+
// text node rather than allocating a fresh object every loop iteration.
|
|
14
|
+
(text) =>
|
|
15
|
+
((token) => (scope, acc) => {
|
|
16
|
+
acc.push(token);
|
|
17
|
+
})(Object.freeze({ literal: text })),
|
|
18
|
+
(expr) => (scope, acc) => {
|
|
19
|
+
acc.push({ value: expr(scope) });
|
|
20
|
+
},
|
|
21
|
+
0,
|
|
22
|
+
() => /** @type {import('./types.js').Token[]} */ ([]),
|
|
23
|
+
(acc) => acc,
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Join a token stream into the string `sjabloon/text` would have produced:
|
|
28
|
+
* literals verbatim, values as `String(value ?? '')`.
|
|
29
|
+
*
|
|
30
|
+
* @param {readonly import('./types.js').Token[]} tokens A render's output.
|
|
31
|
+
* @returns {string} The joined text.
|
|
32
|
+
*/
|
|
33
|
+
export const text = (tokens) => {
|
|
34
|
+
let s = "";
|
|
35
|
+
// One `?? ''` per token, so a literal never stringifies and a nullish value
|
|
36
|
+
// still renders empty. Widened here because each token carries one key or
|
|
37
|
+
// the other, which the public union deliberately does not model.
|
|
38
|
+
for (const t of /** @type {readonly { literal?: string, value?: unknown }[]} */ (tokens))
|
|
39
|
+
// Stringifying an arbitrary value is this helper's documented contract, so
|
|
40
|
+
// `no-base-to-string` is describing the feature rather than a mistake.
|
|
41
|
+
// oxlint-disable-next-line typescript/no-base-to-string
|
|
42
|
+
s += t.literal ?? String(t.value ?? "");
|
|
43
|
+
return s;
|
|
44
|
+
};
|
package/{dist → lib}/text.d.ts
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
import type { SjabloonFunctions, SjabloonRenderer, SjabloonValues } from
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
import type { SjabloonFunctions, SjabloonRenderer, SjabloonValues } from "./types.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Compile a template once, render it many times to a plain string.
|
package/lib/text.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plain-text edition: `{{ }}` interpolates unescaped and renders to a
|
|
3
|
+
* string. Escaping belongs at the output edge, so there is no raw form —
|
|
4
|
+
* `{{ }}` is already raw and `{{{ }}}` is a compile-time error.
|
|
5
|
+
*
|
|
6
|
+
* Definitionally `text(template(str)(values))` from the root entry, but built
|
|
7
|
+
* as a string accumulator so casual string users never allocate tokens.
|
|
8
|
+
*/
|
|
9
|
+
import { litNode, make } from "./core.js";
|
|
10
|
+
|
|
11
|
+
export { isDiagnostic, relocate } from "./core.js";
|
|
12
|
+
|
|
13
|
+
export const { template, render } = make([
|
|
14
|
+
litNode,
|
|
15
|
+
(expr) => (scope, acc, value) => ((value = expr(scope)), (acc.text += String(value ?? ""))),
|
|
16
|
+
0,
|
|
17
|
+
() => ({ text: "" }),
|
|
18
|
+
(acc) => acc.text,
|
|
19
|
+
]);
|
package/{dist → lib}/types.d.ts
RENAMED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import type { XprsnErrorCode } from
|
|
1
|
+
import type { XprsnErrorCode } from "xprsn";
|
|
2
2
|
|
|
3
3
|
export type SjabloonErrorCode =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
| XprsnErrorCode
|
|
5
|
+
| "SJABLOON_EACH_SYNTAX"
|
|
6
|
+
| "SJABLOON_BLOCKED_BINDING"
|
|
7
|
+
| "SJABLOON_UNEXPECTED_TAG"
|
|
8
|
+
| "SJABLOON_UNKNOWN_BLOCK"
|
|
9
|
+
| "SJABLOON_UNCLOSED_BLOCK"
|
|
10
|
+
| "SJABLOON_TOO_DEEP"
|
|
11
|
+
| "SJABLOON_RAW_TAG";
|
|
12
12
|
|
|
13
13
|
export interface SjabloonBlock {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
readonly type: "if" | "each";
|
|
15
|
+
readonly start: number;
|
|
16
|
+
readonly end: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface SjabloonDiagnostic extends Error {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
readonly code: SjabloonErrorCode;
|
|
21
|
+
readonly start: number;
|
|
22
|
+
readonly end: number;
|
|
23
|
+
readonly blocks: readonly SjabloonBlock[];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export type SjabloonValues = Record<string, any>;
|
|
@@ -41,8 +41,8 @@ export type SjabloonFunctions = Record<string, Function>;
|
|
|
41
41
|
* band that has no current row wants exactly that.
|
|
42
42
|
*/
|
|
43
43
|
export interface SjabloonScope {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
root?: any;
|
|
45
|
+
item?: any;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
@@ -53,19 +53,19 @@ export interface SjabloonScope {
|
|
|
53
53
|
* registry functions the template calls, deduplicated.
|
|
54
54
|
*/
|
|
55
55
|
export interface SjabloonRenderer<T> {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
(values?: SjabloonValues, scope?: SjabloonScope): T;
|
|
57
|
+
names: string[];
|
|
58
|
+
functions: string[];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/** One static text run of the template, verbatim. */
|
|
62
62
|
export interface LiteralToken {
|
|
63
|
-
|
|
63
|
+
literal: string;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/** One `{{ }}` interpolation, pre-stringify. Nullish values are preserved. */
|
|
67
67
|
export interface ValueToken {
|
|
68
|
-
|
|
68
|
+
value: unknown;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
@@ -81,3 +81,16 @@ export type Token = LiteralToken | ValueToken;
|
|
|
81
81
|
* through all of them.
|
|
82
82
|
*/
|
|
83
83
|
export function isDiagnostic(error: unknown): error is SjabloonDiagnostic;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Copy a diagnostic into an embedder's coordinates: `prefix` is prepended to
|
|
87
|
+
* the message verbatim, `offset` shifts the span, every other field — the
|
|
88
|
+
* frozen `blocks` context included — is carried over, and the copy is
|
|
89
|
+
* authenticated exactly as the original was.
|
|
90
|
+
*
|
|
91
|
+
* @throws {TypeError} When `diag` is not a sjabloon diagnostic.
|
|
92
|
+
*/
|
|
93
|
+
export function relocate(
|
|
94
|
+
diag: unknown,
|
|
95
|
+
opts?: { prefix?: string; offset?: number },
|
|
96
|
+
): SjabloonDiagnostic;
|
package/package.json
CHANGED
|
@@ -1,108 +1,110 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
2
|
+
"name": "sjabloon",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Tiny, CSP-safe template engine for JavaScript, powered by xprsn expressions. No eval, no new Function.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"csp",
|
|
7
|
+
"handlebars",
|
|
8
|
+
"render",
|
|
9
|
+
"template",
|
|
10
|
+
"template-engine"
|
|
11
|
+
],
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "Robin van der Vleuten",
|
|
15
|
+
"email": "robin@webstronauts.com",
|
|
16
|
+
"url": "https://robinvdvleuten.nl"
|
|
17
|
+
},
|
|
18
|
+
"repository": "getquario/sjabloon",
|
|
19
|
+
"files": [
|
|
20
|
+
"lib"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"module": "lib/index.js",
|
|
24
|
+
"types": "lib/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./lib/index.d.ts",
|
|
28
|
+
"default": "./lib/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./text": {
|
|
31
|
+
"types": "./lib/text.d.ts",
|
|
32
|
+
"default": "./lib/text.js"
|
|
33
|
+
},
|
|
34
|
+
"./html": {
|
|
35
|
+
"types": "./lib/html.d.ts",
|
|
36
|
+
"default": "./lib/html.js"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"bench": "node --disallow-code-generation-from-strings bench/index.js",
|
|
42
|
+
"bench:comparison": "npm --prefix bench/comparison run bench",
|
|
43
|
+
"check": "run-s fmt:check lint fallow size test fuzz:regression test:browser",
|
|
44
|
+
"fallow": "fallow",
|
|
45
|
+
"fmt": "oxfmt",
|
|
46
|
+
"fmt:check": "oxfmt --check",
|
|
47
|
+
"fuzz": "npm run fuzz:prepare && run-s fuzz:compile fuzz:render fuzz:structured",
|
|
48
|
+
"fuzz:compile": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/compile.fuzz.js -i lib/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync .fuzz-corpus/compile fuzz/corpus/compile -- -max_total_time=60 -use_value_profile=1 -dict=fuzz/sjabloon.dict -artifact_prefix=fuzz/",
|
|
49
|
+
"fuzz:prepare": "node -e \"for (const x of ['compile','render','structured']) require('fs').mkdirSync('.fuzz-corpus/'+x,{recursive:true})\"",
|
|
50
|
+
"fuzz:regression": "run-s fuzz:regression:compile fuzz:regression:render fuzz:regression:structured",
|
|
51
|
+
"fuzz:regression:compile": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/compile.fuzz.js -i lib/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync --mode=regression fuzz/corpus/compile -- -artifact_prefix=fuzz/",
|
|
52
|
+
"fuzz:regression:render": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/render.fuzz.js -i lib/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync --mode=regression fuzz/corpus/render -- -artifact_prefix=fuzz/",
|
|
53
|
+
"fuzz:regression:structured": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/structured.fuzz.js -i lib/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync --mode=regression fuzz/corpus/structured -- -artifact_prefix=fuzz/",
|
|
54
|
+
"fuzz:render": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/render.fuzz.js -i lib/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync .fuzz-corpus/render fuzz/corpus/render -- -max_total_time=60 -use_value_profile=1 -dict=fuzz/sjabloon.dict -artifact_prefix=fuzz/",
|
|
55
|
+
"fuzz:structured": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/structured.fuzz.js -i lib/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync .fuzz-corpus/structured fuzz/corpus/structured -- -max_total_time=60 -use_value_profile=1 -dict=fuzz/sjabloon.dict -artifact_prefix=fuzz/",
|
|
56
|
+
"lint": "oxlint",
|
|
57
|
+
"size": "size-limit",
|
|
58
|
+
"test": "run-s test:unit test:types",
|
|
59
|
+
"test:browser": "playwright install chromium && node test/browser/harness.js",
|
|
60
|
+
"test:types": "tsc && attw --pack . --profile esm-only",
|
|
61
|
+
"test:unit": "c8 --100 --src lib/ node --disallow-code-generation-from-strings --test --test-concurrency=1 test/*.test.js"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"xprsn": "^0.10.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@arethetypeswrong/cli": "^0.18.3",
|
|
68
|
+
"@jazzer.js/bug-detectors": "^4.0.0",
|
|
69
|
+
"@jazzer.js/core": "^4.0.0",
|
|
70
|
+
"@size-limit/preset-small-lib": "^13.0.3",
|
|
71
|
+
"c8": "^12.0.0",
|
|
72
|
+
"fallow": "^3.17.0",
|
|
73
|
+
"npm-run-all": "^4.1.5",
|
|
74
|
+
"oxfmt": "^0.64.0",
|
|
75
|
+
"oxlint": "^1.78.0",
|
|
76
|
+
"oxlint-tsgolint": "^7.0.2001",
|
|
77
|
+
"playwright": "^1.61.1",
|
|
78
|
+
"size-limit": "^13.0.3",
|
|
79
|
+
"typescript": "7.0.2"
|
|
80
|
+
},
|
|
81
|
+
"size-limit": [
|
|
82
|
+
{
|
|
83
|
+
"name": "sjabloon",
|
|
84
|
+
"path": "lib/index.js",
|
|
85
|
+
"ignore": [
|
|
86
|
+
"xprsn"
|
|
87
|
+
],
|
|
88
|
+
"limit": "2.25 kB"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"name": "sjabloon/text",
|
|
92
|
+
"path": "lib/text.js",
|
|
93
|
+
"ignore": [
|
|
94
|
+
"xprsn"
|
|
95
|
+
],
|
|
96
|
+
"limit": "2.25 kB"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "sjabloon/html",
|
|
100
|
+
"path": "lib/html.js",
|
|
101
|
+
"ignore": [
|
|
102
|
+
"xprsn"
|
|
103
|
+
],
|
|
104
|
+
"limit": "2.3 kB"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"engines": {
|
|
108
|
+
"node": ">=22.12.0"
|
|
109
|
+
}
|
|
108
110
|
}
|
package/dist/core.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{compile as e,isDiagnostic as t}from"xprsn";const n=/^(?:__proto__|constructor|prototype)$/,r=new WeakSet,i=r.add.bind(r),a=r.has.bind(r),o=e=>a(e);let s=e=>{let t=[];for(let n=0,r=1;n<e.length;){let i=e.indexOf(`{{`,n);if(i<0){t.push([0,e.slice(n)]);break}i>n&&t.push([0,e.slice(n,i)]);let a=+(e[i+2]===`{`),o=i+2+a,s=e[o]===`-`,c=-1;if(s&&o++,a&&r&&(c=e.indexOf(`}}}`,o),c<0&&(r=0)),c<0&&(a&&(a=0,o=i+2,s=e[o]===`-`,s&&o++),c=e.indexOf(`}}`,o)),c<0){t.push([0,e.slice(i)]);break}let l=c>o&&e[c-1]===`-`,u=l?c-1:c,d=e.slice(o,u),f=d.trim(),p=o+d.length-d.trimStart().length,m=c+2+a,h=[a?1:2,f,i,m,p],g=t.at(-1);if(s&&g?.[0]===0&&g[1]&&(g[1]=g[1].trimEnd()),t.push(h),n=m,l)for(;/\s/.test(e[n]);)n++}return t},c,l,u,d,f,p,m,h,g,_,v,y,b=()=>Object.freeze(g.slice()),x=(e,t)=>(g.length<256||C(`Template too deeply nested`,`SJABLOON_TOO_DEEP`,t),Object.freeze({type:e,start:t[2],end:t[3]})),S=(e,t)=>(Object.defineProperty(e,"blocks",{value:t,enumerable:!0}),i(e),e);const C=(e,t,n,r=n?.[2]??h.length,i=n?.[3]??h.length)=>{let a=SyntaxError(e);throw a.code=t,a.start=r,a.end=i,S(a,b())};let w=(e,n,r,i=t)=>{throw i(e)?(e.start+=n,e.end+=n,S(e,r)):e},T=e=>C(`Unexpected {{`+e[1]+`}}`,`SJABLOON_UNEXPECTED_TAG`,e),E=(e,t,n)=>{for(let r of e)r(t,n)},D=(e,t)=>t(O(e[1],e[4],b())),O=(t,n,r)=>{let i;try{i=e(t,u)}catch(e){w(e,n,r)}for(let e of i.names)f.includes(e)||p.add(e);for(let e of i.functions)m.add(e);return e=>{try{return i(e)}catch(e){w(e,n,r,i.isDiagnostic)}}},k=e=>{let t=A([`#elif`,`#else`,`/if`]),n=d[1],r=[];return n.startsWith(`#elif `)?r=[k(O(n.slice(6),d[4]+6,b()))]:n===`#else`?(r=A([`/if`]),d[1]===`/if`||T(d)):n!==`/if`&&T(d),(n,i)=>E(e(n)?t:r,n,i)},A=e=>{let t=[];for(let r;r=c[l++];){let i=r[1];if(!r[0])i&&t.push(_(i));else if(r[0]===1)y||C(`Raw {{{`+i+`}}} is not available here; {{ `+i+` }} is already raw`,`SJABLOON_RAW_TAG`,r),t.push(D(r,y));else if(e.includes(i.split(` `)[0]))return d=r,t;else if(i[0]!==`!`)if(i.startsWith(`#if `))g.push(x(`if`,r)),t.push(k(O(i.slice(4),r[4]+4,b()))),g.pop();else if(/^#each(?:\s|$)/.test(i)){g.push(x(`each`,r));let e=/^#each ([\s\S]+) as ((\w+)(?:\s*,\s*(\w+))?)$/.exec(i)||C(`Bad {{`+i+`}}`,`SJABLOON_EACH_SYNTAX`,r),a=e[3],o=e[4],s=r[4]+i.length-e[2].length;if(n.test(a)&&C(`Bad {{`+i+`}}`,`SJABLOON_BLOCKED_BINDING`,r,s,s+a.length),o&&n.test(o)){let e=r[4]+i.length-o.length;C(`Bad {{`+i+`}}`,`SJABLOON_BLOCKED_BINDING`,r,e,e+o.length)}let c=O(e[1],r[4]+6,b()),l=f.length;f.push(a),o&&f.push(o),f.push(`loop`);let u=A([`#else`,`/each`]);f.length=l;let p=[];d[1]===`#else`?(p=A([`/each`]),d[1]===`/each`||T(d)):d[1]!==`/each`&&T(d),g.pop(),t.push((e,t)=>{let n=c(e),r=Array.isArray(n),i=r?n.slice():n&&typeof n==`object`?Object.keys(n).map(e=>[n[e],e]):[];if(!i.length)return E(p,e,t);i.forEach((n,s)=>{let c=r?n:n[0],l=r?s:n[1],d=Object.create(e);d[a]=c,o&&(d[o]=l),d[`@`]=c,d.loop={index:s+1,index0:s,first:!s,last:s===i.length-1,length:i.length},E(u,d,t)})})}else/^#(?:if|elif|else)(?:\s|$)/.test(i)||i[0]===`/`?T(r):i[0]===`#`?C(`Unknown {{`+i+`}}`,`SJABLOON_UNKNOWN_BLOCK`,r):t.push(D(r,v))}return e.length&&C(`Missing {{`+e[e.length-1]+`}}`,`SJABLOON_UNCLOSED_BLOCK`),t},j=([e,t,n,r,i])=>{function a(a,o){_=e,v=t,y=n,u=o,f=[`$`,`@`],p=new Set,m=new Set,h=String(a),g=[],c=s(h),l=0;let d;try{d=A([])}catch(e){throw e instanceof RangeError&&C(`Template too deeply nested`,`SJABLOON_TOO_DEEP`),e}let b=(e,t)=>{e||={};let n=Object.create(e);n.$=t?t.root:e,t?`item`in t&&(n[`@`]=t.item):n[`@`]=e;let a=r();return E(d,n,a),i(a)};return b.names=Array.from(p),b.functions=Array.from(m),b}return{template:a,render:(e,t,n)=>a(e,n)(t)}};export{j as n,o as t};
|
package/dist/html.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"./core.js";const n={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},r=e=>String(e).replace(/[&<>"']/g,e=>n[e]),{template:i,render:a}=e([e=>(t,n)=>{n.s+=e},e=>(t,n,i)=>(i=e(t),n.s+=r(i??``)),e=>(t,n,r)=>(r=e(t),n.s+=String(r??``)),()=>({s:``}),e=>e.s]);export{t as isDiagnostic,a as render,i as template};
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"./core.js";const{template:n,render:r}=e([e=>(e=>(t,n)=>{n.push(e)})(Object.freeze({literal:e})),e=>(t,n)=>{n.push({value:e(t)})},0,()=>[],e=>e]),i=e=>{let t=``;for(let n of e)t+=n.literal??String(n.value??``);return t};export{t as isDiagnostic,r as render,n as template,i as text};
|
package/dist/text.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"./core.js";const{template:n,render:r}=e([e=>(t,n)=>{n.s+=e},e=>(t,n,r)=>(r=e(t),n.s+=String(r??``)),0,()=>({s:``}),e=>e.s]);export{t as isDiagnostic,r as render,n as template};
|