streetui 1.6.0 → 1.7.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/bin.cjs +1 -1
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/{compile-CEom4hkp.d.cts → compile-Cte0nf06.d.cts} +80 -3
- package/dist/{compile-CEom4hkp.d.ts → compile-Cte0nf06.d.ts} +80 -3
- package/dist/create-bin.cjs +1 -1
- package/dist/create-bin.cjs.map +1 -1
- package/dist/create-bin.js +1 -1
- package/dist/create-bin.js.map +1 -1
- package/dist/{hydration-diagnostics-YrG-OJJe.d.ts → hydration-diagnostics-Ddgs3Puu.d.ts} +1 -1
- package/dist/{hydration-diagnostics-D286jpZZ.d.cts → hydration-diagnostics-zK-fihvd.d.cts} +1 -1
- package/dist/index.cjs +439 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -10
- package/dist/index.d.ts +93 -10
- package/dist/index.js +430 -5
- package/dist/index.js.map +1 -1
- package/dist/{server-C2xovHHb.d.cts → server-D4A8eunr.d.cts} +43 -1
- package/dist/{server-xU-BEwAj.d.ts → server-cgmCiPsz.d.ts} +43 -1
- package/dist/server.cjs +1126 -839
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1126 -839
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +375 -111
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +375 -111
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/testing.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as StreetApp } from './compile-
|
|
2
|
-
export { V as VERSION } from './compile-
|
|
3
|
-
import { R as RenderHandle, H as HydrationDiagnostic } from './hydration-diagnostics-
|
|
1
|
+
import { S as StreetApp } from './compile-Cte0nf06.cjs';
|
|
2
|
+
export { V as VERSION } from './compile-Cte0nf06.cjs';
|
|
3
|
+
import { R as RenderHandle, H as HydrationDiagnostic } from './hydration-diagnostics-zK-fihvd.cjs';
|
|
4
4
|
export * from 'streetui/diagnostics';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as StreetApp } from './compile-
|
|
2
|
-
export { V as VERSION } from './compile-
|
|
3
|
-
import { R as RenderHandle, H as HydrationDiagnostic } from './hydration-diagnostics-
|
|
1
|
+
import { S as StreetApp } from './compile-Cte0nf06.js';
|
|
2
|
+
export { V as VERSION } from './compile-Cte0nf06.js';
|
|
3
|
+
import { R as RenderHandle, H as HydrationDiagnostic } from './hydration-diagnostics-Ddgs3Puu.js';
|
|
4
4
|
export * from 'streetui/diagnostics';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/testing.js
CHANGED
|
@@ -253,6 +253,18 @@ var BrowserDOMAdapter = class {
|
|
|
253
253
|
focus(element) {
|
|
254
254
|
element.focus?.();
|
|
255
255
|
}
|
|
256
|
+
body() {
|
|
257
|
+
return document.body ?? null;
|
|
258
|
+
}
|
|
259
|
+
activeElement() {
|
|
260
|
+
return document.activeElement ?? null;
|
|
261
|
+
}
|
|
262
|
+
contains(ancestor, node) {
|
|
263
|
+
return ancestor.contains(node);
|
|
264
|
+
}
|
|
265
|
+
matches(element, selector) {
|
|
266
|
+
return typeof element.matches === "function" && element.matches(selector);
|
|
267
|
+
}
|
|
256
268
|
isElement(node) {
|
|
257
269
|
return node.nodeType === Node.ELEMENT_NODE;
|
|
258
270
|
}
|
|
@@ -310,6 +322,14 @@ var ServerFragment = class {
|
|
|
310
322
|
parent = null;
|
|
311
323
|
children = [];
|
|
312
324
|
};
|
|
325
|
+
var ServerRawHTML = class {
|
|
326
|
+
kind = "raw";
|
|
327
|
+
parent = null;
|
|
328
|
+
html;
|
|
329
|
+
constructor(html) {
|
|
330
|
+
this.html = html;
|
|
331
|
+
}
|
|
332
|
+
};
|
|
313
333
|
var ServerElement = class {
|
|
314
334
|
kind = "element";
|
|
315
335
|
parent = null;
|
|
@@ -460,6 +480,8 @@ function serializeServerNode(node) {
|
|
|
460
480
|
return `<!--${node.data}-->`;
|
|
461
481
|
case "fragment":
|
|
462
482
|
return serializeChildren(node);
|
|
483
|
+
case "raw":
|
|
484
|
+
return node.html;
|
|
463
485
|
case "element": {
|
|
464
486
|
const el = node;
|
|
465
487
|
const tag = el.tagName;
|
|
@@ -499,6 +521,15 @@ var ServerDOMAdapter = class {
|
|
|
499
521
|
createFragment() {
|
|
500
522
|
return new ServerFragment();
|
|
501
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Create a verbatim pre-serialized HTML node (v1.7 static SSR plan, §6).
|
|
526
|
+
* Server-only: the browser adapter does not implement this, and the renderer
|
|
527
|
+
* fast path only invokes it when a static SSR plan is present (SSR). The
|
|
528
|
+
* stored HTML was produced by this same serializer, so it is emitted as-is.
|
|
529
|
+
*/
|
|
530
|
+
createRawHTML(html) {
|
|
531
|
+
return new ServerRawHTML(html);
|
|
532
|
+
}
|
|
502
533
|
appendChild(parent, child) {
|
|
503
534
|
const p = asParent(parent);
|
|
504
535
|
const c = asServer(child);
|
|
@@ -600,6 +631,18 @@ var ServerDOMAdapter = class {
|
|
|
600
631
|
}
|
|
601
632
|
focus() {
|
|
602
633
|
}
|
|
634
|
+
body() {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
activeElement() {
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
contains(_ancestor, _node) {
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
matches(_element, _selector) {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
603
646
|
isElement(node) {
|
|
604
647
|
return asServer(node).kind === "element";
|
|
605
648
|
}
|
|
@@ -650,14 +693,90 @@ var ServerDOMAdapter = class {
|
|
|
650
693
|
}
|
|
651
694
|
};
|
|
652
695
|
|
|
696
|
+
// ../dom/src/focus.ts
|
|
697
|
+
var FOCUSABLE_SELECTOR = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
698
|
+
function focusById(dom, root, id) {
|
|
699
|
+
const el = dom.querySelector(root, `[id="${id}"]`);
|
|
700
|
+
if (el === null) return false;
|
|
701
|
+
dom.focus(el);
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
function focusFirst(dom, container, selector = FOCUSABLE_SELECTOR) {
|
|
705
|
+
const el = dom.querySelector(container, selector);
|
|
706
|
+
if (el === null) return false;
|
|
707
|
+
dom.focus(el);
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
function getFocusable(dom, container, selector = FOCUSABLE_SELECTOR) {
|
|
711
|
+
return Array.from(dom.querySelectorAll(container, selector)).filter(
|
|
712
|
+
(el) => dom.matches(el, selector)
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
function saveFocus(dom) {
|
|
716
|
+
return dom.activeElement();
|
|
717
|
+
}
|
|
718
|
+
function restoreFocus(dom, saved) {
|
|
719
|
+
if (saved !== null) dom.focus(saved);
|
|
720
|
+
}
|
|
721
|
+
function focusInitial(dom, container, initialFocusId) {
|
|
722
|
+
if (initialFocusId !== void 0 && focusById(dom, container, initialFocusId)) return;
|
|
723
|
+
focusFirst(dom, container);
|
|
724
|
+
}
|
|
725
|
+
function trapFocus(dom, container) {
|
|
726
|
+
const onKeydown = (event) => {
|
|
727
|
+
if (event.key !== "Tab") return;
|
|
728
|
+
const items = getFocusable(dom, container);
|
|
729
|
+
if (items.length === 0) {
|
|
730
|
+
event.preventDefault();
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
const first = items[0];
|
|
734
|
+
const last = items[items.length - 1];
|
|
735
|
+
const active = dom.activeElement();
|
|
736
|
+
if (active === null || !dom.contains(container, active)) {
|
|
737
|
+
event.preventDefault();
|
|
738
|
+
dom.focus(first);
|
|
739
|
+
} else if (event.shiftKey && active === first) {
|
|
740
|
+
event.preventDefault();
|
|
741
|
+
dom.focus(last);
|
|
742
|
+
} else if (!event.shiftKey && active === last) {
|
|
743
|
+
event.preventDefault();
|
|
744
|
+
dom.focus(first);
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
dom.addEventListener(container, "keydown", onKeydown);
|
|
748
|
+
return () => dom.removeEventListener(container, "keydown", onKeydown);
|
|
749
|
+
}
|
|
750
|
+
function containFocus(dom, container) {
|
|
751
|
+
const body = dom.body();
|
|
752
|
+
if (body === null) return () => {
|
|
753
|
+
};
|
|
754
|
+
const onFocusIn = (event) => {
|
|
755
|
+
const target = event.target;
|
|
756
|
+
if (target !== null && !dom.contains(container, target)) {
|
|
757
|
+
focusFirst(dom, container);
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
dom.addEventListener(body, "focusin", onFocusIn);
|
|
761
|
+
return () => dom.removeEventListener(body, "focusin", onFocusIn);
|
|
762
|
+
}
|
|
763
|
+
function onEscape(dom, target, handler) {
|
|
764
|
+
const onKeydown = (event) => {
|
|
765
|
+
if (event.key === "Escape") handler();
|
|
766
|
+
};
|
|
767
|
+
dom.addEventListener(target, "keydown", onKeydown);
|
|
768
|
+
return () => dom.removeEventListener(target, "keydown", onKeydown);
|
|
769
|
+
}
|
|
770
|
+
|
|
653
771
|
// ../renderer/src/render-context.ts
|
|
654
|
-
function createRenderContext(dom, graph, container, hydrationDiagnostics) {
|
|
772
|
+
function createRenderContext(dom, graph, container, hydrationDiagnostics, staticHTML) {
|
|
655
773
|
return {
|
|
656
774
|
dom,
|
|
657
775
|
graph,
|
|
658
776
|
instances: /* @__PURE__ */ new Map(),
|
|
659
777
|
container,
|
|
660
|
-
...hydrationDiagnostics !== void 0 ? { hydrationDiagnostics } : {}
|
|
778
|
+
...hydrationDiagnostics !== void 0 ? { hydrationDiagnostics } : {},
|
|
779
|
+
...staticHTML !== void 0 ? { staticHTML } : {}
|
|
661
780
|
};
|
|
662
781
|
}
|
|
663
782
|
|
|
@@ -806,7 +925,12 @@ var TAG_MAP = {
|
|
|
806
925
|
component: "div",
|
|
807
926
|
slot: "div",
|
|
808
927
|
fragment: "div",
|
|
809
|
-
"reactive-list": "ul"
|
|
928
|
+
"reactive-list": "ul",
|
|
929
|
+
// A portal renders as a neutral inline anchor <div> at its declaration site;
|
|
930
|
+
// its children are relocated to a document.body container on the browser
|
|
931
|
+
// (see the portal branch in mount.ts). On the server (no body) it renders
|
|
932
|
+
// inline, so the anchor tag is what SSR/hydration positionally match on.
|
|
933
|
+
portal: "div"
|
|
810
934
|
};
|
|
811
935
|
function resolveTag(type) {
|
|
812
936
|
return TAG_MAP[type] ?? "div";
|
|
@@ -1085,6 +1209,17 @@ function mountGraph(ctx) {
|
|
|
1085
1209
|
}
|
|
1086
1210
|
function mountNode(ctx, graphNode, parentDom) {
|
|
1087
1211
|
const { dom, graph } = ctx;
|
|
1212
|
+
const staticHTML = ctx.staticHTML;
|
|
1213
|
+
if (staticHTML !== void 0 && dom.createRawHTML !== void 0) {
|
|
1214
|
+
const precomputed = staticHTML.get(graphNode.id);
|
|
1215
|
+
if (precomputed !== void 0) {
|
|
1216
|
+
const raw = dom.createRawHTML(precomputed);
|
|
1217
|
+
dom.appendChild(parentDom, raw);
|
|
1218
|
+
const instance2 = new NodeInstance(graphNode, raw);
|
|
1219
|
+
ctx.instances.set(graphNode.id, instance2);
|
|
1220
|
+
return instance2;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1088
1223
|
if (graphNode.type === "application") {
|
|
1089
1224
|
const instance2 = new NodeInstance(graphNode, parentDom);
|
|
1090
1225
|
ctx.instances.set(graphNode.id, instance2);
|
|
@@ -1207,6 +1342,28 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
1207
1342
|
wireReactiveList(ctx, graphNode, instance2, el2);
|
|
1208
1343
|
return instance2;
|
|
1209
1344
|
}
|
|
1345
|
+
if (graphNode.type === "portal") {
|
|
1346
|
+
const anchor = dom.createElement(resolveTag("portal"));
|
|
1347
|
+
dom.setAttribute(anchor, "data-streetui-portal", "");
|
|
1348
|
+
applyNodeProps(ctx, graphNode, anchor);
|
|
1349
|
+
const instance2 = new NodeInstance(graphNode, anchor);
|
|
1350
|
+
ctx.instances.set(graphNode.id, instance2);
|
|
1351
|
+
const body = dom.body();
|
|
1352
|
+
let target = anchor;
|
|
1353
|
+
if (body !== null) {
|
|
1354
|
+
const portalContainer = dom.createElement("div");
|
|
1355
|
+
dom.setAttribute(portalContainer, "data-streetui-portal-container", "");
|
|
1356
|
+
dom.appendChild(body, portalContainer);
|
|
1357
|
+
instance2.trackCleanup(() => dom.removeChild(body, portalContainer));
|
|
1358
|
+
target = portalContainer;
|
|
1359
|
+
}
|
|
1360
|
+
for (const child of graphNode.children) {
|
|
1361
|
+
instance2.addChild(mountNode(ctx, child, target));
|
|
1362
|
+
}
|
|
1363
|
+
dom.appendChild(parentDom, anchor);
|
|
1364
|
+
wireOverlayBehavior(ctx, graphNode, instance2, target);
|
|
1365
|
+
return instance2;
|
|
1366
|
+
}
|
|
1210
1367
|
const tag = resolveTag(graphNode.type);
|
|
1211
1368
|
const el = dom.createElement(tag);
|
|
1212
1369
|
applyNodeProps(ctx, graphNode, el);
|
|
@@ -1356,6 +1513,44 @@ function forgetInstance(ctx, instance) {
|
|
|
1356
1513
|
ctx.instances.delete(instance.graphNode.id);
|
|
1357
1514
|
for (const child of instance.children) forgetInstance(ctx, child);
|
|
1358
1515
|
}
|
|
1516
|
+
function wireOverlayBehavior(ctx, graphNode, instance, target) {
|
|
1517
|
+
const { dom, graph } = ctx;
|
|
1518
|
+
if (dom.body() === null) return;
|
|
1519
|
+
const descFn = graph.getHandler(`__overlay__${graphNode.id}`);
|
|
1520
|
+
if (descFn === void 0) return;
|
|
1521
|
+
const desc = descFn();
|
|
1522
|
+
const openSig = desc.open;
|
|
1523
|
+
if (openSig === void 0 || typeof openSig.subscribe !== "function") return;
|
|
1524
|
+
let active = [];
|
|
1525
|
+
let saved = null;
|
|
1526
|
+
const teardown = () => {
|
|
1527
|
+
for (const fn of active) fn();
|
|
1528
|
+
active = [];
|
|
1529
|
+
};
|
|
1530
|
+
const onOpenChange = (isOpen) => {
|
|
1531
|
+
if (isOpen) {
|
|
1532
|
+
if (desc.restoreFocus) saved = saveFocus(dom);
|
|
1533
|
+
if (desc.takesFocus) focusInitial(dom, target, desc.initialFocusId);
|
|
1534
|
+
if (desc.modal) {
|
|
1535
|
+
active.push(trapFocus(dom, target));
|
|
1536
|
+
active.push(containFocus(dom, target));
|
|
1537
|
+
}
|
|
1538
|
+
if (desc.closeOnEscape && desc.onClose !== void 0) {
|
|
1539
|
+
active.push(onEscape(dom, target, desc.onClose));
|
|
1540
|
+
}
|
|
1541
|
+
} else {
|
|
1542
|
+
teardown();
|
|
1543
|
+
if (desc.restoreFocus && saved !== null) {
|
|
1544
|
+
restoreFocus(dom, saved);
|
|
1545
|
+
saved = null;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
const unsub = openSig.subscribe(onOpenChange);
|
|
1550
|
+
instance.trackCleanup(unsub);
|
|
1551
|
+
instance.trackCleanup(teardown);
|
|
1552
|
+
if (openSig.peek() === true) onOpenChange(true);
|
|
1553
|
+
}
|
|
1359
1554
|
|
|
1360
1555
|
// ../renderer/src/hydration-diagnostics.ts
|
|
1361
1556
|
function formatHydrationDiagnostic(d) {
|
|
@@ -1451,6 +1646,25 @@ function hydrateNode(ctx, graphNode, domNode, path) {
|
|
|
1451
1646
|
wireReactiveList(ctx, graphNode, instance, domNode);
|
|
1452
1647
|
return instance;
|
|
1453
1648
|
}
|
|
1649
|
+
case "portal": {
|
|
1650
|
+
const instance = new NodeInstance(graphNode, domNode);
|
|
1651
|
+
ctx.instances.set(graphNode.id, instance);
|
|
1652
|
+
const body = dom.body();
|
|
1653
|
+
let target = domNode;
|
|
1654
|
+
if (body !== null) {
|
|
1655
|
+
const portalContainer = dom.createElement("div");
|
|
1656
|
+
dom.setAttribute(portalContainer, "data-streetui-portal-container", "");
|
|
1657
|
+
for (const child of dom.childNodes(domNode)) {
|
|
1658
|
+
dom.appendChild(portalContainer, child);
|
|
1659
|
+
}
|
|
1660
|
+
dom.appendChild(body, portalContainer);
|
|
1661
|
+
instance.trackCleanup(() => dom.removeChild(body, portalContainer));
|
|
1662
|
+
target = portalContainer;
|
|
1663
|
+
}
|
|
1664
|
+
hydrateChildren(ctx, graphNode, instance, target, path);
|
|
1665
|
+
wireOverlayBehavior(ctx, graphNode, instance, target);
|
|
1666
|
+
return instance;
|
|
1667
|
+
}
|
|
1454
1668
|
default: {
|
|
1455
1669
|
const instance = new NodeInstance(graphNode, domNode);
|
|
1456
1670
|
ctx.instances.set(graphNode.id, instance);
|
|
@@ -1629,11 +1843,167 @@ function createRenderer(options) {
|
|
|
1629
1843
|
return new StreetRendererImpl(options);
|
|
1630
1844
|
}
|
|
1631
1845
|
|
|
1846
|
+
// ../compiler/dist/diagnostics.js
|
|
1847
|
+
var TEXT_PROP_KEYS = /* @__PURE__ */ new Set(["text", "label", "value"]);
|
|
1848
|
+
function analyzeGraph(graph) {
|
|
1849
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
1850
|
+
const summary = {
|
|
1851
|
+
totalNodes: 0,
|
|
1852
|
+
staticNodes: 0,
|
|
1853
|
+
staticSubtrees: 0,
|
|
1854
|
+
dynamicTextNodes: 0,
|
|
1855
|
+
dynamicAttrNodes: 0,
|
|
1856
|
+
eventNodes: 0,
|
|
1857
|
+
lists: 0,
|
|
1858
|
+
conditionals: 0
|
|
1859
|
+
};
|
|
1860
|
+
const visit = (node) => {
|
|
1861
|
+
let allChildrenStatic = true;
|
|
1862
|
+
for (const child of node.children) {
|
|
1863
|
+
const childSubtreeStatic = visit(child);
|
|
1864
|
+
if (!childSubtreeStatic) allChildrenStatic = false;
|
|
1865
|
+
}
|
|
1866
|
+
let hasDynamicText = false;
|
|
1867
|
+
let hasDynamicAttr = false;
|
|
1868
|
+
for (const ref of node.stateRefs) {
|
|
1869
|
+
if (TEXT_PROP_KEYS.has(ref.propKey)) hasDynamicText = true;
|
|
1870
|
+
else hasDynamicAttr = true;
|
|
1871
|
+
}
|
|
1872
|
+
const hasEvents = node.events.length > 0;
|
|
1873
|
+
const isList = node.type === "reactive-list";
|
|
1874
|
+
const isConditional = node.type === "conditional";
|
|
1875
|
+
const isPortal = node.type === "portal";
|
|
1876
|
+
const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional && !isPortal;
|
|
1877
|
+
const isStaticSubtree = isStatic && allChildrenStatic;
|
|
1878
|
+
nodes.set(node.id, {
|
|
1879
|
+
isStatic,
|
|
1880
|
+
isStaticSubtree,
|
|
1881
|
+
hasDynamicText,
|
|
1882
|
+
hasDynamicAttr,
|
|
1883
|
+
hasEvents,
|
|
1884
|
+
isList,
|
|
1885
|
+
isConditional
|
|
1886
|
+
});
|
|
1887
|
+
summary.totalNodes += 1;
|
|
1888
|
+
if (isStatic) summary.staticNodes += 1;
|
|
1889
|
+
if (isStaticSubtree) summary.staticSubtrees += 1;
|
|
1890
|
+
if (hasDynamicText) summary.dynamicTextNodes += 1;
|
|
1891
|
+
if (hasDynamicAttr) summary.dynamicAttrNodes += 1;
|
|
1892
|
+
if (hasEvents) summary.eventNodes += 1;
|
|
1893
|
+
if (isList) summary.lists += 1;
|
|
1894
|
+
if (isConditional) summary.conditionals += 1;
|
|
1895
|
+
return isStaticSubtree;
|
|
1896
|
+
};
|
|
1897
|
+
visit(graph.root);
|
|
1898
|
+
return { nodes, summary };
|
|
1899
|
+
}
|
|
1900
|
+
function inspectCompilation(graph) {
|
|
1901
|
+
const analysis = analyzeGraph(graph);
|
|
1902
|
+
const nodes = [];
|
|
1903
|
+
const walk = (node, depth) => {
|
|
1904
|
+
const a = analysis.nodes.get(node.id);
|
|
1905
|
+
if (a !== void 0) {
|
|
1906
|
+
const classification = a.isStaticSubtree ? "static-subtree-root" : a.isStatic ? "static" : "dynamic";
|
|
1907
|
+
nodes.push({
|
|
1908
|
+
id: node.id,
|
|
1909
|
+
type: node.type,
|
|
1910
|
+
depth,
|
|
1911
|
+
classification,
|
|
1912
|
+
dynamicText: a.hasDynamicText,
|
|
1913
|
+
dynamicAttrs: a.hasDynamicAttr,
|
|
1914
|
+
events: node.events.map((e) => e.type),
|
|
1915
|
+
boundProps: node.stateRefs.map((r) => r.propKey),
|
|
1916
|
+
isList: a.isList,
|
|
1917
|
+
isConditional: a.isConditional,
|
|
1918
|
+
hydration: a.isStaticSubtree ? "adopt-static" : "verify-dynamic"
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1921
|
+
for (const child of node.children) walk(child, depth + 1);
|
|
1922
|
+
};
|
|
1923
|
+
walk(graph.root, 0);
|
|
1924
|
+
const staticRatio = analysis.summary.totalNodes === 0 ? 0 : analysis.summary.staticNodes / analysis.summary.totalNodes;
|
|
1925
|
+
return {
|
|
1926
|
+
name: graph.name,
|
|
1927
|
+
version: graph.version,
|
|
1928
|
+
summary: { ...analysis.summary, staticRatio: +staticRatio.toFixed(4) },
|
|
1929
|
+
nodes
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
function formatInspection(inspection) {
|
|
1933
|
+
const s = inspection.summary;
|
|
1934
|
+
const lines = [];
|
|
1935
|
+
lines.push(`StreetUI compiler inspection \u2014 ${inspection.name} v${inspection.version}`);
|
|
1936
|
+
lines.push(
|
|
1937
|
+
` nodes=${s.totalNodes} static=${s.staticNodes} staticSubtrees=${s.staticSubtrees} dynamicText=${s.dynamicTextNodes} dynamicAttrs=${s.dynamicAttrNodes} events=${s.eventNodes} lists=${s.lists} conditionals=${s.conditionals} staticRatio=${(s.staticRatio * 100).toFixed(1)}%`
|
|
1938
|
+
);
|
|
1939
|
+
for (const n of inspection.nodes) {
|
|
1940
|
+
const flags = [];
|
|
1941
|
+
if (n.dynamicText) flags.push("text");
|
|
1942
|
+
if (n.dynamicAttrs) flags.push("attr:" + n.boundProps.join(","));
|
|
1943
|
+
if (n.events.length > 0) flags.push("on:" + n.events.join(","));
|
|
1944
|
+
if (n.isList) flags.push("list");
|
|
1945
|
+
if (n.isConditional) flags.push("cond");
|
|
1946
|
+
lines.push(
|
|
1947
|
+
` ${" ".repeat(n.depth)}${n.type}#${n.id} [${n.classification}]` + (flags.length > 0 ? ` {${flags.join(" ")}}` : "")
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
return lines.join("\n");
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
// ../renderer/src/static-ssr-plan.ts
|
|
1954
|
+
function collectMaximalStaticRoots(graph) {
|
|
1955
|
+
const analysis = analyzeGraph(graph);
|
|
1956
|
+
const roots = [];
|
|
1957
|
+
const walk = (node) => {
|
|
1958
|
+
if (node.type !== "application") {
|
|
1959
|
+
const a = analysis.nodes.get(node.id);
|
|
1960
|
+
if (a !== void 0 && a.isStaticSubtree) {
|
|
1961
|
+
roots.push(node);
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
for (const child of node.children) walk(child);
|
|
1966
|
+
};
|
|
1967
|
+
walk(graph.root);
|
|
1968
|
+
return roots;
|
|
1969
|
+
}
|
|
1970
|
+
function serializeStaticSubtree(dom, graph, root) {
|
|
1971
|
+
const container = dom.createElement("div");
|
|
1972
|
+
const ctx = createRenderContext(dom, graph, container);
|
|
1973
|
+
const instance = mountNode(ctx, root, container);
|
|
1974
|
+
const html = dom.serializeInner(container);
|
|
1975
|
+
instance.dispose();
|
|
1976
|
+
ctx.instances.clear();
|
|
1977
|
+
return html;
|
|
1978
|
+
}
|
|
1979
|
+
function buildStaticSSRPlan(compiled) {
|
|
1980
|
+
const graph = compiled.graph;
|
|
1981
|
+
const roots = collectMaximalStaticRoots(graph);
|
|
1982
|
+
const plan = /* @__PURE__ */ new Map();
|
|
1983
|
+
if (roots.length === 0) return plan;
|
|
1984
|
+
const dom = new ServerDOMAdapter();
|
|
1985
|
+
for (const root of roots) {
|
|
1986
|
+
plan.set(root.id, serializeStaticSubtree(dom, graph, root));
|
|
1987
|
+
}
|
|
1988
|
+
return plan;
|
|
1989
|
+
}
|
|
1990
|
+
var PLAN_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1991
|
+
function getStaticSSRPlan(compiled) {
|
|
1992
|
+
let plan = PLAN_CACHE.get(compiled);
|
|
1993
|
+
if (plan === void 0) {
|
|
1994
|
+
plan = buildStaticSSRPlan(compiled);
|
|
1995
|
+
PLAN_CACHE.set(compiled, plan);
|
|
1996
|
+
}
|
|
1997
|
+
return plan;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
1632
2000
|
// ../renderer/src/ssr.ts
|
|
1633
2001
|
function renderToString(compiled, options = {}) {
|
|
1634
2002
|
const dom = options.domAdapter ?? new ServerDOMAdapter();
|
|
2003
|
+
const plan = options.staticPlan === null ? void 0 : options.staticPlan ?? getStaticSSRPlan(compiled);
|
|
2004
|
+
const staticHTML = plan !== void 0 && plan.size > 0 ? plan : void 0;
|
|
1635
2005
|
const container = dom.createElement("div");
|
|
1636
|
-
const ctx = createRenderContext(dom, compiled.graph, container);
|
|
2006
|
+
const ctx = createRenderContext(dom, compiled.graph, container, void 0, staticHTML);
|
|
1637
2007
|
const rootInstance = mountGraph(ctx);
|
|
1638
2008
|
const html = dom.serializeInner(container);
|
|
1639
2009
|
rootInstance.dispose();
|
|
@@ -1928,114 +2298,8 @@ function renderServerThenHydrate(build, options = {}) {
|
|
|
1928
2298
|
};
|
|
1929
2299
|
}
|
|
1930
2300
|
|
|
1931
|
-
// ../compiler/dist/diagnostics.js
|
|
1932
|
-
var TEXT_PROP_KEYS = /* @__PURE__ */ new Set(["text", "label", "value"]);
|
|
1933
|
-
function analyzeGraph(graph) {
|
|
1934
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
1935
|
-
const summary = {
|
|
1936
|
-
totalNodes: 0,
|
|
1937
|
-
staticNodes: 0,
|
|
1938
|
-
staticSubtrees: 0,
|
|
1939
|
-
dynamicTextNodes: 0,
|
|
1940
|
-
dynamicAttrNodes: 0,
|
|
1941
|
-
eventNodes: 0,
|
|
1942
|
-
lists: 0,
|
|
1943
|
-
conditionals: 0
|
|
1944
|
-
};
|
|
1945
|
-
const visit = (node) => {
|
|
1946
|
-
let allChildrenStatic = true;
|
|
1947
|
-
for (const child of node.children) {
|
|
1948
|
-
const childSubtreeStatic = visit(child);
|
|
1949
|
-
if (!childSubtreeStatic) allChildrenStatic = false;
|
|
1950
|
-
}
|
|
1951
|
-
let hasDynamicText = false;
|
|
1952
|
-
let hasDynamicAttr = false;
|
|
1953
|
-
for (const ref of node.stateRefs) {
|
|
1954
|
-
if (TEXT_PROP_KEYS.has(ref.propKey)) hasDynamicText = true;
|
|
1955
|
-
else hasDynamicAttr = true;
|
|
1956
|
-
}
|
|
1957
|
-
const hasEvents = node.events.length > 0;
|
|
1958
|
-
const isList = node.type === "reactive-list";
|
|
1959
|
-
const isConditional = node.type === "conditional";
|
|
1960
|
-
const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional;
|
|
1961
|
-
const isStaticSubtree = isStatic && allChildrenStatic;
|
|
1962
|
-
nodes.set(node.id, {
|
|
1963
|
-
isStatic,
|
|
1964
|
-
isStaticSubtree,
|
|
1965
|
-
hasDynamicText,
|
|
1966
|
-
hasDynamicAttr,
|
|
1967
|
-
hasEvents,
|
|
1968
|
-
isList,
|
|
1969
|
-
isConditional
|
|
1970
|
-
});
|
|
1971
|
-
summary.totalNodes += 1;
|
|
1972
|
-
if (isStatic) summary.staticNodes += 1;
|
|
1973
|
-
if (isStaticSubtree) summary.staticSubtrees += 1;
|
|
1974
|
-
if (hasDynamicText) summary.dynamicTextNodes += 1;
|
|
1975
|
-
if (hasDynamicAttr) summary.dynamicAttrNodes += 1;
|
|
1976
|
-
if (hasEvents) summary.eventNodes += 1;
|
|
1977
|
-
if (isList) summary.lists += 1;
|
|
1978
|
-
if (isConditional) summary.conditionals += 1;
|
|
1979
|
-
return isStaticSubtree;
|
|
1980
|
-
};
|
|
1981
|
-
visit(graph.root);
|
|
1982
|
-
return { nodes, summary };
|
|
1983
|
-
}
|
|
1984
|
-
function inspectCompilation(graph) {
|
|
1985
|
-
const analysis = analyzeGraph(graph);
|
|
1986
|
-
const nodes = [];
|
|
1987
|
-
const walk = (node, depth) => {
|
|
1988
|
-
const a = analysis.nodes.get(node.id);
|
|
1989
|
-
if (a !== void 0) {
|
|
1990
|
-
const classification = a.isStaticSubtree ? "static-subtree-root" : a.isStatic ? "static" : "dynamic";
|
|
1991
|
-
nodes.push({
|
|
1992
|
-
id: node.id,
|
|
1993
|
-
type: node.type,
|
|
1994
|
-
depth,
|
|
1995
|
-
classification,
|
|
1996
|
-
dynamicText: a.hasDynamicText,
|
|
1997
|
-
dynamicAttrs: a.hasDynamicAttr,
|
|
1998
|
-
events: node.events.map((e) => e.type),
|
|
1999
|
-
boundProps: node.stateRefs.map((r) => r.propKey),
|
|
2000
|
-
isList: a.isList,
|
|
2001
|
-
isConditional: a.isConditional,
|
|
2002
|
-
hydration: a.isStaticSubtree ? "adopt-static" : "verify-dynamic"
|
|
2003
|
-
});
|
|
2004
|
-
}
|
|
2005
|
-
for (const child of node.children) walk(child, depth + 1);
|
|
2006
|
-
};
|
|
2007
|
-
walk(graph.root, 0);
|
|
2008
|
-
const staticRatio = analysis.summary.totalNodes === 0 ? 0 : analysis.summary.staticNodes / analysis.summary.totalNodes;
|
|
2009
|
-
return {
|
|
2010
|
-
name: graph.name,
|
|
2011
|
-
version: graph.version,
|
|
2012
|
-
summary: { ...analysis.summary, staticRatio: +staticRatio.toFixed(4) },
|
|
2013
|
-
nodes
|
|
2014
|
-
};
|
|
2015
|
-
}
|
|
2016
|
-
function formatInspection(inspection) {
|
|
2017
|
-
const s = inspection.summary;
|
|
2018
|
-
const lines = [];
|
|
2019
|
-
lines.push(`StreetUI compiler inspection \u2014 ${inspection.name} v${inspection.version}`);
|
|
2020
|
-
lines.push(
|
|
2021
|
-
` nodes=${s.totalNodes} static=${s.staticNodes} staticSubtrees=${s.staticSubtrees} dynamicText=${s.dynamicTextNodes} dynamicAttrs=${s.dynamicAttrNodes} events=${s.eventNodes} lists=${s.lists} conditionals=${s.conditionals} staticRatio=${(s.staticRatio * 100).toFixed(1)}%`
|
|
2022
|
-
);
|
|
2023
|
-
for (const n of inspection.nodes) {
|
|
2024
|
-
const flags = [];
|
|
2025
|
-
if (n.dynamicText) flags.push("text");
|
|
2026
|
-
if (n.dynamicAttrs) flags.push("attr:" + n.boundProps.join(","));
|
|
2027
|
-
if (n.events.length > 0) flags.push("on:" + n.events.join(","));
|
|
2028
|
-
if (n.isList) flags.push("list");
|
|
2029
|
-
if (n.isConditional) flags.push("cond");
|
|
2030
|
-
lines.push(
|
|
2031
|
-
` ${" ".repeat(n.depth)}${n.type}#${n.id} [${n.classification}]` + (flags.length > 0 ? ` {${flags.join(" ")}}` : "")
|
|
2032
|
-
);
|
|
2033
|
-
}
|
|
2034
|
-
return lines.join("\n");
|
|
2035
|
-
}
|
|
2036
|
-
|
|
2037
2301
|
// src/version.ts
|
|
2038
|
-
var VERSION = "1.
|
|
2302
|
+
var VERSION = "1.7.0";
|
|
2039
2303
|
export {
|
|
2040
2304
|
VERSION,
|
|
2041
2305
|
analyzeGraph,
|