@vertz/ui-compiler 0.2.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
1
4
  // src/analyzers/component-analyzer.ts
2
5
  import {
3
6
  SyntaxKind
@@ -169,40 +172,12 @@ class CSSAnalyzer {
169
172
  if (!init || !init.isKind(SyntaxKind2.ArrayLiteralExpression))
170
173
  return false;
171
174
  for (const el of init.getElements()) {
172
- if (el.isKind(SyntaxKind2.StringLiteral))
173
- continue;
174
- if (el.isKind(SyntaxKind2.ObjectLiteralExpression)) {
175
- if (this.isStaticRawDeclaration(el))
176
- continue;
175
+ if (!el.isKind(SyntaxKind2.StringLiteral))
177
176
  return false;
178
- }
179
- return false;
180
177
  }
181
178
  }
182
179
  return true;
183
180
  }
184
- isStaticRawDeclaration(node) {
185
- if (!node.isKind(SyntaxKind2.ObjectLiteralExpression))
186
- return false;
187
- const props = node.getProperties();
188
- if (props.length !== 2)
189
- return false;
190
- let hasProperty = false;
191
- let hasValue = false;
192
- for (const prop of props) {
193
- if (!prop.isKind(SyntaxKind2.PropertyAssignment))
194
- return false;
195
- const init = prop.getInitializer();
196
- if (!init || !init.isKind(SyntaxKind2.StringLiteral))
197
- return false;
198
- const name = prop.getName();
199
- if (name === "property")
200
- hasProperty = true;
201
- else if (name === "value")
202
- hasValue = true;
203
- }
204
- return hasProperty && hasValue;
205
- }
206
181
  extractBlockNames(node) {
207
182
  if (!node.isKind(SyntaxKind2.ObjectLiteralExpression))
208
183
  return [];
@@ -235,24 +210,6 @@ function findBodyNode(sourceFile, component) {
235
210
  class JsxAnalyzer {
236
211
  analyze(sourceFile, component, variables) {
237
212
  const reactiveNames = new Set(variables.filter((v) => v.kind === "signal" || v.kind === "computed").map((v) => v.name));
238
- const signalApiVars = new Map;
239
- const plainPropVars = new Map;
240
- const fieldSignalPropVars = new Map;
241
- const reactiveSourceVars = new Set;
242
- for (const v of variables) {
243
- if (v.signalProperties && v.signalProperties.size > 0) {
244
- signalApiVars.set(v.name, v.signalProperties);
245
- }
246
- if (v.plainProperties && v.plainProperties.size > 0) {
247
- plainPropVars.set(v.name, v.plainProperties);
248
- }
249
- if (v.fieldSignalProperties && v.fieldSignalProperties.size > 0) {
250
- fieldSignalPropVars.set(v.name, v.fieldSignalProperties);
251
- }
252
- if (v.isReactiveSource) {
253
- reactiveSourceVars.add(v.name);
254
- }
255
- }
256
213
  const bodyNode = findBodyNode(sourceFile, component);
257
214
  if (!bodyNode)
258
215
  return [];
@@ -262,71 +219,16 @@ class JsxAnalyzer {
262
219
  const identifiers = collectIdentifiers(expr);
263
220
  const deps = identifiers.filter((id) => reactiveNames.has(id));
264
221
  const uniqueDeps = [...new Set(deps)];
265
- const hasSignalApiAccess = containsSignalApiPropertyAccess(expr, signalApiVars, plainPropVars, fieldSignalPropVars);
266
- const hasReactiveSourceAccess = containsReactiveSourceAccess(expr, reactiveSourceVars);
267
222
  results.push({
268
223
  start: expr.getStart(),
269
224
  end: expr.getEnd(),
270
- reactive: uniqueDeps.length > 0 || hasSignalApiAccess || hasReactiveSourceAccess,
225
+ reactive: uniqueDeps.length > 0,
271
226
  deps: uniqueDeps
272
227
  });
273
228
  }
274
229
  return results;
275
230
  }
276
231
  }
277
- function containsSignalApiPropertyAccess(node, signalApiVars, plainPropVars, fieldSignalPropVars) {
278
- if (signalApiVars.size === 0 && fieldSignalPropVars.size === 0)
279
- return false;
280
- const propAccesses = node.getDescendantsOfKind(SyntaxKind4.PropertyAccessExpression);
281
- for (const pa of propAccesses) {
282
- const obj = pa.getExpression();
283
- const propName = pa.getName();
284
- if (obj.isKind(SyntaxKind4.Identifier)) {
285
- const varName = obj.getText();
286
- const signalProps = signalApiVars.get(varName);
287
- if (signalProps?.has(propName)) {
288
- return true;
289
- }
290
- }
291
- if (obj.isKind(SyntaxKind4.PropertyAccessExpression)) {
292
- const innerExpr = obj.asKindOrThrow(SyntaxKind4.PropertyAccessExpression);
293
- const rootExpr = innerExpr.getExpression();
294
- const middleProp = innerExpr.getName();
295
- if (rootExpr.isKind(SyntaxKind4.Identifier)) {
296
- const rootName = rootExpr.getText();
297
- const fieldSignalProps = fieldSignalPropVars.get(rootName);
298
- if (!fieldSignalProps)
299
- continue;
300
- const signalProps = signalApiVars.get(rootName);
301
- const plainProps = plainPropVars.get(rootName);
302
- if (signalProps?.has(middleProp) || plainProps?.has(middleProp))
303
- continue;
304
- if (fieldSignalProps.has(propName)) {
305
- return true;
306
- }
307
- }
308
- }
309
- }
310
- return false;
311
- }
312
- function containsReactiveSourceAccess(node, reactiveSourceVars) {
313
- if (reactiveSourceVars.size === 0)
314
- return false;
315
- const propAccesses = node.getDescendantsOfKind(SyntaxKind4.PropertyAccessExpression);
316
- for (const pa of propAccesses) {
317
- const obj = pa.getExpression();
318
- if (obj.isKind(SyntaxKind4.Identifier) && reactiveSourceVars.has(obj.getText())) {
319
- return true;
320
- }
321
- }
322
- const identifiers = node.getDescendantsOfKind(SyntaxKind4.Identifier);
323
- for (const id of identifiers) {
324
- if (reactiveSourceVars.has(id.getText())) {
325
- return true;
326
- }
327
- }
328
- return false;
329
- }
330
232
  function collectIdentifiers(node) {
331
233
  const ids = [];
332
234
  const walk = (n) => {
@@ -453,26 +355,21 @@ import { SyntaxKind as SyntaxKind6 } from "ts-morph";
453
355
  // src/signal-api-registry.ts
454
356
  var SIGNAL_API_REGISTRY = {
455
357
  query: {
456
- signalProperties: new Set(["data", "loading", "error", "revalidating"]),
457
- plainProperties: new Set(["refetch", "revalidate", "dispose"])
358
+ signalProperties: new Set(["data", "loading", "error"]),
359
+ plainProperties: new Set(["refetch"])
458
360
  },
459
361
  form: {
460
- signalProperties: new Set(["submitting", "dirty", "valid"]),
461
- plainProperties: new Set(["action", "method", "onSubmit", "reset", "setFieldError", "submit"]),
462
- fieldSignalProperties: new Set(["error", "dirty", "touched", "value"])
362
+ signalProperties: new Set(["submitting", "errors", "values"]),
363
+ plainProperties: new Set(["reset", "submit", "handleSubmit"])
463
364
  },
464
365
  createLoader: {
465
366
  signalProperties: new Set(["data", "loading", "error"]),
466
367
  plainProperties: new Set(["refetch"])
467
368
  }
468
369
  };
469
- var REACTIVE_SOURCE_APIS = new Set(["useContext"]);
470
370
  function isSignalApi(functionName) {
471
371
  return functionName in SIGNAL_API_REGISTRY;
472
372
  }
473
- function isReactiveSourceApi(functionName) {
474
- return REACTIVE_SOURCE_APIS.has(functionName);
475
- }
476
373
  function getSignalApiConfig(functionName) {
477
374
  return SIGNAL_API_REGISTRY[functionName];
478
375
  }
@@ -483,14 +380,10 @@ class ReactivityAnalyzer {
483
380
  const bodyNode = findBodyNode(sourceFile, component);
484
381
  if (!bodyNode)
485
382
  return [];
486
- const { signalApiAliases: importAliases, reactiveSourceAliases } = buildImportAliasMap(sourceFile);
487
- const declaredNames = collectDeclaredNames(bodyNode);
383
+ const importAliases = buildImportAliasMap(sourceFile);
488
384
  const lets = new Map;
489
385
  const consts = new Map;
490
386
  const signalApiVars = new Map;
491
- const reactiveSourceVars = new Set;
492
- const destructuredFromMap = new Map;
493
- const syntheticCounters = new Map;
494
387
  for (const stmt of bodyNode.getChildSyntaxList()?.getChildren() ?? []) {
495
388
  if (!stmt.isKind(SyntaxKind6.VariableStatement))
496
389
  continue;
@@ -504,52 +397,14 @@ class ReactivityAnalyzer {
504
397
  const nameNode = decl.getNameNode();
505
398
  const init = decl.getInitializer();
506
399
  if (nameNode.isKind(SyntaxKind6.ObjectBindingPattern)) {
507
- let signalApiConfig;
508
- let syntheticName;
509
- const hasUnsupportedBindings = nameNode.getElements().some((el) => el.getInitializer() || el.getNameNode().isKind(SyntaxKind6.ObjectBindingPattern));
510
- if (isConst && !hasUnsupportedBindings && init?.isKind(SyntaxKind6.CallExpression)) {
511
- const callExpr = init.asKindOrThrow(SyntaxKind6.CallExpression);
512
- const callName = callExpr.getExpression();
513
- if (callName.isKind(SyntaxKind6.Identifier)) {
514
- const fnName = callName.getText();
515
- const originalName = importAliases.get(fnName);
516
- if (originalName) {
517
- signalApiConfig = getSignalApiConfig(originalName);
518
- if (signalApiConfig) {
519
- let counter = syntheticCounters.get(originalName) ?? 0;
520
- syntheticName = `__${originalName}_${counter}`;
521
- while (declaredNames.has(syntheticName)) {
522
- counter++;
523
- syntheticName = `__${originalName}_${counter}`;
524
- }
525
- syntheticCounters.set(originalName, counter + 1);
526
- signalApiVars.set(syntheticName, signalApiConfig);
527
- consts.set(syntheticName, {
528
- start: decl.getStart(),
529
- end: decl.getEnd(),
530
- deps: []
531
- });
532
- }
533
- }
534
- }
535
- }
400
+ const deps2 = init ? collectIdentifierRefs(init) : [];
536
401
  for (const element of nameNode.getElements()) {
537
402
  const bindingName = element.getName();
538
- const propName = element.getPropertyNameNode()?.getText() ?? bindingName;
539
- if (signalApiConfig && syntheticName) {
540
- const isSignalProp = signalApiConfig.signalProperties.has(propName);
541
- const deps2 = isSignalProp ? [syntheticName] : [];
542
- const entry2 = { start: decl.getStart(), end: decl.getEnd(), deps: deps2 };
403
+ const entry2 = { start: decl.getStart(), end: decl.getEnd(), deps: deps2 };
404
+ if (isLet) {
405
+ lets.set(bindingName, entry2);
406
+ } else if (isConst) {
543
407
  consts.set(bindingName, entry2);
544
- destructuredFromMap.set(bindingName, syntheticName);
545
- } else {
546
- const deps2 = init ? collectIdentifierRefs(init) : [];
547
- const entry2 = { start: decl.getStart(), end: decl.getEnd(), deps: deps2 };
548
- if (isLet) {
549
- lets.set(bindingName, entry2);
550
- } else if (isConst) {
551
- consts.set(bindingName, entry2);
552
- }
553
408
  }
554
409
  }
555
410
  continue;
@@ -562,16 +417,13 @@ class ReactivityAnalyzer {
562
417
  const callName = callExpr.getExpression();
563
418
  if (callName.isKind(SyntaxKind6.Identifier)) {
564
419
  const fnName = callName.getText();
565
- const originalName = importAliases.get(fnName);
566
- if (originalName) {
420
+ const originalName = importAliases.get(fnName) ?? fnName;
421
+ if (isSignalApi(originalName)) {
567
422
  const config = getSignalApiConfig(originalName);
568
423
  if (config) {
569
- signalApiVars.set(name, config);
424
+ signalApiVars.set(name, config.signalProperties);
570
425
  }
571
426
  }
572
- if (reactiveSourceAliases.has(fnName)) {
573
- reactiveSourceVars.add(name);
574
- }
575
427
  }
576
428
  }
577
429
  if (isLet) {
@@ -610,7 +462,7 @@ class ReactivityAnalyzer {
610
462
  for (const [name, info] of consts) {
611
463
  if (computeds.has(name))
612
464
  continue;
613
- const dependsOnReactive = info.deps.some((dep) => signals.has(dep) || computeds.has(dep) || signalApiVars.has(dep) || reactiveSourceVars.has(dep));
465
+ const dependsOnReactive = info.deps.some((dep) => signals.has(dep) || computeds.has(dep));
614
466
  if (dependsOnReactive) {
615
467
  computeds.add(name);
616
468
  changed = true;
@@ -625,11 +477,8 @@ class ReactivityAnalyzer {
625
477
  start: info.start,
626
478
  end: info.end
627
479
  };
628
- const apiConfig = signalApiVars.get(name);
629
- if (apiConfig) {
630
- varInfo.signalProperties = apiConfig.signalProperties;
631
- varInfo.plainProperties = apiConfig.plainProperties;
632
- varInfo.fieldSignalProperties = apiConfig.fieldSignalProperties;
480
+ if (signalApiVars.has(name)) {
481
+ varInfo.signalProperties = signalApiVars.get(name);
633
482
  }
634
483
  results.push(varInfo);
635
484
  }
@@ -640,18 +489,8 @@ class ReactivityAnalyzer {
640
489
  start: info.start,
641
490
  end: info.end
642
491
  };
643
- const apiConfig = signalApiVars.get(name);
644
- if (apiConfig) {
645
- varInfo.signalProperties = apiConfig.signalProperties;
646
- varInfo.plainProperties = apiConfig.plainProperties;
647
- varInfo.fieldSignalProperties = apiConfig.fieldSignalProperties;
648
- }
649
- if (reactiveSourceVars.has(name)) {
650
- varInfo.isReactiveSource = true;
651
- }
652
- const syntheticSource = destructuredFromMap.get(name);
653
- if (syntheticSource) {
654
- varInfo.destructuredFrom = syntheticSource;
492
+ if (signalApiVars.has(name)) {
493
+ varInfo.signalProperties = signalApiVars.get(name);
655
494
  }
656
495
  results.push(varInfo);
657
496
  }
@@ -688,8 +527,7 @@ function collectIdentifierRefs(node) {
688
527
  return refs;
689
528
  }
690
529
  function buildImportAliasMap(sourceFile) {
691
- const signalApiAliases = new Map;
692
- const reactiveSourceAliases = new Set;
530
+ const aliases = new Map;
693
531
  for (const importDecl of sourceFile.getImportDeclarations()) {
694
532
  const moduleSpecifier = importDecl.getModuleSpecifierValue();
695
533
  if (moduleSpecifier !== "@vertz/ui")
@@ -697,37 +535,20 @@ function buildImportAliasMap(sourceFile) {
697
535
  const namedImports = importDecl.getNamedImports();
698
536
  for (const namedImport of namedImports) {
699
537
  const originalName = namedImport.getName();
700
- const localName = namedImport.getAliasNode()?.getText() ?? originalName;
701
- if (isSignalApi(originalName)) {
702
- signalApiAliases.set(localName, originalName);
703
- }
704
- if (isReactiveSourceApi(originalName)) {
705
- reactiveSourceAliases.add(localName);
706
- }
707
- }
708
- }
709
- return { signalApiAliases, reactiveSourceAliases };
710
- }
711
- function collectDeclaredNames(bodyNode) {
712
- const names = new Set;
713
- for (const stmt of bodyNode.getChildSyntaxList()?.getChildren() ?? []) {
714
- if (!stmt.isKind(SyntaxKind6.VariableStatement))
715
- continue;
716
- const declList = stmt.getChildrenOfKind(SyntaxKind6.VariableDeclarationList)[0];
717
- if (!declList)
718
- continue;
719
- for (const decl of declList.getDeclarations()) {
720
- const nameNode = decl.getNameNode();
721
- if (nameNode.isKind(SyntaxKind6.Identifier)) {
722
- names.add(nameNode.getText());
538
+ const aliasNode = namedImport.getAliasNode();
539
+ if (aliasNode) {
540
+ const aliasName = aliasNode.getText();
541
+ if (isSignalApi(originalName)) {
542
+ aliases.set(aliasName, originalName);
543
+ }
723
544
  }
724
545
  }
725
546
  }
726
- return names;
547
+ return aliases;
727
548
  }
728
549
  // src/compiler.ts
729
550
  import MagicString from "magic-string";
730
- import { Project, SyntaxKind as SyntaxKind12, ts } from "ts-morph";
551
+ import { Project, SyntaxKind as SyntaxKind11, ts } from "ts-morph";
731
552
 
732
553
  // src/diagnostics/mutation-diagnostics.ts
733
554
  import { SyntaxKind as SyntaxKind7 } from "ts-morph";
@@ -838,160 +659,8 @@ class PropsDestructuringDiagnostics {
838
659
  }
839
660
  }
840
661
 
841
- // src/diagnostics/ssr-safety-diagnostics.ts
842
- import { SyntaxKind as SyntaxKind8 } from "ts-morph";
843
- var BROWSER_ONLY_GLOBALS = new Set([
844
- "localStorage",
845
- "sessionStorage",
846
- "navigator",
847
- "IntersectionObserver",
848
- "ResizeObserver",
849
- "MutationObserver",
850
- "requestAnimationFrame",
851
- "cancelAnimationFrame",
852
- "requestIdleCallback",
853
- "cancelIdleCallback"
854
- ]);
855
- var BROWSER_ONLY_DOCUMENT_PROPS = new Set([
856
- "querySelector",
857
- "querySelectorAll",
858
- "getElementById",
859
- "cookie"
860
- ]);
861
-
862
- class SSRSafetyDiagnostics {
863
- analyze(sourceFile, component) {
864
- const bodyNode = findBodyNode(sourceFile, component);
865
- if (!bodyNode)
866
- return [];
867
- const diagnostics = [];
868
- bodyNode.forEachDescendant((node) => {
869
- if (!node.isKind(SyntaxKind8.Identifier))
870
- return;
871
- const name = node.getText();
872
- if (BROWSER_ONLY_GLOBALS.has(name)) {
873
- if (isInNestedFunction(node, bodyNode))
874
- return;
875
- if (isInTypeofGuard(node))
876
- return;
877
- const pos = sourceFile.getLineAndColumnAtPos(node.getStart());
878
- diagnostics.push({
879
- code: "ssr-unsafe-api",
880
- message: `\`${name}\` is a browser-only API that is not available during SSR. Move it inside \`onMount()\` or wrap in a \`typeof\` guard.`,
881
- severity: "warning",
882
- line: pos.line,
883
- column: pos.column - 1,
884
- fix: `Move the \`${name}\` usage inside \`onMount(() => { ... })\` or guard with \`typeof ${name} !== 'undefined'\`.`
885
- });
886
- return;
887
- }
888
- if (name === "document") {
889
- const parent = node.getParent();
890
- if (parent?.isKind(SyntaxKind8.PropertyAccessExpression) && parent.getExpression() === node) {
891
- const propName = parent.getName();
892
- if (BROWSER_ONLY_DOCUMENT_PROPS.has(propName)) {
893
- if (isInNestedFunction(node, bodyNode))
894
- return;
895
- if (isInTypeofGuard(node))
896
- return;
897
- const pos = sourceFile.getLineAndColumnAtPos(node.getStart());
898
- diagnostics.push({
899
- code: "ssr-unsafe-api",
900
- message: `\`document.${propName}\` is a browser-only API that is not available during SSR. Move it inside \`onMount()\` or wrap in a \`typeof\` guard.`,
901
- severity: "warning",
902
- line: pos.line,
903
- column: pos.column - 1,
904
- fix: `Move the \`document.${propName}\` usage inside \`onMount(() => { ... })\`.`
905
- });
906
- }
907
- }
908
- }
909
- });
910
- return diagnostics;
911
- }
912
- }
913
- function isInNestedFunction(node, bodyNode) {
914
- let current = node.getParent();
915
- while (current && current !== bodyNode) {
916
- if (current.isKind(SyntaxKind8.ArrowFunction) || current.isKind(SyntaxKind8.FunctionExpression) || current.isKind(SyntaxKind8.FunctionDeclaration) || current.isKind(SyntaxKind8.MethodDeclaration) || current.isKind(SyntaxKind8.Constructor) || current.isKind(SyntaxKind8.GetAccessor) || current.isKind(SyntaxKind8.SetAccessor)) {
917
- return true;
918
- }
919
- current = current.getParent();
920
- }
921
- return false;
922
- }
923
- function isInTypeofGuard(node) {
924
- const parent = node.getParent();
925
- if (parent?.isKind(SyntaxKind8.TypeOfExpression))
926
- return true;
927
- const name = node.getText();
928
- let current = node.getParent();
929
- while (current) {
930
- if (current.isKind(SyntaxKind8.IfStatement)) {
931
- const condition = current.getExpression();
932
- const thenStatement = current.getThenStatement();
933
- if (conditionContainsTypeofFor(condition, name)) {
934
- if (isDescendantOf(node, thenStatement))
935
- return true;
936
- }
937
- if (conditionContainsTypeofFor(condition, "window")) {
938
- if (isDescendantOf(node, thenStatement))
939
- return true;
940
- }
941
- }
942
- if (current.isKind(SyntaxKind8.ConditionalExpression)) {
943
- const condition = current.getCondition();
944
- if (conditionContainsTypeofFor(condition, name)) {
945
- const whenTrue = current.getWhenTrue();
946
- if (isDescendantOf(node, whenTrue))
947
- return true;
948
- }
949
- if (conditionContainsTypeofFor(condition, "window")) {
950
- const whenTrue = current.getWhenTrue();
951
- if (isDescendantOf(node, whenTrue))
952
- return true;
953
- }
954
- }
955
- if (current.isKind(SyntaxKind8.BinaryExpression)) {
956
- const op = current.getOperatorToken();
957
- if (op.getKind() === SyntaxKind8.AmpersandAmpersandToken) {
958
- const left = current.getLeft();
959
- if (conditionContainsTypeofFor(left, name)) {
960
- if (isDescendantOf(node, current.getRight()))
961
- return true;
962
- }
963
- if (conditionContainsTypeofFor(left, "window")) {
964
- if (isDescendantOf(node, current.getRight()))
965
- return true;
966
- }
967
- }
968
- }
969
- current = current.getParent();
970
- }
971
- return false;
972
- }
973
- function conditionContainsTypeofFor(condition, name) {
974
- if (condition.isKind(SyntaxKind8.TypeOfExpression)) {
975
- return condition.getExpression().getText() === name;
976
- }
977
- for (const desc of condition.getDescendantsOfKind(SyntaxKind8.TypeOfExpression)) {
978
- if (desc.getExpression().getText() === name)
979
- return true;
980
- }
981
- return false;
982
- }
983
- function isDescendantOf(node, ancestor) {
984
- let current = node.getParent();
985
- while (current) {
986
- if (current === ancestor)
987
- return true;
988
- current = current.getParent();
989
- }
990
- return false;
991
- }
992
-
993
662
  // src/transformers/computed-transformer.ts
994
- import { SyntaxKind as SyntaxKind9 } from "ts-morph";
663
+ import { SyntaxKind as SyntaxKind8 } from "ts-morph";
995
664
  class ComputedTransformer {
996
665
  transform(source, sourceFile, component, variables) {
997
666
  const computeds = new Set(variables.filter((v) => v.kind === "computed").map((v) => v.name));
@@ -1000,21 +669,11 @@ class ComputedTransformer {
1000
669
  const bodyNode = findBodyNode(sourceFile, component);
1001
670
  if (!bodyNode)
1002
671
  return;
1003
- const destructuredFromMap = new Map;
1004
- const syntheticVarInfo = new Map;
1005
- for (const v of variables) {
1006
- if (v.destructuredFrom) {
1007
- destructuredFromMap.set(v.name, v.destructuredFrom);
1008
- }
1009
- if (v.name.startsWith("__") && v.signalProperties) {
1010
- syntheticVarInfo.set(v.name, v);
1011
- }
1012
- }
1013
672
  transformComputedReads(source, bodyNode, computeds);
1014
673
  for (const stmt of bodyNode.getChildSyntaxList()?.getChildren() ?? []) {
1015
- if (!stmt.isKind(SyntaxKind9.VariableStatement))
674
+ if (!stmt.isKind(SyntaxKind8.VariableStatement))
1016
675
  continue;
1017
- const declList = stmt.getChildrenOfKind(SyntaxKind9.VariableDeclarationList)[0];
676
+ const declList = stmt.getChildrenOfKind(SyntaxKind8.VariableDeclarationList)[0];
1018
677
  if (!declList)
1019
678
  continue;
1020
679
  for (const decl of declList.getDeclarations()) {
@@ -1022,34 +681,8 @@ class ComputedTransformer {
1022
681
  const init = decl.getInitializer();
1023
682
  if (!init)
1024
683
  continue;
1025
- if (nameNode.isKind(SyntaxKind9.ObjectBindingPattern)) {
684
+ if (nameNode.isKind(SyntaxKind8.ObjectBindingPattern)) {
1026
685
  const elements = nameNode.getElements();
1027
- const firstBindingName = elements[0]?.getName();
1028
- const syntheticName = firstBindingName ? destructuredFromMap.get(firstBindingName) : undefined;
1029
- if (syntheticName) {
1030
- const initText = source.slice(init.getStart(), init.getEnd());
1031
- const synthetic = syntheticVarInfo.get(syntheticName);
1032
- const signalProps = synthetic?.signalProperties ?? new Set;
1033
- const lines = [];
1034
- lines.push(`const ${syntheticName} = ${initText}`);
1035
- for (const el of elements) {
1036
- if (el.getDotDotDotToken()) {
1037
- const restName = el.getName();
1038
- lines.push(`const { ...${restName} } = ${syntheticName}`);
1039
- continue;
1040
- }
1041
- const bindingName = el.getName();
1042
- const propName = el.getPropertyNameNode()?.getText() ?? bindingName;
1043
- if (computeds.has(bindingName) && signalProps.has(propName)) {
1044
- lines.push(`const ${bindingName} = computed(() => ${syntheticName}.${propName}.value)`);
1045
- } else {
1046
- lines.push(`const ${bindingName} = ${syntheticName}.${propName}`);
1047
- }
1048
- }
1049
- source.overwrite(stmt.getStart(), stmt.getEnd(), `${lines.join(`;
1050
- `)};`);
1051
- continue;
1052
- }
1053
686
  const computedElements = elements.filter((el) => computeds.has(el.getName()));
1054
687
  if (computedElements.length > 0) {
1055
688
  const initText = source.slice(init.getStart(), init.getEnd());
@@ -1077,7 +710,7 @@ class ComputedTransformer {
1077
710
  }
1078
711
  function transformComputedReads(source, bodyNode, computeds) {
1079
712
  bodyNode.forEachDescendant((node) => {
1080
- if (!node.isKind(SyntaxKind9.Identifier))
713
+ if (!node.isKind(SyntaxKind8.Identifier))
1081
714
  return;
1082
715
  const name = node.getText();
1083
716
  if (!computeds.has(name))
@@ -1085,19 +718,19 @@ function transformComputedReads(source, bodyNode, computeds) {
1085
718
  const parent = node.getParent();
1086
719
  if (!parent)
1087
720
  return;
1088
- if (parent.isKind(SyntaxKind9.VariableDeclaration) && parent.getNameNode() === node) {
721
+ if (parent.isKind(SyntaxKind8.VariableDeclaration) && parent.getNameNode() === node) {
1089
722
  return;
1090
723
  }
1091
- if (parent.isKind(SyntaxKind9.PropertyAccessExpression) && parent.getNameNode() === node) {
724
+ if (parent.isKind(SyntaxKind8.PropertyAccessExpression) && parent.getNameNode() === node) {
1092
725
  return;
1093
726
  }
1094
- if (parent.isKind(SyntaxKind9.PropertyAssignment) && parent.getNameNode() === node) {
727
+ if (parent.isKind(SyntaxKind8.PropertyAssignment) && parent.getNameNode() === node) {
1095
728
  return;
1096
729
  }
1097
- if (parent.isKind(SyntaxKind9.ShorthandPropertyAssignment)) {
730
+ if (parent.isKind(SyntaxKind8.ShorthandPropertyAssignment)) {
1098
731
  return;
1099
732
  }
1100
- if (parent.isKind(SyntaxKind9.BindingElement)) {
733
+ if (parent.isKind(SyntaxKind8.BindingElement)) {
1101
734
  return;
1102
735
  }
1103
736
  source.overwrite(node.getStart(), node.getEnd(), `${name}.value`);
@@ -1105,7 +738,7 @@ function transformComputedReads(source, bodyNode, computeds) {
1105
738
  }
1106
739
 
1107
740
  // src/transformers/jsx-transformer.ts
1108
- import { SyntaxKind as SyntaxKind10 } from "ts-morph";
741
+ import { SyntaxKind as SyntaxKind9 } from "ts-morph";
1109
742
  var varCounter = 0;
1110
743
  function genVar() {
1111
744
  return `__el${varCounter++}`;
@@ -1122,73 +755,51 @@ class JsxTransformer {
1122
755
  return;
1123
756
  const reactiveNames = new Set(variables.filter((v) => v.kind === "signal" || v.kind === "computed").map((v) => v.name));
1124
757
  const jsxMap = new Map(jsxExpressions.map((e) => [e.start, e]));
1125
- const formVarNames = new Set;
1126
- for (const v of variables) {
1127
- if (v.fieldSignalProperties && v.fieldSignalProperties.size > 0) {
1128
- formVarNames.add(v.name);
1129
- }
1130
- }
1131
- this.transformAllJsx(bodyNode, reactiveNames, jsxMap, source, formVarNames);
758
+ this.transformAllJsx(bodyNode, reactiveNames, jsxMap, source);
1132
759
  }
1133
- transformAllJsx(node, reactiveNames, jsxMap, source, formVarNames) {
760
+ transformAllJsx(node, reactiveNames, jsxMap, source) {
1134
761
  if (isJsxTopLevel(node)) {
1135
- const transformed = transformJsxNode(node, reactiveNames, jsxMap, source, formVarNames);
762
+ const transformed = transformJsxNode(node, reactiveNames, jsxMap, source);
1136
763
  source.overwrite(node.getStart(), node.getEnd(), transformed);
1137
764
  return;
1138
765
  }
1139
766
  for (const child of node.getChildren()) {
1140
- this.transformAllJsx(child, reactiveNames, jsxMap, source, formVarNames);
767
+ this.transformAllJsx(child, reactiveNames, jsxMap, source);
1141
768
  }
1142
769
  }
1143
770
  }
1144
771
  function isJsxTopLevel(node) {
1145
- return node.isKind(SyntaxKind10.JsxElement) || node.isKind(SyntaxKind10.JsxSelfClosingElement) || node.isKind(SyntaxKind10.JsxFragment);
772
+ return node.isKind(SyntaxKind9.JsxElement) || node.isKind(SyntaxKind9.JsxSelfClosingElement) || node.isKind(SyntaxKind9.JsxFragment);
1146
773
  }
1147
- function transformJsxNode(node, reactiveNames, jsxMap, source, formVarNames = new Set) {
1148
- if (node.isKind(SyntaxKind10.ParenthesizedExpression)) {
1149
- return transformJsxNode(node.getExpression(), reactiveNames, jsxMap, source, formVarNames);
774
+ function transformJsxNode(node, reactiveNames, jsxMap, source) {
775
+ if (node.isKind(SyntaxKind9.ParenthesizedExpression)) {
776
+ return transformJsxNode(node.getExpression(), reactiveNames, jsxMap, source);
1150
777
  }
1151
- if (node.isKind(SyntaxKind10.JsxElement)) {
1152
- return transformJsxElement(node, reactiveNames, jsxMap, source, formVarNames);
778
+ if (node.isKind(SyntaxKind9.JsxElement)) {
779
+ return transformJsxElement(node, reactiveNames, jsxMap, source);
1153
780
  }
1154
- if (node.isKind(SyntaxKind10.JsxSelfClosingElement)) {
1155
- return transformSelfClosingElement(node, reactiveNames, jsxMap, source, formVarNames);
781
+ if (node.isKind(SyntaxKind9.JsxSelfClosingElement)) {
782
+ return transformSelfClosingElement(node, reactiveNames, jsxMap, source);
1156
783
  }
1157
- if (node.isKind(SyntaxKind10.JsxFragment)) {
1158
- return transformFragment(node, reactiveNames, jsxMap, source, formVarNames);
784
+ if (node.isKind(SyntaxKind9.JsxFragment)) {
785
+ return transformFragment(node, reactiveNames, jsxMap, source);
1159
786
  }
1160
- if (node.isKind(SyntaxKind10.JsxText)) {
787
+ if (node.isKind(SyntaxKind9.JsxText)) {
1161
788
  const text = node.getText().trim();
1162
789
  if (!text)
1163
790
  return "";
1164
- return `__staticText(${JSON.stringify(text)})`;
791
+ return `document.createTextNode(${JSON.stringify(text)})`;
1165
792
  }
1166
793
  return node.getText();
1167
794
  }
1168
- function transformJsxElement(node, reactiveNames, jsxMap, source, formVarNames = new Set) {
1169
- const openingElement = node.getFirstChildByKind(SyntaxKind10.JsxOpeningElement);
795
+ function transformJsxElement(node, reactiveNames, jsxMap, source) {
796
+ const openingElement = node.getFirstChildByKind(SyntaxKind9.JsxOpeningElement);
1170
797
  if (!openingElement)
1171
798
  return node.getText();
1172
799
  const tagName = openingElement.getTagNameNode().getText();
1173
800
  const isComponent = /^[A-Z]/.test(tagName);
1174
801
  if (isComponent) {
1175
- const hasExplicitChildren = openingElement.getAttributes().filter((a) => a.isKind(SyntaxKind10.JsxAttribute)).some((attr) => attr.getNameNode().getText() === "children");
1176
- let extraEntries;
1177
- if (!hasExplicitChildren) {
1178
- const children2 = getJsxChildren(node);
1179
- const nonEmptyChildren = children2.filter((child) => {
1180
- if (child.isKind(SyntaxKind10.JsxText))
1181
- return !!child.getText().trim();
1182
- return true;
1183
- });
1184
- if (nonEmptyChildren.length > 0) {
1185
- const thunkCode = buildComponentChildrenThunk(nonEmptyChildren, reactiveNames, jsxMap, source, formVarNames);
1186
- if (thunkCode) {
1187
- extraEntries = new Map([["children", thunkCode]]);
1188
- }
1189
- }
1190
- }
1191
- const propsObj = buildPropsObject(openingElement, jsxMap, source, reactiveNames, formVarNames, extraEntries);
802
+ const propsObj = buildPropsObject(openingElement, jsxMap, source);
1192
803
  return `${tagName}(${propsObj})`;
1193
804
  }
1194
805
  const elVar = genVar();
@@ -1196,45 +807,31 @@ function transformJsxElement(node, reactiveNames, jsxMap, source, formVarNames =
1196
807
  statements.push(`const ${elVar} = __element(${JSON.stringify(tagName)})`);
1197
808
  const attrs = openingElement.getAttributes();
1198
809
  for (const attr of attrs) {
1199
- if (!attr.isKind(SyntaxKind10.JsxAttribute))
810
+ if (!attr.isKind(SyntaxKind9.JsxAttribute))
1200
811
  continue;
1201
812
  const attrStmt = processAttribute(attr, elVar, jsxMap, source);
1202
813
  if (attrStmt)
1203
814
  statements.push(attrStmt);
1204
815
  }
1205
- const bindStmt = tryBindElement(tagName, openingElement, elVar, formVarNames);
1206
- if (bindStmt)
1207
- statements.push(bindStmt);
1208
816
  const children = getJsxChildren(node);
1209
- const hasChildren = children.some((child) => {
1210
- if (child.isKind(SyntaxKind10.JsxText))
1211
- return !!child.getText().trim();
1212
- return true;
1213
- });
1214
- if (hasChildren) {
1215
- statements.push(`__enterChildren(${elVar})`);
1216
- }
1217
817
  for (const child of children) {
1218
- const childCode = transformChild(child, reactiveNames, jsxMap, elVar, source, formVarNames);
818
+ const childCode = transformChild(child, reactiveNames, jsxMap, elVar, source);
1219
819
  if (childCode)
1220
820
  statements.push(childCode);
1221
821
  }
1222
- if (hasChildren) {
1223
- statements.push(`__exitChildren()`);
1224
- }
1225
822
  return `(() => {
1226
823
  ${statements.map((s) => ` ${s};`).join(`
1227
824
  `)}
1228
825
  return ${elVar};
1229
826
  })()`;
1230
827
  }
1231
- function transformSelfClosingElement(node, reactiveNames, jsxMap, source, formVarNames = new Set) {
1232
- if (!node.isKind(SyntaxKind10.JsxSelfClosingElement))
828
+ function transformSelfClosingElement(node, _reactiveNames, jsxMap, source) {
829
+ if (!node.isKind(SyntaxKind9.JsxSelfClosingElement))
1233
830
  return node.getText();
1234
831
  const tagName = node.getTagNameNode().getText();
1235
832
  const isComponent = /^[A-Z]/.test(tagName);
1236
833
  if (isComponent) {
1237
- const propsObj = buildPropsObject(node, jsxMap, source, reactiveNames, formVarNames);
834
+ const propsObj = buildPropsObject(node, jsxMap, source);
1238
835
  return `${tagName}(${propsObj})`;
1239
836
  }
1240
837
  const elVar = genVar();
@@ -1242,28 +839,25 @@ function transformSelfClosingElement(node, reactiveNames, jsxMap, source, formVa
1242
839
  statements.push(`const ${elVar} = __element(${JSON.stringify(tagName)})`);
1243
840
  const attrs = node.getAttributes();
1244
841
  for (const attr of attrs) {
1245
- if (!attr.isKind(SyntaxKind10.JsxAttribute))
842
+ if (!attr.isKind(SyntaxKind9.JsxAttribute))
1246
843
  continue;
1247
844
  const attrStmt = processAttribute(attr, elVar, jsxMap, source);
1248
845
  if (attrStmt)
1249
846
  statements.push(attrStmt);
1250
847
  }
1251
- const bindStmt = tryBindElement(tagName, node, elVar, formVarNames);
1252
- if (bindStmt)
1253
- statements.push(bindStmt);
1254
848
  return `(() => {
1255
849
  ${statements.map((s) => ` ${s};`).join(`
1256
850
  `)}
1257
851
  return ${elVar};
1258
852
  })()`;
1259
853
  }
1260
- function transformFragment(node, reactiveNames, jsxMap, source, formVarNames = new Set) {
854
+ function transformFragment(node, reactiveNames, jsxMap, source) {
1261
855
  const fragVar = genVar();
1262
856
  const statements = [];
1263
857
  statements.push(`const ${fragVar} = document.createDocumentFragment()`);
1264
858
  const children = getJsxChildren(node);
1265
859
  for (const child of children) {
1266
- const childCode = transformChild(child, reactiveNames, jsxMap, fragVar, source, formVarNames);
860
+ const childCode = transformChild(child, reactiveNames, jsxMap, fragVar, source);
1267
861
  if (childCode)
1268
862
  statements.push(childCode);
1269
863
  }
@@ -1274,7 +868,7 @@ ${statements.map((s) => ` ${s};`).join(`
1274
868
  })()`;
1275
869
  }
1276
870
  function processAttribute(attr, elVar, jsxMap, source) {
1277
- if (!attr.isKind(SyntaxKind10.JsxAttribute))
871
+ if (!attr.isKind(SyntaxKind9.JsxAttribute))
1278
872
  return null;
1279
873
  const attrName = attr.getNameNode().getText();
1280
874
  const init = attr.getInitializer();
@@ -1282,35 +876,35 @@ function processAttribute(attr, elVar, jsxMap, source) {
1282
876
  return null;
1283
877
  if (attrName.startsWith("on") && attrName.length > 2) {
1284
878
  const eventName = attrName[2]?.toLowerCase() + attrName.slice(3);
1285
- if (init.isKind(SyntaxKind10.JsxExpression)) {
879
+ if (init.isKind(SyntaxKind9.JsxExpression)) {
1286
880
  const exprNode = init.getExpression();
1287
881
  const handlerText = exprNode ? source.slice(exprNode.getStart(), exprNode.getEnd()) : "";
1288
882
  return `__on(${elVar}, ${JSON.stringify(eventName)}, ${handlerText})`;
1289
883
  }
1290
884
  return null;
1291
885
  }
1292
- if (init.isKind(SyntaxKind10.StringLiteral)) {
886
+ if (init.isKind(SyntaxKind9.StringLiteral)) {
1293
887
  return `${elVar}.setAttribute(${JSON.stringify(attrName)}, ${init.getText()})`;
1294
888
  }
1295
- if (init.isKind(SyntaxKind10.JsxExpression)) {
889
+ if (init.isKind(SyntaxKind9.JsxExpression)) {
1296
890
  const exprInfo = jsxMap.get(init.getStart());
1297
891
  const exprNode = init.getExpression();
1298
892
  const exprText = exprNode ? source.slice(exprNode.getStart(), exprNode.getEnd()) : "";
1299
893
  if (exprInfo?.reactive) {
1300
894
  return `__attr(${elVar}, ${JSON.stringify(attrName)}, () => ${exprText})`;
1301
895
  }
1302
- return `{ const __v = ${exprText}; if (__v != null && __v !== false) ${elVar}.setAttribute(${JSON.stringify(attrName)}, __v === true ? "" : __v); }`;
896
+ return `${elVar}.setAttribute(${JSON.stringify(attrName)}, ${exprText})`;
1303
897
  }
1304
898
  return null;
1305
899
  }
1306
- function transformChild(child, reactiveNames, jsxMap, parentVar, source, formVarNames = new Set) {
1307
- if (child.isKind(SyntaxKind10.JsxText)) {
900
+ function transformChild(child, reactiveNames, jsxMap, parentVar, source) {
901
+ if (child.isKind(SyntaxKind9.JsxText)) {
1308
902
  const text = child.getText().trim();
1309
903
  if (!text)
1310
904
  return null;
1311
- return `__append(${parentVar}, __staticText(${JSON.stringify(text)}))`;
905
+ return `${parentVar}.appendChild(document.createTextNode(${JSON.stringify(text)}))`;
1312
906
  }
1313
- if (child.isKind(SyntaxKind10.JsxExpression)) {
907
+ if (child.isKind(SyntaxKind9.JsxExpression)) {
1314
908
  const exprInfo = jsxMap.get(child.getStart());
1315
909
  const exprNode = child.getExpression();
1316
910
  if (!exprNode)
@@ -1318,7 +912,7 @@ function transformChild(child, reactiveNames, jsxMap, parentVar, source, formVar
1318
912
  if (exprInfo?.reactive) {
1319
913
  const conditionalCode = tryTransformConditional(exprNode, reactiveNames, jsxMap, source);
1320
914
  if (conditionalCode) {
1321
- return `__append(${parentVar}, ${conditionalCode})`;
915
+ return `${parentVar}.appendChild(${conditionalCode})`;
1322
916
  }
1323
917
  const listCode = tryTransformList(exprNode, reactiveNames, jsxMap, parentVar, source);
1324
918
  if (listCode) {
@@ -1327,60 +921,18 @@ function transformChild(child, reactiveNames, jsxMap, parentVar, source, formVar
1327
921
  }
1328
922
  const exprText = source.slice(exprNode.getStart(), exprNode.getEnd());
1329
923
  if (exprInfo?.reactive) {
1330
- return `__append(${parentVar}, __child(() => ${exprText}))`;
924
+ return `${parentVar}.appendChild(__child(() => ${exprText}))`;
1331
925
  }
1332
926
  return `__insert(${parentVar}, ${exprText})`;
1333
927
  }
1334
- if (child.isKind(SyntaxKind10.JsxElement) || child.isKind(SyntaxKind10.JsxSelfClosingElement) || child.isKind(SyntaxKind10.JsxFragment)) {
1335
- const childCode = transformJsxNode(child, reactiveNames, jsxMap, source, formVarNames);
1336
- return `__append(${parentVar}, ${childCode})`;
1337
- }
1338
- return null;
1339
- }
1340
- function transformChildAsValue(child, reactiveNames, jsxMap, source, formVarNames = new Set) {
1341
- if (child.isKind(SyntaxKind10.JsxText)) {
1342
- const text = child.getText().trim();
1343
- if (!text)
1344
- return null;
1345
- return `__staticText(${JSON.stringify(text)})`;
1346
- }
1347
- if (child.isKind(SyntaxKind10.JsxExpression)) {
1348
- const exprInfo = jsxMap.get(child.getStart());
1349
- const exprNode = child.getExpression();
1350
- if (!exprNode)
1351
- return null;
1352
- if (exprInfo?.reactive) {
1353
- const conditionalCode = tryTransformConditional(exprNode, reactiveNames, jsxMap, source);
1354
- if (conditionalCode) {
1355
- return conditionalCode;
1356
- }
1357
- }
1358
- const exprText = source.slice(exprNode.getStart(), exprNode.getEnd());
1359
- if (exprInfo?.reactive) {
1360
- return `__child(() => ${exprText})`;
1361
- }
1362
- return exprText;
1363
- }
1364
- if (child.isKind(SyntaxKind10.JsxElement) || child.isKind(SyntaxKind10.JsxSelfClosingElement) || child.isKind(SyntaxKind10.JsxFragment)) {
1365
- return transformJsxNode(child, reactiveNames, jsxMap, source, formVarNames);
928
+ if (child.isKind(SyntaxKind9.JsxElement) || child.isKind(SyntaxKind9.JsxSelfClosingElement)) {
929
+ const childCode = transformJsxNode(child, reactiveNames, jsxMap, source);
930
+ return `${parentVar}.appendChild(${childCode})`;
1366
931
  }
1367
932
  return null;
1368
933
  }
1369
- function buildComponentChildrenThunk(children, reactiveNames, jsxMap, source, formVarNames) {
1370
- const values = [];
1371
- for (const child of children) {
1372
- const value = transformChildAsValue(child, reactiveNames, jsxMap, source, formVarNames);
1373
- if (value)
1374
- values.push(value);
1375
- }
1376
- if (values.length === 0)
1377
- return "";
1378
- if (values.length === 1)
1379
- return `() => ${values[0]}`;
1380
- return `() => [${values.join(", ")}]`;
1381
- }
1382
934
  function tryTransformConditional(exprNode, reactiveNames, jsxMap, source) {
1383
- if (exprNode.isKind(SyntaxKind10.ConditionalExpression)) {
935
+ if (exprNode.isKind(SyntaxKind9.ConditionalExpression)) {
1384
936
  const condition = exprNode.getCondition();
1385
937
  const whenTrue = exprNode.getWhenTrue();
1386
938
  const whenFalse = exprNode.getWhenFalse();
@@ -1389,7 +941,7 @@ function tryTransformConditional(exprNode, reactiveNames, jsxMap, source) {
1389
941
  const falseBranch = transformBranch(whenFalse, reactiveNames, jsxMap, source);
1390
942
  return `__conditional(() => ${condText}, () => ${trueBranch}, () => ${falseBranch})`;
1391
943
  }
1392
- if (exprNode.isKind(SyntaxKind10.BinaryExpression) && exprNode.getOperatorToken().getKind() === SyntaxKind10.AmpersandAmpersandToken) {
944
+ if (exprNode.isKind(SyntaxKind9.BinaryExpression) && exprNode.getOperatorToken().getKind() === SyntaxKind9.AmpersandAmpersandToken) {
1393
945
  const left = exprNode.getLeft();
1394
946
  const right = exprNode.getRight();
1395
947
  const condText = source.slice(left.getStart(), left.getEnd());
@@ -1399,13 +951,13 @@ function tryTransformConditional(exprNode, reactiveNames, jsxMap, source) {
1399
951
  return null;
1400
952
  }
1401
953
  function transformBranch(node, reactiveNames, jsxMap, source) {
1402
- if (node.isKind(SyntaxKind10.ParenthesizedExpression)) {
954
+ if (node.isKind(SyntaxKind9.ParenthesizedExpression)) {
1403
955
  return transformBranch(node.getExpression(), reactiveNames, jsxMap, source);
1404
956
  }
1405
- if (node.isKind(SyntaxKind10.JsxElement) || node.isKind(SyntaxKind10.JsxSelfClosingElement) || node.isKind(SyntaxKind10.JsxFragment)) {
957
+ if (node.isKind(SyntaxKind9.JsxElement) || node.isKind(SyntaxKind9.JsxSelfClosingElement) || node.isKind(SyntaxKind9.JsxFragment)) {
1406
958
  return transformJsxNode(node, reactiveNames, jsxMap, source);
1407
959
  }
1408
- if (node.isKind(SyntaxKind10.ConditionalExpression)) {
960
+ if (node.isKind(SyntaxKind9.ConditionalExpression)) {
1409
961
  const nested = tryTransformConditional(node, reactiveNames, jsxMap, source);
1410
962
  if (nested)
1411
963
  return nested;
@@ -1413,10 +965,10 @@ function transformBranch(node, reactiveNames, jsxMap, source) {
1413
965
  return source.slice(node.getStart(), node.getEnd());
1414
966
  }
1415
967
  function tryTransformList(exprNode, reactiveNames, jsxMap, parentVar, source) {
1416
- if (!exprNode.isKind(SyntaxKind10.CallExpression))
968
+ if (!exprNode.isKind(SyntaxKind9.CallExpression))
1417
969
  return null;
1418
970
  const propAccess = exprNode.getExpression();
1419
- if (!propAccess.isKind(SyntaxKind10.PropertyAccessExpression))
971
+ if (!propAccess.isKind(SyntaxKind9.PropertyAccessExpression))
1420
972
  return null;
1421
973
  const methodName = propAccess.getNameNode().getText();
1422
974
  if (methodName !== "map")
@@ -1432,7 +984,7 @@ function tryTransformList(exprNode, reactiveNames, jsxMap, parentVar, source) {
1432
984
  let itemParam = null;
1433
985
  let indexParam = null;
1434
986
  let callbackBody = null;
1435
- if (callbackArg.isKind(SyntaxKind10.ArrowFunction)) {
987
+ if (callbackArg.isKind(SyntaxKind9.ArrowFunction)) {
1436
988
  const params = callbackArg.getParameters();
1437
989
  itemParam = params[0]?.getName() ?? null;
1438
990
  indexParam = params[1]?.getName() ?? null;
@@ -1459,36 +1011,36 @@ function extractKeyFunction(callbackBody, itemParam, indexParam) {
1459
1011
  return `(_item, __i) => __i`;
1460
1012
  }
1461
1013
  function findJsxInBody(node) {
1462
- if (node.isKind(SyntaxKind10.JsxElement) || node.isKind(SyntaxKind10.JsxSelfClosingElement)) {
1014
+ if (node.isKind(SyntaxKind9.JsxElement) || node.isKind(SyntaxKind9.JsxSelfClosingElement)) {
1463
1015
  return node;
1464
1016
  }
1465
- if (node.isKind(SyntaxKind10.Block)) {
1466
- const returnStmt = node.getFirstDescendantByKind(SyntaxKind10.ReturnStatement);
1017
+ if (node.isKind(SyntaxKind9.Block)) {
1018
+ const returnStmt = node.getFirstDescendantByKind(SyntaxKind9.ReturnStatement);
1467
1019
  if (returnStmt) {
1468
1020
  const expr = returnStmt.getExpression();
1469
1021
  if (expr)
1470
1022
  return findJsxInBody(expr);
1471
1023
  }
1472
1024
  }
1473
- if (node.isKind(SyntaxKind10.ParenthesizedExpression)) {
1025
+ if (node.isKind(SyntaxKind9.ParenthesizedExpression)) {
1474
1026
  return findJsxInBody(node.getExpression());
1475
1027
  }
1476
1028
  return null;
1477
1029
  }
1478
1030
  function extractKeyPropValue(jsxNode) {
1479
- const attrs = jsxNode.getDescendantsOfKind(SyntaxKind10.JsxAttribute);
1031
+ const attrs = jsxNode.getDescendantsOfKind(SyntaxKind9.JsxAttribute);
1480
1032
  for (const attr of attrs) {
1481
1033
  if (attr.getNameNode().getText() !== "key")
1482
1034
  continue;
1483
1035
  const init = attr.getInitializer();
1484
1036
  if (!init)
1485
1037
  continue;
1486
- if (init.isKind(SyntaxKind10.JsxExpression)) {
1038
+ if (init.isKind(SyntaxKind9.JsxExpression)) {
1487
1039
  const expr = init.getExpression();
1488
1040
  if (expr)
1489
1041
  return expr.getText();
1490
1042
  }
1491
- if (init.isKind(SyntaxKind10.StringLiteral)) {
1043
+ if (init.isKind(SyntaxKind9.StringLiteral)) {
1492
1044
  return init.getText();
1493
1045
  }
1494
1046
  }
@@ -1503,38 +1055,9 @@ function buildListRenderFunction(callbackBody, itemParam, reactiveNames, jsxMap,
1503
1055
  const bodyText = source.slice(callbackBody.getStart(), callbackBody.getEnd());
1504
1056
  return `(${itemParam}) => ${bodyText}`;
1505
1057
  }
1506
- function sliceWithTransformedJsx(node, reactiveNames, jsxMap, source, formVarNames) {
1507
- const start = node.getStart();
1508
- const end = node.getEnd();
1509
- const jsxNodes = [];
1510
- collectJsxInExpression(node, reactiveNames, jsxMap, source, formVarNames, jsxNodes);
1511
- if (jsxNodes.length === 0) {
1512
- return source.slice(start, end);
1513
- }
1514
- jsxNodes.sort((a, b) => a.start - b.start);
1515
- let result = "";
1516
- let cursor = start;
1517
- for (const jsx of jsxNodes) {
1518
- result += source.slice(cursor, jsx.start);
1519
- result += jsx.transformed;
1520
- cursor = jsx.end;
1521
- }
1522
- result += source.slice(cursor, end);
1523
- return result;
1524
- }
1525
- function collectJsxInExpression(node, reactiveNames, jsxMap, source, formVarNames, results) {
1526
- if (isJsxTopLevel(node)) {
1527
- const transformed = transformJsxNode(node, reactiveNames, jsxMap, source, formVarNames);
1528
- results.push({ start: node.getStart(), end: node.getEnd(), transformed });
1529
- return;
1530
- }
1531
- for (const child of node.getChildren()) {
1532
- collectJsxInExpression(child, reactiveNames, jsxMap, source, formVarNames, results);
1533
- }
1534
- }
1535
- function buildPropsObject(element, jsxMap, source, reactiveNames, formVarNames, extraEntries) {
1536
- const attrs = element.isKind(SyntaxKind10.JsxOpeningElement) || element.isKind(SyntaxKind10.JsxSelfClosingElement) ? element.getAttributes().filter((a) => a.isKind(SyntaxKind10.JsxAttribute)) : element.getDescendantsOfKind(SyntaxKind10.JsxAttribute);
1537
- if (attrs.length === 0 && (!extraEntries || extraEntries.size === 0))
1058
+ function buildPropsObject(element, jsxMap, source) {
1059
+ const attrs = element.getDescendantsOfKind(SyntaxKind9.JsxAttribute);
1060
+ if (attrs.length === 0)
1538
1061
  return "{}";
1539
1062
  const props = [];
1540
1063
  for (const attr of attrs) {
@@ -1544,14 +1067,14 @@ function buildPropsObject(element, jsxMap, source, reactiveNames, formVarNames,
1544
1067
  props.push(`${name}: true`);
1545
1068
  continue;
1546
1069
  }
1547
- if (init.isKind(SyntaxKind10.StringLiteral)) {
1070
+ if (init.isKind(SyntaxKind9.StringLiteral)) {
1548
1071
  props.push(`${name}: ${init.getText()}`);
1549
1072
  continue;
1550
1073
  }
1551
- if (init.isKind(SyntaxKind10.JsxExpression)) {
1074
+ if (init.isKind(SyntaxKind9.JsxExpression)) {
1552
1075
  const exprInfo = jsxMap.get(init.getStart());
1553
1076
  const exprNode = init.getExpression();
1554
- const exprText = exprNode ? sliceWithTransformedJsx(exprNode, reactiveNames, jsxMap, source, formVarNames) : "";
1077
+ const exprText = exprNode ? source.slice(exprNode.getStart(), exprNode.getEnd()) : "";
1555
1078
  if (exprInfo?.reactive) {
1556
1079
  props.push(`get ${name}() { return ${exprText}; }`);
1557
1080
  } else {
@@ -1559,11 +1082,6 @@ function buildPropsObject(element, jsxMap, source, reactiveNames, formVarNames,
1559
1082
  }
1560
1083
  }
1561
1084
  }
1562
- if (extraEntries) {
1563
- for (const [key, value] of extraEntries) {
1564
- props.push(`${key}: ${value}`);
1565
- }
1566
- }
1567
1085
  return `{ ${props.join(", ")} }`;
1568
1086
  }
1569
1087
  function getJsxChildren(node) {
@@ -1571,7 +1089,7 @@ function getJsxChildren(node) {
1571
1089
  for (const child of node.getChildren()) {
1572
1090
  if (isJsxChild(child)) {
1573
1091
  children.push(child);
1574
- } else if (child.isKind(SyntaxKind10.SyntaxList)) {
1092
+ } else if (child.isKind(SyntaxKind9.SyntaxList)) {
1575
1093
  for (const grandchild of child.getChildren()) {
1576
1094
  if (isJsxChild(grandchild)) {
1577
1095
  children.push(grandchild);
@@ -1582,30 +1100,7 @@ function getJsxChildren(node) {
1582
1100
  return children;
1583
1101
  }
1584
1102
  function isJsxChild(node) {
1585
- return node.isKind(SyntaxKind10.JsxText) || node.isKind(SyntaxKind10.JsxExpression) || node.isKind(SyntaxKind10.JsxElement) || node.isKind(SyntaxKind10.JsxSelfClosingElement) || node.isKind(SyntaxKind10.JsxFragment);
1586
- }
1587
- function tryBindElement(tagName, element, elVar, formVarNames) {
1588
- if (tagName !== "form" || formVarNames.size === 0)
1589
- return null;
1590
- const attrs = element.getDescendantsOfKind(SyntaxKind10.JsxAttribute);
1591
- for (const attr of attrs) {
1592
- if (attr.getNameNode().getText() !== "onSubmit")
1593
- continue;
1594
- const init = attr.getInitializer();
1595
- if (!init?.isKind(SyntaxKind10.JsxExpression))
1596
- continue;
1597
- const exprNode = init.getExpression();
1598
- if (!exprNode?.isKind(SyntaxKind10.PropertyAccessExpression))
1599
- continue;
1600
- const obj = exprNode.getExpression();
1601
- if (!obj.isKind(SyntaxKind10.Identifier))
1602
- continue;
1603
- const varName = obj.getText();
1604
- if (formVarNames.has(varName)) {
1605
- return `${varName}.__bindElement(${elVar})`;
1606
- }
1607
- }
1608
- return null;
1103
+ return node.isKind(SyntaxKind9.JsxText) || node.isKind(SyntaxKind9.JsxExpression) || node.isKind(SyntaxKind9.JsxElement) || node.isKind(SyntaxKind9.JsxSelfClosingElement);
1609
1104
  }
1610
1105
 
1611
1106
  // src/transformers/mutation-transformer.ts
@@ -1671,23 +1166,15 @@ class MutationTransformer {
1671
1166
  }
1672
1167
 
1673
1168
  // src/transformers/signal-transformer.ts
1674
- import { SyntaxKind as SyntaxKind11 } from "ts-morph";
1169
+ import { SyntaxKind as SyntaxKind10 } from "ts-morph";
1675
1170
  class SignalTransformer {
1676
1171
  transform(source, sourceFile, component, variables, mutationRanges = []) {
1677
1172
  const signals = new Set(variables.filter((v) => v.kind === "signal").map((v) => v.name));
1678
1173
  const signalApiVars = new Map;
1679
- const plainPropVars = new Map;
1680
- const fieldSignalPropVars = new Map;
1681
1174
  for (const v of variables) {
1682
1175
  if (v.signalProperties && v.signalProperties.size > 0) {
1683
1176
  signalApiVars.set(v.name, v.signalProperties);
1684
1177
  }
1685
- if (v.plainProperties && v.plainProperties.size > 0) {
1686
- plainPropVars.set(v.name, v.plainProperties);
1687
- }
1688
- if (v.fieldSignalProperties && v.fieldSignalProperties.size > 0) {
1689
- fieldSignalPropVars.set(v.name, v.fieldSignalProperties);
1690
- }
1691
1178
  }
1692
1179
  const bodyNode = findBodyNode(sourceFile, component);
1693
1180
  if (!bodyNode)
@@ -1696,16 +1183,16 @@ class SignalTransformer {
1696
1183
  transformDeclarations(source, bodyNode, signals);
1697
1184
  transformReferences(source, bodyNode, signals, mutationRanges);
1698
1185
  }
1699
- if (signalApiVars.size > 0 || fieldSignalPropVars.size > 0) {
1700
- transformSignalApiProperties(source, bodyNode, signalApiVars, plainPropVars, fieldSignalPropVars);
1186
+ if (signalApiVars.size > 0) {
1187
+ transformSignalApiProperties(source, bodyNode, signalApiVars);
1701
1188
  }
1702
1189
  }
1703
1190
  }
1704
1191
  function transformDeclarations(source, bodyNode, signals) {
1705
1192
  for (const stmt of bodyNode.getChildSyntaxList()?.getChildren() ?? []) {
1706
- if (!stmt.isKind(SyntaxKind11.VariableStatement))
1193
+ if (!stmt.isKind(SyntaxKind10.VariableStatement))
1707
1194
  continue;
1708
- const declList = stmt.getChildrenOfKind(SyntaxKind11.VariableDeclarationList)[0];
1195
+ const declList = stmt.getChildrenOfKind(SyntaxKind10.VariableDeclarationList)[0];
1709
1196
  if (!declList)
1710
1197
  continue;
1711
1198
  for (const decl of declList.getDeclarations()) {
@@ -1715,7 +1202,7 @@ function transformDeclarations(source, bodyNode, signals) {
1715
1202
  const init = decl.getInitializer();
1716
1203
  if (!init)
1717
1204
  continue;
1718
- const letKeyword = declList.getFirstChildByKind(SyntaxKind11.LetKeyword);
1205
+ const letKeyword = declList.getFirstChildByKind(SyntaxKind10.LetKeyword);
1719
1206
  if (letKeyword) {
1720
1207
  source.overwrite(letKeyword.getStart(), letKeyword.getEnd(), "const");
1721
1208
  }
@@ -1729,7 +1216,7 @@ function isInsideMutationRange(pos, ranges) {
1729
1216
  }
1730
1217
  function transformReferences(source, bodyNode, signals, mutationRanges) {
1731
1218
  bodyNode.forEachDescendant((node) => {
1732
- if (!node.isKind(SyntaxKind11.Identifier))
1219
+ if (!node.isKind(SyntaxKind10.Identifier))
1733
1220
  return;
1734
1221
  const name = node.getText();
1735
1222
  if (!signals.has(name))
@@ -1737,19 +1224,16 @@ function transformReferences(source, bodyNode, signals, mutationRanges) {
1737
1224
  const parent = node.getParent();
1738
1225
  if (!parent)
1739
1226
  return;
1740
- if (parent.isKind(SyntaxKind11.VariableDeclaration) && parent.getNameNode() === node) {
1741
- return;
1742
- }
1743
- if (parent.isKind(SyntaxKind11.PropertyAccessExpression) && parent.getNameNode() === node) {
1227
+ if (parent.isKind(SyntaxKind10.VariableDeclaration) && parent.getNameNode() === node) {
1744
1228
  return;
1745
1229
  }
1746
- if (parent.isKind(SyntaxKind11.PropertyAssignment) && parent.getNameNode() === node) {
1230
+ if (parent.isKind(SyntaxKind10.PropertyAccessExpression) && parent.getNameNode() === node) {
1747
1231
  return;
1748
1232
  }
1749
- if (parent.isKind(SyntaxKind11.ShorthandPropertyAssignment)) {
1233
+ if (parent.isKind(SyntaxKind10.PropertyAssignment) && parent.getNameNode() === node) {
1750
1234
  return;
1751
1235
  }
1752
- if (parent.isKind(SyntaxKind11.BindingElement)) {
1236
+ if (parent.isKind(SyntaxKind10.ShorthandPropertyAssignment)) {
1753
1237
  return;
1754
1238
  }
1755
1239
  if (isInsideMutationRange(node.getStart(), mutationRanges)) {
@@ -1758,72 +1242,32 @@ function transformReferences(source, bodyNode, signals, mutationRanges) {
1758
1242
  source.overwrite(node.getStart(), node.getEnd(), `${name}.value`);
1759
1243
  });
1760
1244
  }
1761
- function transformSignalApiProperties(source, bodyNode, signalApiVars, plainPropVars, fieldSignalPropVars) {
1762
- const threeLevelRanges = [];
1763
- bodyNode.forEachDescendant((node) => {
1764
- if (!node.isKind(SyntaxKind11.PropertyAccessExpression))
1765
- return;
1766
- const outerExpr = node.asKindOrThrow(SyntaxKind11.PropertyAccessExpression);
1767
- const middleExpr = outerExpr.getExpression();
1768
- const leafProp = outerExpr.getName();
1769
- if (!middleExpr.isKind(SyntaxKind11.PropertyAccessExpression))
1770
- return;
1771
- const innerExpr = middleExpr.asKindOrThrow(SyntaxKind11.PropertyAccessExpression);
1772
- const rootExpr = innerExpr.getExpression();
1773
- const middleProp = innerExpr.getName();
1774
- if (!rootExpr.isKind(SyntaxKind11.Identifier))
1775
- return;
1776
- const rootName = rootExpr.getText();
1777
- const fieldSignalProps = fieldSignalPropVars.get(rootName);
1778
- if (!fieldSignalProps)
1779
- return;
1780
- const signalProps = signalApiVars.get(rootName);
1781
- const plainProps = plainPropVars.get(rootName);
1782
- if (signalProps?.has(middleProp) || plainProps?.has(middleProp))
1783
- return;
1784
- if (!fieldSignalProps.has(leafProp))
1785
- return;
1786
- const parent = outerExpr.getParent();
1787
- if (parent?.isKind(SyntaxKind11.PropertyAccessExpression)) {
1788
- const parentProp = parent.asKindOrThrow(SyntaxKind11.PropertyAccessExpression);
1789
- if (parentProp.getExpression() === outerExpr && parentProp.getName() === "value") {
1790
- threeLevelRanges.push({ start: outerExpr.getStart(), end: outerExpr.getEnd() });
1791
- return;
1792
- }
1793
- }
1794
- source.appendLeft(outerExpr.getEnd(), ".value");
1795
- threeLevelRanges.push({ start: outerExpr.getStart(), end: outerExpr.getEnd() });
1796
- });
1245
+ function transformSignalApiProperties(source, bodyNode, signalApiVars) {
1797
1246
  bodyNode.forEachDescendant((node) => {
1798
- if (!node.isKind(SyntaxKind11.PropertyAccessExpression))
1799
- return;
1800
- const expr = node.asKindOrThrow(SyntaxKind11.PropertyAccessExpression);
1801
- const nodeStart = expr.getStart();
1802
- if (threeLevelRanges.some((r) => nodeStart >= r.start && nodeStart < r.end))
1247
+ if (!node.isKind(SyntaxKind10.PropertyAccessExpression))
1803
1248
  return;
1249
+ const expr = node.asKindOrThrow(SyntaxKind10.PropertyAccessExpression);
1804
1250
  const objExpr = expr.getExpression();
1805
1251
  const propName = expr.getName();
1806
- if (!objExpr.isKind(SyntaxKind11.Identifier))
1252
+ if (!objExpr.isKind(SyntaxKind10.Identifier))
1807
1253
  return;
1808
1254
  const varName = objExpr.getText();
1809
1255
  const signalProps = signalApiVars.get(varName);
1810
1256
  if (!signalProps || !signalProps.has(propName))
1811
1257
  return;
1812
1258
  const parent = expr.getParent();
1813
- if (parent?.isKind(SyntaxKind11.PropertyAccessExpression)) {
1814
- const parentProp = parent.asKindOrThrow(SyntaxKind11.PropertyAccessExpression);
1259
+ if (parent?.isKind(SyntaxKind10.PropertyAccessExpression)) {
1260
+ const parentProp = parent.asKindOrThrow(SyntaxKind10.PropertyAccessExpression);
1815
1261
  if (parentProp.getExpression() === expr && parentProp.getName() === "value") {
1816
1262
  return;
1817
1263
  }
1818
1264
  }
1819
- source.appendLeft(expr.getEnd(), ".value");
1265
+ source.appendRight(expr.getEnd(), ".value");
1820
1266
  });
1821
1267
  }
1822
1268
 
1823
1269
  // src/compiler.ts
1824
- function compile(source, optionsOrFilename) {
1825
- const options = typeof optionsOrFilename === "string" ? { filename: optionsOrFilename } : optionsOrFilename ?? {};
1826
- const filename = options.filename ?? "input.tsx";
1270
+ function compile(source, filename = "input.tsx") {
1827
1271
  const project = new Project({
1828
1272
  useInMemoryFileSystem: true,
1829
1273
  compilerOptions: {
@@ -1874,7 +1318,7 @@ function compile(source, optionsOrFilename) {
1874
1318
  usedFeatures.add("__text");
1875
1319
  usedFeatures.add("__attr");
1876
1320
  }
1877
- const hasEvents = sourceFile.getDescendantsOfKind(SyntaxKind12.JsxAttribute).some((attr) => {
1321
+ const hasEvents = sourceFile.getDescendantsOfKind(SyntaxKind11.JsxAttribute).some((attr) => {
1878
1322
  const name = attr.getNameNode().getText();
1879
1323
  return name.startsWith("on") && name.length > 2;
1880
1324
  });
@@ -1885,14 +1329,11 @@ function compile(source, optionsOrFilename) {
1885
1329
  jsxTransformer.transform(s, sourceFile, component, variables, jsxExpressions);
1886
1330
  const mutationDiags = new MutationDiagnostics;
1887
1331
  allDiagnostics.push(...mutationDiags.analyze(sourceFile, component, variables));
1888
- const ssrDiags = new SSRSafetyDiagnostics;
1889
- allDiagnostics.push(...ssrDiags.analyze(sourceFile, component));
1890
1332
  }
1891
1333
  const propsDiags = new PropsDestructuringDiagnostics;
1892
1334
  allDiagnostics.push(...propsDiags.analyze(sourceFile, components));
1893
1335
  detectDomHelpers(s.toString(), usedFeatures);
1894
- const target = options.target ?? "dom";
1895
- const imports = buildImportStatement(usedFeatures, target);
1336
+ const imports = buildImportStatement(usedFeatures);
1896
1337
  if (imports) {
1897
1338
  s.prepend(`${imports}
1898
1339
  `);
@@ -1908,16 +1349,12 @@ function compile(source, optionsOrFilename) {
1908
1349
  };
1909
1350
  }
1910
1351
  var DOM_HELPERS = [
1911
- "__append",
1912
1352
  "__child",
1913
- "__enterChildren",
1914
- "__exitChildren",
1915
1353
  "__insert",
1916
1354
  "__conditional",
1917
1355
  "__list",
1918
1356
  "__show",
1919
- "__classList",
1920
- "__staticText"
1357
+ "__classList"
1921
1358
  ];
1922
1359
  function detectDomHelpers(output, usedFeatures) {
1923
1360
  for (const helper of DOM_HELPERS) {
@@ -1926,7 +1363,7 @@ function detectDomHelpers(output, usedFeatures) {
1926
1363
  }
1927
1364
  }
1928
1365
  }
1929
- function buildImportStatement(features, target) {
1366
+ function buildImportStatement(features) {
1930
1367
  const runtimeImports = [];
1931
1368
  const domImports = [];
1932
1369
  for (const feature of features) {
@@ -1936,13 +1373,12 @@ function buildImportStatement(features, target) {
1936
1373
  domImports.push(feature);
1937
1374
  }
1938
1375
  }
1939
- const internalsSource = target === "tui" ? "@vertz/tui/internals" : "@vertz/ui/internals";
1940
1376
  const parts = [];
1941
1377
  if (runtimeImports.length > 0) {
1942
1378
  parts.push(`import { ${runtimeImports.sort().join(", ")} } from '@vertz/ui';`);
1943
1379
  }
1944
1380
  if (domImports.length > 0) {
1945
- parts.push(`import { ${domImports.sort().join(", ")} } from '${internalsSource}';`);
1381
+ parts.push(`import { ${domImports.sort().join(", ")} } from '@vertz/ui/internals';`);
1946
1382
  }
1947
1383
  return parts.length > 0 ? parts.join(`
1948
1384
  `) : null;
@@ -2013,7 +1449,6 @@ import {
2013
1449
  FONT_SIZE_SCALE,
2014
1450
  FONT_WEIGHT_SCALE,
2015
1451
  HEIGHT_AXIS_PROPERTIES,
2016
- KEYWORD_MAP,
2017
1452
  LINE_HEIGHT_SCALE,
2018
1453
  PROPERTY_MAP,
2019
1454
  PSEUDO_MAP,
@@ -2023,7 +1458,7 @@ import {
2023
1458
  SIZE_KEYWORDS,
2024
1459
  SPACING_SCALE
2025
1460
  } from "@vertz/ui/internals";
2026
- import { Project as Project2, SyntaxKind as SyntaxKind13, ts as ts2 } from "ts-morph";
1461
+ import { Project as Project2, SyntaxKind as SyntaxKind12, ts as ts2 } from "ts-morph";
2027
1462
 
2028
1463
  class CSSExtractor {
2029
1464
  extract(source, filePath) {
@@ -2034,28 +1469,28 @@ class CSSExtractor {
2034
1469
  const sourceFile = project.createSourceFile(filePath, source);
2035
1470
  const allCssRules = [];
2036
1471
  const allBlockNames = [];
2037
- const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind13.CallExpression);
1472
+ const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind12.CallExpression);
2038
1473
  for (const call of callExpressions) {
2039
1474
  const expression = call.getExpression();
2040
- if (!expression.isKind(SyntaxKind13.Identifier) || expression.getText() !== "css") {
1475
+ if (!expression.isKind(SyntaxKind12.Identifier) || expression.getText() !== "css") {
2041
1476
  continue;
2042
1477
  }
2043
1478
  const args = call.getArguments();
2044
1479
  if (args.length === 0)
2045
1480
  continue;
2046
1481
  const firstArg = args[0];
2047
- if (!firstArg.isKind(SyntaxKind13.ObjectLiteralExpression))
1482
+ if (!firstArg.isKind(SyntaxKind12.ObjectLiteralExpression))
2048
1483
  continue;
2049
1484
  if (!isStaticCSSCall(firstArg))
2050
1485
  continue;
2051
1486
  for (const prop of firstArg.getProperties()) {
2052
- if (!prop.isKind(SyntaxKind13.PropertyAssignment))
1487
+ if (!prop.isKind(SyntaxKind12.PropertyAssignment))
2053
1488
  continue;
2054
1489
  const blockName = prop.getName();
2055
1490
  allBlockNames.push(blockName);
2056
1491
  const className = generateClassName(filePath, blockName);
2057
1492
  const init = prop.getInitializer();
2058
- if (!init || !init.isKind(SyntaxKind13.ArrayLiteralExpression))
1493
+ if (!init || !init.isKind(SyntaxKind12.ArrayLiteralExpression))
2059
1494
  continue;
2060
1495
  const entries = extractEntries(init);
2061
1496
  const rules = buildCSSRules(className, entries);
@@ -2070,18 +1505,18 @@ class CSSExtractor {
2070
1505
  }
2071
1506
  }
2072
1507
  function isStaticCSSCall(node) {
2073
- if (!node.isKind(SyntaxKind13.ObjectLiteralExpression))
1508
+ if (!node.isKind(SyntaxKind12.ObjectLiteralExpression))
2074
1509
  return false;
2075
1510
  for (const prop of node.getProperties()) {
2076
- if (!prop.isKind(SyntaxKind13.PropertyAssignment))
1511
+ if (!prop.isKind(SyntaxKind12.PropertyAssignment))
2077
1512
  return false;
2078
1513
  const initializer = prop.getInitializer();
2079
- if (!initializer || !initializer.isKind(SyntaxKind13.ArrayLiteralExpression))
1514
+ if (!initializer || !initializer.isKind(SyntaxKind12.ArrayLiteralExpression))
2080
1515
  return false;
2081
1516
  for (const element of initializer.getElements()) {
2082
- if (element.isKind(SyntaxKind13.StringLiteral))
1517
+ if (element.isKind(SyntaxKind12.StringLiteral))
2083
1518
  continue;
2084
- if (element.isKind(SyntaxKind13.ObjectLiteralExpression)) {
1519
+ if (element.isKind(SyntaxKind12.ObjectLiteralExpression)) {
2085
1520
  if (!isStaticNestedObject(element))
2086
1521
  return false;
2087
1522
  continue;
@@ -2092,110 +1527,55 @@ function isStaticCSSCall(node) {
2092
1527
  return true;
2093
1528
  }
2094
1529
  function isStaticNestedObject(node) {
2095
- if (!node.isKind(SyntaxKind13.ObjectLiteralExpression))
1530
+ if (!node.isKind(SyntaxKind12.ObjectLiteralExpression))
2096
1531
  return false;
2097
1532
  for (const prop of node.getProperties()) {
2098
- if (!prop.isKind(SyntaxKind13.PropertyAssignment))
1533
+ if (!prop.isKind(SyntaxKind12.PropertyAssignment))
2099
1534
  return false;
2100
1535
  const init = prop.getInitializer();
2101
- if (!init || !init.isKind(SyntaxKind13.ArrayLiteralExpression))
1536
+ if (!init || !init.isKind(SyntaxKind12.ArrayLiteralExpression))
2102
1537
  return false;
2103
1538
  for (const el of init.getElements()) {
2104
- if (el.isKind(SyntaxKind13.StringLiteral))
2105
- continue;
2106
- if (el.isKind(SyntaxKind13.ObjectLiteralExpression)) {
2107
- if (isStaticRawDeclaration(el))
2108
- continue;
1539
+ if (!el.isKind(SyntaxKind12.StringLiteral))
2109
1540
  return false;
2110
- }
2111
- return false;
2112
1541
  }
2113
1542
  }
2114
1543
  return true;
2115
1544
  }
2116
- function isStaticRawDeclaration(node) {
2117
- if (!node.isKind(SyntaxKind13.ObjectLiteralExpression))
2118
- return false;
2119
- const props = node.getProperties();
2120
- if (props.length !== 2)
2121
- return false;
2122
- let hasProperty = false;
2123
- let hasValue = false;
2124
- for (const prop of props) {
2125
- if (!prop.isKind(SyntaxKind13.PropertyAssignment))
2126
- return false;
2127
- const init = prop.getInitializer();
2128
- if (!init || !init.isKind(SyntaxKind13.StringLiteral))
2129
- return false;
2130
- const name = prop.getName();
2131
- if (name === "property")
2132
- hasProperty = true;
2133
- else if (name === "value")
2134
- hasValue = true;
2135
- }
2136
- return hasProperty && hasValue;
2137
- }
2138
1545
  function extractEntries(arrayNode) {
2139
- if (!arrayNode.isKind(SyntaxKind13.ArrayLiteralExpression))
1546
+ if (!arrayNode.isKind(SyntaxKind12.ArrayLiteralExpression))
2140
1547
  return [];
2141
1548
  const results = [];
2142
1549
  for (const element of arrayNode.getElements()) {
2143
- if (element.isKind(SyntaxKind13.StringLiteral)) {
1550
+ if (element.isKind(SyntaxKind12.StringLiteral)) {
2144
1551
  results.push({ kind: "shorthand", value: element.getLiteralValue() });
2145
- } else if (element.isKind(SyntaxKind13.ObjectLiteralExpression)) {
1552
+ } else if (element.isKind(SyntaxKind12.ObjectLiteralExpression)) {
2146
1553
  for (const prop of element.getProperties()) {
2147
- if (!prop.isKind(SyntaxKind13.PropertyAssignment))
1554
+ if (!prop.isKind(SyntaxKind12.PropertyAssignment))
2148
1555
  continue;
2149
1556
  const selector = prop.getName();
2150
1557
  const nameNode = prop.getNameNode();
2151
- const actualSelector = nameNode.isKind(SyntaxKind13.StringLiteral) ? nameNode.getLiteralValue() : selector;
1558
+ const actualSelector = nameNode.isKind(SyntaxKind12.StringLiteral) ? nameNode.getLiteralValue() : selector;
2152
1559
  const init = prop.getInitializer();
2153
- if (!init || !init.isKind(SyntaxKind13.ArrayLiteralExpression))
1560
+ if (!init || !init.isKind(SyntaxKind12.ArrayLiteralExpression))
2154
1561
  continue;
2155
1562
  const nestedEntries = [];
2156
- const rawDeclarations = [];
2157
1563
  for (const el of init.getElements()) {
2158
- if (el.isKind(SyntaxKind13.StringLiteral)) {
1564
+ if (el.isKind(SyntaxKind12.StringLiteral)) {
2159
1565
  nestedEntries.push(el.getLiteralValue());
2160
- } else if (el.isKind(SyntaxKind13.ObjectLiteralExpression)) {
2161
- const rawDecl = extractRawDeclaration(el);
2162
- if (rawDecl)
2163
- rawDeclarations.push(rawDecl);
2164
1566
  }
2165
1567
  }
2166
1568
  results.push({
2167
1569
  kind: "nested",
2168
1570
  value: "",
2169
1571
  selector: actualSelector,
2170
- entries: nestedEntries,
2171
- rawDeclarations
1572
+ entries: nestedEntries
2172
1573
  });
2173
1574
  }
2174
1575
  }
2175
1576
  }
2176
1577
  return results;
2177
1578
  }
2178
- function extractRawDeclaration(node) {
2179
- if (!node.isKind(SyntaxKind13.ObjectLiteralExpression))
2180
- return null;
2181
- let property = null;
2182
- let value = null;
2183
- for (const prop of node.getProperties()) {
2184
- if (!prop.isKind(SyntaxKind13.PropertyAssignment))
2185
- return null;
2186
- const name = prop.getName();
2187
- const init = prop.getInitializer();
2188
- if (!init || !init.isKind(SyntaxKind13.StringLiteral))
2189
- return null;
2190
- if (name === "property")
2191
- property = init.getLiteralValue();
2192
- else if (name === "value")
2193
- value = init.getLiteralValue();
2194
- }
2195
- if (property && value)
2196
- return { property, value };
2197
- return null;
2198
- }
2199
1579
  function buildCSSRules(className, entries) {
2200
1580
  const rules = [];
2201
1581
  const baseDecls = [];
@@ -2226,12 +1606,7 @@ function buildCSSRules(className, entries) {
2226
1606
  continue;
2227
1607
  nestedDecls.push(...resolved);
2228
1608
  }
2229
- if (entry.rawDeclarations) {
2230
- for (const raw of entry.rawDeclarations) {
2231
- nestedDecls.push(`${raw.property}: ${raw.value};`);
2232
- }
2233
- }
2234
- const resolvedSelector = entry.selector.replaceAll("&", `.${className}`);
1609
+ const resolvedSelector = entry.selector.replace("&", `.${className}`);
2235
1610
  if (nestedDecls.length > 0) {
2236
1611
  rules.push(formatCSSRule(resolvedSelector, nestedDecls));
2237
1612
  }
@@ -2278,10 +1653,6 @@ function resolveDeclarations(parsed) {
2278
1653
  if (DISPLAY_MAP[property] !== undefined && value === null) {
2279
1654
  return [`display: ${DISPLAY_MAP[property]};`];
2280
1655
  }
2281
- const keyword = KEYWORD_MAP[property];
2282
- if (keyword !== undefined && value === null) {
2283
- return keyword.map((d) => `${d.property}: ${d.value};`);
2284
- }
2285
1656
  const mapping = PROPERTY_MAP[property];
2286
1657
  if (!mapping || value === null)
2287
1658
  return null;
@@ -2418,39 +1789,39 @@ class RouteCSSManifest {
2418
1789
  import {
2419
1790
  COLOR_NAMESPACES as COLOR_NAMESPACES2,
2420
1791
  CSS_COLOR_KEYWORDS as CSS_COLOR_KEYWORDS2,
2421
- KEYWORD_MAP as KEYWORD_MAP2,
1792
+ KEYWORD_MAP,
2422
1793
  PROPERTY_MAP as PROPERTY_MAP2,
2423
1794
  PSEUDO_PREFIXES as PSEUDO_PREFIXES2,
2424
1795
  SPACING_SCALE as SPACING_SCALE2
2425
1796
  } from "@vertz/ui/internals";
2426
- import { SyntaxKind as SyntaxKind14 } from "ts-morph";
2427
- var KNOWN_PROPERTIES = new Set([...Object.keys(PROPERTY_MAP2), ...Object.keys(KEYWORD_MAP2)]);
1797
+ import { SyntaxKind as SyntaxKind13 } from "ts-morph";
1798
+ var KNOWN_PROPERTIES = new Set([...Object.keys(PROPERTY_MAP2), ...Object.keys(KEYWORD_MAP)]);
2428
1799
  var SPACING_VALUES = new Set(Object.keys(SPACING_SCALE2));
2429
1800
  var SPACING_PROPERTIES = new Set(Object.entries(PROPERTY_MAP2).filter(([_, mapping]) => mapping.valueType === "spacing").map(([key]) => key));
2430
1801
 
2431
1802
  class CSSDiagnostics {
2432
1803
  analyze(sourceFile) {
2433
1804
  const diagnostics = [];
2434
- const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind14.CallExpression);
1805
+ const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind13.CallExpression);
2435
1806
  for (const call of callExpressions) {
2436
1807
  const expression = call.getExpression();
2437
- if (!expression.isKind(SyntaxKind14.Identifier) || expression.getText() !== "css") {
1808
+ if (!expression.isKind(SyntaxKind13.Identifier) || expression.getText() !== "css") {
2438
1809
  continue;
2439
1810
  }
2440
1811
  const args = call.getArguments();
2441
1812
  if (args.length === 0)
2442
1813
  continue;
2443
1814
  const firstArg = args[0];
2444
- if (!firstArg || !firstArg.isKind(SyntaxKind14.ObjectLiteralExpression))
1815
+ if (!firstArg || !firstArg.isKind(SyntaxKind13.ObjectLiteralExpression))
2445
1816
  continue;
2446
1817
  for (const prop of firstArg.getProperties()) {
2447
- if (!prop.isKind(SyntaxKind14.PropertyAssignment))
1818
+ if (!prop.isKind(SyntaxKind13.PropertyAssignment))
2448
1819
  continue;
2449
1820
  const init = prop.getInitializer();
2450
- if (!init || !init.isKind(SyntaxKind14.ArrayLiteralExpression))
1821
+ if (!init || !init.isKind(SyntaxKind13.ArrayLiteralExpression))
2451
1822
  continue;
2452
1823
  for (const element of init.getElements()) {
2453
- if (!element.isKind(SyntaxKind14.StringLiteral))
1824
+ if (!element.isKind(SyntaxKind13.StringLiteral))
2454
1825
  continue;
2455
1826
  const value = element.getLiteralValue();
2456
1827
  const pos = sourceFile.getLineAndColumnAtPos(element.getStart());
@@ -2568,152 +1939,6 @@ class CSSDiagnostics {
2568
1939
  }
2569
1940
  }
2570
1941
  }
2571
- // src/library-plugin.ts
2572
- import { readFile } from "node:fs/promises";
2573
- import remapping from "@ampproject/remapping";
2574
- import MagicString2 from "magic-string";
2575
- import { Project as Project3, ts as ts3 } from "ts-morph";
2576
-
2577
- // src/transformers/hydration-transformer.ts
2578
- import { SyntaxKind as SyntaxKind15 } from "ts-morph";
2579
- class HydrationTransformer {
2580
- transform(s, sourceFile) {
2581
- const componentAnalyzer = new ComponentAnalyzer;
2582
- const components = componentAnalyzer.analyze(sourceFile);
2583
- for (const component of components) {
2584
- if (this._isInteractive(sourceFile, component)) {
2585
- this._addHydrationMarker(s, sourceFile, component);
2586
- }
2587
- }
2588
- }
2589
- _isInteractive(sourceFile, component) {
2590
- const bodyNode = findBodyNode(sourceFile, component);
2591
- if (!bodyNode)
2592
- return false;
2593
- for (const stmt of bodyNode.getChildSyntaxList()?.getChildren() ?? []) {
2594
- if (!stmt.isKind(SyntaxKind15.VariableStatement))
2595
- continue;
2596
- const declList = stmt.getChildrenOfKind(SyntaxKind15.VariableDeclarationList)[0];
2597
- if (!declList)
2598
- continue;
2599
- if (declList.getText().startsWith("let ")) {
2600
- return true;
2601
- }
2602
- }
2603
- return false;
2604
- }
2605
- _addHydrationMarker(s, sourceFile, component) {
2606
- const bodyNode = findBodyNode(sourceFile, component);
2607
- if (!bodyNode)
2608
- return;
2609
- const returnStmts = bodyNode.getDescendantsOfKind(SyntaxKind15.ReturnStatement);
2610
- for (const ret of returnStmts) {
2611
- const expr = ret.getExpression();
2612
- if (!expr)
2613
- continue;
2614
- const rootJsx = this._findRootJsx(expr);
2615
- if (rootJsx) {
2616
- this._injectAttribute(s, rootJsx, component.name);
2617
- return;
2618
- }
2619
- }
2620
- const arrowBodies = sourceFile.getDescendantsOfKind(SyntaxKind15.ArrowFunction);
2621
- for (const arrow of arrowBodies) {
2622
- const body = arrow.getBody();
2623
- if (body.getStart() === component.bodyStart && body.getEnd() === component.bodyEnd) {
2624
- const rootJsx = this._findRootJsx(body);
2625
- if (rootJsx) {
2626
- this._injectAttribute(s, rootJsx, component.name);
2627
- return;
2628
- }
2629
- }
2630
- }
2631
- }
2632
- _findRootJsx(node) {
2633
- if (node.isKind(SyntaxKind15.JsxElement) || node.isKind(SyntaxKind15.JsxSelfClosingElement)) {
2634
- return node;
2635
- }
2636
- if (node.isKind(SyntaxKind15.ParenthesizedExpression)) {
2637
- const inner = node.getExpression();
2638
- return this._findRootJsx(inner);
2639
- }
2640
- for (const child of node.getChildren()) {
2641
- const found = this._findRootJsx(child);
2642
- if (found)
2643
- return found;
2644
- }
2645
- return null;
2646
- }
2647
- _injectAttribute(s, jsxNode, componentName) {
2648
- if (jsxNode.isKind(SyntaxKind15.JsxSelfClosingElement)) {
2649
- const tagName = jsxNode.getChildrenOfKind(SyntaxKind15.Identifier)[0];
2650
- if (tagName) {
2651
- const insertPos = tagName.getEnd();
2652
- s.appendLeft(insertPos, ` data-v-id="${componentName}"`);
2653
- }
2654
- } else if (jsxNode.isKind(SyntaxKind15.JsxElement)) {
2655
- const openingElement = jsxNode.getChildrenOfKind(SyntaxKind15.JsxOpeningElement)[0];
2656
- if (openingElement) {
2657
- const tagName = openingElement.getChildrenOfKind(SyntaxKind15.Identifier)[0];
2658
- if (tagName) {
2659
- const insertPos = tagName.getEnd();
2660
- s.appendLeft(insertPos, ` data-v-id="${componentName}"`);
2661
- }
2662
- }
2663
- }
2664
- }
2665
- }
2666
-
2667
- // src/library-plugin.ts
2668
- function createVertzLibraryPlugin(options) {
2669
- const filter = options?.filter ?? /\.tsx$/;
2670
- return {
2671
- name: "vertz-library-plugin",
2672
- setup(build) {
2673
- build.onLoad({ filter }, async (args) => {
2674
- const source = await readFile(args.path, "utf-8");
2675
- const hydrationS = new MagicString2(source);
2676
- const hydrationProject = new Project3({
2677
- useInMemoryFileSystem: true,
2678
- compilerOptions: {
2679
- jsx: ts3.JsxEmit.Preserve,
2680
- strict: true
2681
- }
2682
- });
2683
- const hydrationSourceFile = hydrationProject.createSourceFile(args.path, source);
2684
- const hydrationTransformer = new HydrationTransformer;
2685
- hydrationTransformer.transform(hydrationS, hydrationSourceFile);
2686
- const hydratedCode = hydrationS.toString();
2687
- const hydrationMap = hydrationS.generateMap({
2688
- source: args.path,
2689
- includeContent: true
2690
- });
2691
- const compileResult = compile(hydratedCode, {
2692
- filename: args.path,
2693
- target: options?.target
2694
- });
2695
- const errors = compileResult.diagnostics.filter((d) => d.severity === "error");
2696
- if (errors.length > 0) {
2697
- const messages = errors.map((d) => `${d.code}: ${d.message} (line ${d.line})`);
2698
- throw new Error(`Vertz compilation errors in ${args.path}:
2699
- ${messages.join(`
2700
- `)}`);
2701
- }
2702
- for (const d of compileResult.diagnostics) {
2703
- if (d.severity === "warning") {
2704
- console.warn(`[vertz-library-plugin] ${args.path}:${d.line} ${d.code}: ${d.message}`);
2705
- }
2706
- }
2707
- const remapped = remapping([compileResult.map, hydrationMap], () => null);
2708
- const mapBase64 = Buffer.from(remapped.toString()).toString("base64");
2709
- const sourceMapComment = `
2710
- //# sourceMappingURL=data:application/json;base64,${mapBase64}`;
2711
- const contents = compileResult.code + sourceMapComment;
2712
- return { contents, loader: "tsx" };
2713
- });
2714
- }
2715
- };
2716
- }
2717
1942
  // src/transformers/css-transformer.ts
2718
1943
  import {
2719
1944
  ALIGNMENT_MAP as ALIGNMENT_MAP2,
@@ -2724,7 +1949,6 @@ import {
2724
1949
  FONT_SIZE_SCALE as FONT_SIZE_SCALE2,
2725
1950
  FONT_WEIGHT_SCALE as FONT_WEIGHT_SCALE2,
2726
1951
  HEIGHT_AXIS_PROPERTIES as HEIGHT_AXIS_PROPERTIES2,
2727
- KEYWORD_MAP as KEYWORD_MAP3,
2728
1952
  LINE_HEIGHT_SCALE as LINE_HEIGHT_SCALE2,
2729
1953
  PROPERTY_MAP as PROPERTY_MAP3,
2730
1954
  PSEUDO_MAP as PSEUDO_MAP2,
@@ -2734,7 +1958,7 @@ import {
2734
1958
  SIZE_KEYWORDS as SIZE_KEYWORDS2,
2735
1959
  SPACING_SCALE as SPACING_SCALE3
2736
1960
  } from "@vertz/ui/internals";
2737
- import { SyntaxKind as SyntaxKind16 } from "ts-morph";
1961
+ import { SyntaxKind as SyntaxKind14 } from "ts-morph";
2738
1962
 
2739
1963
  class CSSTransformer {
2740
1964
  transform(s, sourceFile, cssCalls, filePath) {
@@ -2767,17 +1991,17 @@ class CSSTransformer {
2767
1991
  if (args.length === 0)
2768
1992
  return { classNames, cssRules };
2769
1993
  const firstArg = args[0];
2770
- if (!firstArg || !firstArg.isKind(SyntaxKind16.ObjectLiteralExpression)) {
1994
+ if (!firstArg || !firstArg.isKind(SyntaxKind14.ObjectLiteralExpression)) {
2771
1995
  return { classNames, cssRules };
2772
1996
  }
2773
1997
  for (const prop of firstArg.getProperties()) {
2774
- if (!prop.isKind(SyntaxKind16.PropertyAssignment))
1998
+ if (!prop.isKind(SyntaxKind14.PropertyAssignment))
2775
1999
  continue;
2776
2000
  const blockName = prop.getName();
2777
2001
  const className = generateClassName2(filePath, blockName);
2778
2002
  classNames[blockName] = className;
2779
2003
  const init = prop.getInitializer();
2780
- if (!init || !init.isKind(SyntaxKind16.ArrayLiteralExpression))
2004
+ if (!init || !init.isKind(SyntaxKind14.ArrayLiteralExpression))
2781
2005
  continue;
2782
2006
  const entries = extractEntries2(init);
2783
2007
  const rules = buildCSSRules2(className, entries);
@@ -2791,7 +2015,7 @@ class CSSTransformer {
2791
2015
  }
2792
2016
  }
2793
2017
  function findCallAtPosition(sourceFile, start) {
2794
- const calls = sourceFile.getDescendantsOfKind(SyntaxKind16.CallExpression);
2018
+ const calls = sourceFile.getDescendantsOfKind(SyntaxKind14.CallExpression);
2795
2019
  for (const call of calls) {
2796
2020
  if (call.getStart() === start)
2797
2021
  return call;
@@ -2799,66 +2023,39 @@ function findCallAtPosition(sourceFile, start) {
2799
2023
  return null;
2800
2024
  }
2801
2025
  function extractEntries2(arrayNode) {
2802
- if (!arrayNode.isKind(SyntaxKind16.ArrayLiteralExpression))
2026
+ if (!arrayNode.isKind(SyntaxKind14.ArrayLiteralExpression))
2803
2027
  return [];
2804
2028
  const results = [];
2805
2029
  for (const element of arrayNode.getElements()) {
2806
- if (element.isKind(SyntaxKind16.StringLiteral)) {
2030
+ if (element.isKind(SyntaxKind14.StringLiteral)) {
2807
2031
  results.push({ kind: "shorthand", value: element.getLiteralValue() });
2808
- } else if (element.isKind(SyntaxKind16.ObjectLiteralExpression)) {
2032
+ } else if (element.isKind(SyntaxKind14.ObjectLiteralExpression)) {
2809
2033
  for (const prop of element.getProperties()) {
2810
- if (!prop.isKind(SyntaxKind16.PropertyAssignment))
2034
+ if (!prop.isKind(SyntaxKind14.PropertyAssignment))
2811
2035
  continue;
2812
2036
  const selector = prop.getName();
2813
2037
  const nameNode = prop.getNameNode();
2814
- const actualSelector = nameNode.isKind(SyntaxKind16.StringLiteral) ? nameNode.getLiteralValue() : selector;
2038
+ const actualSelector = nameNode.isKind(SyntaxKind14.StringLiteral) ? nameNode.getLiteralValue() : selector;
2815
2039
  const init = prop.getInitializer();
2816
- if (!init || !init.isKind(SyntaxKind16.ArrayLiteralExpression))
2040
+ if (!init || !init.isKind(SyntaxKind14.ArrayLiteralExpression))
2817
2041
  continue;
2818
2042
  const nestedEntries = [];
2819
- const rawDeclarations = [];
2820
2043
  for (const el of init.getElements()) {
2821
- if (el.isKind(SyntaxKind16.StringLiteral)) {
2044
+ if (el.isKind(SyntaxKind14.StringLiteral)) {
2822
2045
  nestedEntries.push(el.getLiteralValue());
2823
- } else if (el.isKind(SyntaxKind16.ObjectLiteralExpression)) {
2824
- const rawDecl = extractRawDeclaration2(el);
2825
- if (rawDecl)
2826
- rawDeclarations.push(rawDecl);
2827
2046
  }
2828
2047
  }
2829
2048
  results.push({
2830
2049
  kind: "nested",
2831
2050
  value: "",
2832
2051
  selector: actualSelector,
2833
- entries: nestedEntries,
2834
- rawDeclarations
2052
+ entries: nestedEntries
2835
2053
  });
2836
2054
  }
2837
2055
  }
2838
2056
  }
2839
2057
  return results;
2840
2058
  }
2841
- function extractRawDeclaration2(node) {
2842
- if (!node.isKind(SyntaxKind16.ObjectLiteralExpression))
2843
- return null;
2844
- let property = null;
2845
- let value = null;
2846
- for (const prop of node.getProperties()) {
2847
- if (!prop.isKind(SyntaxKind16.PropertyAssignment))
2848
- return null;
2849
- const name = prop.getName();
2850
- const init = prop.getInitializer();
2851
- if (!init || !init.isKind(SyntaxKind16.StringLiteral))
2852
- return null;
2853
- if (name === "property")
2854
- property = init.getLiteralValue();
2855
- else if (name === "value")
2856
- value = init.getLiteralValue();
2857
- }
2858
- if (property && value)
2859
- return { property, value };
2860
- return null;
2861
- }
2862
2059
  function generateClassName2(filePath, blockName) {
2863
2060
  const input = `${filePath}::${blockName}`;
2864
2061
  const hash = djb2Hash2(input);
@@ -2901,12 +2098,7 @@ function buildCSSRules2(className, entries) {
2901
2098
  continue;
2902
2099
  nestedDecls.push(...resolved);
2903
2100
  }
2904
- if (entry.rawDeclarations) {
2905
- for (const raw of entry.rawDeclarations) {
2906
- nestedDecls.push(`${raw.property}: ${raw.value};`);
2907
- }
2908
- }
2909
- const resolvedSelector = entry.selector.replaceAll("&", `.${className}`);
2101
+ const resolvedSelector = entry.selector.replace("&", `.${className}`);
2910
2102
  if (nestedDecls.length > 0) {
2911
2103
  rules.push(formatCSSRule2(resolvedSelector, nestedDecls));
2912
2104
  }
@@ -2953,10 +2145,6 @@ function resolveInline(parsed) {
2953
2145
  if (DISPLAY_MAP2[property] !== undefined && value === null) {
2954
2146
  return [`display: ${DISPLAY_MAP2[property]};`];
2955
2147
  }
2956
- const keyword = KEYWORD_MAP3[property];
2957
- if (keyword !== undefined && value === null) {
2958
- return keyword.map((d) => `${d.property}: ${d.value};`);
2959
- }
2960
2148
  const mapping = PROPERTY_MAP3[property];
2961
2149
  if (!mapping || value === null)
2962
2150
  return null;
@@ -3018,8 +2206,97 @@ function resolveColorInline(value) {
3018
2206
  return value;
3019
2207
  return null;
3020
2208
  }
2209
+ // src/transformers/hydration-transformer.ts
2210
+ import { SyntaxKind as SyntaxKind15 } from "ts-morph";
2211
+ class HydrationTransformer {
2212
+ transform(s, sourceFile) {
2213
+ const componentAnalyzer = new ComponentAnalyzer;
2214
+ const components = componentAnalyzer.analyze(sourceFile);
2215
+ for (const component of components) {
2216
+ if (this._isInteractive(sourceFile, component)) {
2217
+ this._addHydrationMarker(s, sourceFile, component);
2218
+ }
2219
+ }
2220
+ }
2221
+ _isInteractive(sourceFile, component) {
2222
+ const bodyNode = findBodyNode(sourceFile, component);
2223
+ if (!bodyNode)
2224
+ return false;
2225
+ for (const stmt of bodyNode.getChildSyntaxList()?.getChildren() ?? []) {
2226
+ if (!stmt.isKind(SyntaxKind15.VariableStatement))
2227
+ continue;
2228
+ const declList = stmt.getChildrenOfKind(SyntaxKind15.VariableDeclarationList)[0];
2229
+ if (!declList)
2230
+ continue;
2231
+ if (declList.getText().startsWith("let ")) {
2232
+ return true;
2233
+ }
2234
+ }
2235
+ return false;
2236
+ }
2237
+ _addHydrationMarker(s, sourceFile, component) {
2238
+ const bodyNode = findBodyNode(sourceFile, component);
2239
+ if (!bodyNode)
2240
+ return;
2241
+ const returnStmts = bodyNode.getDescendantsOfKind(SyntaxKind15.ReturnStatement);
2242
+ for (const ret of returnStmts) {
2243
+ const expr = ret.getExpression();
2244
+ if (!expr)
2245
+ continue;
2246
+ const rootJsx = this._findRootJsx(expr);
2247
+ if (rootJsx) {
2248
+ this._injectAttribute(s, rootJsx, component.name);
2249
+ return;
2250
+ }
2251
+ }
2252
+ const arrowBodies = sourceFile.getDescendantsOfKind(SyntaxKind15.ArrowFunction);
2253
+ for (const arrow of arrowBodies) {
2254
+ const body = arrow.getBody();
2255
+ if (body.getStart() === component.bodyStart && body.getEnd() === component.bodyEnd) {
2256
+ const rootJsx = this._findRootJsx(body);
2257
+ if (rootJsx) {
2258
+ this._injectAttribute(s, rootJsx, component.name);
2259
+ return;
2260
+ }
2261
+ }
2262
+ }
2263
+ }
2264
+ _findRootJsx(node) {
2265
+ if (node.isKind(SyntaxKind15.JsxElement) || node.isKind(SyntaxKind15.JsxSelfClosingElement)) {
2266
+ return node;
2267
+ }
2268
+ if (node.isKind(SyntaxKind15.ParenthesizedExpression)) {
2269
+ const inner = node.getExpression();
2270
+ return this._findRootJsx(inner);
2271
+ }
2272
+ for (const child of node.getChildren()) {
2273
+ const found = this._findRootJsx(child);
2274
+ if (found)
2275
+ return found;
2276
+ }
2277
+ return null;
2278
+ }
2279
+ _injectAttribute(s, jsxNode, componentName) {
2280
+ if (jsxNode.isKind(SyntaxKind15.JsxSelfClosingElement)) {
2281
+ const tagName = jsxNode.getChildrenOfKind(SyntaxKind15.Identifier)[0];
2282
+ if (tagName) {
2283
+ const insertPos = tagName.getEnd();
2284
+ s.appendLeft(insertPos, ` data-v-id="${componentName}"`);
2285
+ }
2286
+ } else if (jsxNode.isKind(SyntaxKind15.JsxElement)) {
2287
+ const openingElement = jsxNode.getChildrenOfKind(SyntaxKind15.JsxOpeningElement)[0];
2288
+ if (openingElement) {
2289
+ const tagName = openingElement.getChildrenOfKind(SyntaxKind15.Identifier)[0];
2290
+ if (tagName) {
2291
+ const insertPos = tagName.getEnd();
2292
+ s.appendLeft(insertPos, ` data-v-id="${componentName}"`);
2293
+ }
2294
+ }
2295
+ }
2296
+ }
2297
+ }
3021
2298
  // src/transformers/prop-transformer.ts
3022
- import { SyntaxKind as SyntaxKind17 } from "ts-morph";
2299
+ import { SyntaxKind as SyntaxKind16 } from "ts-morph";
3023
2300
 
3024
2301
  class PropTransformer {
3025
2302
  transform(_source, _sourceFile, _component, _variables, _jsxExpressions) {}
@@ -3028,7 +2305,7 @@ class PropTransformer {
3028
2305
  return "{}";
3029
2306
  const props = [];
3030
2307
  for (const attr of attrs) {
3031
- if (!attr.isKind(SyntaxKind17.JsxAttribute))
2308
+ if (!attr.isKind(SyntaxKind16.JsxAttribute))
3032
2309
  continue;
3033
2310
  const name = attr.getNameNode().getText();
3034
2311
  const init = attr.getInitializer();
@@ -3036,11 +2313,11 @@ class PropTransformer {
3036
2313
  props.push(`${name}: true`);
3037
2314
  continue;
3038
2315
  }
3039
- if (init.isKind(SyntaxKind17.StringLiteral)) {
2316
+ if (init.isKind(SyntaxKind16.StringLiteral)) {
3040
2317
  props.push(`${name}: ${init.getText()}`);
3041
2318
  continue;
3042
2319
  }
3043
- if (init.isKind(SyntaxKind17.JsxExpression)) {
2320
+ if (init.isKind(SyntaxKind16.JsxExpression)) {
3044
2321
  const exprInfo = jsxMap.get(init.getStart());
3045
2322
  const exprNode = init.getExpression();
3046
2323
  const exprText = exprNode?.getText() ?? "";
@@ -3110,13 +2387,306 @@ ${entries.join(`
3110
2387
  `)}
3111
2388
  };`;
3112
2389
  }
2390
+ // src/vite-plugin.ts
2391
+ import remapping from "@ampproject/remapping";
2392
+ import MagicString2 from "magic-string";
2393
+ import { Project as Project3, ts as ts3 } from "ts-morph";
2394
+ var VIRTUAL_CSS_PREFIX = "\x00vertz-css:";
2395
+ var DEFAULT_INCLUDE = ["**/*.tsx", "**/*.jsx"];
2396
+ function vertzPlugin(options) {
2397
+ const include = options?.include ?? DEFAULT_INCLUDE;
2398
+ const exclude = options?.exclude ?? [];
2399
+ const enableCssExtraction = options?.cssExtraction ?? true;
2400
+ let resolvedConfig;
2401
+ let isProduction = false;
2402
+ const cssHmrHandler = new CSSHMRHandler;
2403
+ const cssExtractor = new CSSExtractor;
2404
+ const fileExtractions = new Map;
2405
+ function shouldTransform(id) {
2406
+ const cleanId = id.split("?")[0] ?? id;
2407
+ for (const pattern of exclude) {
2408
+ if (matchGlob(cleanId, pattern))
2409
+ return false;
2410
+ }
2411
+ for (const pattern of include) {
2412
+ if (matchGlob(cleanId, pattern))
2413
+ return true;
2414
+ }
2415
+ return false;
2416
+ }
2417
+ return {
2418
+ name: "vertz",
2419
+ enforce: "pre",
2420
+ config(_userConfig, env) {
2421
+ if (options?.ssr && env.isSsrBuild) {
2422
+ return {
2423
+ resolve: {
2424
+ alias: {
2425
+ "@vertz/ui/jsx-runtime": "@vertz/ui-server/jsx-runtime",
2426
+ "@vertz/ui/jsx-dev-runtime": "@vertz/ui-server/jsx-runtime"
2427
+ }
2428
+ }
2429
+ };
2430
+ }
2431
+ return;
2432
+ },
2433
+ configResolved(cfg) {
2434
+ resolvedConfig = cfg;
2435
+ isProduction = resolvedConfig.command === "build" || resolvedConfig.mode === "production";
2436
+ },
2437
+ configureServer(server) {
2438
+ if (!options?.ssr)
2439
+ return;
2440
+ const ssrOptions = typeof options.ssr === "object" ? options.ssr : {};
2441
+ server.middlewares.use(async (req, res, next) => {
2442
+ const url = req.url || "/";
2443
+ if (!req.headers.accept?.includes("text/html") && !req.url?.endsWith(".html") && req.url !== "/") {
2444
+ return next();
2445
+ }
2446
+ if (url.startsWith("/@") || url.startsWith("/node_modules") || url.includes("?") || /\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/.test(url)) {
2447
+ return next();
2448
+ }
2449
+ try {
2450
+ const { readFileSync } = await import("node:fs");
2451
+ const { resolve } = await import("node:path");
2452
+ let template = readFileSync(resolve(server.config.root, "index.html"), "utf-8");
2453
+ template = await server.transformIndexHtml(url, template);
2454
+ let entry = ssrOptions.entry;
2455
+ if (!entry) {
2456
+ const scriptMatch = template.match(/<script[^>]*type="module"[^>]*src="([^"]+)"/);
2457
+ if (scriptMatch?.[1]) {
2458
+ entry = scriptMatch[1];
2459
+ } else {
2460
+ throw new Error("Could not auto-detect entry from index.html. Please specify ssr.entry in vertz plugin options.");
2461
+ }
2462
+ }
2463
+ const ssrEntryMod = server.moduleGraph.getModuleById("\x00vertz:ssr-entry");
2464
+ if (ssrEntryMod) {
2465
+ server.moduleGraph.invalidateModule(ssrEntryMod);
2466
+ }
2467
+ const ssrEntry = await server.ssrLoadModule("\x00vertz:ssr-entry");
2468
+ const appHtml = await ssrEntry.renderToString(url);
2469
+ let html;
2470
+ if (template.includes("<!--ssr-outlet-->")) {
2471
+ html = template.replace("<!--ssr-outlet-->", appHtml);
2472
+ } else {
2473
+ html = template.replace(/(<div[^>]*id="app"[^>]*>)([\s\S]*?)(<\/div>)/, `$1${appHtml}$3`);
2474
+ }
2475
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
2476
+ res.end(html);
2477
+ } catch (err) {
2478
+ server.ssrFixStacktrace(err);
2479
+ next(err);
2480
+ }
2481
+ });
2482
+ },
2483
+ resolveId(id) {
2484
+ if (id.startsWith(VIRTUAL_CSS_PREFIX)) {
2485
+ return id;
2486
+ }
2487
+ if (id === "\x00vertz:ssr-entry") {
2488
+ return id;
2489
+ }
2490
+ return;
2491
+ },
2492
+ load(id) {
2493
+ if (id.startsWith(VIRTUAL_CSS_PREFIX)) {
2494
+ const sourceFile = id.slice(VIRTUAL_CSS_PREFIX.length);
2495
+ const extraction = fileExtractions.get(sourceFile);
2496
+ if (extraction) {
2497
+ return extraction.css;
2498
+ }
2499
+ return "";
2500
+ }
2501
+ if (id === "\x00vertz:ssr-entry") {
2502
+ const ssrOptions = typeof options?.ssr === "object" ? options.ssr : {};
2503
+ const entry = ssrOptions.entry || "/src/index.ts";
2504
+ return generateSSREntry(entry);
2505
+ }
2506
+ return;
2507
+ },
2508
+ transform(code, id) {
2509
+ if (!shouldTransform(id)) {
2510
+ return;
2511
+ }
2512
+ const cleanId = id.split("?")[0] ?? id;
2513
+ const hydrationS = new MagicString2(code);
2514
+ const hydrationProject = new Project3({
2515
+ useInMemoryFileSystem: true,
2516
+ compilerOptions: {
2517
+ jsx: ts3.JsxEmit.Preserve,
2518
+ strict: true
2519
+ }
2520
+ });
2521
+ const hydrationSourceFile = hydrationProject.createSourceFile(cleanId, code);
2522
+ const hydrationTransformer = new HydrationTransformer;
2523
+ hydrationTransformer.transform(hydrationS, hydrationSourceFile);
2524
+ const hydratedCode = hydrationS.toString();
2525
+ const hydrationMap = hydrationS.generateMap({
2526
+ source: cleanId,
2527
+ includeContent: true
2528
+ });
2529
+ const compileResult = compile(hydratedCode, cleanId);
2530
+ const remapped = remapping([
2531
+ compileResult.map,
2532
+ hydrationMap
2533
+ ], () => null);
2534
+ const rawChainedMap = JSON.parse(remapped.toString());
2535
+ const chainedMap = {
2536
+ ...rawChainedMap,
2537
+ sourcesContent: rawChainedMap.sourcesContent?.map((c) => c ?? "")
2538
+ };
2539
+ let transformedCode = compileResult.code;
2540
+ const extraction = cssExtractor.extract(code, cleanId);
2541
+ if (extraction.css.length > 0) {
2542
+ fileExtractions.set(cleanId, extraction);
2543
+ if (isProduction && enableCssExtraction) {
2544
+ transformedCode = `import '${VIRTUAL_CSS_PREFIX}${cleanId}';
2545
+ ${transformedCode}`;
2546
+ }
2547
+ cssHmrHandler.register(cleanId, extraction.css);
2548
+ }
2549
+ return {
2550
+ code: transformedCode,
2551
+ map: chainedMap
2552
+ };
2553
+ },
2554
+ handleHotUpdate(ctx) {
2555
+ const { file, modules } = ctx;
2556
+ if (file.includes(".vertz/generated/") || file.includes(".vertz\\generated\\")) {
2557
+ const affectedModules = [];
2558
+ for (const mod of modules) {
2559
+ affectedModules.push(mod);
2560
+ for (const importer of mod.importers) {
2561
+ affectedModules.push(importer);
2562
+ }
2563
+ }
2564
+ return affectedModules.length > 0 ? affectedModules : undefined;
2565
+ }
2566
+ if (!shouldTransform(file))
2567
+ return;
2568
+ const content = ctx.read();
2569
+ const processContent = (newCode) => {
2570
+ const extraction = cssExtractor.extract(newCode, file);
2571
+ const hmrResult = cssHmrHandler.update(file, extraction.css);
2572
+ if (hmrResult.hasChanged) {
2573
+ fileExtractions.set(file, extraction);
2574
+ const virtualId = VIRTUAL_CSS_PREFIX + file;
2575
+ const cssModule = ctx.server.moduleGraph.getModuleById(virtualId);
2576
+ if (cssModule) {
2577
+ ctx.server.moduleGraph.invalidateModule(cssModule);
2578
+ return [cssModule, ...modules];
2579
+ }
2580
+ }
2581
+ return;
2582
+ };
2583
+ if (typeof content === "string") {
2584
+ return processContent(content);
2585
+ }
2586
+ return content.then(processContent);
2587
+ },
2588
+ generateBundle() {
2589
+ if (!isProduction || !enableCssExtraction)
2590
+ return;
2591
+ const usedFiles = new Set(fileExtractions.keys());
2592
+ const deadCssEliminator = new DeadCSSEliminator;
2593
+ const liveCSS = deadCssEliminator.eliminate(fileExtractions, usedFiles);
2594
+ if (options?.routeMap && options.routeMap.size > 0) {
2595
+ const routeManifest = new RouteCSSManifest;
2596
+ const manifest = routeManifest.build(options.routeMap, fileExtractions);
2597
+ const codeSplitter = new CSSCodeSplitter;
2598
+ const chunks = codeSplitter.split(manifest, fileExtractions);
2599
+ for (const [route, css] of Object.entries(chunks)) {
2600
+ if (css.length === 0)
2601
+ continue;
2602
+ const fileName = route === "__common" ? "assets/common.css" : `assets/route-${sanitizeRoute(route)}.css`;
2603
+ this.emitFile({
2604
+ type: "asset",
2605
+ fileName,
2606
+ source: css
2607
+ });
2608
+ }
2609
+ } else if (liveCSS.length > 0) {
2610
+ this.emitFile({
2611
+ type: "asset",
2612
+ fileName: "assets/vertz.css",
2613
+ source: liveCSS
2614
+ });
2615
+ }
2616
+ }
2617
+ };
2618
+ }
2619
+ function generateSSREntry(userEntry) {
2620
+ return `
2621
+ import { installDomShim, toVNode } from '@vertz/ui-server/dom-shim';
2622
+ import { renderToStream, streamToString } from '@vertz/ui-server';
2623
+
2624
+ /**
2625
+ * Render the app to an HTML string for the given URL.
2626
+ */
2627
+ export async function renderToString(url) {
2628
+ // Normalize URL: strip /index.html suffix that Vite's SPA fallback may add
2629
+ const normalizedUrl = url.endsWith('/index.html')
2630
+ ? url.slice(0, -'/index.html'.length) || '/'
2631
+ : url;
2632
+
2633
+ // Set SSR context flag — invalidate and re-set on every call so
2634
+ // module-scope code (e.g. createRouter) picks up the current URL.
2635
+ globalThis.__SSR_URL__ = normalizedUrl;
2636
+
2637
+ // Install DOM shim so @vertz/ui components work
2638
+ installDomShim();
2639
+
2640
+ // Import the user's app entry (dynamic import for fresh module state)
2641
+ const userModule = await import('${userEntry}');
2642
+
2643
+ // Call the default export or named App export
2644
+ const createApp = userModule.default || userModule.App;
2645
+ if (typeof createApp !== 'function') {
2646
+ throw new Error('App entry must export a default function or named App function');
2647
+ }
2648
+
2649
+ const app = createApp();
2650
+
2651
+ // Convert to VNode if needed
2652
+ const vnode = toVNode(app);
2653
+
2654
+ // Render to stream and convert to string
2655
+ const stream = renderToStream(vnode);
2656
+ const html = await streamToString(stream);
2657
+
2658
+ return html;
2659
+ }
2660
+ `;
2661
+ }
2662
+ function matchGlob(filePath, pattern) {
2663
+ if (pattern.startsWith("**/") && pattern.endsWith("/**")) {
2664
+ const segment = pattern.slice(3, -3);
2665
+ return filePath.includes(`/${segment}/`) || filePath.includes(`\\${segment}\\`);
2666
+ }
2667
+ if (pattern.startsWith("**/")) {
2668
+ const suffix = pattern.slice(3);
2669
+ if (suffix.startsWith("*.")) {
2670
+ const ext = suffix.slice(1);
2671
+ return filePath.endsWith(ext);
2672
+ }
2673
+ return filePath.includes(suffix);
2674
+ }
2675
+ if (pattern.startsWith("*.")) {
2676
+ const ext = pattern.slice(1);
2677
+ return filePath.endsWith(ext);
2678
+ }
2679
+ return filePath.includes(pattern);
2680
+ }
2681
+ function sanitizeRoute(route) {
2682
+ return route.replace(/^\//, "").replace(/\//g, "-").replace(/[^a-zA-Z0-9-]/g, "_").replace(/^$/, "index");
2683
+ }
3113
2684
  export {
3114
2685
  generateThemeTypes,
3115
2686
  generateCSSProperties,
3116
- createVertzLibraryPlugin,
2687
+ vertzPlugin as default,
3117
2688
  compile,
3118
2689
  SignalTransformer,
3119
- SSRSafetyDiagnostics,
3120
2690
  RouteCSSManifest,
3121
2691
  ReactivityAnalyzer,
3122
2692
  PropsDestructuringDiagnostics,