@vertz/ui-server 0.2.22 → 0.2.24
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/bun-dev-server.d.ts +29 -1
- package/dist/bun-dev-server.js +307 -34
- package/dist/bun-plugin/fast-refresh-dom-state.js +1 -1
- package/dist/bun-plugin/fast-refresh-runtime.js +6 -2
- package/dist/bun-plugin/index.js +138 -47
- package/dist/dom-shim/index.d.ts +2 -0
- package/dist/dom-shim/index.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +12 -5
- package/dist/shared/{chunk-2qsqp9xj.js → chunk-eenfpa59.js} +20 -10
- package/dist/shared/{chunk-qzdhe6bn.js → chunk-g0zqrb60.js} +7 -1
- package/dist/shared/{chunk-1363r1qw.js → chunk-zs75v8qj.js} +29 -3
- package/dist/ssr/index.d.ts +5 -3
- package/dist/ssr/index.js +5 -3
- package/package.json +5 -5
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
captureDOMState,
|
|
4
4
|
restoreDOMState
|
|
5
|
-
} from "../shared/chunk-
|
|
5
|
+
} from "../shared/chunk-eenfpa59.js";
|
|
6
6
|
import"../shared/chunk-eb80r8e8.js";
|
|
7
7
|
|
|
8
8
|
// src/bun-plugin/fast-refresh-runtime.ts
|
|
@@ -40,9 +40,10 @@ function __$refreshReg(moduleId, name, factory, hash) {
|
|
|
40
40
|
return;
|
|
41
41
|
existing.factory = factory;
|
|
42
42
|
existing.hash = hash;
|
|
43
|
+
existing.dirty = true;
|
|
43
44
|
dirtyModules.add(moduleId);
|
|
44
45
|
} else {
|
|
45
|
-
mod.set(name, { factory, instances: [], hash });
|
|
46
|
+
mod.set(name, { factory, instances: [], hash, dirty: false });
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
function __$refreshTrack(moduleId, name, element, args, cleanups, contextScope, signals = []) {
|
|
@@ -68,6 +69,9 @@ function __$refreshPerform(moduleId) {
|
|
|
68
69
|
return;
|
|
69
70
|
performingRefresh = true;
|
|
70
71
|
for (const [name, record] of mod) {
|
|
72
|
+
if (!record.dirty)
|
|
73
|
+
continue;
|
|
74
|
+
record.dirty = false;
|
|
71
75
|
const { factory, instances } = record;
|
|
72
76
|
const updatedInstances = [];
|
|
73
77
|
for (const instance of instances) {
|
package/dist/bun-plugin/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
transformRouteSplitting
|
|
23
23
|
} from "@vertz/ui-compiler";
|
|
24
24
|
import MagicString3 from "magic-string";
|
|
25
|
-
import { Project as Project2, ts as
|
|
25
|
+
import { Project as Project2, ts as ts5 } from "ts-morph";
|
|
26
26
|
|
|
27
27
|
// src/bun-plugin/context-stable-ids.ts
|
|
28
28
|
import { ts } from "ts-morph";
|
|
@@ -72,19 +72,18 @@ function loadEntitySchema(schemaPath) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// src/bun-plugin/fast-refresh-codegen.ts
|
|
75
|
-
function generateRefreshPreamble(moduleId
|
|
75
|
+
function generateRefreshPreamble(moduleId) {
|
|
76
76
|
const escapedId = moduleId.replace(/['\\]/g, "\\$&");
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const noop = "() => {}";
|
|
78
|
+
const noopArr = "() => []";
|
|
79
|
+
const noopNull = "() => null";
|
|
80
|
+
const noopPassthrough = "(_m, _n, el) => el";
|
|
81
|
+
return `const __$fr = globalThis[Symbol.for('vertz:fast-refresh')] ?? {};
|
|
82
|
+
` + `const { ` + `__$refreshReg = ${noop}, ` + `__$refreshTrack = ${noopPassthrough}, ` + `__$refreshPerform = ${noop}, ` + `pushScope: __$pushScope = ${noopArr}, ` + `popScope: __$popScope = ${noop}, ` + `_tryOnCleanup: __$tryCleanup = ${noop}, ` + `runCleanups: __$runCleanups = ${noop}, ` + `getContextScope: __$getCtx = ${noopNull}, ` + `setContextScope: __$setCtx = ${noopNull}, ` + `startSignalCollection: __$startSigCol = ${noop}, ` + `stopSignalCollection: __$stopSigCol = ${noopArr} } = __$fr;
|
|
79
83
|
` + `const __$moduleId = '${escapedId}';
|
|
80
84
|
`;
|
|
81
|
-
if (contentHash) {
|
|
82
|
-
code += `const __$moduleHash = '${contentHash}';
|
|
83
|
-
`;
|
|
84
|
-
}
|
|
85
|
-
return code;
|
|
86
85
|
}
|
|
87
|
-
function generateRefreshWrapper(componentName) {
|
|
86
|
+
function generateRefreshWrapper(componentName, componentHash) {
|
|
88
87
|
return `
|
|
89
88
|
const __$orig_${componentName} = ${componentName};
|
|
90
89
|
` + `${componentName} = function(...__$args) {
|
|
@@ -99,20 +98,22 @@ const __$orig_${componentName} = ${componentName};
|
|
|
99
98
|
` + ` }
|
|
100
99
|
` + ` return __$refreshTrack(__$moduleId, '${componentName}', __$ret, __$args, __$scope, __$ctx, __$sigs);
|
|
101
100
|
` + `};
|
|
102
|
-
` + `__$refreshReg(__$moduleId, '${componentName}', ${componentName},
|
|
101
|
+
` + `__$refreshReg(__$moduleId, '${componentName}', ${componentName}, '${componentHash}');
|
|
103
102
|
`;
|
|
104
103
|
}
|
|
105
104
|
function generateRefreshPerform() {
|
|
106
105
|
return `__$refreshPerform(__$moduleId);
|
|
107
106
|
`;
|
|
108
107
|
}
|
|
109
|
-
function generateRefreshCode(moduleId, components,
|
|
108
|
+
function generateRefreshCode(moduleId, components, source) {
|
|
110
109
|
if (components.length === 0)
|
|
111
110
|
return null;
|
|
112
|
-
const preamble = generateRefreshPreamble(moduleId
|
|
111
|
+
const preamble = generateRefreshPreamble(moduleId);
|
|
113
112
|
let epilogue = "";
|
|
114
113
|
for (const comp of components) {
|
|
115
|
-
|
|
114
|
+
const body = source.slice(comp.bodyStart, comp.bodyEnd);
|
|
115
|
+
const hash = Bun.hash(body).toString(36);
|
|
116
|
+
epilogue += generateRefreshWrapper(comp.name, hash);
|
|
116
117
|
}
|
|
117
118
|
epilogue += generateRefreshPerform();
|
|
118
119
|
return { preamble, epilogue };
|
|
@@ -267,6 +268,8 @@ function resolveCrossFileFields(filePath, propFlows, options) {
|
|
|
267
268
|
if (childFields.hasOpaqueAccess) {
|
|
268
269
|
hasOpaqueAccess = true;
|
|
269
270
|
}
|
|
271
|
+
} else {
|
|
272
|
+
hasOpaqueAccess = true;
|
|
270
273
|
}
|
|
271
274
|
}
|
|
272
275
|
return { fields, hasOpaqueAccess };
|
|
@@ -274,9 +277,33 @@ function resolveCrossFileFields(filePath, propFlows, options) {
|
|
|
274
277
|
|
|
275
278
|
// src/bun-plugin/field-selection-manifest.ts
|
|
276
279
|
import { analyzeComponentPropFields } from "@vertz/ui-compiler";
|
|
280
|
+
import { ts as ts2 } from "ts-morph";
|
|
281
|
+
var RE_EXPORT_PATTERN = /export\s+(?:\{|\*)\s*.*?\bfrom\b/;
|
|
282
|
+
function parseReExports(sourceText, filePath) {
|
|
283
|
+
if (!RE_EXPORT_PATTERN.test(sourceText))
|
|
284
|
+
return [];
|
|
285
|
+
const sourceFile = ts2.createSourceFile(filePath, sourceText, ts2.ScriptTarget.Latest, true);
|
|
286
|
+
const reExports = [];
|
|
287
|
+
for (const stmt of sourceFile.statements) {
|
|
288
|
+
if (!ts2.isExportDeclaration(stmt) || !stmt.moduleSpecifier)
|
|
289
|
+
continue;
|
|
290
|
+
const source = stmt.moduleSpecifier.getText(sourceFile).replace(/^['"]|['"]$/g, "");
|
|
291
|
+
if (!stmt.exportClause) {
|
|
292
|
+
reExports.push({ name: "*", originalName: "*", source });
|
|
293
|
+
} else if (ts2.isNamedExports(stmt.exportClause)) {
|
|
294
|
+
for (const el of stmt.exportClause.elements) {
|
|
295
|
+
const exportedName = el.name.getText(sourceFile);
|
|
296
|
+
const originalName = el.propertyName ? el.propertyName.getText(sourceFile) : exportedName;
|
|
297
|
+
reExports.push({ name: exportedName, originalName, source });
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return reExports;
|
|
302
|
+
}
|
|
277
303
|
|
|
278
304
|
class FieldSelectionManifest {
|
|
279
305
|
fileComponents = new Map;
|
|
306
|
+
fileReExports = new Map;
|
|
280
307
|
importResolver = () => {
|
|
281
308
|
return;
|
|
282
309
|
};
|
|
@@ -287,30 +314,68 @@ class FieldSelectionManifest {
|
|
|
287
314
|
registerFile(filePath, sourceText) {
|
|
288
315
|
const components = analyzeComponentPropFields(filePath, sourceText);
|
|
289
316
|
this.fileComponents.set(filePath, components);
|
|
317
|
+
const reExports = parseReExports(sourceText, filePath);
|
|
318
|
+
this.fileReExports.set(filePath, reExports);
|
|
290
319
|
this.resolvedCache.clear();
|
|
291
320
|
}
|
|
292
321
|
updateFile(filePath, sourceText) {
|
|
293
322
|
const oldComponents = this.fileComponents.get(filePath);
|
|
294
323
|
const newComponents = analyzeComponentPropFields(filePath, sourceText);
|
|
295
|
-
const
|
|
296
|
-
if (
|
|
324
|
+
const componentsChanged = !componentsEqual(oldComponents, newComponents);
|
|
325
|
+
if (componentsChanged) {
|
|
297
326
|
this.fileComponents.set(filePath, newComponents);
|
|
327
|
+
}
|
|
328
|
+
const oldReExports = this.fileReExports.get(filePath);
|
|
329
|
+
const newReExports = parseReExports(sourceText, filePath);
|
|
330
|
+
const reExportsChanged = !reExportsEqual(oldReExports, newReExports);
|
|
331
|
+
if (reExportsChanged) {
|
|
332
|
+
this.fileReExports.set(filePath, newReExports);
|
|
333
|
+
}
|
|
334
|
+
const changed = componentsChanged || reExportsChanged;
|
|
335
|
+
if (changed) {
|
|
298
336
|
this.resolvedCache.clear();
|
|
299
337
|
}
|
|
300
338
|
return { changed };
|
|
301
339
|
}
|
|
302
340
|
deleteFile(filePath) {
|
|
303
341
|
this.fileComponents.delete(filePath);
|
|
342
|
+
this.fileReExports.delete(filePath);
|
|
304
343
|
this.resolvedCache.clear();
|
|
305
344
|
}
|
|
306
345
|
getComponentPropFields(filePath, componentName, propName) {
|
|
307
346
|
const components = this.fileComponents.get(filePath);
|
|
308
|
-
if (
|
|
347
|
+
if (components) {
|
|
348
|
+
const component = components.find((c) => c.componentName === componentName);
|
|
349
|
+
if (component)
|
|
350
|
+
return component.props[propName];
|
|
351
|
+
}
|
|
352
|
+
return this.followReExports(filePath, componentName, propName, new Set);
|
|
353
|
+
}
|
|
354
|
+
followReExports(filePath, componentName, propName, visited) {
|
|
355
|
+
if (visited.has(filePath))
|
|
309
356
|
return;
|
|
310
|
-
|
|
311
|
-
|
|
357
|
+
visited.add(filePath);
|
|
358
|
+
const reExports = this.fileReExports.get(filePath);
|
|
359
|
+
if (!reExports)
|
|
312
360
|
return;
|
|
313
|
-
|
|
361
|
+
for (const re of reExports) {
|
|
362
|
+
if (re.name !== componentName && re.name !== "*")
|
|
363
|
+
continue;
|
|
364
|
+
const targetPath = this.importResolver(re.source, filePath);
|
|
365
|
+
if (!targetPath)
|
|
366
|
+
continue;
|
|
367
|
+
const targetName = re.name === "*" ? componentName : re.originalName;
|
|
368
|
+
const targetComponents = this.fileComponents.get(targetPath);
|
|
369
|
+
if (targetComponents) {
|
|
370
|
+
const component = targetComponents.find((c) => c.componentName === targetName);
|
|
371
|
+
if (component)
|
|
372
|
+
return component.props[propName];
|
|
373
|
+
}
|
|
374
|
+
const result = this.followReExports(targetPath, targetName, propName, visited);
|
|
375
|
+
if (result)
|
|
376
|
+
return result;
|
|
377
|
+
}
|
|
378
|
+
return;
|
|
314
379
|
}
|
|
315
380
|
getResolvedPropFields(filePath, componentName, propName) {
|
|
316
381
|
const cacheKey = `${filePath}::${componentName}::${propName}`;
|
|
@@ -383,10 +448,37 @@ function componentsEqual(a, b) {
|
|
|
383
448
|
if (aFieldsSorted[k] !== bFieldsSorted[k])
|
|
384
449
|
return false;
|
|
385
450
|
}
|
|
451
|
+
if (aProp.forwarded.length !== bProp.forwarded.length)
|
|
452
|
+
return false;
|
|
453
|
+
for (let f = 0;f < aProp.forwarded.length; f++) {
|
|
454
|
+
const af = aProp.forwarded[f];
|
|
455
|
+
const bf = bProp.forwarded[f];
|
|
456
|
+
if (af.componentName !== bf.componentName)
|
|
457
|
+
return false;
|
|
458
|
+
if (af.importSource !== bf.importSource)
|
|
459
|
+
return false;
|
|
460
|
+
if (af.propName !== bf.propName)
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
386
463
|
}
|
|
387
464
|
}
|
|
388
465
|
return true;
|
|
389
466
|
}
|
|
467
|
+
function reExportsEqual(a, b) {
|
|
468
|
+
if (!a)
|
|
469
|
+
return b.length === 0;
|
|
470
|
+
if (a.length !== b.length)
|
|
471
|
+
return false;
|
|
472
|
+
for (let i = 0;i < a.length; i++) {
|
|
473
|
+
if (a[i].name !== b[i].name)
|
|
474
|
+
return false;
|
|
475
|
+
if (a[i].originalName !== b[i].originalName)
|
|
476
|
+
return false;
|
|
477
|
+
if (a[i].source !== b[i].source)
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
390
482
|
|
|
391
483
|
// src/bun-plugin/file-path-hash.ts
|
|
392
484
|
function filePathHash(filePath) {
|
|
@@ -461,7 +553,7 @@ async function processImage(opts) {
|
|
|
461
553
|
|
|
462
554
|
// src/bun-plugin/image-transform.ts
|
|
463
555
|
import MagicString2 from "magic-string";
|
|
464
|
-
import { Project, ts as
|
|
556
|
+
import { Project, ts as ts3 } from "ts-morph";
|
|
465
557
|
function escapeAttr(value) {
|
|
466
558
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
467
559
|
}
|
|
@@ -535,13 +627,13 @@ function findImageImportName(source) {
|
|
|
535
627
|
function findImageJsxElements(sourceFile, localName) {
|
|
536
628
|
const results = [];
|
|
537
629
|
function visit(node) {
|
|
538
|
-
if (
|
|
630
|
+
if (ts3.isJsxSelfClosingElement(node)) {
|
|
539
631
|
const tagName = node.tagName.getText(sourceFile.compilerNode);
|
|
540
632
|
if (tagName === localName) {
|
|
541
633
|
results.push(node);
|
|
542
634
|
}
|
|
543
635
|
}
|
|
544
|
-
|
|
636
|
+
ts3.forEachChild(node, visit);
|
|
545
637
|
}
|
|
546
638
|
visit(sourceFile.compilerNode);
|
|
547
639
|
return results;
|
|
@@ -549,7 +641,7 @@ function findImageJsxElements(sourceFile, localName) {
|
|
|
549
641
|
function extractStaticProps(element, sourceFile) {
|
|
550
642
|
const attrs = element.attributes;
|
|
551
643
|
for (const attr of attrs.properties) {
|
|
552
|
-
if (
|
|
644
|
+
if (ts3.isJsxSpreadAttribute(attr))
|
|
553
645
|
return null;
|
|
554
646
|
}
|
|
555
647
|
let src = null;
|
|
@@ -582,7 +674,7 @@ function extractStaticProps(element, sourceFile) {
|
|
|
582
674
|
"fit"
|
|
583
675
|
]);
|
|
584
676
|
for (const attr of attrs.properties) {
|
|
585
|
-
if (!
|
|
677
|
+
if (!ts3.isJsxAttribute(attr))
|
|
586
678
|
continue;
|
|
587
679
|
const name = attr.name.getText(sourceFile.compilerNode);
|
|
588
680
|
const value = attr.initializer;
|
|
@@ -686,15 +778,15 @@ function extractStaticProps(element, sourceFile) {
|
|
|
686
778
|
function extractStaticString(value, _sourceFile) {
|
|
687
779
|
if (!value)
|
|
688
780
|
return null;
|
|
689
|
-
if (
|
|
781
|
+
if (ts3.isStringLiteral(value)) {
|
|
690
782
|
return value.text;
|
|
691
783
|
}
|
|
692
|
-
if (
|
|
784
|
+
if (ts3.isJsxExpression(value) && value.expression) {
|
|
693
785
|
const expr = value.expression;
|
|
694
|
-
if (
|
|
786
|
+
if (ts3.isStringLiteral(expr)) {
|
|
695
787
|
return expr.text;
|
|
696
788
|
}
|
|
697
|
-
if (
|
|
789
|
+
if (ts3.isNoSubstitutionTemplateLiteral(expr)) {
|
|
698
790
|
return expr.text;
|
|
699
791
|
}
|
|
700
792
|
}
|
|
@@ -703,9 +795,9 @@ function extractStaticString(value, _sourceFile) {
|
|
|
703
795
|
function extractStaticNumber(value, _sourceFile) {
|
|
704
796
|
if (!value)
|
|
705
797
|
return null;
|
|
706
|
-
if (
|
|
798
|
+
if (ts3.isJsxExpression(value) && value.expression) {
|
|
707
799
|
const expr = value.expression;
|
|
708
|
-
if (
|
|
800
|
+
if (ts3.isNumericLiteral(expr)) {
|
|
709
801
|
return Number(expr.text);
|
|
710
802
|
}
|
|
711
803
|
}
|
|
@@ -714,18 +806,18 @@ function extractStaticNumber(value, _sourceFile) {
|
|
|
714
806
|
function extractStaticBoolean(value, _sourceFile) {
|
|
715
807
|
if (!value)
|
|
716
808
|
return null;
|
|
717
|
-
if (
|
|
809
|
+
if (ts3.isJsxExpression(value) && value.expression) {
|
|
718
810
|
const expr = value.expression;
|
|
719
|
-
if (expr.kind ===
|
|
811
|
+
if (expr.kind === ts3.SyntaxKind.TrueKeyword)
|
|
720
812
|
return true;
|
|
721
|
-
if (expr.kind ===
|
|
813
|
+
if (expr.kind === ts3.SyntaxKind.FalseKeyword)
|
|
722
814
|
return false;
|
|
723
815
|
}
|
|
724
816
|
return null;
|
|
725
817
|
}
|
|
726
818
|
|
|
727
819
|
// src/bun-plugin/island-id-inject.ts
|
|
728
|
-
import { ts as
|
|
820
|
+
import { ts as ts4 } from "ts-morph";
|
|
729
821
|
function injectIslandIds(source, sourceFile, relFilePath) {
|
|
730
822
|
const originalSource = source.original;
|
|
731
823
|
if (!originalSource.includes("<Island") && !originalSource.includes("Island")) {
|
|
@@ -759,20 +851,20 @@ function findIslandImportName(source) {
|
|
|
759
851
|
function findIslandJsxElements(sourceFile, localName) {
|
|
760
852
|
const results = [];
|
|
761
853
|
function visit(node) {
|
|
762
|
-
if (
|
|
854
|
+
if (ts4.isJsxSelfClosingElement(node)) {
|
|
763
855
|
const tagName = node.tagName.getText(sourceFile.compilerNode);
|
|
764
856
|
if (tagName === localName) {
|
|
765
857
|
results.push(node);
|
|
766
858
|
}
|
|
767
859
|
}
|
|
768
|
-
|
|
860
|
+
ts4.forEachChild(node, visit);
|
|
769
861
|
}
|
|
770
862
|
visit(sourceFile.compilerNode);
|
|
771
863
|
return results;
|
|
772
864
|
}
|
|
773
865
|
function hasIdProp(element, sourceFile) {
|
|
774
866
|
for (const attr of element.attributes.properties) {
|
|
775
|
-
if (
|
|
867
|
+
if (ts4.isJsxAttribute(attr)) {
|
|
776
868
|
const name = attr.name.getText(sourceFile.compilerNode);
|
|
777
869
|
if (name === "id")
|
|
778
870
|
return true;
|
|
@@ -782,7 +874,7 @@ function hasIdProp(element, sourceFile) {
|
|
|
782
874
|
}
|
|
783
875
|
function extractComponentName(element, sourceFile) {
|
|
784
876
|
for (const attr of element.attributes.properties) {
|
|
785
|
-
if (!
|
|
877
|
+
if (!ts4.isJsxAttribute(attr))
|
|
786
878
|
continue;
|
|
787
879
|
const name = attr.name.getText(sourceFile.compilerNode);
|
|
788
880
|
if (name !== "component")
|
|
@@ -790,8 +882,8 @@ function extractComponentName(element, sourceFile) {
|
|
|
790
882
|
const value = attr.initializer;
|
|
791
883
|
if (!value)
|
|
792
884
|
return null;
|
|
793
|
-
if (
|
|
794
|
-
if (
|
|
885
|
+
if (ts4.isJsxExpression(value) && value.expression) {
|
|
886
|
+
if (ts4.isIdentifier(value.expression)) {
|
|
795
887
|
return value.expression.text;
|
|
796
888
|
}
|
|
797
889
|
}
|
|
@@ -896,7 +988,7 @@ function createVertzBunPlugin(options) {
|
|
|
896
988
|
fieldSelectionManifest.setImportResolver(fieldSelectionResolveImport);
|
|
897
989
|
let fieldSelectionFileCount = 0;
|
|
898
990
|
for (const [filePath] of manifests) {
|
|
899
|
-
if (filePath.endsWith(".tsx")) {
|
|
991
|
+
if (filePath.endsWith(".tsx") || filePath.endsWith(".ts")) {
|
|
900
992
|
try {
|
|
901
993
|
const sourceText = readFileSync3(filePath, "utf-8");
|
|
902
994
|
fieldSelectionManifest.registerFile(filePath, sourceText);
|
|
@@ -953,7 +1045,7 @@ function createVertzBunPlugin(options) {
|
|
|
953
1045
|
const hydrationProject = new Project2({
|
|
954
1046
|
useInMemoryFileSystem: true,
|
|
955
1047
|
compilerOptions: {
|
|
956
|
-
jsx:
|
|
1048
|
+
jsx: ts5.JsxEmit.Preserve,
|
|
957
1049
|
strict: true
|
|
958
1050
|
}
|
|
959
1051
|
});
|
|
@@ -1066,8 +1158,7 @@ function createVertzBunPlugin(options) {
|
|
|
1066
1158
|
let refreshEpilogue = "";
|
|
1067
1159
|
if (fastRefresh) {
|
|
1068
1160
|
const components = componentAnalyzer.analyze(hydrationSourceFile);
|
|
1069
|
-
const
|
|
1070
|
-
const refreshCode = generateRefreshCode(args.path, components, contentHash);
|
|
1161
|
+
const refreshCode = generateRefreshCode(args.path, components, source);
|
|
1071
1162
|
if (refreshCode) {
|
|
1072
1163
|
refreshPreamble = refreshCode.preamble;
|
|
1073
1164
|
refreshEpilogue = refreshCode.epilogue;
|
|
@@ -1094,7 +1185,7 @@ function createVertzBunPlugin(options) {
|
|
|
1094
1185
|
}
|
|
1095
1186
|
if (hmr) {
|
|
1096
1187
|
contents += `
|
|
1097
|
-
import.meta.hot.accept();
|
|
1188
|
+
if (import.meta.hot) import.meta.hot.accept();
|
|
1098
1189
|
`;
|
|
1099
1190
|
}
|
|
1100
1191
|
contents += sourceMapComment;
|
|
@@ -1164,7 +1255,7 @@ import.meta.hot.accept();
|
|
|
1164
1255
|
if (changed) {
|
|
1165
1256
|
manifestsRecord = null;
|
|
1166
1257
|
}
|
|
1167
|
-
if (filePath.endsWith(".tsx")) {
|
|
1258
|
+
if (filePath.endsWith(".tsx") || filePath.endsWith(".ts")) {
|
|
1168
1259
|
fieldSelectionManifest.updateFile(filePath, sourceText);
|
|
1169
1260
|
}
|
|
1170
1261
|
if (logger?.isEnabled("manifest")) {
|
package/dist/dom-shim/index.d.ts
CHANGED
|
@@ -102,6 +102,8 @@ declare class SSRElement extends SSRNode {
|
|
|
102
102
|
set disabled(value: boolean);
|
|
103
103
|
get checked(): boolean;
|
|
104
104
|
set checked(value: boolean);
|
|
105
|
+
get selected(): boolean;
|
|
106
|
+
set selected(value: boolean);
|
|
105
107
|
get rows(): number;
|
|
106
108
|
set rows(value: number);
|
|
107
109
|
get scope(): string;
|
package/dist/dom-shim/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -80,6 +80,7 @@ declare function renderAssetTags(assets: AssetDescriptor[]): string;
|
|
|
80
80
|
* Returns an empty string if the CSS is empty.
|
|
81
81
|
*/
|
|
82
82
|
declare function inlineCriticalCss(css: string): string;
|
|
83
|
+
import { FallbackFontName as FallbackFontName2, FontFallbackMetrics as FontFallbackMetrics5 } from "@vertz/ui";
|
|
83
84
|
import { FallbackFontName, FontDescriptor, FontFallbackMetrics } from "@vertz/ui";
|
|
84
85
|
/**
|
|
85
86
|
* Auto-detect which system font to use as fallback base.
|
|
@@ -589,4 +590,4 @@ declare function collectStreamChunks(stream: ReadableStream<Uint8Array>): Promis
|
|
|
589
590
|
* @param nonce - Optional CSP nonce to add to the inline script tag.
|
|
590
591
|
*/
|
|
591
592
|
declare function createTemplateChunk(slotId: number, resolvedHtml: string, nonce?: string): string;
|
|
592
|
-
export { wrapWithHydrationMarkers, streamToString, ssrStorage, ssrRenderToString, ssrDiscoverQueries, setGlobalSSRTimeout, serializeToHtml, safeSerialize, resetSlotCounter, renderToStream, renderToHTMLStream, renderToHTML, renderPage, renderHeadToHtml, renderAssetTags, registerSSRQuery, rawHtml, isInSSR, inlineCriticalCss, getStreamingRuntimeScript, getSSRUrl, getSSRQueries, getGlobalSSRTimeout, getAccessSetForSSR, generateSSRHtml, extractFontMetrics, encodeChunk, detectFallbackFont, createTemplateChunk, createSlotPlaceholder, createSessionScript, createSSRHandler, createSSRDataChunk, createSSRAdapter, createAccessSetScript, collectStreamChunks, clearGlobalSSRTimeout, VNode, SessionResolver, SessionData, SSRSessionInfo, SSRRenderResult, SSRQueryEntry2 as SSRQueryEntry, SSRModule, SSRHandlerOptions, SSRDiscoverResult, RenderToStreamOptions, RenderToHTMLStreamOptions, RenderToHTMLOptions, RawHtml, PageOptions, HydrationOptions, HeadEntry, HeadCollector, GenerateSSRHtmlOptions, AssetDescriptor };
|
|
593
|
+
export { wrapWithHydrationMarkers, streamToString, ssrStorage, ssrRenderToString, ssrDiscoverQueries, setGlobalSSRTimeout, serializeToHtml, safeSerialize, resetSlotCounter, renderToStream, renderToHTMLStream, renderToHTML, renderPage, renderHeadToHtml, renderAssetTags, registerSSRQuery, rawHtml, isInSSR, inlineCriticalCss, getStreamingRuntimeScript, getSSRUrl, getSSRQueries, getGlobalSSRTimeout, getAccessSetForSSR, generateSSRHtml, extractFontMetrics, encodeChunk, detectFallbackFont, createTemplateChunk, createSlotPlaceholder, createSessionScript, createSSRHandler, createSSRDataChunk, createSSRAdapter, createAccessSetScript, collectStreamChunks, clearGlobalSSRTimeout, VNode, SessionResolver, SessionData, SSRSessionInfo, SSRRenderResult, SSRQueryEntry2 as SSRQueryEntry, SSRModule, SSRHandlerOptions, SSRDiscoverResult, RenderToStreamOptions, RenderToHTMLStreamOptions, RenderToHTMLOptions, RawHtml, PageOptions, HydrationOptions, HeadEntry, HeadCollector, GenerateSSRHtmlOptions, FontFallbackMetrics5 as FontFallbackMetrics, FallbackFontName2 as FallbackFontName, AssetDescriptor };
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
ssrDiscoverQueries,
|
|
20
20
|
ssrRenderToString,
|
|
21
21
|
streamToString
|
|
22
|
-
} from "./shared/chunk-
|
|
22
|
+
} from "./shared/chunk-g0zqrb60.js";
|
|
23
23
|
import {
|
|
24
24
|
clearGlobalSSRTimeout,
|
|
25
25
|
createSSRAdapter,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
registerSSRQuery,
|
|
32
32
|
setGlobalSSRTimeout,
|
|
33
33
|
ssrStorage
|
|
34
|
-
} from "./shared/chunk-
|
|
34
|
+
} from "./shared/chunk-zs75v8qj.js";
|
|
35
35
|
|
|
36
36
|
// src/asset-pipeline.ts
|
|
37
37
|
function renderAssetTags(assets) {
|
|
@@ -59,6 +59,7 @@ function inlineCriticalCss(css) {
|
|
|
59
59
|
return `<style>${safeCss}</style>`;
|
|
60
60
|
}
|
|
61
61
|
// src/font-metrics.ts
|
|
62
|
+
import { access as fsAccess } from "node:fs/promises";
|
|
62
63
|
import { readFile } from "node:fs/promises";
|
|
63
64
|
import { join } from "node:path";
|
|
64
65
|
import { fromBuffer } from "@capsizecss/unpack";
|
|
@@ -127,9 +128,15 @@ function getPrimarySrcPath(descriptor) {
|
|
|
127
128
|
return first.path;
|
|
128
129
|
return null;
|
|
129
130
|
}
|
|
130
|
-
function resolveFilePath(urlPath, rootDir) {
|
|
131
|
+
async function resolveFilePath(urlPath, rootDir) {
|
|
131
132
|
const cleaned = urlPath.startsWith("/") ? urlPath.slice(1) : urlPath;
|
|
132
|
-
|
|
133
|
+
const direct = join(rootDir, cleaned);
|
|
134
|
+
try {
|
|
135
|
+
await fsAccess(direct);
|
|
136
|
+
return direct;
|
|
137
|
+
} catch {
|
|
138
|
+
return join(rootDir, "public", cleaned);
|
|
139
|
+
}
|
|
133
140
|
}
|
|
134
141
|
async function extractFontMetrics(fonts, rootDir) {
|
|
135
142
|
const result = {};
|
|
@@ -143,7 +150,7 @@ async function extractFontMetrics(fonts, rootDir) {
|
|
|
143
150
|
if (!srcPath.toLowerCase().endsWith(".woff2"))
|
|
144
151
|
continue;
|
|
145
152
|
try {
|
|
146
|
-
const filePath = resolveFilePath(srcPath, rootDir);
|
|
153
|
+
const filePath = await resolveFilePath(srcPath, rootDir);
|
|
147
154
|
const buffer = await readFile(filePath);
|
|
148
155
|
const metrics = await fromBuffer(buffer);
|
|
149
156
|
const fallbackFont = typeof adjustFontFallback === "string" ? adjustFontFallback : detectFallbackFont(descriptor.fallback);
|
|
@@ -7,17 +7,28 @@ function captureDOMState(element) {
|
|
|
7
7
|
scrollPositions: captureScrollPositions(element)
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
|
+
function formFieldKey(el, index) {
|
|
11
|
+
const name = el.getAttribute("name");
|
|
12
|
+
if (name)
|
|
13
|
+
return `name:${name}`;
|
|
14
|
+
const id = el.getAttribute("id");
|
|
15
|
+
if (id)
|
|
16
|
+
return `id:${id}`;
|
|
17
|
+
const placeholder = el.getAttribute("placeholder");
|
|
18
|
+
if (placeholder)
|
|
19
|
+
return `placeholder:${placeholder}`;
|
|
20
|
+
return `pos:${el.tagName.toLowerCase()}:${index}`;
|
|
21
|
+
}
|
|
10
22
|
function captureFormFields(element) {
|
|
11
23
|
const fields = new Map;
|
|
12
24
|
const inputs = element.querySelectorAll("input, textarea, select");
|
|
13
|
-
for (
|
|
14
|
-
const
|
|
15
|
-
if (!name)
|
|
16
|
-
continue;
|
|
25
|
+
for (let i = 0;i < inputs.length; i++) {
|
|
26
|
+
const el = inputs[i];
|
|
17
27
|
const type = el.type ?? "";
|
|
18
28
|
if (type === "file")
|
|
19
29
|
continue;
|
|
20
|
-
|
|
30
|
+
const key = formFieldKey(el, i);
|
|
31
|
+
fields.set(key, {
|
|
21
32
|
value: el.value ?? "",
|
|
22
33
|
checked: el.checked ?? false,
|
|
23
34
|
selectedIndex: el.selectedIndex ?? -1,
|
|
@@ -87,11 +98,10 @@ function restoreFormFields(element, fields) {
|
|
|
87
98
|
if (fields.size === 0)
|
|
88
99
|
return;
|
|
89
100
|
const inputs = element.querySelectorAll("input, textarea, select");
|
|
90
|
-
for (
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const saved = fields.get(name);
|
|
101
|
+
for (let i = 0;i < inputs.length; i++) {
|
|
102
|
+
const el = inputs[i];
|
|
103
|
+
const key = formFieldKey(el, i);
|
|
104
|
+
const saved = fields.get(key);
|
|
95
105
|
if (!saved)
|
|
96
106
|
continue;
|
|
97
107
|
if (saved.type === "file")
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
setGlobalSSRTimeout,
|
|
7
7
|
ssrStorage,
|
|
8
8
|
toVNode
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-zs75v8qj.js";
|
|
10
10
|
|
|
11
11
|
// src/html-serializer.ts
|
|
12
12
|
var VOID_ELEMENTS = new Set([
|
|
@@ -51,6 +51,9 @@ function serializeToHtml(node) {
|
|
|
51
51
|
return node.html;
|
|
52
52
|
}
|
|
53
53
|
const { tag, attrs, children } = node;
|
|
54
|
+
if (tag === "fragment") {
|
|
55
|
+
return children.map((child) => serializeToHtml(child)).join("");
|
|
56
|
+
}
|
|
54
57
|
const attrStr = serializeAttrs(attrs);
|
|
55
58
|
if (VOID_ELEMENTS.has(tag)) {
|
|
56
59
|
return `<${tag}${attrStr}>`;
|
|
@@ -141,6 +144,9 @@ function renderToStream(tree, options) {
|
|
|
141
144
|
return serializeToHtml(placeholder);
|
|
142
145
|
}
|
|
143
146
|
const { tag, attrs, children } = node;
|
|
147
|
+
if (tag === "fragment") {
|
|
148
|
+
return children.map((child) => walkAndSerialize(child)).join("");
|
|
149
|
+
}
|
|
144
150
|
const isRawText = RAW_TEXT_ELEMENTS.has(tag);
|
|
145
151
|
const attrStr = Object.entries(attrs).map(([k, v]) => ` ${k}="${escapeAttr(v)}"`).join("");
|
|
146
152
|
if (VOID_ELEMENTS.has(tag)) {
|
|
@@ -403,6 +403,16 @@ class SSRElement extends SSRNode {
|
|
|
403
403
|
delete this.attrs.checked;
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
|
+
get selected() {
|
|
407
|
+
return "selected" in this.attrs;
|
|
408
|
+
}
|
|
409
|
+
set selected(value) {
|
|
410
|
+
if (value) {
|
|
411
|
+
this.attrs.selected = "";
|
|
412
|
+
} else {
|
|
413
|
+
delete this.attrs.selected;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
406
416
|
get rows() {
|
|
407
417
|
return Number(this.attrs.rows) || 0;
|
|
408
418
|
}
|
|
@@ -558,19 +568,35 @@ function installDomShim() {
|
|
|
558
568
|
cookie: ""
|
|
559
569
|
};
|
|
560
570
|
globalThis.document = fakeDocument;
|
|
571
|
+
const windowStubs = {
|
|
572
|
+
scrollTo: () => {},
|
|
573
|
+
scroll: () => {},
|
|
574
|
+
addEventListener: () => {},
|
|
575
|
+
removeEventListener: () => {},
|
|
576
|
+
dispatchEvent: () => true,
|
|
577
|
+
getComputedStyle: () => ({}),
|
|
578
|
+
matchMedia: () => ({ matches: false, addListener: () => {}, removeListener: () => {} })
|
|
579
|
+
};
|
|
561
580
|
if (typeof window === "undefined") {
|
|
562
581
|
globalThis.window = {
|
|
563
582
|
location: { pathname: ssrStorage.getStore()?.url || "/", search: "", hash: "" },
|
|
564
583
|
history: {
|
|
565
584
|
pushState: () => {},
|
|
566
585
|
replaceState: () => {}
|
|
567
|
-
}
|
|
586
|
+
},
|
|
587
|
+
...windowStubs
|
|
568
588
|
};
|
|
569
589
|
} else {
|
|
570
|
-
globalThis.window
|
|
571
|
-
|
|
590
|
+
const win = globalThis.window;
|
|
591
|
+
win.location = {
|
|
592
|
+
...win.location || {},
|
|
572
593
|
pathname: ssrStorage.getStore()?.url || "/"
|
|
573
594
|
};
|
|
595
|
+
for (const [key, val] of Object.entries(windowStubs)) {
|
|
596
|
+
if (typeof win[key] !== "function") {
|
|
597
|
+
win[key] = val;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
574
600
|
}
|
|
575
601
|
globalThis.Node = SSRNode;
|
|
576
602
|
globalThis.HTMLElement = SSRElement;
|