sjabloon 0.4.0 → 0.4.1
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 +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -0
- package/package.json +37 -14
- package/src/index.js +31 -17
- package/dist/index.module.js +0 -1
- package/dist/index.umd.js +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# sjabloon
|
|
2
2
|
|
|
3
|
-
A tiny, CSP-safe template engine for JavaScript. **~
|
|
3
|
+
A tiny, CSP-safe template engine for JavaScript. **~1.2KB min+gzip (~2.5KB with [xprsn](https://www.npmjs.com/package/xprsn)), one dependency.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/sjabloon)
|
|
6
6
|
[](https://github.com/robinvdvleuten/sjabloon/actions/workflows/test.yml)
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("xprsn");const t={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},n=e=>String(e).replace(/[&<>"']/g,e=>t[e]),r=/^(?:__proto__|constructor|prototype)$/,i=e=>Array.isArray(e)?e.map((e,t)=>[e,t]):e&&typeof e==`object`?Object.keys(e).map(t=>[e[t],t]):[];let a=e=>{let t=[];for(let n=0,r=1;n<e.length;){let i=e.indexOf(`{{`,n);if(i<0){t.push({text:e.slice(n)});break}i>n&&t.push({text:e.slice(n,i)});let a=e.charCodeAt(i+2)===123,o=i+2+a,s=e.charCodeAt(o)===45,c=-1;if(s&&o++,a&&r&&(c=e.indexOf(`}}}`,o),c<0&&(r=0)),c<0&&(a&&(a=!1,o=i+2,s=e.charCodeAt(o)===45,s&&o++),c=e.indexOf(`}}`,o)),c<0){t.push({text:e.slice(i)});break}let l=c>o&&e.charCodeAt(c-1)===45,u=e.slice(o,l?c-1:c).trim(),d=a?{raw:u}:{tag:u};d.l=s,d.r=l,t.push(d),n=c+2+a}return t},o,s,c,l,u,d,f,p=e=>{throw SyntaxError(e)},m=(e,t)=>e.map(e=>e(t)).join(``),h=(e,t)=>(e=>n=>t(e(n)??``))(_(e)),g=(...e)=>{let t=e.filter(e=>e&&!u.has(e));return t.forEach(e=>u.add(e)),()=>t.forEach(e=>u.delete(e))},_=t=>{let n=(0,e.compile)(t,c);for(let e of n.names)u.has(e)||d.add(e);for(let e of n.functions)f.add(e);return n},v=e=>{let t=y([`#elif`,`#else`,`/if`]),n=l.startsWith(`#elif `)?[v(_(l.slice(6)))]:l===`#else`?y([`/if`]):[];return r=>m(e(r)?t:n,r)},y=e=>{let t=[];for(let a;a=o[s++];)if(a.text!=null)t.push((e=>()=>e)(a.text));else if(a.raw!=null)t.push(h(a.raw,String));else if(e.includes(a.tag.split(` `)[0]))return l=a.tag,t;else if(a.tag[0]!==`!`)if(a.tag.startsWith(`#if `))t.push(v(_(a.tag.slice(4))));else if(a.tag.startsWith(`#each `)){let e=/^#each ([\s\S]+) as (\w+)(?:\s*,\s*(\w+))?$/.exec(a.tag)||p(`Bad {{`+a.tag+`}}`),n=_(e[1]),o=e[2],s=e[3];(r.test(o)||s&&r.test(s))&&p(`Bad {{`+a.tag+`}}`);let c=g(o,s,`loop`),u=y([`#else`,`/each`]);c();let d=l===`#else`?y([`/each`]):[];t.push(e=>{let t=i(n(e));return t.length?t.map(([n,r],i)=>{let a=Object.create(e);return a[o]=n,s&&(a[s]=r),a[`@`]=n,a.loop={index:i+1,index0:i,first:!i,last:i===t.length-1,length:t.length},m(u,a)}).join(``):m(d,e)})}else a.tag[0]===`#`||a.tag[0]===`/`?p(`Unexpected {{`+a.tag+`}}`):t.push(h(a.tag,n));return e.length&&p(`Missing {{`+e[e.length-1]+`}}`),t};function b(e,t){c=t,u=new Set([`$`,`@`]),d=new Set,f=new Set,o=a(String(e)),o.forEach((e,t)=>{e.l&&o[t-1]?.text&&(o[t-1].text=o[t-1].text.trimEnd()),e.r&&o[t+1]?.text&&(o[t+1].text=o[t+1].text.trimStart())}),s=0;let n=y([]),r=(e,t)=>{e||={};let r=Object.create(e);return r.$=t?t.root:e,t?`item`in t&&(r[`@`]=t.item):r[`@`]=e,m(n,r)};return r.names=Array.from(d),r.functions=Array.from(f),r}function x(e,t,n){return b(e,n)(t)}exports.render=x,exports.template=b;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{compile as e}from"xprsn";const t={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},n=e=>String(e).replace(/[&<>"']/g,e=>t[e]),r=/^(?:__proto__|constructor|prototype)$/,i=e=>Array.isArray(e)?e.map((e,t)=>[e,t]):e&&typeof e==`object`?Object.keys(e).map(t=>[e[t],t]):[];let a=e=>{let t=[];for(let n=0,r=1;n<e.length;){let i=e.indexOf(`{{`,n);if(i<0){t.push({text:e.slice(n)});break}i>n&&t.push({text:e.slice(n,i)});let a=e.charCodeAt(i+2)===123,o=i+2+a,s=e.charCodeAt(o)===45,c=-1;if(s&&o++,a&&r&&(c=e.indexOf(`}}}`,o),c<0&&(r=0)),c<0&&(a&&(a=!1,o=i+2,s=e.charCodeAt(o)===45,s&&o++),c=e.indexOf(`}}`,o)),c<0){t.push({text:e.slice(i)});break}let l=c>o&&e.charCodeAt(c-1)===45,u=e.slice(o,l?c-1:c).trim(),d=a?{raw:u}:{tag:u};d.l=s,d.r=l,t.push(d),n=c+2+a}return t},o,s,c,l,u,d,f,p=e=>{throw SyntaxError(e)},m=(e,t)=>e.map(e=>e(t)).join(``),h=(e,t)=>(e=>n=>t(e(n)??``))(_(e)),g=(...e)=>{let t=e.filter(e=>e&&!u.has(e));return t.forEach(e=>u.add(e)),()=>t.forEach(e=>u.delete(e))},_=t=>{let n=e(t,c);for(let e of n.names)u.has(e)||d.add(e);for(let e of n.functions)f.add(e);return n},v=e=>{let t=y([`#elif`,`#else`,`/if`]),n=l.startsWith(`#elif `)?[v(_(l.slice(6)))]:l===`#else`?y([`/if`]):[];return r=>m(e(r)?t:n,r)},y=e=>{let t=[];for(let a;a=o[s++];)if(a.text!=null)t.push((e=>()=>e)(a.text));else if(a.raw!=null)t.push(h(a.raw,String));else if(e.includes(a.tag.split(` `)[0]))return l=a.tag,t;else if(a.tag[0]!==`!`)if(a.tag.startsWith(`#if `))t.push(v(_(a.tag.slice(4))));else if(a.tag.startsWith(`#each `)){let e=/^#each ([\s\S]+) as (\w+)(?:\s*,\s*(\w+))?$/.exec(a.tag)||p(`Bad {{`+a.tag+`}}`),n=_(e[1]),o=e[2],s=e[3];(r.test(o)||s&&r.test(s))&&p(`Bad {{`+a.tag+`}}`);let c=g(o,s,`loop`),u=y([`#else`,`/each`]);c();let d=l===`#else`?y([`/each`]):[];t.push(e=>{let t=i(n(e));return t.length?t.map(([n,r],i)=>{let a=Object.create(e);return a[o]=n,s&&(a[s]=r),a[`@`]=n,a.loop={index:i+1,index0:i,first:!i,last:i===t.length-1,length:t.length},m(u,a)}).join(``):m(d,e)})}else a.tag[0]===`#`||a.tag[0]===`/`?p(`Unexpected {{`+a.tag+`}}`):t.push(h(a.tag,n));return e.length&&p(`Missing {{`+e[e.length-1]+`}}`),t};function b(e,t){c=t,u=new Set([`$`,`@`]),d=new Set,f=new Set,o=a(String(e)),o.forEach((e,t)=>{e.l&&o[t-1]?.text&&(o[t-1].text=o[t-1].text.trimEnd()),e.r&&o[t+1]?.text&&(o[t+1].text=o[t+1].text.trimStart())}),s=0;let n=y([]),r=(e,t)=>{e||={};let r=Object.create(e);return r.$=t?t.root:e,t?`item`in t&&(r[`@`]=t.item):r[`@`]=e,m(n,r)};return r.names=Array.from(d),r.functions=Array.from(f),r}function x(e,t,n){return b(e,n)(t)}export{x as render,b as template};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sjabloon",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Tiny, CSP-safe template engine for JavaScript, powered by xprsn expressions. No eval, no new Function.",
|
|
5
5
|
"repository": "robinvdvleuten/sjabloon",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,16 +11,14 @@
|
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
13
13
|
"source": "src/index.js",
|
|
14
|
-
"main": "
|
|
15
|
-
"module": "
|
|
16
|
-
"
|
|
17
|
-
"types": "./index.d.ts",
|
|
14
|
+
"main": "dist/index.cjs",
|
|
15
|
+
"module": "dist/index.js",
|
|
16
|
+
"types": "index.d.ts",
|
|
18
17
|
"exports": {
|
|
19
18
|
".": {
|
|
20
19
|
"types": "./index.d.ts",
|
|
21
|
-
"import": "./dist/index.
|
|
22
|
-
"require": "./dist/index.cjs"
|
|
23
|
-
"default": "./dist/index.module.js"
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"require": "./dist/index.cjs"
|
|
24
22
|
}
|
|
25
23
|
},
|
|
26
24
|
"files": [
|
|
@@ -28,11 +26,31 @@
|
|
|
28
26
|
"src",
|
|
29
27
|
"index.d.ts"
|
|
30
28
|
],
|
|
29
|
+
"size-limit": [
|
|
30
|
+
{
|
|
31
|
+
"path": "dist/index.js",
|
|
32
|
+
"limit": "1.25 kB"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"path": "dist/index.cjs",
|
|
36
|
+
"limit": "1.25 kB"
|
|
37
|
+
}
|
|
38
|
+
],
|
|
31
39
|
"scripts": {
|
|
32
|
-
"
|
|
40
|
+
"bench": "node bench/index.js",
|
|
41
|
+
"build": "tsdown",
|
|
42
|
+
"fuzz": "npm run fuzz:prepare && run-s fuzz:compile fuzz:render fuzz:structured",
|
|
43
|
+
"fuzz:prepare": "node -e \"for (const x of ['compile','render','structured']) require('fs').mkdirSync('.fuzz-corpus/'+x,{recursive:true})\"",
|
|
44
|
+
"fuzz:compile": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/compile.fuzz.js -i src/ --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/",
|
|
45
|
+
"fuzz:render": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/render.fuzz.js -i src/ --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/",
|
|
46
|
+
"fuzz:structured": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/structured.fuzz.js -i src/ --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/",
|
|
47
|
+
"fuzz:regression": "run-s fuzz:regression:compile fuzz:regression:render fuzz:regression:structured",
|
|
48
|
+
"fuzz:regression:compile": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/compile.fuzz.js -i src/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync --mode=regression fuzz/corpus/compile -- -artifact_prefix=fuzz/",
|
|
49
|
+
"fuzz:regression:render": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/render.fuzz.js -i src/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync --mode=regression fuzz/corpus/render -- -artifact_prefix=fuzz/",
|
|
50
|
+
"fuzz:regression:structured": "NODE_OPTIONS=--disallow-code-generation-from-strings jazzer fuzz/structured.fuzz.js -i src/ --customHooks fuzz/hooks.js --disableBugDetectors='command-injection|path-traversal|ssrf' --sync --mode=regression fuzz/corpus/structured -- -artifact_prefix=fuzz/",
|
|
33
51
|
"prepublishOnly": "npm run build",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
52
|
+
"size": "size-limit",
|
|
53
|
+
"test": "node --disallow-code-generation-from-strings node_modules/tape/bin/tape test/*.test.js"
|
|
36
54
|
},
|
|
37
55
|
"keywords": [
|
|
38
56
|
"template",
|
|
@@ -42,10 +60,15 @@
|
|
|
42
60
|
"handlebars"
|
|
43
61
|
],
|
|
44
62
|
"dependencies": {
|
|
45
|
-
"xprsn": "^0.4.
|
|
63
|
+
"xprsn": "^0.4.1"
|
|
46
64
|
},
|
|
47
65
|
"devDependencies": {
|
|
48
|
-
"
|
|
49
|
-
"
|
|
66
|
+
"@jazzer.js/bug-detectors": "^4.0.0",
|
|
67
|
+
"@jazzer.js/core": "^4.0.0",
|
|
68
|
+
"@size-limit/file": "^12.1.0",
|
|
69
|
+
"npm-run-all": "^4.1.5",
|
|
70
|
+
"size-limit": "^12.1.0",
|
|
71
|
+
"tape": "^5.9.0",
|
|
72
|
+
"tsdown": "^0.22.12"
|
|
50
73
|
}
|
|
51
74
|
}
|
package/src/index.js
CHANGED
|
@@ -7,16 +7,39 @@ import { compile } from 'xprsn';
|
|
|
7
7
|
|
|
8
8
|
const ESC = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' };
|
|
9
9
|
const esc = s => String(s).replace(/[&<>"']/g, c => ESC[c]);
|
|
10
|
+
const BLOCKED = /^(?:__proto__|constructor|prototype)$/;
|
|
10
11
|
|
|
11
12
|
// What `#each` walks: [value, key] pairs — array indexes or own object keys.
|
|
12
13
|
const pairs = lv => Array.isArray(lv) ? lv.map((x, j) => [x, j])
|
|
13
14
|
: lv && typeof lv === 'object' ? Object.keys(lv).map(k => [lv[k], k])
|
|
14
15
|
: [];
|
|
15
16
|
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
|
|
17
|
+
// Linear scan into text/tag/raw tokens. Dashes hug braces (`{{- x -}}` trims;
|
|
18
|
+
// `{{ -x }}` stays unary minus). Prefer {{{ }}} over {{ }}. `triple` latches
|
|
19
|
+
// off once }}} is gone so {{{...}}×N does not rescan to EOF (stays O(n)).
|
|
20
|
+
let lex = s => {
|
|
21
|
+
const out = [];
|
|
22
|
+
for (let i = 0, triple = 1; i < s.length; ) {
|
|
23
|
+
const a = s.indexOf('{{', i);
|
|
24
|
+
if (a < 0) { out.push({ text: s.slice(i) }); break; }
|
|
25
|
+
if (a > i) out.push({ text: s.slice(i, a) });
|
|
26
|
+
let raw = s.charCodeAt(a + 2) === 123, p = a + 2 + raw, l = s.charCodeAt(p) === 45, b = -1;
|
|
27
|
+
if (l) p++;
|
|
28
|
+
if (raw && triple) { b = s.indexOf('}}}', p); if (b < 0) triple = 0; }
|
|
29
|
+
if (b < 0) {
|
|
30
|
+
if (raw) { raw = !1; p = a + 2; l = s.charCodeAt(p) === 45; if (l) p++; }
|
|
31
|
+
b = s.indexOf('}}', p);
|
|
32
|
+
}
|
|
33
|
+
if (b < 0) { out.push({ text: s.slice(a) }); break; }
|
|
34
|
+
const r = b > p && s.charCodeAt(b - 1) === 45;
|
|
35
|
+
const body = s.slice(p, r ? b - 1 : b).trim(), t = raw ? { raw: body } : { tag: body };
|
|
36
|
+
t.l = l;
|
|
37
|
+
t.r = r;
|
|
38
|
+
out.push(t);
|
|
39
|
+
i = b + 2 + raw;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
};
|
|
20
43
|
|
|
21
44
|
// Shared parser state; parsing is synchronous so this is safe.
|
|
22
45
|
// `nms` collects free variables, `fnms` the registry functions called.
|
|
@@ -75,6 +98,7 @@ let parse = stops => {
|
|
|
75
98
|
} else if (t.tag.startsWith('#each ')) {
|
|
76
99
|
const m = /^#each ([\s\S]+) as (\w+)(?:\s*,\s*(\w+))?$/.exec(t.tag) || err('Bad {{' + t.tag + '}}');
|
|
77
100
|
const list = cp(m[1]), name = m[2], idx = m[3];
|
|
101
|
+
if (BLOCKED.test(name) || idx && BLOCKED.test(idx)) err('Bad {{' + t.tag + '}}');
|
|
78
102
|
// `name`, `idx`, and `loop` are engine-bound inside the body, so
|
|
79
103
|
// exclude them from names there and restore outer bindings after.
|
|
80
104
|
const restore = scope(name, idx, 'loop');
|
|
@@ -137,21 +161,11 @@ export function template(str, funcs) {
|
|
|
137
161
|
bound = new Set(['$', '@']);
|
|
138
162
|
nms = new Set();
|
|
139
163
|
fnms = new Set();
|
|
140
|
-
toks =
|
|
141
|
-
const parts = String(str).split(TAGS);
|
|
142
|
-
for (let j = 0; j < parts.length; j += 7) {
|
|
143
|
-
if (parts[j]) toks.push({ text: parts[j] });
|
|
144
|
-
if (j + 1 >= parts.length) break;
|
|
145
|
-
const raw = parts[j + 2] != null;
|
|
146
|
-
const t = raw ? { raw: parts[j + 2] } : { tag: parts[j + 5] };
|
|
147
|
-
t.l = parts[j + (raw ? 1 : 4)] === '-';
|
|
148
|
-
t.r = parts[j + (raw ? 3 : 6)] === '-';
|
|
149
|
-
toks.push(t);
|
|
150
|
-
}
|
|
164
|
+
toks = lex(String(str));
|
|
151
165
|
// `{{-` / `-}}` eat the whitespace touching that side of the tag.
|
|
152
166
|
toks.forEach((t, k) => {
|
|
153
|
-
if (t.l && toks[k - 1]?.text) toks[k - 1].text = toks[k - 1].text.
|
|
154
|
-
if (t.r && toks[k + 1]?.text) toks[k + 1].text = toks[k + 1].text.
|
|
167
|
+
if (t.l && toks[k - 1]?.text) toks[k - 1].text = toks[k - 1].text.trimEnd();
|
|
168
|
+
if (t.r && toks[k + 1]?.text) toks[k + 1].text = toks[k + 1].text.trimStart();
|
|
155
169
|
});
|
|
156
170
|
i = 0;
|
|
157
171
|
const nodes = parse([]);
|
package/dist/index.module.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{compile as t}from"xprsn";function r(t,r){(null==r||r>t.length)&&(r=t.length);for(var n=0,e=Array(r);n<r;n++)e[n]=t[n];return e}function n(t,n){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(e)return(e=e.call(t)).next.bind(e);if(Array.isArray(t)||(e=function(t,n){if(t){if("string"==typeof t)return r(t,n);var e={}.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?r(t,n):void 0}}(t))||n&&t&&"number"==typeof t.length){e&&(t=e);var a=0;return function(){return a>=t.length?{done:!0}:{done:!1,value:t[a++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var e,a,i,u,o,l,f,c={"&":"&","<":"<",">":">",'"':""","'":"'"},s=function(t){return String(t).replace(/[&<>"']/g,function(t){return c[t]})},h=/\{\{\{(-)?\s*([\s\S]*?)\s*(-)?\}\}\}|\{\{(-)?\s*([\s\S]*?)\s*(-)?\}\}/,g=function(t){throw SyntaxError(t)},p=function(t,r){return t.map(function(t){return t(r)}).join("")},v=function(t,r){return n=d(t),function(t){var e;return r(null!=(e=n(t))?e:"")};var n},d=function(r){for(var e,a=t(r,i),u=n(a.names);!(e=u()).done;){var c=e.value;o.has(c)||l.add(c)}for(var s,h=n(a.functions);!(s=h()).done;)f.add(s.value);return a},m=function(t){var r=y(["#elif","#else","/if"]),n=u.startsWith("#elif ")?[m(d(u.slice(6)))]:"#else"===u?y(["/if"]):[];return function(e){return p(t(e)?r:n,e)}},y=function(t){for(var r,n,i=[],l=function(){if(null!=n.text)i.push((x=n.text,function(){return x}));else if(null!=n.raw)i.push(v(n.raw,String));else{if(t.includes(n.tag.split(" ")[0]))return u=n.tag,{v:i};if("!"===n.tag[0]);else if(n.tag.startsWith("#if "))i.push(m(d(n.tag.slice(4))));else if(n.tag.startsWith("#each ")){var r=/^#each ([\s\S]+) as (\w+)(?:\s*,\s*(\w+))?$/.exec(n.tag)||g("Bad {{"+n.tag+"}}"),e=d(r[1]),a=r[2],l=r[3],f=function(){var t=[].slice.call(arguments).filter(function(t){return t&&!o.has(t)});return t.forEach(function(t){return o.add(t)}),function(){return t.forEach(function(t){return o.delete(t)})}}(a,l,"loop"),c=y(["#else","/each"]);f();var h="#else"===u?y(["/each"]):[];i.push(function(t){var r,n=(r=e(t),Array.isArray(r)?r.map(function(t,r){return[t,r]}):r&&"object"==typeof r?Object.keys(r).map(function(t){return[r[t],t]}):[]);return n.length?n.map(function(r,e){var i=r[0],u=r[1],o=Object.create(t);return o[a]=i,l&&(o[l]=u),o["@"]=i,o.loop={index:e+1,index0:e,first:!e,last:e===n.length-1,length:n.length},p(c,o)}).join(""):p(h,t)})}else"#"===n.tag[0]||"/"===n.tag[0]?g("Unexpected {{"+n.tag+"}}"):i.push(v(n.tag,s))}var x};n=e[a++];)if(r=l())return r.v;return t.length&&g("Missing {{"+t[t.length-1]+"}}"),i};function x(t,r){i=r,o=new Set(["$","@"]),l=new Set,f=new Set,e=[];for(var n=String(t).split(h),u=0;u<n.length&&(n[u]&&e.push({text:n[u]}),!(u+1>=n.length));u+=7){var c=null!=n[u+2],s=c?{raw:n[u+2]}:{tag:n[u+5]};s.l="-"===n[u+(c?1:4)],s.r="-"===n[u+(c?3:6)],e.push(s)}e.forEach(function(t,r){var n,a;t.l&&null!=(n=e[r-1])&&n.text&&(e[r-1].text=e[r-1].text.replace(/\s+$/,"")),t.r&&null!=(a=e[r+1])&&a.text&&(e[r+1].text=e[r+1].text.replace(/^\s+/,""))}),a=0;var g=y([]),v=function(t,r){t=t||{};var n=Object.create(t);return n.$=r?r.root:t,r?"item"in r&&(n["@"]=r.item):n["@"]=t,p(g,n)};return v.names=Array.from(l),v.functions=Array.from(f),v}function S(t,r,n){return x(t,n)(r)}export{S as render,x as template};
|
package/dist/index.umd.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("xprsn")):"function"==typeof define&&define.amd?define(["exports","xprsn"],e):e((t||self).sjabloon={},t.xprsn)}(this,function(t,e){function n(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=Array(e);n<e;n++)r[n]=t[n];return r}function r(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(r)return(r=r.call(t)).next.bind(r);if(Array.isArray(t)||(r=function(t,e){if(t){if("string"==typeof t)return n(t,e);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var a=0;return function(){return a>=t.length?{done:!0}:{done:!1,value:t[a++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,i,o,u,l,f,s,c={"&":"&","<":"<",">":">",'"':""","'":"'"},p=function(t){return String(t).replace(/[&<>"']/g,function(t){return c[t]})},h=/\{\{\{(-)?\s*([\s\S]*?)\s*(-)?\}\}\}|\{\{(-)?\s*([\s\S]*?)\s*(-)?\}\}/,g=function(t){throw SyntaxError(t)},d=function(t,e){return t.map(function(t){return t(e)}).join("")},v=function(t,e){return n=m(t),function(t){var r;return e(null!=(r=n(t))?r:"")};var n},m=function(t){for(var n,a=e.compile(t,o),i=r(a.names);!(n=i()).done;){var u=n.value;l.has(u)||f.add(u)}for(var c,p=r(a.functions);!(c=p()).done;)s.add(c.value);return a},y=function(t){var e=x(["#elif","#else","/if"]),n=u.startsWith("#elif ")?[y(m(u.slice(6)))]:"#else"===u?x(["/if"]):[];return function(r){return d(t(r)?e:n,r)}},x=function(t){for(var e,n,r=[],o=function(){if(null!=n.text)r.push((h=n.text,function(){return h}));else if(null!=n.raw)r.push(v(n.raw,String));else{if(t.includes(n.tag.split(" ")[0]))return u=n.tag,{v:r};if("!"===n.tag[0]);else if(n.tag.startsWith("#if "))r.push(y(m(n.tag.slice(4))));else if(n.tag.startsWith("#each ")){var e=/^#each ([\s\S]+) as (\w+)(?:\s*,\s*(\w+))?$/.exec(n.tag)||g("Bad {{"+n.tag+"}}"),a=m(e[1]),i=e[2],o=e[3],f=function(){var t=[].slice.call(arguments).filter(function(t){return t&&!l.has(t)});return t.forEach(function(t){return l.add(t)}),function(){return t.forEach(function(t){return l.delete(t)})}}(i,o,"loop"),s=x(["#else","/each"]);f();var c="#else"===u?x(["/each"]):[];r.push(function(t){var e,n=(e=a(t),Array.isArray(e)?e.map(function(t,e){return[t,e]}):e&&"object"==typeof e?Object.keys(e).map(function(t){return[e[t],t]}):[]);return n.length?n.map(function(e,r){var a=e[0],u=e[1],l=Object.create(t);return l[i]=a,o&&(l[o]=u),l["@"]=a,l.loop={index:r+1,index0:r,first:!r,last:r===n.length-1,length:n.length},d(s,l)}).join(""):d(c,t)})}else"#"===n.tag[0]||"/"===n.tag[0]?g("Unexpected {{"+n.tag+"}}"):r.push(v(n.tag,p))}var h};n=a[i++];)if(e=o())return e.v;return t.length&&g("Missing {{"+t[t.length-1]+"}}"),r};function b(t,e){o=e,l=new Set(["$","@"]),f=new Set,s=new Set,a=[];for(var n=String(t).split(h),r=0;r<n.length&&(n[r]&&a.push({text:n[r]}),!(r+1>=n.length));r+=7){var u=null!=n[r+2],c=u?{raw:n[r+2]}:{tag:n[r+5]};c.l="-"===n[r+(u?1:4)],c.r="-"===n[r+(u?3:6)],a.push(c)}a.forEach(function(t,e){var n,r;t.l&&null!=(n=a[e-1])&&n.text&&(a[e-1].text=a[e-1].text.replace(/\s+$/,"")),t.r&&null!=(r=a[e+1])&&r.text&&(a[e+1].text=a[e+1].text.replace(/^\s+/,""))}),i=0;var p=x([]),g=function(t,e){t=t||{};var n=Object.create(t);return n.$=e?e.root:t,e?"item"in e&&(n["@"]=e.item):n["@"]=t,d(p,n)};return g.names=Array.from(f),g.functions=Array.from(s),g}t.render=function(t,e,n){return b(t,n)(e)},t.template=b});
|