@lumencast/compiler 0.1.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.
@@ -0,0 +1,270 @@
1
+ // LSML 1.0 → flat RenderBundle compiler.
2
+ //
3
+ // LSML lets authors write idiomatic primitives with inline `bind: { value: "path" }`,
4
+ // CSS-style `style.fontSize`, `repeat.template`, `animate` directives. The runtime
5
+ // expects a flat shape: per-node `bindings` map, primitive-specific prop names
6
+ // (Solar lineage: `text.size`, `text.colour`), and `repeat` whose template is its
7
+ // only child.
8
+ //
9
+ // This compiler bridges the two formats. It does NOT execute the bundle — it
10
+ // produces a JSON the runtime then renders.
11
+ export function compileBundle(lsml, options = {}) {
12
+ if (lsml.lsml !== "1.0") {
13
+ throw new Error(`compiler: only LSML 1.0 is supported, got ${lsml.lsml}`);
14
+ }
15
+ return {
16
+ scene_version: lsml.scene_version,
17
+ root: compileNode(lsml.layout, options),
18
+ ...(lsml.operator_inputs
19
+ ? {
20
+ operator_inputs: lsml.operator_inputs.map((oi) => ({
21
+ path: oi.path,
22
+ label: oi.label,
23
+ type: oi.type,
24
+ writable_by: oi.writable_by,
25
+ ...(oi.group !== undefined ? { group: oi.group } : {}),
26
+ ...(oi.constraints ?? {}),
27
+ })),
28
+ }
29
+ : {}),
30
+ ...(lsml.external_adapters
31
+ ? {
32
+ external_adapters: lsml.external_adapters,
33
+ }
34
+ : {}),
35
+ };
36
+ }
37
+ function compileNode(node, opts) {
38
+ if (node.kind === "repeat") {
39
+ return compileRepeat(node, opts);
40
+ }
41
+ const props = {};
42
+ const bindings = {};
43
+ // Common: bind.value/src → bindings
44
+ if (node.bind?.value !== undefined)
45
+ bindings["value"] = node.bind.value;
46
+ if (node.bind?.src !== undefined)
47
+ bindings["src"] = node.bind.src;
48
+ if (node.bindStyle) {
49
+ for (const [k, v] of Object.entries(node.bindStyle))
50
+ bindings[k] = v;
51
+ }
52
+ switch (node.kind) {
53
+ case "stack":
54
+ if (node.direction !== undefined)
55
+ props["direction"] = node.direction;
56
+ if (node.gap !== undefined)
57
+ props["gap"] = node.gap;
58
+ if (node.align !== undefined)
59
+ props["align"] = mapAlign(node.align);
60
+ if (node.justify !== undefined)
61
+ props["justify"] = mapJustify(node.justify);
62
+ if (node.padding !== undefined)
63
+ props["padding"] = node.padding;
64
+ if (node.rtl !== undefined)
65
+ props["rtl"] = node.rtl;
66
+ break;
67
+ case "grid":
68
+ if (node.columns !== undefined)
69
+ props["columns"] = node.columns;
70
+ if (node.rows !== undefined)
71
+ props["rows"] = node.rows;
72
+ if (node.gap !== undefined)
73
+ props["gap"] = node.gap;
74
+ if (node.padding !== undefined)
75
+ props["padding"] = node.padding;
76
+ break;
77
+ case "frame":
78
+ if (node.size !== undefined) {
79
+ props["width"] = node.size.w;
80
+ props["height"] = node.size.h;
81
+ }
82
+ if (node.position !== undefined) {
83
+ props["x"] = node.position.x;
84
+ props["y"] = node.position.y;
85
+ }
86
+ if (node.background !== undefined)
87
+ props["background"] = node.background;
88
+ break;
89
+ case "text":
90
+ mapTextStyle(node, props);
91
+ if (node.format !== undefined)
92
+ props["format"] = node.format;
93
+ if (node.maxLines !== undefined)
94
+ props["maxLines"] = node.maxLines;
95
+ break;
96
+ case "image":
97
+ props["alt"] = node.alt;
98
+ props["width"] = node.size.w;
99
+ props["height"] = node.size.h;
100
+ if (node.fit !== undefined)
101
+ props["fit"] = node.fit;
102
+ break;
103
+ case "shape":
104
+ props["geometry"] = node.geometry;
105
+ if (node.size !== undefined) {
106
+ props["width"] = node.size.w;
107
+ props["height"] = node.size.h;
108
+ }
109
+ if (node.pathData !== undefined)
110
+ props["pathData"] = node.pathData;
111
+ if (node.fill !== undefined)
112
+ props["fill"] = node.fill;
113
+ if (node.stroke !== undefined)
114
+ props["stroke"] = node.stroke;
115
+ if (node.cornerRadius !== undefined)
116
+ props["cornerRadius"] = node.cornerRadius;
117
+ if (node.ariaLabel !== undefined)
118
+ props["ariaLabel"] = node.ariaLabel;
119
+ break;
120
+ case "media":
121
+ props["kind_hint"] = node.kind_hint;
122
+ if (node.controls !== undefined)
123
+ props["controls"] = node.controls;
124
+ if (node.autoplay !== undefined)
125
+ props["autoplay"] = node.autoplay;
126
+ if (node.muted !== undefined)
127
+ props["muted"] = node.muted;
128
+ if (node.loop !== undefined)
129
+ props["loop"] = node.loop;
130
+ if (node.size !== undefined) {
131
+ props["width"] = node.size.w;
132
+ props["height"] = node.size.h;
133
+ }
134
+ break;
135
+ }
136
+ const children = node.children?.map((c) => compileNode(c, opts));
137
+ const out = { kind: node.kind };
138
+ if (node.id !== undefined)
139
+ out.id = node.id;
140
+ if (Object.keys(props).length > 0)
141
+ out.props = props;
142
+ if (Object.keys(bindings).length > 0)
143
+ out.bindings = bindings;
144
+ if (children && children.length > 0)
145
+ out.children = children;
146
+ // Animate directive → transitions on the listed prop keys.
147
+ if (node.animate) {
148
+ const tx = compileAnimate(node.animate);
149
+ if (tx) {
150
+ const transitions = {};
151
+ if (node.animate.opacity !== undefined)
152
+ transitions["opacity"] = tx;
153
+ if (node.animate.transform?.scale !== undefined)
154
+ transitions["scale"] = tx;
155
+ if (node.animate.transform?.rotate !== undefined)
156
+ transitions["rotate"] = tx;
157
+ if (node.animate.transform?.translate !== undefined) {
158
+ transitions["x"] = tx;
159
+ transitions["y"] = tx;
160
+ }
161
+ // Type assertion: RenderNode.transitions matches Transition shape; the
162
+ // cast keeps the compiler self-contained without re-importing the runtime
163
+ // Transition type.
164
+ if (Object.keys(transitions).length > 0) {
165
+ out.transitions = transitions;
166
+ }
167
+ }
168
+ }
169
+ return out;
170
+ }
171
+ function compileRepeat(node, opts) {
172
+ if (!node.bind?.items) {
173
+ throw new Error(`compiler: repeat node "${node.id ?? "<anon>"}" missing bind.items`);
174
+ }
175
+ const compiledTemplate = compileNode(node.template, opts);
176
+ const out = {
177
+ kind: "repeat",
178
+ bindings: { items: node.bind.items },
179
+ children: [compiledTemplate],
180
+ };
181
+ if (node.id !== undefined)
182
+ out.id = node.id;
183
+ return out;
184
+ }
185
+ function mapTextStyle(node, props) {
186
+ if (!node.style)
187
+ return;
188
+ const s = node.style;
189
+ // Solar's Text primitive consumes size/weight/colour (UK), not CSS-style names.
190
+ if (s.fontSize !== undefined)
191
+ props["size"] = s.fontSize;
192
+ if (s.fontWeight !== undefined)
193
+ props["weight"] = s.fontWeight;
194
+ if (s.color !== undefined)
195
+ props["colour"] = s.color;
196
+ if (s.textAlign !== undefined)
197
+ props["align"] = mapTextAlign(s.textAlign);
198
+ if (s.lineHeight !== undefined)
199
+ props["lineHeight"] = s.lineHeight;
200
+ }
201
+ function mapAlign(a) {
202
+ // LSML uses CSS-grid vocabulary; Solar's Stack consumes flexbox vocabulary.
203
+ switch (a) {
204
+ case "start":
205
+ return "flex-start";
206
+ case "center":
207
+ return "center";
208
+ case "end":
209
+ return "flex-end";
210
+ case "stretch":
211
+ return "stretch";
212
+ }
213
+ }
214
+ function mapJustify(j) {
215
+ switch (j) {
216
+ case "start":
217
+ return "flex-start";
218
+ case "center":
219
+ return "center";
220
+ case "end":
221
+ return "flex-end";
222
+ case "space-between":
223
+ return "space-between";
224
+ case "space-around":
225
+ return "space-around";
226
+ }
227
+ }
228
+ function mapTextAlign(a) {
229
+ switch (a) {
230
+ case "start":
231
+ return "left";
232
+ case "end":
233
+ return "right";
234
+ default:
235
+ return a;
236
+ }
237
+ }
238
+ function compileAnimate(a) {
239
+ const t = a.transition;
240
+ if (!t)
241
+ return undefined;
242
+ if (t.easing === "spring") {
243
+ const out = { kind: "spring" };
244
+ if (t.stiffness !== undefined)
245
+ out.stiffness = t.stiffness;
246
+ if (t.damping !== undefined)
247
+ out.damping = t.damping;
248
+ return out;
249
+ }
250
+ return {
251
+ kind: "tween",
252
+ duration_ms: t.duration ?? 200,
253
+ ease: mapEase(t.easing),
254
+ };
255
+ }
256
+ function mapEase(e) {
257
+ switch (e) {
258
+ case "linear":
259
+ return "linear";
260
+ case "ease-in":
261
+ return "cubic-in";
262
+ case "ease-out":
263
+ return "cubic-out";
264
+ case "ease-in-out":
265
+ return "cubic-in-out";
266
+ default:
267
+ return undefined;
268
+ }
269
+ }
270
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,sFAAsF;AACtF,mFAAmF;AACnF,+EAA+E;AAC/E,kFAAkF;AAClF,cAAc;AACd,EAAE;AACF,6EAA6E;AAC7E,4CAA4C;AAkB5C,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,UAA0B,EAAE;IAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,6CAA6C,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,eAAe;YACtB,CAAC,CAAC;gBACE,eAAe,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;oBACjD,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,KAAK,EAAE,EAAE,CAAC,KAAK;oBACf,IAAI,EAAE,EAAE,CAAC,IAAa;oBACtB,WAAW,EAAE,EAAE,CAAC,WAAW;oBAC3B,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtD,GAAG,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC;iBAC1B,CAAC,CAAC;aACJ;YACH,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,iBAAiB;YACxB,CAAC,CAAC;gBACE,iBAAiB,EAAE,IAAI,CAAC,iBAAsD;aAC/E;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAc,EAAE,IAAoB;IACvD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,KAAK,GAA4B,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAE5C,oCAAoC;IACpC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS;QAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACxE,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,SAAS;QAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAClE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,OAAO;YACV,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;gBAAE,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;YACtE,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YACpD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpE,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAChE,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YACpD,MAAM;QAER,KAAK,MAAM;YACT,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAChE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YACvD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YACpD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAChE,MAAM;QAER,KAAK,OAAO;YACV,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7B,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAChC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC7B,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;gBAAE,KAAK,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;YACzE,MAAM;QAER,KAAK,MAAM;YACT,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1B,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7D,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAAE,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YACnE,MAAM;QAER,KAAK,OAAO;YACV,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YACxB,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7B,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9B,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;gBAAE,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;YACpD,MAAM;QAER,KAAK,OAAO;YACV,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YAClC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7B,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAAE,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YACnE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YACvD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7D,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;gBAAE,KAAK,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/E,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;gBAAE,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;YACtE,MAAM;QAER,KAAK,OAAO;YACV,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;YACpC,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAAE,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YACnE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAAE,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YACnE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAC1D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YACvD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7B,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,CAAC;YACD,MAAM;IACV,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjE,MAAM,GAAG,GAAe,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS;QAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;IACrD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC9D,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAE7D,2DAA2D;IAC3D,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,WAAW,GAAsD,EAAE,CAAC;YAC1E,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS;gBAAE,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YACpE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,KAAK,SAAS;gBAAE,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YAC3E,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS;gBAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YAC7E,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;gBACpD,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;gBACtB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACxB,CAAC;YACD,uEAAuE;YACvE,0EAA0E;YAC1E,mBAAmB;YACnB,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxC,GAAG,CAAC,WAAW,GAAG,WAAwC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB,EAAE,IAAoB;IAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,EAAE,IAAI,QAAQ,sBAAsB,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,gBAAgB,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAe;QACtB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;QACpC,QAAQ,EAAE,CAAC,gBAAgB,CAAC;KAC7B,CAAC;IACF,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS;QAAE,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5C,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,YAAY,CAAC,IAAc,EAAE,KAA8B;IAClE,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO;IACxB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;IACrB,gFAAgF;IAChF,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACzD,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;IAC/D,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;IACrD,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1E,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;QAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;AACrE,CAAC;AAED,SAAS,QAAQ,CAAC,CAA6D;IAC7E,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,OAAO;YACV,OAAO,YAAY,CAAC;QACtB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,UAAU,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,CAA+D;IACjF,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,OAAO;YACV,OAAO,YAAY,CAAC;QACtB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,UAAU,CAAC;QACpB,KAAK,eAAe;YAClB,OAAO,eAAe,CAAC;QACzB,KAAK,cAAc;YACjB,OAAO,cAAc,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,CAA2D;IAC/E,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,OAAO;YACV,OAAO,MAAM,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,CAAuB;IAQ7C,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;IACvB,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,GAAG,GAA6D,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACzF,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS;YAAE,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;QAC3D,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;YAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;QACrD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,CAAC,CAAC,QAAQ,IAAI,GAAG;QAC9B,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CACd,CAA2E;IAE3E,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,SAAS;YACZ,OAAO,UAAU,CAAC;QACpB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO,cAAc,CAAC;QACxB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { compileBundle, type CompileOptions } from "./compile.js";
2
+ export { canonicalize, hashBundle, ZERO_HASH } from "./canonicalize.js";
3
+ export type { LSMLBundle, LSMLNode, LSMLPrimitiveKind, LSMLBindObject, LSMLAnimateDirective, LSMLStack, LSMLGrid, LSMLFrame, LSMLText, LSMLImage, LSMLShape, LSMLMedia, LSMLRepeat, LSMLOperatorInput, } from "./lsml-types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EACV,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,UAAU,EACV,iBAAiB,GAClB,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // Public surface of @lumencast/compiler.
2
+ export { compileBundle } from "./compile.js";
3
+ export { canonicalize, hashBundle, ZERO_HASH } from "./canonicalize.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,OAAO,EAAE,aAAa,EAAuB,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,152 @@
1
+ export type LSMLPrimitiveKind = "stack" | "grid" | "frame" | "text" | "image" | "shape" | "media" | "repeat";
2
+ export interface LSMLBindObject {
3
+ /** Most primitives bind a `value` to a leaf path. */
4
+ value?: string;
5
+ /** image / media bind a `src`. */
6
+ src?: string;
7
+ /** repeat binds `items`. */
8
+ items?: string;
9
+ }
10
+ export interface LSMLAnimateDirective {
11
+ transition?: {
12
+ duration?: number;
13
+ easing?: "linear" | "ease-in" | "ease-out" | "ease-in-out" | "spring";
14
+ stiffness?: number;
15
+ damping?: number;
16
+ };
17
+ transform?: {
18
+ translate?: [number, number];
19
+ scale?: number | [number, number];
20
+ rotate?: number;
21
+ };
22
+ opacity?: number;
23
+ filter?: {
24
+ blur?: number;
25
+ brightness?: number;
26
+ };
27
+ }
28
+ export interface LSMLBaseNode {
29
+ kind: LSMLPrimitiveKind;
30
+ id?: string;
31
+ bind?: LSMLBindObject;
32
+ bindStyle?: Record<string, string>;
33
+ animate?: LSMLAnimateDirective;
34
+ children?: LSMLNode[];
35
+ }
36
+ export interface LSMLStack extends LSMLBaseNode {
37
+ kind: "stack";
38
+ direction?: "horizontal" | "vertical";
39
+ gap?: number;
40
+ align?: "start" | "center" | "end" | "stretch";
41
+ justify?: "start" | "center" | "end" | "space-between" | "space-around";
42
+ padding?: number | [number, number, number, number];
43
+ rtl?: "auto" | boolean;
44
+ }
45
+ export interface LSMLGrid extends LSMLBaseNode {
46
+ kind: "grid";
47
+ columns: number | unknown[];
48
+ rows?: number | unknown[];
49
+ gap?: number | [number, number];
50
+ padding?: number | unknown[];
51
+ }
52
+ export interface LSMLFrame extends LSMLBaseNode {
53
+ kind: "frame";
54
+ size?: {
55
+ w: number;
56
+ h: number;
57
+ };
58
+ position?: {
59
+ x: number;
60
+ y: number;
61
+ };
62
+ background?: string;
63
+ }
64
+ export interface LSMLText extends LSMLBaseNode {
65
+ kind: "text";
66
+ style?: {
67
+ fontSize?: number | string;
68
+ fontWeight?: number;
69
+ color?: string;
70
+ textAlign?: "start" | "center" | "end" | "left" | "right";
71
+ lineHeight?: number;
72
+ };
73
+ format?: {
74
+ kind: string;
75
+ [extra: string]: unknown;
76
+ };
77
+ maxLines?: number;
78
+ }
79
+ export interface LSMLImage extends LSMLBaseNode {
80
+ kind: "image";
81
+ alt: string;
82
+ size: {
83
+ w: number;
84
+ h: number;
85
+ };
86
+ fit?: "contain" | "cover" | "fill" | "none";
87
+ }
88
+ export interface LSMLShape extends LSMLBaseNode {
89
+ kind: "shape";
90
+ geometry: "rect" | "circle" | "path";
91
+ size?: {
92
+ w: number;
93
+ h: number;
94
+ };
95
+ pathData?: string;
96
+ fill?: string;
97
+ stroke?: {
98
+ color: string;
99
+ width: number;
100
+ };
101
+ cornerRadius?: number;
102
+ ariaLabel?: string;
103
+ }
104
+ export interface LSMLMedia extends LSMLBaseNode {
105
+ kind: "media";
106
+ kind_hint: "video" | "audio";
107
+ controls?: boolean;
108
+ autoplay?: boolean;
109
+ muted?: boolean;
110
+ loop?: boolean;
111
+ size?: {
112
+ w: number;
113
+ h: number;
114
+ };
115
+ }
116
+ export interface LSMLRepeat extends LSMLBaseNode {
117
+ kind: "repeat";
118
+ scope: string;
119
+ key?: string;
120
+ template: LSMLNode;
121
+ limit?: number;
122
+ }
123
+ export type LSMLNode = LSMLStack | LSMLGrid | LSMLFrame | LSMLText | LSMLImage | LSMLShape | LSMLMedia | LSMLRepeat;
124
+ export interface LSMLOperatorInput {
125
+ path: string;
126
+ label: string;
127
+ type: string;
128
+ constraints?: Record<string, unknown>;
129
+ writable_by: string[];
130
+ group?: string;
131
+ [extra: string]: unknown;
132
+ }
133
+ export interface LSMLBundle {
134
+ lsml: "1.0";
135
+ scene_id: string;
136
+ scene_version: string;
137
+ layout: LSMLNode;
138
+ operator_inputs?: LSMLOperatorInput[];
139
+ external_adapters?: unknown[];
140
+ defaults?: Record<string, unknown>;
141
+ assets?: {
142
+ allowedHosts?: string[];
143
+ fonts?: unknown[];
144
+ preload?: string[];
145
+ };
146
+ i18n?: {
147
+ default_locale?: string;
148
+ locales?: Record<string, Record<string, string>>;
149
+ };
150
+ metadata?: Record<string, unknown>;
151
+ }
152
+ //# sourceMappingURL=lsml-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsml-types.d.ts","sourceRoot":"","sources":["../src/lsml-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ // LSML 1.0 input types — what authors write.
2
+ // Reference: lumencast-protocol/spec/LSML-1.md
3
+ export {};
4
+ //# sourceMappingURL=lsml-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsml-types.js","sourceRoot":"","sources":["../src/lsml-types.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,+CAA+C"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@lumencast/compiler",
3
+ "version": "0.1.0",
4
+ "description": "LSML 1.0 → flat RenderBundle compiler. Lets authors write idiomatic LSML and feed it to @lumencast/runtime.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src"
19
+ ],
20
+ "homepage": "https://github.com/Lumencast/lumencast-js/tree/main/packages/compiler",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/Lumencast/lumencast-js.git",
24
+ "directory": "packages/compiler"
25
+ },
26
+ "engines": {
27
+ "node": ">=22"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "registry": "https://registry.npmjs.org/"
32
+ },
33
+ "dependencies": {
34
+ "@lumencast/protocol": "0.1.0",
35
+ "@lumencast/runtime": "0.1.0"
36
+ },
37
+ "devDependencies": {
38
+ "vitest": "^4.1.5"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -b",
42
+ "typecheck": "tsc -b --pretty",
43
+ "test": "vitest run"
44
+ }
45
+ }
@@ -0,0 +1,64 @@
1
+ // Canonical JSON form per LSML 1.0 §3 — deterministic stringification used for
2
+ // content-addressing scenes by sha256.
3
+ //
4
+ // Rules:
5
+ // 1. UTF-8 encoding (handled by Node's default)
6
+ // 2. Object keys sorted lexicographically at every nesting level
7
+ // 3. No insignificant whitespace (no newlines/tabs)
8
+ // 4. Numbers in shortest decimal form (JSON.stringify default)
9
+ // 5. The `scene_version` field MUST be set to all-zeros during hashing,
10
+ // then replaced with `sha256:<hash>`.
11
+
12
+ export const ZERO_HASH = "sha256:" + "0".repeat(64);
13
+
14
+ export function canonicalize(value: unknown): string {
15
+ return stringify(value);
16
+ }
17
+
18
+ /** Compute the sha256 content hash of a bundle, then return a copy with
19
+ * `scene_version` set to that hash. Uses Node's built-in `crypto.subtle`
20
+ * (Node ≥ 18) or the browser's `window.crypto.subtle`. */
21
+ export async function hashBundle<T extends { scene_version: string }>(bundle: T): Promise<T> {
22
+ const stub = { ...bundle, scene_version: ZERO_HASH };
23
+ const canonical = canonicalize(stub);
24
+ const bytes = new TextEncoder().encode(canonical);
25
+ const subtle = getSubtle();
26
+ const digest = await subtle.digest("SHA-256", bytes);
27
+ const hex = bytesToHex(new Uint8Array(digest));
28
+ return { ...bundle, scene_version: `sha256:${hex}` };
29
+ }
30
+
31
+ function stringify(v: unknown): string {
32
+ if (v === null) return "null";
33
+ if (typeof v === "boolean" || typeof v === "number") return JSON.stringify(v);
34
+ if (typeof v === "string") return JSON.stringify(v);
35
+ if (Array.isArray(v)) {
36
+ return "[" + v.map(stringify).join(",") + "]";
37
+ }
38
+ if (typeof v === "object") {
39
+ const obj = v as Record<string, unknown>;
40
+ const keys = Object.keys(obj).sort();
41
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stringify(obj[k])).join(",") + "}";
42
+ }
43
+ // undefined / function / symbol — JSON has no representation; drop.
44
+ return "null";
45
+ }
46
+
47
+ function bytesToHex(bytes: Uint8Array): string {
48
+ let s = "";
49
+ for (const b of bytes) s += b.toString(16).padStart(2, "0");
50
+ return s;
51
+ }
52
+
53
+ interface SubtleLike {
54
+ digest(algorithm: "SHA-256", data: Uint8Array): Promise<ArrayBuffer>;
55
+ }
56
+
57
+ function getSubtle(): SubtleLike {
58
+ // Node ≥ 18 exposes crypto.subtle on globalThis; browsers via window.crypto.
59
+ const c = (globalThis as unknown as { crypto?: { subtle?: SubtleLike } }).crypto;
60
+ if (!c?.subtle) {
61
+ throw new Error("compiler: crypto.subtle not available — Node >= 18 or browser required");
62
+ }
63
+ return c.subtle;
64
+ }