@askrjs/askr 0.4.1 → 0.4.2
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/CHANGELOG.md +12 -0
- package/dist/benchmark.js +3 -3
- package/dist/boot/index.js +1 -1
- package/dist/{boot-C5HnQZio.js → boot-DUJkrqGs.js} +1 -1
- package/dist/foundations/interactions/index.js +1 -1
- package/dist/{interactions-BAa2xuJ-.js → interactions-B_wfsDQg.js} +4 -0
- package/dist/{render-sync-CUxvoVab.js → render-sync-Qz-9Hcqw.js} +159 -17
- package/dist/router/index.js +1 -1
- package/dist/ssg/index.js +1 -1
- package/dist/ssr/index.js +2 -2
- package/dist/{ssr-9LOx_bEu.js → ssr-DueDLmhp.js} +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/{verify-hydration-D_cyn1OX.js → verify-hydration-Jh5rnm_w.js} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.2 — 2026-10-01
|
|
4
|
+
|
|
5
|
+
- fix(foundations): honor previously cancelled click and keyboard events in
|
|
6
|
+
`pressable()` and `rovingFocus()` while preserving disabled propagation
|
|
7
|
+
suppression and native keyboard activation timing.
|
|
8
|
+
- fix(ssr): support private sibling component opt-in to render descendants once
|
|
9
|
+
before ancestor attributes, preserving legacy attribute order and output for
|
|
10
|
+
ordinary hosts, scoped lifetimes, namespaces, portals, and streaming transport.
|
|
11
|
+
- fix(ssr): finalize private component reference metadata after the rendered
|
|
12
|
+
root and its portals, preserving ordinary attribute evaluation and error
|
|
13
|
+
boundaries without repeating components or caller ID functions.
|
|
14
|
+
|
|
3
15
|
## 0.4.1 — 2026-10-01
|
|
4
16
|
|
|
5
17
|
- fix(data): honor defined-query `skipInitialFetch` and `initialData` options,
|
package/dist/benchmark.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { y as flushSync } from "./instance-DL-YKrj6.js";
|
|
2
2
|
import { a as state, i as selector } from "./state-i9D4EtY6.js";
|
|
3
3
|
import { i as jsxs, n as jsx } from "./jsx-runtime-C4idqHY0.js";
|
|
4
|
-
import { r as createIsland } from "./boot-
|
|
4
|
+
import { r as createIsland } from "./boot-DUJkrqGs.js";
|
|
5
5
|
import { n as For } from "./control-hr3B0QaD.js";
|
|
6
6
|
//#region src/bench/components/benchmark-row.tsx
|
|
7
7
|
function BenchmarkRow({ item, isSelected, onSelect, onRemove }) {
|
|
@@ -58,8 +58,8 @@ function BenchmarkTable({ rows, isSelected, onSelect, onRemove }) {
|
|
|
58
58
|
}
|
|
59
59
|
const benchmarkMetadata = {
|
|
60
60
|
packageName: "@askrjs/askr",
|
|
61
|
-
packageVersion: "0.4.
|
|
62
|
-
buildLabel: "0.4.
|
|
61
|
+
packageVersion: "0.4.2",
|
|
62
|
+
buildLabel: "0.4.2-local"
|
|
63
63
|
};
|
|
64
64
|
function getBenchmarkMetadata() {
|
|
65
65
|
return { ...benchmarkMetadata };
|
package/dist/boot/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as cleanupApp, i as createIslands, n as createSPA, o as hasApp, r as createIsland, t as hydrateSPA } from "../boot-
|
|
1
|
+
import { a as cleanupApp, i as createIslands, n as createSPA, o as hasApp, r as createIsland, t as hydrateSPA } from "../boot-DUJkrqGs.js";
|
|
2
2
|
export { cleanupApp, createIsland, createIslands, createSPA, hasApp, hydrateSPA };
|
|
@@ -3966,7 +3966,7 @@ async function hydrateSPA(config) {
|
|
|
3966
3966
|
onCommit: captureClientMarkup
|
|
3967
3967
|
});
|
|
3968
3968
|
if (shouldVerifyHydrationMarkup(config)) {
|
|
3969
|
-
const { captureServerHydrationMarkup, verifyClientHydrationMarkup, verifyHydrationSyncForUrl } = await import("./verify-hydration-
|
|
3969
|
+
const { captureServerHydrationMarkup, verifyClientHydrationMarkup, verifyHydrationSyncForUrl } = await import("./verify-hydration-Jh5rnm_w.js");
|
|
3970
3970
|
if (!verifyHydrationSyncForUrl({
|
|
3971
3971
|
root: rootElement,
|
|
3972
3972
|
url: currentUrl,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as focusable, i as hoverable, n as mergeInteractionProps, o as dismissable, r as rovingFocus, s as pressable, t as applyInteractionPolicy } from "../../interactions-
|
|
1
|
+
import { a as focusable, i as hoverable, n as mergeInteractionProps, o as dismissable, r as rovingFocus, s as pressable, t as applyInteractionPolicy } from "../../interactions-B_wfsDQg.js";
|
|
2
2
|
export { applyInteractionPolicy, dismissable, focusable, hoverable, mergeInteractionProps, pressable, rovingFocus };
|
|
@@ -8,6 +8,7 @@ function pressable({ disabled, onPress, isNativeButton = false }) {
|
|
|
8
8
|
e.stopPropagation?.();
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
+
if (e.defaultPrevented) return;
|
|
11
12
|
onPress?.(e);
|
|
12
13
|
} };
|
|
13
14
|
if (isNativeButton) {
|
|
@@ -25,6 +26,7 @@ function pressable({ disabled, onPress, isNativeButton = false }) {
|
|
|
25
26
|
e.stopPropagation?.();
|
|
26
27
|
return;
|
|
27
28
|
}
|
|
29
|
+
if (e.defaultPrevented) return;
|
|
28
30
|
if (e.key === "Enter") {
|
|
29
31
|
e.preventDefault?.();
|
|
30
32
|
onPress?.(e);
|
|
@@ -38,6 +40,7 @@ function pressable({ disabled, onPress, isNativeButton = false }) {
|
|
|
38
40
|
e.stopPropagation?.();
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
43
|
+
if (e.defaultPrevented) return;
|
|
41
44
|
if (e.key === " ") {
|
|
42
45
|
e.preventDefault?.();
|
|
43
46
|
onPress?.(e);
|
|
@@ -118,6 +121,7 @@ function rovingFocus(options) {
|
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
function handleKeyDown(e) {
|
|
124
|
+
if (e.defaultPrevented) return;
|
|
121
125
|
const { key } = e;
|
|
122
126
|
let direction;
|
|
123
127
|
if (orientation === "horizontal" || orientation === "both") {
|
|
@@ -473,6 +473,16 @@ var StreamSink = class {
|
|
|
473
473
|
//#region src/ssr/attrs.ts
|
|
474
474
|
const ESCAPED_ATTR_VALUE_CACHE_LIMIT = 512;
|
|
475
475
|
const escapedAttrValueCache = /* @__PURE__ */ new Map();
|
|
476
|
+
function readReferenceAttributeCell(cell) {
|
|
477
|
+
const descriptor = cell && Object.getOwnPropertyDescriptor(cell, "value");
|
|
478
|
+
if (!descriptor || !("value" in descriptor) || descriptor.value !== void 0 && typeof descriptor.value !== "string") throw new TypeError("SSR reference attribute cells require a string or undefined data value.");
|
|
479
|
+
return descriptor.value;
|
|
480
|
+
}
|
|
481
|
+
function renderReferenceAttributeCell(name, cell, sink) {
|
|
482
|
+
const value = readReferenceAttributeCell(cell);
|
|
483
|
+
if (value === void 0) return;
|
|
484
|
+
sink.write(" " + name + "=\"" + getEscapedAttrValue(value) + "\"");
|
|
485
|
+
}
|
|
476
486
|
function isEventHandler(key) {
|
|
477
487
|
return key.length >= 2 && key.slice(0, 2).toLowerCase() === "on";
|
|
478
488
|
}
|
|
@@ -489,13 +499,13 @@ function resolvePropValue(value) {
|
|
|
489
499
|
* element whose attributes are inspected before they are written. Returns
|
|
490
500
|
* `props` itself when nothing needs reading.
|
|
491
501
|
*/
|
|
492
|
-
function resolveReactiveAttributeProps(props) {
|
|
502
|
+
function resolveReactiveAttributeProps(props, referenceCells) {
|
|
493
503
|
if (!props || typeof props !== "object") return props;
|
|
494
504
|
let resolved = null;
|
|
495
505
|
const propsObj = props;
|
|
496
506
|
for (const key in propsObj) {
|
|
497
507
|
const value = propsObj[key];
|
|
498
|
-
if (typeof value !== "function" || isSkippedProp(key) || isEventHandler(key)) continue;
|
|
508
|
+
if (typeof value !== "function" || isSkippedProp(key) || isEventHandler(key) || referenceCells && Object.prototype.hasOwnProperty.call(referenceCells, key)) continue;
|
|
499
509
|
resolved ??= { ...propsObj };
|
|
500
510
|
resolved[key] = resolvePropValue(value);
|
|
501
511
|
}
|
|
@@ -522,7 +532,7 @@ function getEscapedAttrValue(value) {
|
|
|
522
532
|
* object values on custom elements) have no markup and are left out; the
|
|
523
533
|
* client applies them when it hydrates.
|
|
524
534
|
*/
|
|
525
|
-
function renderAttrsDirect(props, sink, tagName = "") {
|
|
535
|
+
function renderAttrsDirect(props, sink, tagName = "", referenceCells) {
|
|
526
536
|
if (!props || typeof props !== "object") return;
|
|
527
537
|
const customElement = isCustomElementName(tagName);
|
|
528
538
|
const propsObj = props;
|
|
@@ -530,6 +540,14 @@ function renderAttrsDirect(props, sink, tagName = "") {
|
|
|
530
540
|
if (isSkippedProp(key) || key === "dangerouslySetInnerHTML") continue;
|
|
531
541
|
if (isEventHandler(key)) continue;
|
|
532
542
|
if (key.charCodeAt(0) === 95) continue;
|
|
543
|
+
if (referenceCells && Object.prototype.hasOwnProperty.call(referenceCells, key)) {
|
|
544
|
+
if (key !== "aria-labelledby" && key !== "aria-describedby" && key !== "aria-controls") throw new TypeError("SSR reference attribute cells only support derived ARIA references.");
|
|
545
|
+
const cell = referenceCells[key];
|
|
546
|
+
readReferenceAttributeCell(cell);
|
|
547
|
+
if (sink.writeReferenceAttribute) sink.writeReferenceAttribute(key, cell);
|
|
548
|
+
else renderReferenceAttributeCell(key, cell, sink);
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
533
551
|
const value = resolvePropValue(propsObj[key]);
|
|
534
552
|
if (isPropertyOnlyProp(tagName, key, value)) continue;
|
|
535
553
|
if (value !== null && typeof value === "object" && key.startsWith("attr:")) continue;
|
|
@@ -690,6 +708,9 @@ function stopRenderPhase() {
|
|
|
690
708
|
* render contains preloaded resource slots. Portal hosts write tokens that
|
|
691
709
|
* are replaced with their final content once the render root completes.
|
|
692
710
|
*/
|
|
711
|
+
const CHILDREN_BEFORE_ATTRS = Symbol.for("askr.ssr.children-before-attrs");
|
|
712
|
+
const ATTRIBUTE_ROOT = Symbol.for("askr.ssr.attribute-root");
|
|
713
|
+
const ATTRIBUTE_CELLS = Symbol.for("askr.ssr.attribute-cells");
|
|
693
714
|
/**
|
|
694
715
|
* Collects writes so they can be published or dropped. An ErrorBoundary's
|
|
695
716
|
* subtree renders into one first, so markup from a subtree that then throws
|
|
@@ -701,24 +722,38 @@ var BufferedSink = class {
|
|
|
701
722
|
}
|
|
702
723
|
write(html) {
|
|
703
724
|
if (html) this.operations.push({
|
|
704
|
-
|
|
725
|
+
kind: "text",
|
|
705
726
|
text: html
|
|
706
727
|
});
|
|
707
728
|
}
|
|
708
729
|
writePortalHost(token) {
|
|
709
730
|
this.operations.push({
|
|
710
|
-
|
|
731
|
+
kind: "portal",
|
|
711
732
|
text: token
|
|
712
733
|
});
|
|
713
734
|
}
|
|
735
|
+
writeReferenceAttribute(name, cell) {
|
|
736
|
+
this.operations.push({
|
|
737
|
+
kind: "reference",
|
|
738
|
+
name,
|
|
739
|
+
cell
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
beginAttributeRoot() {
|
|
743
|
+
this.operations.push({ kind: "root" });
|
|
744
|
+
}
|
|
714
745
|
/** The buffered markup, without portal host tokens. */
|
|
715
746
|
html() {
|
|
716
747
|
let html = "";
|
|
717
|
-
for (const operation of this.operations) if (
|
|
748
|
+
for (const operation of this.operations) if (operation.kind === "text") html += operation.text;
|
|
718
749
|
return html;
|
|
719
750
|
}
|
|
720
751
|
publishTo(sink) {
|
|
721
|
-
for (const operation of this.operations) if (operation.
|
|
752
|
+
for (const operation of this.operations) if (operation.kind === "root") sink.beginAttributeRoot?.();
|
|
753
|
+
else if (operation.kind === "reference") {
|
|
754
|
+
if (sink.writeReferenceAttribute) sink.writeReferenceAttribute(operation.name, operation.cell);
|
|
755
|
+
else sink.write(referenceAttributeToken(operation.name, operation.cell));
|
|
756
|
+
} else if (operation.kind === "portal" && sink.writePortalHost) sink.writePortalHost(operation.text);
|
|
722
757
|
else sink.write(operation.text);
|
|
723
758
|
}
|
|
724
759
|
};
|
|
@@ -736,8 +771,14 @@ var PortalSink = class {
|
|
|
736
771
|
writePortalHost(token) {
|
|
737
772
|
(this.buffered ??= []).push(token);
|
|
738
773
|
}
|
|
774
|
+
beginAttributeRoot() {
|
|
775
|
+
this.buffered ??= [];
|
|
776
|
+
}
|
|
777
|
+
writeReferenceAttribute(name, cell) {
|
|
778
|
+
(this.buffered ??= []).push(referenceAttributeToken(name, cell));
|
|
779
|
+
}
|
|
739
780
|
flush(ctx) {
|
|
740
|
-
if (this.buffered) this.sink.write(resolvePortals(this.buffered.join(""), ctx));
|
|
781
|
+
if (this.buffered) this.sink.write(resolveReferenceAttributes(resolvePortals(this.buffered.join(""), ctx)));
|
|
741
782
|
}
|
|
742
783
|
};
|
|
743
784
|
let current = null;
|
|
@@ -777,11 +818,18 @@ function componentOutput(value) {
|
|
|
777
818
|
}
|
|
778
819
|
function renderComponent(fn, props, sink) {
|
|
779
820
|
const render = state();
|
|
821
|
+
const destination = sink;
|
|
822
|
+
const attributeRoot = props[ATTRIBUTE_ROOT] === true ? new BufferedSink() : null;
|
|
823
|
+
if (attributeRoot) {
|
|
824
|
+
attributeRoot.beginAttributeRoot();
|
|
825
|
+
sink = attributeRoot;
|
|
826
|
+
}
|
|
780
827
|
let owner = render.owner;
|
|
781
828
|
for (;;) {
|
|
782
829
|
const instance = new ComponentInstance(owner, fn, props);
|
|
783
830
|
instance.server = true;
|
|
784
831
|
instance.serverContext = render.ctx;
|
|
832
|
+
if (attributeRoot) render.attributeRoots.add(instance);
|
|
785
833
|
const output = runComponent(instance);
|
|
786
834
|
const resources = getCurrentRenderData()?.resources;
|
|
787
835
|
if (instance.serverResourceKeys.length && resources && Object.keys(resources).some((key) => /^r:\d+$/.test(key))) sink.write(`<!--askr-resource:${instance.serverResourceKeys.join(",")}-->`);
|
|
@@ -795,6 +843,7 @@ function renderComponent(fn, props, sink) {
|
|
|
795
843
|
}
|
|
796
844
|
if (!instance.boundary) {
|
|
797
845
|
withOwner(instance, () => renderValue(componentOutput(output), sink));
|
|
846
|
+
attributeRoot?.publishTo(destination);
|
|
798
847
|
return;
|
|
799
848
|
}
|
|
800
849
|
const buffer = new BufferedSink();
|
|
@@ -812,9 +861,11 @@ function renderComponent(fn, props, sink) {
|
|
|
812
861
|
} finally {
|
|
813
862
|
reportBoundaryCleanupErrors(cleanupErrors);
|
|
814
863
|
}
|
|
864
|
+
attributeRoot?.publishTo(destination);
|
|
815
865
|
return;
|
|
816
866
|
}
|
|
817
867
|
buffer.publishTo(sink);
|
|
868
|
+
attributeRoot?.publishTo(destination);
|
|
818
869
|
return;
|
|
819
870
|
}
|
|
820
871
|
}
|
|
@@ -906,19 +957,35 @@ function renderChild(child, sink) {
|
|
|
906
957
|
function assertElementName(name) {
|
|
907
958
|
if (!/^[A-Za-z][A-Za-z0-9._:-]*$/.test(name)) throw new TypeError(`Invalid SSR element name: ${JSON.stringify(name)}`);
|
|
908
959
|
}
|
|
960
|
+
/** Resolve only inputs needed to choose the child's parsing/selection context. */
|
|
961
|
+
function resolveEarlyContextProps(props, names) {
|
|
962
|
+
const descriptors = Object.getOwnPropertyDescriptors(props);
|
|
963
|
+
for (const name of names) {
|
|
964
|
+
if (!(name in props)) continue;
|
|
965
|
+
const value = props[name];
|
|
966
|
+
descriptors[name] = {
|
|
967
|
+
value: typeof value === "function" ? untrack(() => readValue(value)) : value,
|
|
968
|
+
enumerable: descriptors[name]?.enumerable ?? true,
|
|
969
|
+
configurable: true,
|
|
970
|
+
writable: true
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
return Object.create(Object.getPrototypeOf(props), descriptors);
|
|
974
|
+
}
|
|
909
975
|
function renderElement(tag, props, sink) {
|
|
910
976
|
assertElementName(tag);
|
|
911
977
|
if (VOID_ELEMENTS.has(tag)) {
|
|
912
978
|
sink.write("<" + tag);
|
|
913
|
-
|
|
979
|
+
renderHostAttrs(props, sink, tag);
|
|
914
980
|
sink.write(" />");
|
|
915
981
|
return;
|
|
916
982
|
}
|
|
917
983
|
const render = state();
|
|
984
|
+
const childrenBeforeAttrs = props[CHILDREN_BEFORE_ATTRS] === true;
|
|
918
985
|
const parentNamespace = render.namespace;
|
|
919
986
|
const lower = tag.toLowerCase();
|
|
920
987
|
const namespace = getElementNamespace(parentNamespace, lower);
|
|
921
|
-
let elementProps = lower === "annotation-xml" || namespace === "html" && (lower === "select" || lower === "option" && parentNamespace === "select") ? resolveReactiveAttributeProps(props) ?? props : props;
|
|
988
|
+
let elementProps = lower === "annotation-xml" || namespace === "html" && (lower === "select" || lower === "option" && parentNamespace === "select") ? childrenBeforeAttrs ? resolveEarlyContextProps(props, lower === "annotation-xml" ? ["encoding"] : lower === "select" ? ["value", "multiple"] : ["value"]) : resolveReactiveAttributeProps(props, referenceCellsFor(props)) ?? props : props;
|
|
922
989
|
const selection = render.selectSelections[render.selectSelections.length - 1];
|
|
923
990
|
let renderedChildren = null;
|
|
924
991
|
if (lower === "option" && parentNamespace === "select" && selection) {
|
|
@@ -933,14 +1000,27 @@ function renderElement(tag, props, sink) {
|
|
|
933
1000
|
} else value = String(own);
|
|
934
1001
|
const selected = selection.values.has(value) && (selection.multiple || !selection.matched);
|
|
935
1002
|
if (selected) selection.matched = true;
|
|
936
|
-
|
|
1003
|
+
if (childrenBeforeAttrs) {
|
|
1004
|
+
const descriptors = Object.getOwnPropertyDescriptors(elementProps);
|
|
1005
|
+
descriptors.selected = {
|
|
1006
|
+
value: selected,
|
|
1007
|
+
enumerable: true,
|
|
1008
|
+
configurable: true,
|
|
1009
|
+
writable: true
|
|
1010
|
+
};
|
|
1011
|
+
elementProps = Object.create(Object.getPrototypeOf(elementProps), descriptors);
|
|
1012
|
+
} else elementProps = {
|
|
937
1013
|
...elementProps,
|
|
938
1014
|
selected
|
|
939
1015
|
};
|
|
940
1016
|
}
|
|
941
1017
|
if (renderedChildren) {
|
|
1018
|
+
if (childrenBeforeAttrs) {
|
|
1019
|
+
writeBufferedElement(tag, elementProps, null, sink, renderedChildren);
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
942
1022
|
sink.write("<" + tag);
|
|
943
|
-
|
|
1023
|
+
renderHostAttrs(elementProps, sink, tag);
|
|
944
1024
|
sink.write(">");
|
|
945
1025
|
renderedChildren.publishTo(sink);
|
|
946
1026
|
sink.write("</" + tag + ">");
|
|
@@ -959,7 +1039,7 @@ function renderElement(tag, props, sink) {
|
|
|
959
1039
|
}
|
|
960
1040
|
const rawText = getRawTextElementInContext(parentNamespace, namespace, lower);
|
|
961
1041
|
try {
|
|
962
|
-
withNamespace(getChildNamespace(parentNamespace, namespace, lower, elementProps), () => writeElement(tag, elementProps, rawText, sink));
|
|
1042
|
+
withNamespace(getChildNamespace(parentNamespace, namespace, lower, elementProps), () => writeElement(tag, elementProps, rawText, sink, childrenBeforeAttrs));
|
|
963
1043
|
} finally {
|
|
964
1044
|
if (nextSelection) render.selectSelections.pop();
|
|
965
1045
|
}
|
|
@@ -1045,9 +1125,24 @@ function optionTextValue(html) {
|
|
|
1045
1125
|
}
|
|
1046
1126
|
return text;
|
|
1047
1127
|
}
|
|
1048
|
-
function
|
|
1128
|
+
function writeBufferedElement(tag, props, rawText, sink, children) {
|
|
1129
|
+
const opening = new BufferedSink();
|
|
1130
|
+
opening.write("<" + tag);
|
|
1131
|
+
renderHostAttrs(props, opening, rawText === null ? tag : void 0);
|
|
1132
|
+
opening.write(">");
|
|
1133
|
+
opening.publishTo(sink);
|
|
1134
|
+
children.publishTo(sink);
|
|
1135
|
+
sink.write("</" + tag + ">");
|
|
1136
|
+
}
|
|
1137
|
+
function writeElement(tag, props, rawText, sink, childrenBeforeAttrs) {
|
|
1138
|
+
if (childrenBeforeAttrs) {
|
|
1139
|
+
const children = new BufferedSink();
|
|
1140
|
+
writeContent(props, rawText, children);
|
|
1141
|
+
writeBufferedElement(tag, props, rawText, sink, children);
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1049
1144
|
sink.write("<" + tag);
|
|
1050
|
-
|
|
1145
|
+
renderHostAttrs(props, sink, rawText === null ? tag : void 0);
|
|
1051
1146
|
sink.write(">");
|
|
1052
1147
|
writeContent(props, rawText, sink);
|
|
1053
1148
|
sink.write("</" + tag + ">");
|
|
@@ -1124,6 +1219,49 @@ function flattenText(value, element) {
|
|
|
1124
1219
|
visit(value);
|
|
1125
1220
|
return out;
|
|
1126
1221
|
}
|
|
1222
|
+
function referenceCellsFor(props) {
|
|
1223
|
+
const cells = props[ATTRIBUTE_CELLS];
|
|
1224
|
+
if (!cells || typeof cells !== "object") return void 0;
|
|
1225
|
+
const render = state();
|
|
1226
|
+
for (let owner = render.owner; owner; owner = owner.parent) if (render.attributeRoots.has(owner)) return cells;
|
|
1227
|
+
}
|
|
1228
|
+
function renderHostAttrs(props, sink, tag) {
|
|
1229
|
+
const cells = referenceCellsFor(props);
|
|
1230
|
+
if (!cells) {
|
|
1231
|
+
renderAttrsDirect(props, sink, tag);
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
renderAttrsDirect(props, {
|
|
1235
|
+
write: (html) => sink.write(html),
|
|
1236
|
+
writeReferenceAttribute: (name, cell) => {
|
|
1237
|
+
if (sink.writeReferenceAttribute) sink.writeReferenceAttribute(name, cell);
|
|
1238
|
+
else sink.write(referenceAttributeToken(name, cell));
|
|
1239
|
+
}
|
|
1240
|
+
}, tag, cells);
|
|
1241
|
+
}
|
|
1242
|
+
function referenceAttributeToken(name, cell) {
|
|
1243
|
+
const render = state();
|
|
1244
|
+
readReferenceAttributeCell(cell);
|
|
1245
|
+
if (render.referenceAttributeNonce === null) {
|
|
1246
|
+
const nonce = globalThis.crypto.getRandomValues(/* @__PURE__ */ new Uint32Array(4));
|
|
1247
|
+
render.referenceAttributeNonce = Array.from(nonce, (part) => part.toString(16).padStart(8, "0")).join("");
|
|
1248
|
+
}
|
|
1249
|
+
const token = `<!--askr-attribute:${render.referenceAttributeNonce}:${render.nextReferenceAttribute++}-->`;
|
|
1250
|
+
render.referenceAttributes.set(token, {
|
|
1251
|
+
name,
|
|
1252
|
+
cell
|
|
1253
|
+
});
|
|
1254
|
+
return token;
|
|
1255
|
+
}
|
|
1256
|
+
function resolveReferenceAttributes(html) {
|
|
1257
|
+
let resolved = html;
|
|
1258
|
+
for (const [token, { name, cell }] of state().referenceAttributes) {
|
|
1259
|
+
const sink = new StringSink();
|
|
1260
|
+
renderReferenceAttributeCell(name, cell, sink);
|
|
1261
|
+
resolved = resolved.replace(token, () => sink.toString());
|
|
1262
|
+
}
|
|
1263
|
+
return resolved;
|
|
1264
|
+
}
|
|
1127
1265
|
function renderToString(value, namespace) {
|
|
1128
1266
|
const sink = new StringSink();
|
|
1129
1267
|
withNamespace(namespace, () => renderValue(value, sink));
|
|
@@ -1159,7 +1297,11 @@ function withServerRender(ctx, fn) {
|
|
|
1159
1297
|
owner,
|
|
1160
1298
|
namespace: "html",
|
|
1161
1299
|
portalNamespaces: /* @__PURE__ */ new Map(),
|
|
1162
|
-
selectSelections: []
|
|
1300
|
+
selectSelections: [],
|
|
1301
|
+
attributeRoots: /* @__PURE__ */ new WeakSet(),
|
|
1302
|
+
referenceAttributes: /* @__PURE__ */ new Map(),
|
|
1303
|
+
referenceAttributeNonce: null,
|
|
1304
|
+
nextReferenceAttribute: 0
|
|
1163
1305
|
};
|
|
1164
1306
|
let result;
|
|
1165
1307
|
try {
|
|
@@ -1227,7 +1369,7 @@ function renderToStringSync(component, props, options) {
|
|
|
1227
1369
|
const sink = new StringSink();
|
|
1228
1370
|
renderValue(rootElement(component, props ?? {}, nonce), sink);
|
|
1229
1371
|
sink.end();
|
|
1230
|
-
const html = resolvePortals(sink.toString(), ctx);
|
|
1372
|
+
const html = resolveReferenceAttributes(resolvePortals(sink.toString(), ctx));
|
|
1231
1373
|
options?.onContext?.(ctx);
|
|
1232
1374
|
return html + serializeHydrationRenderData(ctx.hydrationData ?? void 0, ctx.dataRuntime);
|
|
1233
1375
|
});
|
package/dist/router/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { n as createRouteRegistry } from "../manifest-BNupb86f.js";
|
|
|
6
6
|
import { a as group, c as route, i as fallback, n as resolveDeferredValues, o as index, r as routeData, s as page, t as Resolve } from "../deferred-nGZglpj6.js";
|
|
7
7
|
import { a as isSafeHref, r as assertPathHrefStaysOnOrigin } from "../url-C9xMpMMv.js";
|
|
8
8
|
import { o as mergeProps } from "../compose-ref-ccRU59BM.js";
|
|
9
|
-
import { t as applyInteractionPolicy } from "../interactions-
|
|
9
|
+
import { t as applyInteractionPolicy } from "../interactions-B_wfsDQg.js";
|
|
10
10
|
//#region src/router/route-query.ts
|
|
11
11
|
function getRouteQueryHistoryMode(options) {
|
|
12
12
|
if (options.history) return options.history;
|
package/dist/ssg/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ct as encodePathSegment, mt as prepareRouteHydrationData, nt as getRend
|
|
|
2
2
|
import { n as createRouteRegistry } from "../manifest-BNupb86f.js";
|
|
3
3
|
import { c as route, n as resolveDeferredValues } from "../deferred-nGZglpj6.js";
|
|
4
4
|
import { n as renderDocument } from "../ssr-DPfdcq0e.js";
|
|
5
|
-
import { n as renderToString } from "../ssr-
|
|
5
|
+
import { n as renderToString } from "../ssr-DueDLmhp.js";
|
|
6
6
|
import * as fs$1 from "node:fs/promises";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as pathModule from "node:path";
|
package/dist/ssr/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { T as SSRDataMissingError } from "../render-context-DGHnEveC.js";
|
|
2
|
-
import { a as SSRAccessDecisionError, i as renderRouteRequestToString, n as renderToString, r as renderRouteRequest, t as renderToStream } from "../ssr-
|
|
3
|
-
import { c as getRenderContext, d as escapeHtml, l as withRenderContext, n as renderToStringSync, s as createRenderContext, u as withRenderContextAsync } from "../render-sync-
|
|
2
|
+
import { a as SSRAccessDecisionError, i as renderRouteRequestToString, n as renderToString, r as renderRouteRequest, t as renderToStream } from "../ssr-DueDLmhp.js";
|
|
3
|
+
import { c as getRenderContext, d as escapeHtml, l as withRenderContext, n as renderToStringSync, s as createRenderContext, u as withRenderContextAsync } from "../render-sync-Qz-9Hcqw.js";
|
|
4
4
|
export { SSRAccessDecisionError, SSRDataMissingError, createRenderContext, escapeHtml, getRenderContext, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, withRenderContext, withRenderContextAsync };
|
|
@@ -5,7 +5,7 @@ import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetch
|
|
|
5
5
|
import { C as removeRouteBasePath, S as normalizeRouteBasePath, _ as getMatchingRouteRecord, a as resolveRouteRequest, n as getRouteRenderContext } from "./resolution-CF1BqHLm.js";
|
|
6
6
|
import { t as createDataRuntime } from "./data-runtime-i-RD0Ffm.js";
|
|
7
7
|
import { n as renderDocument } from "./ssr-DPfdcq0e.js";
|
|
8
|
-
import { a as serializeHydrationRenderData, i as StringSink, n as renderToStringSync, o as withHydratedAuth, r as StreamSink, s as createRenderContext, t as renderSSRRouteAppToSink, u as withRenderContextAsync } from "./render-sync-
|
|
8
|
+
import { a as serializeHydrationRenderData, i as StringSink, n as renderToStringSync, o as withHydratedAuth, r as StreamSink, s as createRenderContext, t as renderSSRRouteAppToSink, u as withRenderContextAsync } from "./render-sync-Qz-9Hcqw.js";
|
|
9
9
|
//#region src/ssr/errors.ts
|
|
10
10
|
/**
|
|
11
11
|
* Thrown by synchronous route SSR (`renderToString()`/`renderToStream()`) when
|
package/dist/testing/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { y as flushSync } from "../instance-DL-YKrj6.js";
|
|
2
2
|
import { n as createSource, s as notify, u as readSource } from "../hooks-kjLigwDJ.js";
|
|
3
3
|
import { v as matchRoute } from "../resolution-CF1BqHLm.js";
|
|
4
|
-
import { a as cleanupApp, n as createSPA, r as createIsland } from "../boot-
|
|
4
|
+
import { a as cleanupApp, n as createSPA, r as createIsland } from "../boot-DUJkrqGs.js";
|
|
5
5
|
import { h as addInvalidationListener, t as createDataRuntime, u as resolveDataRuntimeState } from "../data-runtime-i-RD0Ffm.js";
|
|
6
6
|
import { a as loadingQueryState, i as freshQueryState, o as refreshingQueryState, r as errorQueryState, s as staleQueryState } from "../data-BsnOUpQ6.js";
|
|
7
7
|
import { i as normalizeAsyncDataError } from "../shared-O2ZnmYAf.js";
|
|
@@ -2,7 +2,7 @@ import { r as validateCspNonce } from "./csp-nonce-D-XM_uuJ.js";
|
|
|
2
2
|
import { g as withHydrationVerificationRender, v as getHydrationRenderUrl } from "./render-context-DGHnEveC.js";
|
|
3
3
|
import { C as removeRouteBasePath, S as normalizeRouteBasePath, f as currentAuth, n as getRouteRenderContext, y as resolveRouteFromRoutes } from "./resolution-CF1BqHLm.js";
|
|
4
4
|
import { t as SSR_RENDER_DATA_ATTR } from "./ssr-DPfdcq0e.js";
|
|
5
|
-
import { i as StringSink, s as createRenderContext, t as renderSSRRouteAppToSink } from "./render-sync-
|
|
5
|
+
import { i as StringSink, s as createRenderContext, t as renderSSRRouteAppToSink } from "./render-sync-Qz-9Hcqw.js";
|
|
6
6
|
//#region src/ssr/render-resolved.ts
|
|
7
7
|
function sameRouteParams(left, right) {
|
|
8
8
|
if (!left || !right) return !left && !right;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askrjs/askr",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "A TypeScript UI runtime with getter-based state, fine-grained bindings, transactional commits with rollback, and one route graph for SPA, SSR, and SSG.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"askr",
|