@vesk/compiler 0.2.50-canary.9 → 0.2.51

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.
@@ -1,8 +1,15 @@
1
- import { StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, ForLoop, TrackDecl, RuntimeStatement, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
1
+ import { Expression, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, ForLoop, TrackDecl, RuntimeStatement, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
2
2
  import { isStaticIR, collectTrackedNames, transformTracked, transformTrackedInit, semicolonizeStatement } from '@vesk/compiler/src/client-codegen';
3
- import { unwrapTrackCall, stripTrackGeneric, hasTopLevelComma, skipWhitespace, findBalancedEnd, startsWithIdentifier } from '@vesk/compiler/src/scan';
4
- import { escapeHtml, indent, exprJS, extractTopLevelNames, extractRuntimeNames, buildParamInit, __vskHydrate, __vskMarkerless, __vskImportedNames, setVskImportedNames, setVskForceClaim, takeVskForceClaim, nextVskId, } from '@vesk/compiler/src/server-utils';
3
+ import { unwrapTrackCall, stripTrackGeneric, hasTopLevelComma, skipWhitespace, findBalancedEnd, startsWithIdentifier, callsIdentifier } from '@vesk/compiler/src/scan';
4
+ import { escapeHtml, indent, exprJS, extractTopLevelNames, extractRuntimeNames, buildParamInit, VOID_ELEMENTS, __vskHydrate, __vskMarkerless, __vskImportedNames, setVskImportedNames, setVskForceClaim, takeVskForceClaim, nextVskId, } from '@vesk/compiler/src/server-utils';
5
5
  import { localValueImportNames } from '@vesk/compiler/src/module-imports';
6
+ import { lowerJsxInExpression } from '@vesk/compiler/src/server-jsx-lowering';
7
+ import { print } from 'esrap';
8
+ import tsPrinter from 'esrap/languages/ts';
9
+ /** Print an already-lowered AST with the plain TS printer (no JSX remains). */
10
+ function printLoweredTs(ast) {
11
+ return print(ast, tsPrinter()).code;
12
+ }
6
13
  import { vskImportValueNames } from '@vesk/compiler/src/vsk-imports';
7
14
  // Hydrate-mode component-boundary wrapper. Each server-rendered component call
8
15
  // is preceded by a `<!--vsk-->` marker and a single container element: the
@@ -45,7 +52,7 @@ function componentMarker(compName) {
45
52
  export function irNodeToJS(node, importedNames, isAsync = false, tracked) {
46
53
  importedNames = importedNames || __vskImportedNames;
47
54
  if (node instanceof StaticNode)
48
- return staticNodeToJS(node, isAsync, tracked);
55
+ return staticNodeToJS(node, isAsync, tracked, __inForeignContent);
49
56
  if (node instanceof TextNode) {
50
57
  if (!node.value)
51
58
  return '';
@@ -107,8 +114,17 @@ export function irNodeToJS(node, importedNames, isAsync = false, tracked) {
107
114
  `})();`,
108
115
  ].join('\n');
109
116
  }
110
- if (node instanceof RuntimeStatement)
117
+ if (node instanceof RuntimeStatement) {
118
+ const stmt = node;
119
+ const lowered = stmt.ast ? lowerJsxInExpression(stmt.ast) : null;
120
+ if (lowered && lowered !== stmt.ast && (tracked?.size ?? 0) === 0) {
121
+ return semicolonizeStatement(printLoweredTs(lowered));
122
+ }
123
+ if (lowered && lowered !== stmt.ast) {
124
+ return semicolonizeStatement(transformTracked({ ...node, ast: lowered }, tracked || new Map()));
125
+ }
111
126
  return semicolonizeStatement(transformTracked(node, tracked || new Map()));
127
+ }
112
128
  if (node instanceof SlotNode) {
113
129
  // Markerless mode drops the slot boundary comments: SSR output is plain
114
130
  // HTML and slot claims scope structurally (createLayoutSlot subject to the
@@ -133,9 +149,32 @@ function isEvent(target) {
133
149
  return !!target && target.startsWith('on') && target.length > 2;
134
150
  }
135
151
  function exprJSX(node, tracked) {
136
- return exprJS(transformTracked(node, tracked || new Map()));
152
+ // A function-valued child — `<For each={items}>{(item) => <li/>}</For>` —
153
+ // carries JSX inside an EXPRESSION, and the server has no IR node for it, so
154
+ // it used to be printed verbatim and the render threw "Unexpected token '<'".
155
+ // Lower it to the string the body emitter would have produced. Client output
156
+ // is untouched (a chunk goes through esbuild's tsx loader, so JSX is legal
157
+ // there).
158
+ const lowered = node.ast ? lowerJsxInExpression(node.ast) : null;
159
+ const didLower = lowered !== node.ast;
160
+ if (didLower && (tracked?.size ?? 0) === 0) {
161
+ // `transformTracked` returns the RAW source when there is nothing to
162
+ // rewrite, which would throw the lowering away. With no tracked names there
163
+ // are no rewrites to lose.
164
+ return exprJS(printLoweredTs(lowered));
165
+ }
166
+ return exprJS(transformTracked({ ...node, ast: lowered }, tracked || new Map()));
137
167
  }
138
- function staticNodeToJS(node, isAsync = false, tracked) {
168
+ /**
169
+ * True while emitting inside `<svg>`/`<math>`, where self-closing syntax is
170
+ * part of the content model rather than ignored. Module-level because the
171
+ * emitter already recurses through `irNodeToJS`, and threading a context
172
+ * parameter through every call site would touch a dozen emitters that have no
173
+ * interest in it.
174
+ */
175
+ let __inForeignContent = false;
176
+ const FOREIGN_ROOTS = new Set(['svg', 'math']);
177
+ function staticNodeToJS(node, isAsync = false, tracked, inForeign = false) {
139
178
  const lines = [];
140
179
  const dynAttrTargets = new Set();
141
180
  for (const child of node.children) {
@@ -169,18 +208,31 @@ function staticNodeToJS(node, isAsync = false, tracked) {
169
208
  }
170
209
  }
171
210
  if (node.selfClosing) {
172
- let tag = openTag + ' />';
211
+ const voidOrForeign = VOID_ELEMENTS.has(node.tag) || inForeign;
212
+ // A self-closing JSX element is NOT a self-closing HTML element. The HTML
213
+ // parser ignores the trailing slash on anything that is not a void element,
214
+ // so `<div class="dot" />` opens a `<div>` and every following sibling
215
+ // becomes its child — the served document's structure silently diverges
216
+ // from the client's, which builds a real element with `createElement`.
217
+ // Void elements keep `/>`, and so does anything inside `<svg>`/`<math>`,
218
+ // where self-closing syntax IS part of the content model.
219
+ const tail = voidOrForeign ? ' />' : `></${node.tag}>`;
173
220
  if (hasDynamicAttrs) {
174
- let expr = JSON.stringify(tag);
221
+ // Dynamic attributes must land INSIDE the open tag. They used to be
222
+ // appended after it — `<img /> src="..."` — which made the parser drop
223
+ // them, so `<div style={{ backgroundColor: accent }} />` served with no
224
+ // `style` at all and the colour silently vanished.
225
+ let expr = JSON.stringify(openTag);
175
226
  for (const child of node.children) {
176
227
  if (child instanceof DynamicBinding && child.kind === 'attribute' && child.target !== 'ref' && !isEvent(child.target)) {
177
228
  expr += ` + __attr(${JSON.stringify(child.target)}, ${exprJSX(child.expression, tracked)})`;
178
229
  }
179
230
  }
231
+ expr += ` + ${JSON.stringify(tail)}`;
180
232
  lines.push(`__out.push(${expr});`);
181
233
  }
182
234
  else {
183
- lines.push(`__out.push(${JSON.stringify(tag)});`);
235
+ lines.push(`__out.push(${JSON.stringify(openTag + tail)});`);
184
236
  }
185
237
  return lines.join('\n');
186
238
  }
@@ -198,11 +250,15 @@ function staticNodeToJS(node, isAsync = false, tracked) {
198
250
  else {
199
251
  lines.push(`__out.push(${JSON.stringify(openTag + '>')});`);
200
252
  }
253
+ const prevForeign = __inForeignContent;
254
+ if (FOREIGN_ROOTS.has(node.tag))
255
+ __inForeignContent = true;
201
256
  for (const child of childNodes) {
202
257
  const code = irNodeToJS(child, null, isAsync, tracked);
203
258
  if (code)
204
259
  lines.push(code);
205
260
  }
261
+ __inForeignContent = prevForeign;
206
262
  lines.push(`__out.push(${JSON.stringify('</' + node.tag + '>')});`);
207
263
  return lines.join('\n');
208
264
  }
@@ -461,19 +517,35 @@ function componentCallToJS(node, importedNames, isAsync = false, tracked) {
461
517
  }
462
518
  }
463
519
  if (regularChildren.length > 0) {
464
- const childLines = [];
465
- for (const child of regularChildren) {
466
- const code = irNodeToJS(child, importedNames, isAsync, tracked);
467
- if (code)
468
- childLines.push(code);
520
+ // A single function-valued child (`<For each={items}>{(item) => …}</For>`,
521
+ // or a reference to one) must stay a FUNCTION: `For` calls it per item.
522
+ // Wrapping it in the `(() => { const __out = []; … })()` text emitter made it
523
+ // return undefined, so For rendered an empty list.
524
+ const fnType = regularChildren.length === 1 && regularChildren[0] instanceof DynamicBinding && regularChildren[0].kind === 'text'
525
+ ? regularChildren[0].expression.ast?.type
526
+ : null;
527
+ const isFnChild = fnType === 'ArrowFunctionExpression'
528
+ || fnType === 'FunctionExpression'
529
+ || fnType === 'Identifier'
530
+ || fnType === 'MemberExpression';
531
+ if (isFnChild) {
532
+ propsEntries.push(`children: ${exprJSX(regularChildren[0].expression, tracked)}`);
469
533
  }
470
- if (childLines.length > 0) {
471
- const childrenVar = `__ch${nextVskId()}`;
472
- propsEntries.push(`children: ${childrenVar}`);
473
- lines.push(`const ${childrenVar} = ${isAsync ? 'await (async ' : '('}() => {`);
474
- lines.push(`const __out = [];`);
475
- lines.push(indent(childLines.join('\n')));
476
- lines.push(`return __out.join(''); })();`);
534
+ else {
535
+ const childLines = [];
536
+ for (const child of regularChildren) {
537
+ const code = irNodeToJS(child, importedNames, isAsync, tracked);
538
+ if (code)
539
+ childLines.push(code);
540
+ }
541
+ if (childLines.length > 0) {
542
+ const childrenVar = `__ch${nextVskId()}`;
543
+ propsEntries.push(`children: ${childrenVar}`);
544
+ lines.push(`const ${childrenVar} = ${isAsync ? 'await (async ' : '('}() => {`);
545
+ lines.push(`const __out = [];`);
546
+ lines.push(indent(childLines.join('\n')));
547
+ lines.push(`return __out.join(''); })();`);
548
+ }
477
549
  }
478
550
  }
479
551
  const propsObj = `{ ${propsEntries.join(', ')} }`;
@@ -503,10 +575,10 @@ function componentCallToJS(node, importedNames, isAsync = false, tracked) {
503
575
  }
504
576
  const callExpr = `${awaitKw}${calleeVar}(${propsObj}, __registry, (${calleeVar}.__veskScope || __vesk))`;
505
577
  if (__vskHydrate && !__vskMarkerless) {
506
- lines.push(`__out.push(${JSON.stringify(componentMarker(compName))} + (${callExpr} || ''));`);
578
+ lines.push(`__out.push(${JSON.stringify(componentMarker(compName))} + __flat(${callExpr}));`);
507
579
  }
508
580
  else {
509
- lines.push(`__out.push(${callExpr} || '');`);
581
+ lines.push(`__out.push(__flat(${callExpr}));`);
510
582
  }
511
583
  return lines.join('\n');
512
584
  }
@@ -524,6 +596,9 @@ export function generateFunctionBody(comp, importedNames) {
524
596
  lines.push(`const __styleText = (v) => { if (typeof v === 'string') return v; if (v && typeof v === 'object') { let s = ''; for (const k in v) { const x = v[k]; if (x == null || x === false) continue; s += k.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()) + ':' + x + ';'; } return s; } return String(v); };`);
525
597
  lines.push(`const __attr = (n, v) => (v == null || v === false) ? '' : ' ' + n + '="' + __escape(n === 'style' ? __styleText(v) : String(v)) + '"';`);
526
598
  lines.push(`const raw = (s) => s == null ? '' : String(s);`);
599
+ // A component may return an ARRAY of strings (`<For>` maps its children), and
600
+ // `Array#toString` joins the rows with commas — `<li>a</li>,<li>b</li>`.
601
+ lines.push(`const __flat = (v) => Array.isArray(v) ? v.join('') : (v == null ? '' : String(v));`);
527
602
  lines.push(`const __tk = globalThis.__vsk_ssr_token || '';`);
528
603
  if (asyncMode) {
529
604
  lines.push(`const __pk = __tk ? '__vsk_ssr_promises_' + __tk : '__vsk_ssr_promises';`);
@@ -563,6 +638,105 @@ export function generateFunctionBody(comp, importedNames) {
563
638
  __currentCompName = '';
564
639
  return lines.join('\n');
565
640
  }
641
+ /**
642
+ * Whether a component body needs `track` / `get` / `set` destructured into its
643
+ * `__vesk` scope.
644
+ *
645
+ * A `TrackDecl` (`const &[n] = track(0)`) always needs them. A PLAIN
646
+ * `const n = track(0)` does not lower to a TrackDecl — it stays a raw
647
+ * `RuntimeStatement` whose source still calls `track` — and used to reach the
648
+ * server renderer unbound, taking the whole page down with
649
+ * "track is not defined". The client codegen imports these names
650
+ * unconditionally, so the server has to recognise the plain form too or the
651
+ * two halves of a file disagree about what is in scope.
652
+ */
653
+ function bodyNeedsRuntimeCells(nodes) {
654
+ for (const node of nodes) {
655
+ if (node instanceof TrackDecl)
656
+ return true;
657
+ // Raw statement / expression text: the only place a plain `track(...)`
658
+ // call can appear outside a lowered node.
659
+ if (node instanceof RuntimeStatement && callsIdentifier(node.raw, 'track'))
660
+ return true;
661
+ if (node instanceof Expression && callsIdentifier(node.raw, 'track'))
662
+ return true;
663
+ if (node instanceof ForLoop) {
664
+ if (callsIdentifier(node.init, 'track'))
665
+ return true;
666
+ if (callsIdentifier(node.update, 'track'))
667
+ return true;
668
+ if (callsIdentifier(node.condition.raw, 'track'))
669
+ return true;
670
+ if (bodyNeedsRuntimeCells(node.bodyTemplate))
671
+ return true;
672
+ }
673
+ if (node instanceof StaticNode) {
674
+ for (const attr of node.attributes) {
675
+ if (callsIdentifier(attr.value, 'track'))
676
+ return true;
677
+ }
678
+ if (bodyNeedsRuntimeCells(node.children))
679
+ return true;
680
+ }
681
+ if (node instanceof ComponentCall) {
682
+ for (const prop of node.props) {
683
+ if (callsIdentifier(prop.value.raw, 'track'))
684
+ return true;
685
+ }
686
+ for (const spread of node.spreadProps) {
687
+ if (callsIdentifier(spread.raw, 'track'))
688
+ return true;
689
+ }
690
+ if (bodyNeedsRuntimeCells(node.children))
691
+ return true;
692
+ }
693
+ if (node instanceof ServerBlock || node instanceof ClientBlock || node instanceof HeadBlock) {
694
+ if (bodyNeedsRuntimeCells(node.children))
695
+ return true;
696
+ }
697
+ if (node instanceof PropSlot && bodyNeedsRuntimeCells(node.body))
698
+ return true;
699
+ if (node instanceof MapRegion) {
700
+ if (callsIdentifier(node.expression.raw, 'track'))
701
+ return true;
702
+ if (bodyNeedsRuntimeCells(node.bodyTemplate))
703
+ return true;
704
+ if (bodyNeedsRuntimeCells(node.alternateNodes))
705
+ return true;
706
+ }
707
+ if (node instanceof OpaqueDynamicRegion) {
708
+ if (callsIdentifier(node.condition.raw, 'track'))
709
+ return true;
710
+ if (bodyNeedsRuntimeCells(node.consequentNodes))
711
+ return true;
712
+ if (bodyNeedsRuntimeCells(node.alternateNodes))
713
+ return true;
714
+ }
715
+ if (node instanceof WhileLoop) {
716
+ if (callsIdentifier(node.condition.raw, 'track'))
717
+ return true;
718
+ if (bodyNeedsRuntimeCells(node.bodyTemplate))
719
+ return true;
720
+ }
721
+ if (node instanceof SwitchBlock) {
722
+ if (callsIdentifier(node.discriminant.raw, 'track'))
723
+ return true;
724
+ for (const c of node.cases) {
725
+ if (c.test && callsIdentifier(c.test.raw, 'track'))
726
+ return true;
727
+ if (bodyNeedsRuntimeCells(c.body))
728
+ return true;
729
+ }
730
+ }
731
+ if (node instanceof TryCatch) {
732
+ if (bodyNeedsRuntimeCells(node.bodyTemplate))
733
+ return true;
734
+ if (bodyNeedsRuntimeCells(node.catchBody))
735
+ return true;
736
+ }
737
+ }
738
+ return false;
739
+ }
566
740
  /**
567
741
  * Builds the compiled body source for every component in an IR root. Used by
568
742
  * both `buildComponentMap` (live functions) and `precompile.ts` (AOT SSR plans
@@ -579,7 +753,7 @@ export function buildComponentEntries(irRoot) {
579
753
  const componentNames = new Set(irRoot.components.map((c) => c.name));
580
754
  const topValueNames = topNames.filter((n) => !componentNames.has(n));
581
755
  const importedNames = new Set([...runtimeNames, ...localValueNames, ...topValueNames]);
582
- const hasTracked = irRoot.components.some((c) => c.body.some((n) => n instanceof TrackDecl));
756
+ const hasTracked = irRoot.components.some((c) => bodyNeedsRuntimeCells(c.body));
583
757
  const extraNames = hasTracked ? ['get', 'set', 'track'] : [];
584
758
  // Values exported by a `.vsk` module (`export const MAX = 10`) are hoisted
585
759
  // into this file's `__vesk` and must be destructured into component scope.
@@ -0,0 +1,16 @@
1
+ /** True when `node` contains JSX anywhere. */
2
+ export declare function containsJsx(node: unknown, depth?: number): boolean;
3
+ declare const RAW = "__raw";
4
+ /**
5
+ * JSX text semantics, matching what the compiler emits for StaticNode text:
6
+ * lines are trimmed, blank lines vanish, and interior newlines collapse to a
7
+ * single space. Getting this wrong is visible as stray whitespace in SSR HTML.
8
+ */
9
+ export declare function normalizeJsxText(value: string): string;
10
+ /**
11
+ * Rewrite every JSX node inside `ast` into the string it would have rendered.
12
+ * Returns the original node when there is no JSX, so the common path is free.
13
+ */
14
+ export declare function lowerJsxInExpression(ast: unknown): unknown;
15
+ export { RAW as RAW_HELPER };
16
+ //# sourceMappingURL=server-jsx-lowering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-jsx-lowering.d.ts","sourceRoot":"","sources":["../src/server-jsx-lowering.ts"],"names":[],"mappings":"AAwBA,8CAA8C;AAC9C,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,OAAO,CAa7D;AAKD,QAAA,MAAM,GAAG,UAAU,CAAC;AAEpB;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBtD;AAiLD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG1D;AAED,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,CAAC"}
@@ -0,0 +1,226 @@
1
+ /** True when `node` contains JSX anywhere. */
2
+ export function containsJsx(node, depth = 0) {
3
+ if (!node || typeof node !== 'object' || depth > 40)
4
+ return false;
5
+ if (Array.isArray(node)) {
6
+ for (const item of node)
7
+ if (containsJsx(item, depth + 1))
8
+ return true;
9
+ return false;
10
+ }
11
+ const type = node.type;
12
+ if (type === 'JSXElement' || type === 'JSXFragment')
13
+ return true;
14
+ for (const key of Object.keys(node)) {
15
+ const value = node[key];
16
+ if (value && typeof value === 'object' && containsJsx(value, depth + 1))
17
+ return true;
18
+ }
19
+ return false;
20
+ }
21
+ /** The helper names the generated server body already defines. */
22
+ const ESCAPE = '__escape';
23
+ const ATTR = '__attr';
24
+ const RAW = '__raw';
25
+ /**
26
+ * JSX text semantics, matching what the compiler emits for StaticNode text:
27
+ * lines are trimmed, blank lines vanish, and interior newlines collapse to a
28
+ * single space. Getting this wrong is visible as stray whitespace in SSR HTML.
29
+ */
30
+ export function normalizeJsxText(value) {
31
+ const lines = value.split(/\r\n|\n|\r/);
32
+ let lastNonEmpty = -1;
33
+ for (let i = 0; i < lines.length; i++) {
34
+ if (/[^ \t]/.test(lines[i]))
35
+ lastNonEmpty = i;
36
+ }
37
+ let out = '';
38
+ for (let i = 0; i < lines.length; i++) {
39
+ let line = lines[i].replace(/\t/g, ' ');
40
+ if (i !== 0)
41
+ line = line.replace(/^ +/, '');
42
+ if (i !== lines.length - 1)
43
+ line = line.replace(/ +$/, '');
44
+ if (line) {
45
+ if (i !== lastNonEmpty)
46
+ line += ' ';
47
+ out += line;
48
+ }
49
+ }
50
+ return out;
51
+ }
52
+ function lower(node, ctx) {
53
+ if (Array.isArray(node))
54
+ return node.map((n) => lower(n, ctx));
55
+ if (!node || typeof node !== 'object')
56
+ return node;
57
+ const n = node;
58
+ if (n.type === 'JSXElement') {
59
+ const opening = n.openingElement;
60
+ const name = jsxTagName(opening.name);
61
+ const attrs = lowerAttributes(opening.attributes, ctx);
62
+ const children = lowerChildren(n.children, ctx);
63
+ // statics[0] opens the tag, attributes interleave, then '>', then children,
64
+ // then the closing tag. Getting the '>' placement wrong silently produced
65
+ // `<lia</li>` — a tag that never closes and swallows the next element.
66
+ const statics = [`<${name}`, ...attrs.statics.slice(1)];
67
+ statics[statics.length - 1] += '>';
68
+ const quasis = [...statics, `</${name}>`];
69
+ const expressions = [...attrs.exprs, ...children];
70
+ return template(quasis, expressions);
71
+ }
72
+ if (n.type === 'JSXFragment') {
73
+ return template(['', ''], lowerChildren(n.children, ctx));
74
+ }
75
+ // Any other node: rebuild it with lowered children.
76
+ const out = {};
77
+ for (const key of Object.keys(n)) {
78
+ if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range') {
79
+ out[key] = n[key];
80
+ continue;
81
+ }
82
+ const value = n[key];
83
+ out[key] = value && typeof value === 'object' ? lower(value, ctx) : value;
84
+ }
85
+ return out;
86
+ }
87
+ function jsxTagName(nameNode) {
88
+ const n = nameNode;
89
+ if (!n)
90
+ return 'div';
91
+ if (n.type === 'JSXIdentifier')
92
+ return String(n.name);
93
+ if (n.type === 'JSXMemberExpression') {
94
+ const object = jsxTagName(n.object);
95
+ const property = n.property;
96
+ return `${object}.${String(property?.name)}`;
97
+ }
98
+ if (n.type === 'JSXNamespacedName') {
99
+ const ns = n.namespace;
100
+ const name = n.name;
101
+ return `${String(ns?.name)}:${String(name?.name)}`;
102
+ }
103
+ return 'div';
104
+ }
105
+ function lowerAttributes(attrs, ctx) {
106
+ const statics = [''];
107
+ const exprs = [];
108
+ const push = (text, expr) => {
109
+ if (expr === undefined) {
110
+ statics[statics.length - 1] += text;
111
+ return;
112
+ }
113
+ statics[statics.length - 1] += text;
114
+ statics.push('');
115
+ exprs.push(expr);
116
+ };
117
+ for (const attr of attrs || []) {
118
+ const a = attr;
119
+ if (a.type === 'JSXSpreadAttribute') {
120
+ // A spread inside a function-valued child is not lowered; dropping it
121
+ // would be silently wrong, so it is reported instead.
122
+ console.error('[vesk] a spread attribute in a JSX expression is not supported yet (dropped):', String(a.argument ?? '').slice(0, 60));
123
+ continue;
124
+ }
125
+ const name = jsxAttrName(a.name);
126
+ const value = a.value;
127
+ if (value === null || value === undefined) {
128
+ push(` ${name}`);
129
+ continue;
130
+ }
131
+ if (value.type === 'StringLiteral') {
132
+ push(` ${name}="${escapeAttrText(String(value.value))}"`);
133
+ continue;
134
+ }
135
+ if (value.type === 'JSXExpressionContainer') {
136
+ const inner = value.expression;
137
+ if (!inner || inner.type === 'JSXEmptyExpression') {
138
+ push(` ${name}="true"`);
139
+ continue;
140
+ }
141
+ push(` ${name}="`, callNode(ATTR, [literal(name), coerceString(lower(inner, ctx))]));
142
+ push('"');
143
+ continue;
144
+ }
145
+ push(` ${name}="`, callNode(ATTR, [literal(name), coerceString(lower(value, ctx))]));
146
+ push('"');
147
+ }
148
+ return { statics, exprs };
149
+ }
150
+ function jsxAttrName(nameNode) {
151
+ const n = nameNode;
152
+ if (!n)
153
+ return 'data';
154
+ if (n.type === 'JSXIdentifier')
155
+ return String(n.name);
156
+ return jsxTagName(n);
157
+ }
158
+ function lowerChildren(children, ctx) {
159
+ const out = [];
160
+ for (const child of children || []) {
161
+ const c = child;
162
+ if (c.type === 'JSXText') {
163
+ const text = normalizeJsxText(String(c.value ?? ''));
164
+ if (text)
165
+ out.push(literal(text));
166
+ continue;
167
+ }
168
+ if (c.type === 'JSXExpressionContainer') {
169
+ const inner = c.expression;
170
+ if (!inner || inner.type === 'JSXEmptyExpression')
171
+ continue;
172
+ const lowered = lower(inner, ctx);
173
+ out.push(coerceString(lowered));
174
+ continue;
175
+ }
176
+ const lowered = lower(c, ctx);
177
+ out.push(coerceString(lowered));
178
+ }
179
+ return out;
180
+ }
181
+ /** `{v}` in HTML output must be escaped, exactly as the body emitter does. */
182
+ function coerceString(node) {
183
+ if (!node || typeof node !== 'object')
184
+ return callNode(ESCAPE, [literal(String(node))]);
185
+ const n = node;
186
+ // Already a template literal we built: its parts are static text, but any
187
+ // expression inside came from a nested container that escaped itself.
188
+ if (n.type === 'TemplateLiteral')
189
+ return n;
190
+ if (n.type === 'Literal' || n.type === 'StringLiteral')
191
+ return callNode(ESCAPE, [node]);
192
+ return callNode(ESCAPE, [callNode('String', [node])]);
193
+ }
194
+ /** Assemble a template literal: `statics.length === expressions.length + 1`. */
195
+ function template(statics, expressions) {
196
+ const quasis = statics.map((raw, i) => ({
197
+ type: 'TemplateElement',
198
+ value: { raw },
199
+ tail: i === statics.length - 1,
200
+ }));
201
+ return { type: 'TemplateLiteral', quasis, expressions };
202
+ }
203
+ function literal(value) {
204
+ return { type: 'Literal', value };
205
+ }
206
+ function callNode(callee, args) {
207
+ return {
208
+ type: 'CallExpression',
209
+ callee: { type: 'Identifier', name: callee },
210
+ arguments: args,
211
+ optional: false,
212
+ };
213
+ }
214
+ function escapeAttrText(value) {
215
+ return value.split('&').join('&amp;').split('<').join('&lt;').split('>').join('&gt;').split('"').join('&quot;');
216
+ }
217
+ /**
218
+ * Rewrite every JSX node inside `ast` into the string it would have rendered.
219
+ * Returns the original node when there is no JSX, so the common path is free.
220
+ */
221
+ export function lowerJsxInExpression(ast) {
222
+ if (!containsJsx(ast))
223
+ return ast;
224
+ return lower(ast, { track: false });
225
+ }
226
+ export { RAW as RAW_HELPER };
@@ -1,4 +1,5 @@
1
1
  import type { IRNode } from '@vesk/compiler/src/ir';
2
+ export declare const VOID_ELEMENTS: Set<string>;
2
3
  export declare let __vskHydrate: boolean;
3
4
  export declare let __vskMarkerless: boolean;
4
5
  export declare let __vskId: number;
@@ -1 +1 @@
1
- {"version":3,"file":"server-utils.d.ts","sourceRoot":"","sources":["../src/server-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-utils.d.ts","sourceRoot":"","sources":["../src/server-utils.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ import { parse } from '@vesk/compiler/src/parser';
4
4
  import { generateIR } from '@vesk/compiler/src/ir-generator';
5
5
  import { htmlTagName, htmlTagEnd } from '@vesk/compiler/src/scan';
6
6
  import { importModuleTarget, extractImportNames, stripTrackDeclMarkers } from '@vesk/compiler/src/tokens';
7
- const VOID_ELEMENTS = new Set([
7
+ export const VOID_ELEMENTS = new Set([
8
8
  'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr',
9
9
  ]);
10
10
  const RAW_TEXT_ELEMENTS = new Set(['style', 'script', 'title']);
@@ -1 +1 @@
1
- {"version":3,"file":"strip-ts.d.ts","sourceRoot":"","sources":["../src/strip-ts.ts"],"names":[],"mappings":"AAwBA,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAOzD;AAUD,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAgB7C;AAYD,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAUtD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAmF1C;AAWD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBnD"}
1
+ {"version":3,"file":"strip-ts.d.ts","sourceRoot":"","sources":["../src/strip-ts.ts"],"names":[],"mappings":"AAwBA,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAOzD;AAUD,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAgB7C;AAYD,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAUtD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAmF1C;AAkDD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBnD"}