@ketvietlab/ketjs 0.1.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/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/agent/capabilities.d.ts +62 -0
- package/dist/agent/capabilities.d.ts.map +1 -0
- package/dist/agent/capabilities.js +89 -0
- package/dist/agent/capabilities.js.map +1 -0
- package/dist/agent/permissions.d.ts +56 -0
- package/dist/agent/permissions.d.ts.map +1 -0
- package/dist/agent/permissions.js +209 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +698 -0
- package/dist/cli.js.map +1 -0
- package/dist/codegen/dts.d.ts +3 -0
- package/dist/codegen/dts.d.ts.map +1 -0
- package/dist/codegen/dts.js +94 -0
- package/dist/codegen/dts.js.map +1 -0
- package/dist/data/adapter.d.ts +4 -0
- package/dist/data/adapter.d.ts.map +1 -0
- package/dist/data/adapter.js +18 -0
- package/dist/data/adapter.js.map +1 -0
- package/dist/data/changeset.d.ts +49 -0
- package/dist/data/changeset.d.ts.map +1 -0
- package/dist/data/changeset.js +206 -0
- package/dist/data/changeset.js.map +1 -0
- package/dist/data/expr.d.ts +59 -0
- package/dist/data/expr.d.ts.map +1 -0
- package/dist/data/expr.js +61 -0
- package/dist/data/expr.js.map +1 -0
- package/dist/data/fleet.d.ts +28 -0
- package/dist/data/fleet.d.ts.map +1 -0
- package/dist/data/fleet.js +82 -0
- package/dist/data/fleet.js.map +1 -0
- package/dist/data/list-search.d.ts +93 -0
- package/dist/data/list-search.d.ts.map +1 -0
- package/dist/data/list-search.js +268 -0
- package/dist/data/list-search.js.map +1 -0
- package/dist/data/migrate.d.ts +75 -0
- package/dist/data/migrate.d.ts.map +1 -0
- package/dist/data/migrate.js +136 -0
- package/dist/data/migrate.js.map +1 -0
- package/dist/data/pool.d.ts +20 -0
- package/dist/data/pool.d.ts.map +1 -0
- package/dist/data/pool.js +92 -0
- package/dist/data/pool.js.map +1 -0
- package/dist/data/query.d.ts +111 -0
- package/dist/data/query.d.ts.map +1 -0
- package/dist/data/query.js +268 -0
- package/dist/data/query.js.map +1 -0
- package/dist/data/sqlite.d.ts +3 -0
- package/dist/data/sqlite.d.ts.map +1 -0
- package/dist/data/sqlite.js +107 -0
- package/dist/data/sqlite.js.map +1 -0
- package/dist/data/time.d.ts +9 -0
- package/dist/data/time.d.ts.map +1 -0
- package/dist/data/time.js +107 -0
- package/dist/data/time.js.map +1 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/apps.d.ts +43 -0
- package/dist/kernel/apps.d.ts.map +1 -0
- package/dist/kernel/apps.js +234 -0
- package/dist/kernel/apps.js.map +1 -0
- package/dist/kernel/compose.d.ts +6 -0
- package/dist/kernel/compose.d.ts.map +1 -0
- package/dist/kernel/compose.js +976 -0
- package/dist/kernel/compose.js.map +1 -0
- package/dist/kernel/define.d.ts +9 -0
- package/dist/kernel/define.d.ts.map +1 -0
- package/dist/kernel/define.js +140 -0
- package/dist/kernel/define.js.map +1 -0
- package/dist/kernel/diff.d.ts +11 -0
- package/dist/kernel/diff.d.ts.map +1 -0
- package/dist/kernel/diff.js +106 -0
- package/dist/kernel/diff.js.map +1 -0
- package/dist/kernel/errors.d.ts +17 -0
- package/dist/kernel/errors.d.ts.map +1 -0
- package/dist/kernel/errors.js +43 -0
- package/dist/kernel/errors.js.map +1 -0
- package/dist/kernel/graph.d.ts +3 -0
- package/dist/kernel/graph.d.ts.map +1 -0
- package/dist/kernel/graph.js +56 -0
- package/dist/kernel/graph.js.map +1 -0
- package/dist/kernel/i18n.d.ts +43 -0
- package/dist/kernel/i18n.d.ts.map +1 -0
- package/dist/kernel/i18n.js +79 -0
- package/dist/kernel/i18n.js.map +1 -0
- package/dist/kernel/index.d.ts +7 -0
- package/dist/kernel/index.d.ts.map +1 -0
- package/dist/kernel/index.js +7 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/kernel/layout.d.ts +17 -0
- package/dist/kernel/layout.d.ts.map +1 -0
- package/dist/kernel/layout.js +77 -0
- package/dist/kernel/layout.js.map +1 -0
- package/dist/kernel/menu.d.ts +27 -0
- package/dist/kernel/menu.d.ts.map +1 -0
- package/dist/kernel/menu.js +65 -0
- package/dist/kernel/menu.js.map +1 -0
- package/dist/kernel/modules.d.ts +31 -0
- package/dist/kernel/modules.d.ts.map +1 -0
- package/dist/kernel/modules.js +322 -0
- package/dist/kernel/modules.js.map +1 -0
- package/dist/kernel/routes.d.ts +24 -0
- package/dist/kernel/routes.d.ts.map +1 -0
- package/dist/kernel/routes.js +98 -0
- package/dist/kernel/routes.js.map +1 -0
- package/dist/kernel/types.d.ts +8 -0
- package/dist/kernel/types.d.ts.map +1 -0
- package/dist/kernel/types.js +67 -0
- package/dist/kernel/types.js.map +1 -0
- package/dist/kernel/workspace.d.ts +62 -0
- package/dist/kernel/workspace.d.ts.map +1 -0
- package/dist/kernel/workspace.js +156 -0
- package/dist/kernel/workspace.js.map +1 -0
- package/dist/scaffold/index.d.ts +2 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +49 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/templates/app.test.ts.tmpl +17 -0
- package/dist/scaffold/templates/biome.json.tmpl +30 -0
- package/dist/scaffold/templates/dev.mjs.tmpl +16 -0
- package/dist/scaffold/templates/gitignore.tmpl +24 -0
- package/dist/scaffold/templates/ket.workspace.ts.tmpl +18 -0
- package/dist/scaffold/templates/module.ts.tmpl +27 -0
- package/dist/scaffold/templates/package.json.tmpl +25 -0
- package/dist/scaffold/templates/tsconfig.json.tmpl +15 -0
- package/dist/server/boot.d.ts +173 -0
- package/dist/server/boot.d.ts.map +1 -0
- package/dist/server/boot.js +659 -0
- package/dist/server/boot.js.map +1 -0
- package/dist/server/config.d.ts +48 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +82 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/ctx.d.ts +13 -0
- package/dist/server/ctx.d.ts.map +1 -0
- package/dist/server/ctx.js +496 -0
- package/dist/server/ctx.js.map +1 -0
- package/dist/server/fn.d.ts +34 -0
- package/dist/server/fn.d.ts.map +1 -0
- package/dist/server/fn.js +170 -0
- package/dist/server/fn.js.map +1 -0
- package/dist/server/http.d.ts +79 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +459 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/idem.d.ts +31 -0
- package/dist/server/idem.d.ts.map +1 -0
- package/dist/server/idem.js +68 -0
- package/dist/server/idem.js.map +1 -0
- package/dist/server/jobs.d.ts +5 -0
- package/dist/server/jobs.d.ts.map +1 -0
- package/dist/server/jobs.js +24 -0
- package/dist/server/jobs.js.map +1 -0
- package/dist/server/multipart.d.ts +18 -0
- package/dist/server/multipart.d.ts.map +1 -0
- package/dist/server/multipart.js +183 -0
- package/dist/server/multipart.js.map +1 -0
- package/dist/server/project.d.ts +9 -0
- package/dist/server/project.d.ts.map +1 -0
- package/dist/server/project.js +67 -0
- package/dist/server/project.js.map +1 -0
- package/dist/server/queue.d.ts +80 -0
- package/dist/server/queue.d.ts.map +1 -0
- package/dist/server/queue.js +494 -0
- package/dist/server/queue.js.map +1 -0
- package/dist/server/respond.d.ts +91 -0
- package/dist/server/respond.d.ts.map +1 -0
- package/dist/server/respond.js +99 -0
- package/dist/server/respond.js.map +1 -0
- package/dist/server/runtime.d.ts +14 -0
- package/dist/server/runtime.d.ts.map +1 -0
- package/dist/server/runtime.js +25 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/session.d.ts +55 -0
- package/dist/server/session.d.ts.map +1 -0
- package/dist/server/session.js +172 -0
- package/dist/server/session.js.map +1 -0
- package/dist/server/sessionstore.d.ts +54 -0
- package/dist/server/sessionstore.d.ts.map +1 -0
- package/dist/server/sessionstore.js +232 -0
- package/dist/server/sessionstore.js.map +1 -0
- package/dist/server/storage/index.d.ts +11 -0
- package/dist/server/storage/index.d.ts.map +1 -0
- package/dist/server/storage/index.js +31 -0
- package/dist/server/storage/index.js.map +1 -0
- package/dist/server/storage/local.d.ts +5 -0
- package/dist/server/storage/local.d.ts.map +1 -0
- package/dist/server/storage/local.js +165 -0
- package/dist/server/storage/local.js.map +1 -0
- package/dist/server/storage/s3.d.ts +11 -0
- package/dist/server/storage/s3.d.ts.map +1 -0
- package/dist/server/storage/s3.js +133 -0
- package/dist/server/storage/s3.js.map +1 -0
- package/dist/server/storage/sigv4.d.ts +23 -0
- package/dist/server/storage/sigv4.d.ts.map +1 -0
- package/dist/server/storage/sigv4.js +79 -0
- package/dist/server/storage/sigv4.js.map +1 -0
- package/dist/server/storage/types.d.ts +37 -0
- package/dist/server/storage/types.d.ts.map +1 -0
- package/dist/server/storage/types.js +82 -0
- package/dist/server/storage/types.js.map +1 -0
- package/dist/server/stream.d.ts +43 -0
- package/dist/server/stream.d.ts.map +1 -0
- package/dist/server/stream.js +117 -0
- package/dist/server/stream.js.map +1 -0
- package/dist/server/streamstore.d.ts +29 -0
- package/dist/server/streamstore.d.ts.map +1 -0
- package/dist/server/streamstore.js +140 -0
- package/dist/server/streamstore.js.map +1 -0
- package/dist/server/tenants.d.ts +108 -0
- package/dist/server/tenants.d.ts.map +1 -0
- package/dist/server/tenants.js +172 -0
- package/dist/server/tenants.js.map +1 -0
- package/dist/server/transport/index.d.ts +5 -0
- package/dist/server/transport/index.d.ts.map +1 -0
- package/dist/server/transport/index.js +3 -0
- package/dist/server/transport/index.js.map +1 -0
- package/dist/server/transport/memory.d.ts +14 -0
- package/dist/server/transport/memory.d.ts.map +1 -0
- package/dist/server/transport/memory.js +36 -0
- package/dist/server/transport/memory.js.map +1 -0
- package/dist/server/transport/types.d.ts +44 -0
- package/dist/server/transport/types.d.ts.map +1 -0
- package/dist/server/transport/types.js +79 -0
- package/dist/server/transport/types.js.map +1 -0
- package/dist/server/worker.d.ts +33 -0
- package/dist/server/worker.d.ts.map +1 -0
- package/dist/server/worker.js +428 -0
- package/dist/server/worker.js.map +1 -0
- package/dist/testing.d.ts +146 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +406 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme/contracts.d.ts +4 -0
- package/dist/theme/contracts.d.ts.map +1 -0
- package/dist/theme/contracts.js +87 -0
- package/dist/theme/contracts.js.map +1 -0
- package/dist/theme/index.d.ts +8 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +7 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/joints.d.ts +19 -0
- package/dist/theme/joints.d.ts.map +1 -0
- package/dist/theme/joints.js +126 -0
- package/dist/theme/joints.js.map +1 -0
- package/dist/theme/ktl/compile.d.ts +26 -0
- package/dist/theme/ktl/compile.d.ts.map +1 -0
- package/dist/theme/ktl/compile.js +226 -0
- package/dist/theme/ktl/compile.js.map +1 -0
- package/dist/theme/ktl/lexer.d.ts +20 -0
- package/dist/theme/ktl/lexer.d.ts.map +1 -0
- package/dist/theme/ktl/lexer.js +56 -0
- package/dist/theme/ktl/lexer.js.map +1 -0
- package/dist/theme/ktl/parser.d.ts +64 -0
- package/dist/theme/ktl/parser.d.ts.map +1 -0
- package/dist/theme/ktl/parser.js +220 -0
- package/dist/theme/ktl/parser.js.map +1 -0
- package/dist/theme/render.d.ts +19 -0
- package/dist/theme/render.d.ts.map +1 -0
- package/dist/theme/render.js +246 -0
- package/dist/theme/render.js.map +1 -0
- package/dist/theme/templates.d.ts +2 -0
- package/dist/theme/templates.d.ts.map +1 -0
- package/dist/theme/templates.js +40 -0
- package/dist/theme/templates.js.map +1 -0
- package/dist/theme/tokens.d.ts +4 -0
- package/dist/theme/tokens.d.ts.map +1 -0
- package/dist/theme/tokens.js +15 -0
- package/dist/theme/tokens.js.map +1 -0
- package/dist/theme/viewmodel.d.ts +6 -0
- package/dist/theme/viewmodel.d.ts.map +1 -0
- package/dist/theme/viewmodel.js +40 -0
- package/dist/theme/viewmodel.js.map +1 -0
- package/dist/types.d.ts +614 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Rendering a joint inside a first-party screen.
|
|
2
|
+
//
|
|
3
|
+
// The screens are `html`` ` — typed, interactive, ours. What fills them is KTL —
|
|
4
|
+
// stringly-typed, sandboxed, a stranger's. That split is deliberate and it is the
|
|
5
|
+
// same one the storefront already makes: the code that runs is ours, the code that
|
|
6
|
+
// extends is theirs and cannot run.
|
|
7
|
+
//
|
|
8
|
+
// The alternative was a fill that is a function. It would have been typed, and it
|
|
9
|
+
// would have been arbitrary JavaScript from another module running in this process
|
|
10
|
+
// — which is the thing KTL exists to prevent. It would also have made `fills` the
|
|
11
|
+
// first part of the manifest that is not data: unprintable by `ket manifest`,
|
|
12
|
+
// undiffable by `ket diff`, unsnapshotable. A fill is text.
|
|
13
|
+
import { compileKtl } from './ktl/compile.js';
|
|
14
|
+
import { contractProps } from './contracts.js';
|
|
15
|
+
import { renderIsland, trustedMarkup } from '@ketvietlab/ketjs-view';
|
|
16
|
+
import { KetError } from '../kernel/errors.js';
|
|
17
|
+
export function createJoints(manifest, o = {}) {
|
|
18
|
+
// Compiled once. A fill is KTL source, so compiling per request would parse the
|
|
19
|
+
// same text on every page view.
|
|
20
|
+
const compiled = new Map();
|
|
21
|
+
const atRuntime = manifest.disabledModules !== undefined;
|
|
22
|
+
const stack = [];
|
|
23
|
+
const omitted = (key) => (manifest.joints[key]?.omittedBy.length ?? 0) > 0;
|
|
24
|
+
const renderJoint = (key, props) => {
|
|
25
|
+
const definition = manifest.joints[key];
|
|
26
|
+
if (!definition) {
|
|
27
|
+
throw new KetError({
|
|
28
|
+
code: 'E_UNKNOWN_JOINT',
|
|
29
|
+
message: `no installed module publishes joint "${key}"`,
|
|
30
|
+
hint: `published joints: ${Object.keys(manifest.joints).join(', ') || '(none)'}`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (omitted(key))
|
|
34
|
+
return '';
|
|
35
|
+
if (stack.includes(key)) {
|
|
36
|
+
throw new KetError({
|
|
37
|
+
code: 'E_JOINT_CYCLE',
|
|
38
|
+
message: `joint recursion: ${[...stack, key].join(' -> ')}`,
|
|
39
|
+
hint: 'a fill may render another joint, but never itself through any chain',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (stack.length >= 16)
|
|
43
|
+
throw new KetError({ code: 'E_JOINT_TOO_DEEP', message: 'joint rendering exceeds 16 levels' });
|
|
44
|
+
stack.push(key);
|
|
45
|
+
try {
|
|
46
|
+
const scope = contractProps(manifest, 'joint', key, definition.props, props);
|
|
47
|
+
return (compiled.get(key) ?? []).map((entry) => entry.render(scope)).join('');
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
stack.pop();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const renderIslandAt = (name, scope) => {
|
|
54
|
+
const factory = o.islands?.[name];
|
|
55
|
+
const definition = manifest.islands[name];
|
|
56
|
+
if (!factory || !definition) {
|
|
57
|
+
if (atRuntime)
|
|
58
|
+
return '';
|
|
59
|
+
throw new KetError({
|
|
60
|
+
code: 'E_UNKNOWN_ISLAND',
|
|
61
|
+
message: `a fill places island "${name}", which no installed module provides`,
|
|
62
|
+
hint: `available islands: ${Object.keys(o.islands ?? {}).join(', ') || '(none)'}`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return renderIsland(name, factory, contractProps(manifest, 'island', name, definition.props, scope), {
|
|
66
|
+
key: definition.key,
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
for (const fill of manifest.fills) {
|
|
70
|
+
const list = compiled.get(fill.joint) ?? [];
|
|
71
|
+
const entry = compileKtl(fill.template, {
|
|
72
|
+
name: `${fill.joint}#${list.length}`,
|
|
73
|
+
...(o.translate ? { translate: o.translate } : {}),
|
|
74
|
+
renderJoint,
|
|
75
|
+
renderIsland: renderIslandAt,
|
|
76
|
+
});
|
|
77
|
+
const module = manifest.modules[fill.by];
|
|
78
|
+
for (const used of entry.jointsUsed) {
|
|
79
|
+
const target = manifest.joints[used];
|
|
80
|
+
if (!target)
|
|
81
|
+
throw new KetError({
|
|
82
|
+
code: 'E_FILL_UNKNOWN_JOINT',
|
|
83
|
+
module: fill.by,
|
|
84
|
+
message: `fill for "${fill.joint}" renders unknown joint "${used}"`,
|
|
85
|
+
});
|
|
86
|
+
if (target.owner !== fill.by && !module?.depends?.includes(target.owner))
|
|
87
|
+
throw new KetError({
|
|
88
|
+
code: 'E_FILL_NOT_DEPENDED',
|
|
89
|
+
module: fill.by,
|
|
90
|
+
message: `fill for "${fill.joint}" renders "${used}" without depending on "${target.owner}"`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
for (const used of entry.islandsUsed) {
|
|
94
|
+
const target = manifest.islands[used];
|
|
95
|
+
if (!target && !atRuntime)
|
|
96
|
+
throw new KetError({
|
|
97
|
+
code: 'E_FILL_UNKNOWN_ISLAND',
|
|
98
|
+
module: fill.by,
|
|
99
|
+
message: `fill for "${fill.joint}" places unknown island "${used}"`,
|
|
100
|
+
});
|
|
101
|
+
if (target && target.by !== fill.by && !module?.depends?.includes(target.by))
|
|
102
|
+
throw new KetError({
|
|
103
|
+
code: 'E_FILL_NOT_DEPENDED',
|
|
104
|
+
module: fill.by,
|
|
105
|
+
message: `fill for "${fill.joint}" places "${used}" without depending on "${target.by}"`,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
list.push(entry);
|
|
109
|
+
compiled.set(fill.joint, list);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
shows: (key) => {
|
|
113
|
+
if (!manifest.joints[key]) {
|
|
114
|
+
throw new KetError({
|
|
115
|
+
code: 'E_UNKNOWN_JOINT',
|
|
116
|
+
message: `no installed module publishes joint "${key}"`,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return !omitted(key);
|
|
120
|
+
},
|
|
121
|
+
render(key, props = {}) {
|
|
122
|
+
return trustedMarkup(renderJoint(key, props));
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=joints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joints.js","sourceRoot":"","sources":["../../../../../../packages/ketjs/src/theme/joints.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,mFAAmF;AACnF,oCAAoC;AACpC,EAAE;AACF,kFAAkF;AAClF,mFAAmF;AACnF,kFAAkF;AAClF,8EAA8E;AAC9E,4DAA4D;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAGpE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAe9C,MAAM,UAAU,YAAY,CAC1B,QAAkB,EAClB,CAAC,GAGG,EAAE;IAEN,gFAAgF;IAChF,gCAAgC;IAChC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAgD,CAAA;IACxE,MAAM,SAAS,GAAG,QAAQ,CAAC,eAAe,KAAK,SAAS,CAAA;IACxD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAG,CAAC,GAAW,EAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IAE3F,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,KAA8B,EAAU,EAAE;QAC1E,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACvC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,wCAAwC,GAAG,GAAG;gBACvD,IAAI,EAAE,qBAAqB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE;aACjF,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAA;QAC3B,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,oBAAoB,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBAC3D,IAAI,EAAE,qEAAqE;aAC5E,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE;YACpB,MAAM,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAA;QAChG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACf,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YAC5E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC/E,CAAC;gBAAS,CAAC;YACT,KAAK,CAAC,GAAG,EAAE,CAAA;QACb,CAAC;IACH,CAAC,CAAA;IAED,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,KAA8B,EAAU,EAAE;QAC9E,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACzC,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;YAC5B,IAAI,SAAS;gBAAE,OAAO,EAAE,CAAA;YACxB,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,yBAAyB,IAAI,uCAAuC;gBAC7E,IAAI,EAAE,sBAAsB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE;aAClF,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;YACnG,GAAG,EAAE,UAAU,CAAC,GAAG;SACpB,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;QAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE;YACtC,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;YACpC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,WAAW;YACX,YAAY,EAAE,cAAc;SAC7B,CAAC,CAAA;QACF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACxC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACpC,IAAI,CAAC,MAAM;gBACT,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,sBAAsB;oBAC5B,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,OAAO,EAAE,aAAa,IAAI,CAAC,KAAK,4BAA4B,IAAI,GAAG;iBACpE,CAAC,CAAA;YACJ,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;gBACtE,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,qBAAqB;oBAC3B,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,OAAO,EAAE,aAAa,IAAI,CAAC,KAAK,cAAc,IAAI,2BAA2B,MAAM,CAAC,KAAK,GAAG;iBAC7F,CAAC,CAAA;QACN,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YACrC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS;gBACvB,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,uBAAuB;oBAC7B,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,OAAO,EAAE,aAAa,IAAI,CAAC,KAAK,4BAA4B,IAAI,GAAG;iBACpE,CAAC,CAAA;YACJ,IAAI,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1E,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,qBAAqB;oBAC3B,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,OAAO,EAAE,aAAa,IAAI,CAAC,KAAK,aAAa,IAAI,2BAA2B,MAAM,CAAC,EAAE,GAAG;iBACzF,CAAC,CAAA;QACN,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChB,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAChC,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,iBAAiB;oBACvB,OAAO,EAAE,wCAAwC,GAAG,GAAG;iBACxD,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACtB,CAAC;QACD,MAAM,CAAC,GAAG,EAAE,KAAK,GAAG,EAAE;YACpB,OAAO,aAAa,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;QAC/C,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type Filter = (value: unknown, arg?: unknown) => unknown;
|
|
2
|
+
export type Scope = Record<string, unknown>;
|
|
3
|
+
export type JointRenderer = (joint: string, scope: Scope) => string;
|
|
4
|
+
export type RegionRenderer = (name: string, scope: Scope) => string;
|
|
5
|
+
export type IslandRenderer = (name: string, scope: Scope) => string;
|
|
6
|
+
export type SectionsRenderer = (scope: Scope) => string;
|
|
7
|
+
export type CompileOpts = {
|
|
8
|
+
filters?: Record<string, Filter>;
|
|
9
|
+
/** Bound translator. A theme writes {{ 'website.page.title' | _ }}. */
|
|
10
|
+
translate?: (key: string, params?: Record<string, unknown>) => string;
|
|
11
|
+
renderJoint?: JointRenderer;
|
|
12
|
+
renderRegion?: RegionRenderer;
|
|
13
|
+
renderIsland?: IslandRenderer;
|
|
14
|
+
renderSections?: SectionsRenderer;
|
|
15
|
+
/** Renders another template by name, with the scope this one built for it. */
|
|
16
|
+
renderTemplate?: (name: string, scope: Scope, from: string) => string;
|
|
17
|
+
name?: string;
|
|
18
|
+
};
|
|
19
|
+
export type Compiled = {
|
|
20
|
+
render(scope: Scope): string;
|
|
21
|
+
jointsUsed: string[];
|
|
22
|
+
regionsUsed: string[];
|
|
23
|
+
islandsUsed: string[];
|
|
24
|
+
};
|
|
25
|
+
export declare function compileKtl(source: string, opts?: CompileOpts): Compiled;
|
|
26
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../../../../packages/ketjs/src/theme/ktl/compile.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,OAAO,CAAA;AAC/D,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAC3C,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,CAAA;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,CAAA;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,CAAA;AACnE,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAA;AAEvD,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,uEAAuE;IACvE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAA;IACrE,WAAW,CAAC,EAAE,aAAa,CAAA;IAC3B,YAAY,CAAC,EAAE,cAAc,CAAA;IAC7B,YAAY,CAAC,EAAE,cAAc,CAAA;IAC7B,cAAc,CAAC,EAAE,gBAAgB,CAAA;IACjC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB,CAAA;AAwGD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,QAAQ,CA4H3E"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Compile KTL to a tree of closures.
|
|
2
|
+
//
|
|
3
|
+
// There is no `new Function`, no `eval`, no string-to-code path anywhere here.
|
|
4
|
+
// A compiled template is a plain JavaScript function that can only read from the
|
|
5
|
+
// scope it is handed and call filters that were registered by name. That is the
|
|
6
|
+
// whole security argument for installing a stranger's theme.
|
|
7
|
+
import { parse } from './parser.js';
|
|
8
|
+
import { escapeHtml } from '@ketvietlab/ketjs-view';
|
|
9
|
+
import { KetError } from '../../kernel/errors.js';
|
|
10
|
+
// Intl formatters are expensive to construct and cheap to reuse. Building one per
|
|
11
|
+
// interpolation made the money filter cost more than the entire rest of the
|
|
12
|
+
// template engine put together — 4.5s against 38ms over the same 5000 renders.
|
|
13
|
+
const formatters = new Map();
|
|
14
|
+
const formatter = (locale, opts) => {
|
|
15
|
+
const key = locale + '|' + (opts.style ?? '') + (opts.currency ?? '');
|
|
16
|
+
let f = formatters.get(key);
|
|
17
|
+
if (!f) {
|
|
18
|
+
f = new Intl.NumberFormat(locale, opts);
|
|
19
|
+
formatters.set(key, f);
|
|
20
|
+
}
|
|
21
|
+
return f;
|
|
22
|
+
};
|
|
23
|
+
const BASE_FILTERS = {
|
|
24
|
+
upper: (v) => String(v ?? '').toUpperCase(),
|
|
25
|
+
lower: (v) => String(v ?? '').toLowerCase(),
|
|
26
|
+
money: (v, arg) => formatter(String(arg ?? 'vi-VN'), { style: 'currency', currency: 'VND' }).format(Number(v ?? 0) / 100),
|
|
27
|
+
number: (v) => formatter('vi-VN', {}).format(Number(v ?? 0)),
|
|
28
|
+
default: (v, arg) => (v == null || v === '' ? arg : v),
|
|
29
|
+
length: (v) => (Array.isArray(v) ? v.length : String(v ?? '').length),
|
|
30
|
+
truncate: (v, arg) => {
|
|
31
|
+
const n = Number(arg ?? 80);
|
|
32
|
+
const s = String(v ?? '');
|
|
33
|
+
return s.length > n ? s.slice(0, n) + '…' : s;
|
|
34
|
+
},
|
|
35
|
+
json: (v) => JSON.stringify(v),
|
|
36
|
+
};
|
|
37
|
+
// Reads one own-property at a time. A drop is a null-prototype object, so there is
|
|
38
|
+
// nothing above it to walk into even if a name slipped past the parser.
|
|
39
|
+
const hasOwn = Object.prototype.hasOwnProperty;
|
|
40
|
+
function readPath(scope, parts, where) {
|
|
41
|
+
// The scope chain bottoms out at a null-prototype object, so the first hop needs
|
|
42
|
+
// no own-property guard: "constructor" and friends resolve to undefined anyway.
|
|
43
|
+
let cur = scope[parts[0]];
|
|
44
|
+
for (let i = 1; i < parts.length; i++) {
|
|
45
|
+
if (cur == null || typeof cur !== 'object')
|
|
46
|
+
return undefined;
|
|
47
|
+
const p = parts[i];
|
|
48
|
+
if (!hasOwn.call(cur, p))
|
|
49
|
+
return undefined;
|
|
50
|
+
cur = cur[p];
|
|
51
|
+
}
|
|
52
|
+
if (typeof cur === 'function') {
|
|
53
|
+
throw new KetError({
|
|
54
|
+
code: 'E_KTL_CALLABLE',
|
|
55
|
+
message: `${where} reached a function via "${parts.join('.')}"`,
|
|
56
|
+
hint: 'view models must expose data only',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return cur;
|
|
60
|
+
}
|
|
61
|
+
function compileExpr(e, o) {
|
|
62
|
+
if (e.k === 'lit') {
|
|
63
|
+
const v = e.value;
|
|
64
|
+
return () => v;
|
|
65
|
+
}
|
|
66
|
+
if (e.k === 'path') {
|
|
67
|
+
const parts = e.parts, where = at(o);
|
|
68
|
+
return (s) => readPath(s, parts, where);
|
|
69
|
+
}
|
|
70
|
+
if (e.k === 'not') {
|
|
71
|
+
const inner = compileExpr(e.src, o);
|
|
72
|
+
return (s) => !inner(s);
|
|
73
|
+
}
|
|
74
|
+
if (e.k === 'cmp') {
|
|
75
|
+
const l = compileExpr(e.left, o), r = compileExpr(e.right, o), op = e.op;
|
|
76
|
+
return (s) => {
|
|
77
|
+
const a = l(s), b = r(s);
|
|
78
|
+
if (op === '==')
|
|
79
|
+
return a === b;
|
|
80
|
+
if (op === '!=')
|
|
81
|
+
return a !== b;
|
|
82
|
+
if (op === '>')
|
|
83
|
+
return a > b;
|
|
84
|
+
if (op === '<')
|
|
85
|
+
return a < b;
|
|
86
|
+
if (op === '>=')
|
|
87
|
+
return a >= b;
|
|
88
|
+
return a <= b;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const src = compileExpr(e.src, o);
|
|
92
|
+
const arg = e.arg ? compileExpr(e.arg, o) : null;
|
|
93
|
+
const fn = o.filters[e.name];
|
|
94
|
+
if (!fn) {
|
|
95
|
+
throw new KetError({
|
|
96
|
+
code: 'E_KTL_UNKNOWN_FILTER',
|
|
97
|
+
message: `${at(o)} uses unknown filter "${e.name}"`,
|
|
98
|
+
hint: `registered filters: ${Object.keys(o.filters).sort().join(', ')}`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return (s) => fn(src(s), arg ? arg(s) : undefined);
|
|
102
|
+
}
|
|
103
|
+
/** Where an error is: the template name doubles as its file name, plus the line. */
|
|
104
|
+
const at = (o) => `template "${o.name}"` + (o.line ? ` line ${o.line}` : '');
|
|
105
|
+
export function compileKtl(source, opts = {}) {
|
|
106
|
+
const name = opts.name ?? '(anonymous)';
|
|
107
|
+
// Translation arrives as a filter rather than a function in scope, because scope
|
|
108
|
+
// holds data only — a theme that could call functions would be a theme that could
|
|
109
|
+
// run code, which is the whole thing KTL exists to prevent.
|
|
110
|
+
//
|
|
111
|
+
// The filter is named _ , the way gettext and Odoo name it: it appears often
|
|
112
|
+
// enough in markup that a longer name would cost more than it explains.
|
|
113
|
+
const filters = {
|
|
114
|
+
...BASE_FILTERS,
|
|
115
|
+
...(opts.translate
|
|
116
|
+
? {
|
|
117
|
+
_: (v, arg) => opts.translate(String(v), arg),
|
|
118
|
+
}
|
|
119
|
+
: {}),
|
|
120
|
+
...(opts.filters ?? {}),
|
|
121
|
+
};
|
|
122
|
+
const jointsUsed = [];
|
|
123
|
+
const regionsUsed = [];
|
|
124
|
+
const islandsUsed = [];
|
|
125
|
+
const compileNodes = (nodes) => nodes.map((n) => {
|
|
126
|
+
if (n.k === 'text') {
|
|
127
|
+
const v = n.value;
|
|
128
|
+
return (_s, out) => {
|
|
129
|
+
out.push(v);
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (n.k === 'out') {
|
|
133
|
+
const t = compileExpr(n.expr, { filters, name, line: n.line });
|
|
134
|
+
const raw = n.raw;
|
|
135
|
+
return (s, out) => {
|
|
136
|
+
const v = t(s);
|
|
137
|
+
out.push(v == null ? '' : raw ? String(v) : escapeHtml(v));
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (n.k === 'if') {
|
|
141
|
+
const cond = compileExpr(n.cond, { filters, name, line: n.line });
|
|
142
|
+
const a = compileNodes(n.then), b = compileNodes(n.else);
|
|
143
|
+
return (s, out) => {
|
|
144
|
+
for (const f of cond(s) ? a : b)
|
|
145
|
+
f(s, out);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (n.k === 'for') {
|
|
149
|
+
const src = compileExpr(n.src, { filters, name, line: n.line });
|
|
150
|
+
const body = compileNodes(n.body);
|
|
151
|
+
const varName = n.name;
|
|
152
|
+
return (s, out) => {
|
|
153
|
+
const list = src(s);
|
|
154
|
+
if (!Array.isArray(list))
|
|
155
|
+
return;
|
|
156
|
+
const n = list.length;
|
|
157
|
+
// One child scope for the whole loop rather than one per item. The body
|
|
158
|
+
// runs synchronously and never retains it, so reuse is safe.
|
|
159
|
+
const inner = Object.create(s);
|
|
160
|
+
const loop = { index: 0, first: true, last: n === 1, length: n };
|
|
161
|
+
inner['loop'] = loop;
|
|
162
|
+
for (let i = 0; i < n; i++) {
|
|
163
|
+
inner[varName] = list[i];
|
|
164
|
+
loop.index = i;
|
|
165
|
+
loop.first = i === 0;
|
|
166
|
+
loop.last = i === n - 1;
|
|
167
|
+
for (const f of body)
|
|
168
|
+
f(inner, out);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (n.k === 'joint') {
|
|
173
|
+
jointsUsed.push(n.joint);
|
|
174
|
+
const key = n.joint;
|
|
175
|
+
return (s, out) => {
|
|
176
|
+
out.push(opts.renderJoint ? opts.renderJoint(key, s) : '');
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
if (n.k === 'sections') {
|
|
180
|
+
return (s, out) => {
|
|
181
|
+
out.push(opts.renderSections ? opts.renderSections(s) : '');
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (n.k === 'render') {
|
|
185
|
+
const target = n.template;
|
|
186
|
+
const args = Object.entries(n.args).map(([k, e]) => [k, compileExpr(e, { filters, name, line: n.line })]);
|
|
187
|
+
const where = at({ name, line: n.line });
|
|
188
|
+
return (s, out) => {
|
|
189
|
+
// A null-prototype object with only what was passed. Not Object.create(s):
|
|
190
|
+
// the callee must not be able to read the caller by accident, or on purpose.
|
|
191
|
+
const inner = Object.create(null);
|
|
192
|
+
for (const [k, thunk] of args)
|
|
193
|
+
inner[k] = thunk(s);
|
|
194
|
+
out.push(opts.renderTemplate ? opts.renderTemplate(target, inner, where) : '');
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if (n.k === 'island') {
|
|
198
|
+
islandsUsed.push(n.name);
|
|
199
|
+
const iname = n.name;
|
|
200
|
+
return (s, out) => {
|
|
201
|
+
out.push(opts.renderIsland ? opts.renderIsland(iname, s) : '');
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
regionsUsed.push(n.name);
|
|
205
|
+
const rname = n.name;
|
|
206
|
+
return (s, out) => {
|
|
207
|
+
out.push(opts.renderRegion ? opts.renderRegion(rname, s) : '');
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
const program = compileNodes(parse(source));
|
|
211
|
+
return {
|
|
212
|
+
jointsUsed,
|
|
213
|
+
regionsUsed,
|
|
214
|
+
islandsUsed,
|
|
215
|
+
render(scope) {
|
|
216
|
+
const out = [];
|
|
217
|
+
// sealScope() already hands over a null-prototype object; copying it again
|
|
218
|
+
// on every render was pure waste.
|
|
219
|
+
const safe = Object.getPrototypeOf(scope) === null ? scope : Object.assign(Object.create(null), scope);
|
|
220
|
+
for (const f of program)
|
|
221
|
+
f(safe, out);
|
|
222
|
+
return out.join('');
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../../../../../../packages/ketjs/src/theme/ktl/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type Token = {
|
|
2
|
+
type: 'text';
|
|
3
|
+
value: string;
|
|
4
|
+
line: number;
|
|
5
|
+
} | {
|
|
6
|
+
type: 'expr';
|
|
7
|
+
value: string;
|
|
8
|
+
line: number;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'tag';
|
|
11
|
+
value: string;
|
|
12
|
+
line: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function lex(src: string): Token[];
|
|
15
|
+
export declare class KtlSyntaxError extends Error {
|
|
16
|
+
code: string;
|
|
17
|
+
line: number;
|
|
18
|
+
constructor(message: string, line: number);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=lexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../../../../packages/ketjs/src/theme/ktl/lexer.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,KAAK,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhD,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,CAsCxC;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,IAAI,SAAiB;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAGxC;CACF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// KTL — Ket Template Language.
|
|
2
|
+
//
|
|
3
|
+
// Themes are third-party code installed into somebody else's app, so a theme must
|
|
4
|
+
// not be able to run arbitrary JavaScript: no fetch, no env, no database. That is
|
|
5
|
+
// why this is a separate language rather than a tagged template literal, and why
|
|
6
|
+
// it compiles to a tree of closures instead of through `new Function`.
|
|
7
|
+
export function lex(src) {
|
|
8
|
+
const out = [];
|
|
9
|
+
let i = 0;
|
|
10
|
+
let line = 1;
|
|
11
|
+
const countLines = (s) => {
|
|
12
|
+
for (const ch of s)
|
|
13
|
+
if (ch === '\n')
|
|
14
|
+
line++;
|
|
15
|
+
};
|
|
16
|
+
while (i < src.length) {
|
|
17
|
+
const openExpr = src.indexOf('{{', i);
|
|
18
|
+
const openTag = src.indexOf('{%', i);
|
|
19
|
+
const openNote = src.indexOf('{#', i);
|
|
20
|
+
const next = [openExpr, openTag, openNote].filter((n) => n !== -1).sort((a, b) => a - b)[0] ?? -1;
|
|
21
|
+
if (next === -1) {
|
|
22
|
+
const value = src.slice(i);
|
|
23
|
+
if (value)
|
|
24
|
+
out.push({ type: 'text', value, line });
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
if (next > i) {
|
|
28
|
+
const value = src.slice(i, next);
|
|
29
|
+
out.push({ type: 'text', value, line });
|
|
30
|
+
countLines(value);
|
|
31
|
+
}
|
|
32
|
+
// A comment is lexed and dropped rather than left to the text branch, so it
|
|
33
|
+
// never reaches the output. Templates are files now; a language a theme author
|
|
34
|
+
// cannot annotate is a language they will annotate wrongly, in the markup.
|
|
35
|
+
const open = src.slice(next, next + 2);
|
|
36
|
+
const closer = open === '{{' ? '}}' : open === '{%' ? '%}' : '#}';
|
|
37
|
+
const close = src.indexOf(closer, next + 2);
|
|
38
|
+
if (close === -1)
|
|
39
|
+
throw new KtlSyntaxError(`unterminated ${open} at line ${line}`, line);
|
|
40
|
+
const raw = src.slice(next + 2, close).trim();
|
|
41
|
+
if (open !== '{#')
|
|
42
|
+
out.push({ type: open === '{{' ? 'expr' : 'tag', value: raw, line });
|
|
43
|
+
countLines(src.slice(next, close));
|
|
44
|
+
i = close + closer.length;
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
export class KtlSyntaxError extends Error {
|
|
49
|
+
code = 'E_KTL_SYNTAX';
|
|
50
|
+
line;
|
|
51
|
+
constructor(message, line) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.line = line;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=lexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexer.js","sourceRoot":"","sources":["../../../../../../../packages/ketjs/src/theme/ktl/lexer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export type Expr = {
|
|
2
|
+
k: 'path';
|
|
3
|
+
parts: string[];
|
|
4
|
+
} | {
|
|
5
|
+
k: 'lit';
|
|
6
|
+
value: string | number | boolean;
|
|
7
|
+
} | {
|
|
8
|
+
k: 'filter';
|
|
9
|
+
src: Expr;
|
|
10
|
+
name: string;
|
|
11
|
+
arg: Expr | null;
|
|
12
|
+
} | {
|
|
13
|
+
k: 'cmp';
|
|
14
|
+
op: string;
|
|
15
|
+
left: Expr;
|
|
16
|
+
right: Expr;
|
|
17
|
+
} | {
|
|
18
|
+
k: 'not';
|
|
19
|
+
src: Expr;
|
|
20
|
+
};
|
|
21
|
+
export type Node = {
|
|
22
|
+
k: 'text';
|
|
23
|
+
value: string;
|
|
24
|
+
} | {
|
|
25
|
+
k: 'out';
|
|
26
|
+
expr: Expr;
|
|
27
|
+
raw: boolean;
|
|
28
|
+
line: number;
|
|
29
|
+
} | {
|
|
30
|
+
k: 'if';
|
|
31
|
+
cond: Expr;
|
|
32
|
+
then: Node[];
|
|
33
|
+
else: Node[];
|
|
34
|
+
line: number;
|
|
35
|
+
} | {
|
|
36
|
+
k: 'for';
|
|
37
|
+
name: string;
|
|
38
|
+
src: Expr;
|
|
39
|
+
body: Node[];
|
|
40
|
+
line: number;
|
|
41
|
+
} | {
|
|
42
|
+
k: 'render';
|
|
43
|
+
template: string;
|
|
44
|
+
args: Record<string, Expr>;
|
|
45
|
+
line: number;
|
|
46
|
+
} | {
|
|
47
|
+
k: 'joint';
|
|
48
|
+
joint: string;
|
|
49
|
+
line: number;
|
|
50
|
+
} | {
|
|
51
|
+
k: 'region';
|
|
52
|
+
name: string;
|
|
53
|
+
line: number;
|
|
54
|
+
} | {
|
|
55
|
+
k: 'island';
|
|
56
|
+
name: string;
|
|
57
|
+
line: number;
|
|
58
|
+
} | {
|
|
59
|
+
k: 'sections';
|
|
60
|
+
line: number;
|
|
61
|
+
};
|
|
62
|
+
export declare function parseExpr(src: string, line: number): Expr;
|
|
63
|
+
export declare function parse(src: string): Node[];
|
|
64
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../../../../packages/ketjs/src/theme/ktl/parser.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,IAAI,GACZ;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAC9B;IAAE,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,GAC9C;IAAE,CAAC,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,CAAC,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACjD;IAAE,CAAC,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,CAAA;AAE3B,MAAM,MAAM,IAAI,GACZ;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,CAAC,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,CAAC,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,CAAC,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,CAAC,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAOnC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAsCzD;AAmDD,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,CAqHzC"}
|