pagegraph 0.11.0 → 0.13.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.
Files changed (100) hide show
  1. package/README.md +403 -148
  2. package/dist/audit.d.ts +2 -2
  3. package/dist/audit.js +4 -4
  4. package/dist/build-only/audit.d.ts +1 -0
  5. package/dist/build-only/audit.js +6 -0
  6. package/dist/build-only/audit.js.map +1 -0
  7. package/dist/build-only/claims.d.ts +1 -0
  8. package/dist/build-only/claims.js +6 -0
  9. package/dist/build-only/claims.js.map +1 -0
  10. package/dist/build-only/config.d.ts +1 -0
  11. package/dist/build-only/config.js +6 -0
  12. package/dist/build-only/config.js.map +1 -0
  13. package/dist/build-only/oxlint.d.ts +1 -0
  14. package/dist/build-only/oxlint.js +6 -0
  15. package/dist/build-only/oxlint.js.map +1 -0
  16. package/dist/build-only/tanstack-start.d.ts +1 -0
  17. package/dist/build-only/tanstack-start.js +6 -0
  18. package/dist/build-only/tanstack-start.js.map +1 -0
  19. package/dist/build-only/vite.d.ts +1 -0
  20. package/dist/build-only/vite.js +6 -0
  21. package/dist/build-only/vite.js.map +1 -0
  22. package/dist/{checks-nk8ZRRIA.js → checks-BS-aDXB_.js} +4 -142
  23. package/dist/checks-BS-aDXB_.js.map +1 -0
  24. package/dist/claims-Bch7Lxlo.d.ts +92 -0
  25. package/dist/claims-Bv7voeEV.js +431 -0
  26. package/dist/claims-Bv7voeEV.js.map +1 -0
  27. package/dist/claims.d.ts +94 -0
  28. package/dist/claims.js +2 -0
  29. package/dist/cli.js +10368 -8485
  30. package/dist/cli.js.map +1 -1
  31. package/dist/config.d.ts +4 -83
  32. package/dist/config.js +3 -122
  33. package/dist/config.js.map +1 -1
  34. package/dist/{content-CB_kHmJ3.js → content-CHd0X4s6.js} +3 -2
  35. package/dist/{content-CB_kHmJ3.js.map → content-CHd0X4s6.js.map} +1 -1
  36. package/dist/{content-DVL2iyGU.d.ts → content-DgNr7apS.d.ts} +5 -130
  37. package/dist/declare-D5o7hwmv.js +9 -0
  38. package/dist/declare-D5o7hwmv.js.map +1 -0
  39. package/dist/document-CztEu3Vd.d.ts +109 -0
  40. package/dist/document-Dvemcv7V.js +379 -0
  41. package/dist/document-Dvemcv7V.js.map +1 -0
  42. package/dist/facts-1OKclPOk.js +115 -0
  43. package/dist/facts-1OKclPOk.js.map +1 -0
  44. package/dist/graph-D1PIndsC.d.ts +12238 -0
  45. package/dist/graph-DMNOLXLu.js +172 -0
  46. package/dist/graph-DMNOLXLu.js.map +1 -0
  47. package/dist/index-C5w9ripz.d.ts +204 -0
  48. package/dist/index.d.ts +6 -196
  49. package/dist/index.js +55 -134
  50. package/dist/index.js.map +1 -1
  51. package/dist/inline-BbS93GAT.js +682 -0
  52. package/dist/inline-BbS93GAT.js.map +1 -0
  53. package/dist/llms-Dhr_5u2O.js +19 -0
  54. package/dist/llms-Dhr_5u2O.js.map +1 -0
  55. package/dist/markdown-C6dRE9zD.js +168 -0
  56. package/dist/markdown-C6dRE9zD.js.map +1 -0
  57. package/dist/markdown-path-lJB9BAVZ.js +6 -0
  58. package/dist/markdown-path-lJB9BAVZ.js.map +1 -0
  59. package/dist/message-CuBjgZ74.js +12 -0
  60. package/dist/message-CuBjgZ74.js.map +1 -0
  61. package/dist/oxlint.d.ts +58 -0
  62. package/dist/oxlint.js +202 -0
  63. package/dist/oxlint.js.map +1 -0
  64. package/dist/page-heads-BfjWQvau.d.ts +108 -0
  65. package/dist/page-heads-BgbaIjj9.js +25 -0
  66. package/dist/page-heads-BgbaIjj9.js.map +1 -0
  67. package/dist/projections-Bk-qOOsR.d.ts +78 -0
  68. package/dist/projections-D0oOFKiY.js +142 -0
  69. package/dist/projections-D0oOFKiY.js.map +1 -0
  70. package/dist/react.d.ts +27 -12051
  71. package/dist/react.js +14 -4
  72. package/dist/react.js.map +1 -1
  73. package/dist/route-config-35ZEzkNC.js +308 -0
  74. package/dist/route-config-35ZEzkNC.js.map +1 -0
  75. package/dist/route-config-wneg6ktn.d.ts +29 -0
  76. package/dist/tanstack-start/index.d.ts +56 -0
  77. package/dist/tanstack-start/index.js +717 -0
  78. package/dist/tanstack-start/index.js.map +1 -0
  79. package/dist/tanstack-start/markdown.d.ts +12 -0
  80. package/dist/tanstack-start/markdown.js +149 -0
  81. package/dist/tanstack-start/markdown.js.map +1 -0
  82. package/dist/tanstack-start/prerender-worker.d.ts +2 -0
  83. package/dist/tanstack-start/prerender-worker.js +7 -0
  84. package/dist/tanstack-start/prerender-worker.js.map +1 -0
  85. package/dist/tanstack-start/react.d.ts +7 -0
  86. package/dist/tanstack-start/react.js +12 -0
  87. package/dist/tanstack-start/react.js.map +1 -0
  88. package/dist/tanstack-start/server.d.ts +20 -0
  89. package/dist/tanstack-start/server.js +77 -0
  90. package/dist/tanstack-start/server.js.map +1 -0
  91. package/dist/vite-graph-loader-CsGiYNWE.js +105 -0
  92. package/dist/vite-graph-loader-CsGiYNWE.js.map +1 -0
  93. package/dist/vite-graph-loader-DZCwejuJ.d.ts +133 -0
  94. package/dist/vite.d.ts +2 -28
  95. package/dist/vite.js +1 -307
  96. package/dist/wire-B4RQMc4e.js +26 -0
  97. package/dist/wire-B4RQMc4e.js.map +1 -0
  98. package/package.json +70 -7
  99. package/dist/checks-nk8ZRRIA.js.map +0 -1
  100. package/dist/vite.js.map +0 -1
@@ -0,0 +1,109 @@
1
+ import { m as Register } from "./graph-D1PIndsC.js";
2
+ import { f as Message, h as SectionItem, m as SectionDocument, o as Facts, p as PageDocument, u as BodyEntry } from "./page-heads-BfjWQvau.js";
3
+ import { D as SectionKind } from "./index-C5w9ripz.js";
4
+ import { ComponentPropsWithRef, ReactNode } from "react";
5
+ //#region src/react/document.d.ts
6
+ /** Augment with `facts: typeof facts` to check Fact ids across the application. */
7
+ type FactId = Register extends {
8
+ facts: infer F extends Facts;
9
+ } ? Extract<keyof F, string> : string;
10
+ type MutableSection = Omit<SectionDocument, "title" | "body" | "items"> & {
11
+ title?: Message;
12
+ body: Array<BodyEntry>;
13
+ items: Array<MutableItem>;
14
+ };
15
+ type MutableItem = Omit<SectionItem, "title" | "href" | "body" | "cells"> & {
16
+ title?: Message;
17
+ href?: string;
18
+ body: Array<BodyEntry>;
19
+ cells: Array<Message>;
20
+ };
21
+ interface Collector {
22
+ path: string;
23
+ site: string;
24
+ facts?: Facts;
25
+ sectionCount: number;
26
+ sections: Array<MutableSection>;
27
+ messages: Array<Message>;
28
+ records: Map<string, () => void>;
29
+ links: Set<MutableItem>;
30
+ completed: boolean;
31
+ }
32
+ declare const CaptureRequest: import("react").Context<Collector | undefined>;
33
+ interface ChildrenProps {
34
+ children?: ReactNode;
35
+ source?: string;
36
+ }
37
+ interface FactProps {
38
+ id: FactId;
39
+ list?: boolean;
40
+ }
41
+ declare function createCollector(options: {
42
+ path: string;
43
+ site: string;
44
+ facts?: Facts;
45
+ }): Collector;
46
+ /** Mark the page body; ancestor layouts remain outside the captured document. */
47
+ declare function DocumentProvider({ collector: supplied, children }: {
48
+ collector?: Collector;
49
+ children: ReactNode;
50
+ }): import("react").JSX.Element;
51
+ /** Static text for head()/JSON-LD; use format: "markdown" to retain inline marks. */
52
+ declare function messageText(node: ReactNode, options?: {
53
+ format?: "text" | "markdown";
54
+ facts?: Facts;
55
+ site?: string;
56
+ path?: string;
57
+ }): string;
58
+ declare function T({ children, source }: ChildrenProps): import("react").JSX.Element;
59
+ /**
60
+ * Mark an inline heading in place without adding markup. Capture assigns it to the nearest
61
+ * Section.Item, otherwise Section, and records one title message instead of body text.
62
+ * Accepts the same inline children as T. A title prop or another Title on that owner is an error.
63
+ */
64
+ declare function Title({ children, source }: ChildrenProps): import("react").JSX.Element;
65
+ declare function Fact({ id, list }: FactProps): import("react").JSX.Element;
66
+ declare function ItemRoot(props: ChildrenProps & {
67
+ /** Capture-only heading; use Title to mark a visible heading in place. */
68
+ title?: ReactNode;
69
+ }): import("react").JSX.Element;
70
+ declare function SectionRoot({ evidence, kind, id, title, language, children, source }: ChildrenProps & {
71
+ kind: string | SectionKind;
72
+ id: string;
73
+ evidence?: boolean;
74
+ /** Capture-only heading; use Title to mark a visible heading in place. */
75
+ title?: ReactNode;
76
+ language?: string;
77
+ }): import("react").JSX.Element;
78
+ /**
79
+ * Render the card's anchor and record its destination on the enclosing Section.Item.
80
+ * Use `createLink(Section.Item.Link)` for TanStack navigation: Router supplies the resolved href,
81
+ * including params, search and hash, so the page and twin share one destination.
82
+ * Anchor props and refs pass through. An item may contain only one such link;
83
+ * capture rejects missing or disabled destinations.
84
+ */
85
+ declare function ItemLink(props: ComponentPropsWithRef<"a">): import("react").JSX.Element;
86
+ declare const Section: typeof SectionRoot & {
87
+ Item: typeof ItemRoot & {
88
+ Link: typeof ItemLink;
89
+ };
90
+ };
91
+ /**
92
+ * Render children unchanged outside capture. Under DocumentProvider, children never render or record;
93
+ * describe is the only twin output, and omitting it contributes nothing to the twin.
94
+ */
95
+ declare function Visual({ describe, children, source }: ChildrenProps & {
96
+ describe?: string;
97
+ }): import("react").JSX.Element | null;
98
+ declare function ForAgents(props: ChildrenProps): import("react").JSX.Element;
99
+ declare function ForHumans(props: ChildrenProps): import("react").JSX.Element;
100
+ declare function finishDocument(collector: Collector, metadata: {
101
+ title: string;
102
+ description: string;
103
+ }, html: string): PageDocument;
104
+ declare function useCapturePage(): string | undefined;
105
+ /** Host for TanStack createLink: capture receives the same resolved anchor props as normal SSR. */
106
+ declare function CaptureAnchor(props: ComponentPropsWithRef<"a">): import("react").JSX.Element;
107
+ //#endregion
108
+ export { Fact as a, ForHumans as c, Title as d, Visual as f, useCapturePage as g, messageText as h, DocumentProvider as i, Section as l, finishDocument as m, CaptureRequest as n, FactId as o, createCollector as p, Collector as r, ForAgents as s, CaptureAnchor as t, T as u };
109
+ //# sourceMappingURL=document-CztEu3Vd.d.ts.map
@@ -0,0 +1,379 @@
1
+ import { a as RESERVED_SECTION_ID_PREFIX, n as inlineMarkdown, o as hashDocument, r as plainText, s as contentHash, t as documentLinkHref } from "./inline-BbS93GAT.js";
2
+ import { i as resolveFact } from "./facts-1OKclPOk.js";
3
+ import { useRouter } from "@tanstack/react-router";
4
+ import { createContext, isValidElement, useContext, useId, useMemo } from "react";
5
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/react/document.tsx
7
+ const CaptureRequest = createContext(void 0);
8
+ const Capture = createContext(void 0);
9
+ function CaptureProvider({ collector, section, item, audience, suppress, link, children }) {
10
+ const value = useMemo(() => ({
11
+ collector,
12
+ ...section === void 0 ? {} : { section },
13
+ ...item === void 0 ? {} : { item },
14
+ audience,
15
+ suppress,
16
+ ...link === void 0 ? {} : { link }
17
+ }), [
18
+ collector,
19
+ section,
20
+ item,
21
+ audience,
22
+ suppress,
23
+ link
24
+ ]);
25
+ return /* @__PURE__ */ jsx(Capture.Provider, {
26
+ value,
27
+ children
28
+ });
29
+ }
30
+ function createCollector(options) {
31
+ return {
32
+ ...options,
33
+ sectionCount: 0,
34
+ sections: [],
35
+ messages: [],
36
+ records: /* @__PURE__ */ new Map(),
37
+ links: /* @__PURE__ */ new Set(),
38
+ completed: false
39
+ };
40
+ }
41
+ /** Mark the page body; ancestor layouts remain outside the captured document. */
42
+ function DocumentProvider({ collector: supplied, children }) {
43
+ const request = useContext(CaptureRequest);
44
+ const router = useRouter({ warn: false });
45
+ if (import.meta.env?.DEV && router !== null && router !== void 0) {
46
+ const match = router.stores.matches.get().at(-1);
47
+ if (match !== void 0 && match.staticData.markdown !== "rendered") throw new Error(`DocumentProvider on ${match.pathname} requires staticData.markdown: "rendered"; declare it on the page route.`);
48
+ }
49
+ const collector = supplied ?? request;
50
+ if (collector === void 0) return /* @__PURE__ */ jsx(Fragment$1, { children });
51
+ return /* @__PURE__ */ jsx(CaptureProvider, {
52
+ collector,
53
+ audience: "all",
54
+ suppress: false,
55
+ children
56
+ });
57
+ }
58
+ function record(context, id, apply) {
59
+ context.collector.records.set(id, apply);
60
+ return /* @__PURE__ */ jsx("template", { "data-document-record": id });
61
+ }
62
+ const sourceOf = (source) => source ?? "<inline>:1";
63
+ function elementProps(node) {
64
+ return node.props;
65
+ }
66
+ function factProps(node) {
67
+ const props = node.props;
68
+ if (typeof props !== "object" || props === null || !("id" in props) || typeof props.id !== "string") throw new Error("Fact requires an id");
69
+ return {
70
+ id: props.id,
71
+ ..."list" in props && props.list === true ? { list: true } : {}
72
+ };
73
+ }
74
+ /** Sanitize without executing components: identity is authored text, inline marks and fact ids. */
75
+ function inlineTree(node, options = {}) {
76
+ if (node === void 0 || node === null || typeof node === "boolean") return [];
77
+ if (typeof node === "string" || typeof node === "number") return [String(node)];
78
+ if (Array.isArray(node)) return node.flatMap((child) => inlineTree(child, options));
79
+ if (!isValidElement(node)) throw new Error("T only accepts text, em, strong, a, code, br, and Fact");
80
+ if (node.type === T) return inlineTree(elementProps(node).children, options);
81
+ if (node.type === Fact) {
82
+ const { id, list } = factProps(node);
83
+ const definition = resolveFact(id, options.facts);
84
+ if (list && definition.kind !== "list") throw new Error(`Fact "${id}" is not a list`);
85
+ return [{
86
+ fact: id,
87
+ text: definition.text
88
+ }];
89
+ }
90
+ const tag = node.type;
91
+ if (tag !== "em" && tag !== "strong" && tag !== "a" && tag !== "code" && tag !== "br") throw new Error(`T only accepts text, em, strong, a, code, br, and Fact; found ${typeof tag === "string" ? tag : "a component"}`);
92
+ const props = elementProps(node);
93
+ const href = tag === "a" ? props.href : void 0;
94
+ if (tag === "a" && typeof href !== "string") throw new Error("An anchor in T needs a string href");
95
+ return [{
96
+ tag,
97
+ ...href === void 0 ? {} : { href: documentLinkHref(href, options.site === void 0 ? void 0 : new URL(options.path ?? "/", options.site)) },
98
+ children: inlineTree(props.children, options)
99
+ }];
100
+ }
101
+ function authoredTree(tree) {
102
+ return tree.map((node) => typeof node === "string" ? node : "fact" in node ? { fact: node.fact } : {
103
+ tag: node.tag,
104
+ ...node.href === void 0 ? {} : { href: node.href },
105
+ children: authoredTree(node.children)
106
+ });
107
+ }
108
+ /** Static text for head()/JSON-LD; use format: "markdown" to retain inline marks. */
109
+ function messageText(node, options = {}) {
110
+ const tree = inlineTree(isValidElement(node) && node.type === Title ? node.props.children : node, options);
111
+ return options.format === "markdown" ? inlineMarkdown(tree) : plainText(tree);
112
+ }
113
+ function messageFor(node, source, context) {
114
+ const options = context.collector;
115
+ const linkedContent = context.link === void 0 || context.link === context.item?.href ? node : /* @__PURE__ */ jsx("a", {
116
+ href: context.link,
117
+ children: node
118
+ });
119
+ const tree = inlineTree(linkedContent, options);
120
+ const authored = inlineTree(linkedContent, options.facts === void 0 ? {} : { facts: options.facts });
121
+ const refs = /* @__PURE__ */ new Set();
122
+ const visit = (nodes) => {
123
+ for (const child of nodes) if (typeof child !== "string") if ("fact" in child) refs.add(child.fact);
124
+ else visit(child.children);
125
+ };
126
+ visit(tree);
127
+ return {
128
+ hash: contentHash(authoredTree(authored)).slice(0, 16),
129
+ tree,
130
+ text: plainText(tree),
131
+ source: sourceOf(source),
132
+ facts: [...refs],
133
+ audience: context.audience
134
+ };
135
+ }
136
+ function append(context, entry) {
137
+ if (context.item !== void 0) {
138
+ context.item.body.push(entry);
139
+ if (entry.type === "message") context.item.cells.push(entry.message);
140
+ } else if (context.section !== void 0) context.section.body.push(entry);
141
+ else {
142
+ let section = context.collector.sections.at(-1);
143
+ if (section?.kind !== `for-${context.audience}`) {
144
+ section = {
145
+ kind: `for-${context.audience}`,
146
+ id: `for-${context.audience}-${context.collector.sections.length}`,
147
+ body: [],
148
+ items: [],
149
+ source: entry.type === "message" ? entry.message.source : entry.source,
150
+ audience: context.audience
151
+ };
152
+ context.collector.sections.push(section);
153
+ }
154
+ section.body.push(entry);
155
+ }
156
+ }
157
+ function T({ children, source }) {
158
+ const id = useId();
159
+ const context = useContext(Capture);
160
+ if (context === void 0 || context.suppress) return /* @__PURE__ */ jsx(Fragment$1, { children });
161
+ const message = messageFor(children, source, context);
162
+ const marker = record(context, id, () => {
163
+ context.collector.messages.push(message);
164
+ append(context, {
165
+ type: "message",
166
+ message
167
+ });
168
+ });
169
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [marker, children] });
170
+ }
171
+ /**
172
+ * Mark an inline heading in place without adding markup. Capture assigns it to the nearest
173
+ * Section.Item, otherwise Section, and records one title message instead of body text.
174
+ * Accepts the same inline children as T. A title prop or another Title on that owner is an error.
175
+ */
176
+ function Title({ children, source }) {
177
+ const id = useId();
178
+ const context = useContext(Capture);
179
+ if (context === void 0 || context.suppress) return /* @__PURE__ */ jsx(Fragment$1, { children });
180
+ const title = messageFor(children, source, context);
181
+ const marker = record(context, id, () => {
182
+ if (context.section === void 0) throw new Error(`Title outside Section on ${context.collector.path}`);
183
+ const owner = context.item ?? context.section;
184
+ if (owner.title !== void 0) throw new Error(`Duplicate document title for ${context.item === void 0 ? `Section "${context.section.id}"` : `Section.Item at ${context.item.source}`} on ${context.collector.path}; use a title prop or one Title`);
185
+ owner.title = title;
186
+ context.collector.messages.push(title);
187
+ if (context.item !== void 0) context.item.cells.unshift(title);
188
+ });
189
+ return /* @__PURE__ */ jsxs(CaptureProvider, {
190
+ ...context,
191
+ suppress: true,
192
+ children: [marker, children]
193
+ });
194
+ }
195
+ function Fact({ id, list }) {
196
+ const context = useContext(Capture);
197
+ const definition = resolveFact(id, context?.collector.facts);
198
+ if (list && definition.kind !== "list") throw new Error(`Fact "${id}" is not a list`);
199
+ return /* @__PURE__ */ jsx(Fragment$1, { children: definition.text });
200
+ }
201
+ function ItemRoot(props) {
202
+ const key = useId();
203
+ const { title, children, source } = props;
204
+ const context = useContext(Capture);
205
+ if (context === void 0 || context.suppress) return /* @__PURE__ */ jsx(Fragment$1, { children });
206
+ if ("href" in props) throw new Error(`Section.Item does not accept href on ${context.collector.path}; render Section.Item.Link instead`);
207
+ if (context.section === void 0) throw new Error(`Section.Item outside Section on ${context.collector.path}`);
208
+ const item = {
209
+ body: [],
210
+ cells: [],
211
+ source: sourceOf(source),
212
+ audience: context.audience
213
+ };
214
+ const heading = title === void 0 ? void 0 : messageFor(title, isValidElement(title) ? title.props.source ?? source : source, {
215
+ ...context,
216
+ item
217
+ });
218
+ if (heading !== void 0) {
219
+ item.title = heading;
220
+ item.cells.push(heading);
221
+ }
222
+ const marker = record(context, key, () => {
223
+ context.section?.items.push(item);
224
+ if (heading !== void 0) context.collector.messages.push(heading);
225
+ });
226
+ return /* @__PURE__ */ jsxs(CaptureProvider, {
227
+ ...context,
228
+ item,
229
+ children: [marker, children]
230
+ });
231
+ }
232
+ function SectionRoot({ evidence, kind, id, title, language, children, source }) {
233
+ const key = useId();
234
+ const context = useContext(Capture);
235
+ if (context === void 0 || context.suppress) return /* @__PURE__ */ jsx(Fragment$1, { children });
236
+ const heading = title === void 0 ? void 0 : messageFor(title, isValidElement(title) ? title.props.source ?? source : source, context);
237
+ const section = {
238
+ ...evidence === void 0 ? {} : { evidence },
239
+ kind: typeof kind === "string" ? kind : kind.kind,
240
+ id,
241
+ ...heading === void 0 ? {} : { title: heading },
242
+ ...language === void 0 ? {} : { language },
243
+ body: [],
244
+ items: [],
245
+ source: sourceOf(source),
246
+ audience: context.audience
247
+ };
248
+ const marker = record(context, key, () => {
249
+ if (id.startsWith("__pagegraph:")) throw new Error(`Document Section id "${id}" on ${context.collector.path} uses reserved prefix "${RESERVED_SECTION_ID_PREFIX}"`);
250
+ if (context.collector.sections.some((entry) => entry.id === id)) throw new Error(`Duplicate document Section id "${id}" on ${context.collector.path}`);
251
+ context.collector.sectionCount++;
252
+ context.collector.sections.push(section);
253
+ if (heading !== void 0) context.collector.messages.push(heading);
254
+ });
255
+ return /* @__PURE__ */ jsxs(CaptureProvider, {
256
+ collector: context.collector,
257
+ section,
258
+ audience: context.audience,
259
+ suppress: false,
260
+ children: [marker, children]
261
+ });
262
+ }
263
+ /**
264
+ * Render the card's anchor and record its destination on the enclosing Section.Item.
265
+ * Use `createLink(Section.Item.Link)` for TanStack navigation: Router supplies the resolved href,
266
+ * including params, search and hash, so the page and twin share one destination.
267
+ * Anchor props and refs pass through. An item may contain only one such link;
268
+ * capture rejects missing or disabled destinations.
269
+ */
270
+ function ItemLink(props) {
271
+ return /* @__PURE__ */ jsx(CapturedAnchor, {
272
+ ...props,
273
+ itemLink: true
274
+ });
275
+ }
276
+ const Item = Object.assign(ItemRoot, { Link: ItemLink });
277
+ const Section = Object.assign(SectionRoot, { Item });
278
+ /**
279
+ * Render children unchanged outside capture. Under DocumentProvider, children never render or record;
280
+ * describe is the only twin output, and omitting it contributes nothing to the twin.
281
+ */
282
+ function Visual({ describe, children, source }) {
283
+ const id = useId();
284
+ const context = useContext(Capture);
285
+ if (context === void 0) return /* @__PURE__ */ jsx(Fragment$1, { children });
286
+ if (context.suppress || describe === void 0) return null;
287
+ return record(context, id, () => append(context, {
288
+ type: "visual",
289
+ text: describe,
290
+ source: sourceOf(source),
291
+ audience: context.audience
292
+ }));
293
+ }
294
+ function AudienceContent({ audience, children }) {
295
+ const context = useContext(Capture);
296
+ if (context === void 0) return audience === "agents" ? null : /* @__PURE__ */ jsx(Fragment$1, { children });
297
+ return /* @__PURE__ */ jsx(CaptureProvider, {
298
+ ...context,
299
+ audience,
300
+ children
301
+ });
302
+ }
303
+ function ForAgents(props) {
304
+ return /* @__PURE__ */ jsx(AudienceContent, {
305
+ ...props,
306
+ audience: "agents"
307
+ });
308
+ }
309
+ function ForHumans(props) {
310
+ return /* @__PURE__ */ jsx(AudienceContent, {
311
+ ...props,
312
+ audience: "humans"
313
+ });
314
+ }
315
+ function finishDocument(collector, metadata, html) {
316
+ if (collector.completed) throw new Error(`Document capture already completed for ${collector.path}`);
317
+ collector.completed = true;
318
+ collector.sections.length = 0;
319
+ collector.messages.length = 0;
320
+ collector.sectionCount = 0;
321
+ collector.links.clear();
322
+ for (const marker of html.matchAll(/<template data-document-record="([^"]+)"><\/template>/g)) {
323
+ const apply = collector.records.get(marker[1] ?? "");
324
+ if (apply === void 0) throw new Error(`Unknown document record on ${collector.path}`);
325
+ apply();
326
+ }
327
+ if (collector.sectionCount === 0) throw new Error(`Document page ${collector.path} recorded no <Section>`);
328
+ for (const section of collector.sections) {
329
+ if (section.kind !== "table" || section.audience === "humans") continue;
330
+ const rows = section.items.filter((item) => item.audience !== "humans").map((item) => ({
331
+ source: item.source,
332
+ width: item.cells.filter((cell) => cell.audience !== "humans").length
333
+ }));
334
+ const expected = rows[0]?.width;
335
+ const invalid = rows.find((row) => row.width === 0 || row.width !== expected);
336
+ if (invalid !== void 0) throw new Error(`Table Section "${section.id}" on ${collector.path} needs equal, nonempty visible cell counts after excluding ForHumans; row at ${invalid.source} has ${invalid.width}, expected ${expected}`);
337
+ }
338
+ const document = {
339
+ path: collector.path,
340
+ ...metadata,
341
+ sections: collector.sections,
342
+ messages: collector.messages,
343
+ facts: [...new Set(collector.messages.flatMap((message) => message.facts))]
344
+ };
345
+ return {
346
+ ...document,
347
+ hash: hashDocument(document)
348
+ };
349
+ }
350
+ function useCapturePage() {
351
+ return useContext(Capture)?.collector.path;
352
+ }
353
+ function CapturedAnchor({ itemLink = false, ...props }) {
354
+ const key = useId();
355
+ const context = useContext(Capture);
356
+ if (context === void 0 || context.suppress) return /* @__PURE__ */ jsx("a", { ...props });
357
+ if (itemLink && context.item === void 0) throw new Error(`Section.Item.Link outside Section.Item on ${context.collector.path}`);
358
+ if (typeof props.href !== "string") throw new Error(`Document page ${context.collector.path}: Link requires a resolved href`);
359
+ const href = documentLinkHref(props.href, new URL(context.collector.path, context.collector.site));
360
+ const item = context.item;
361
+ const marker = itemLink && item !== void 0 ? record(context, key, () => {
362
+ if (context.collector.links.has(item)) throw new Error(`Duplicate Section.Item.Link at ${item.source} on ${context.collector.path}`);
363
+ context.collector.links.add(item);
364
+ item.href = href;
365
+ }) : null;
366
+ return /* @__PURE__ */ jsxs(CaptureProvider, {
367
+ ...context,
368
+ link: itemLink ? void 0 : href,
369
+ children: [marker, /* @__PURE__ */ jsx("a", { ...props })]
370
+ });
371
+ }
372
+ /** Host for TanStack createLink: capture receives the same resolved anchor props as normal SSR. */
373
+ function CaptureAnchor(props) {
374
+ return /* @__PURE__ */ jsx(CapturedAnchor, { ...props });
375
+ }
376
+ //#endregion
377
+ export { ForAgents as a, T as c, createCollector as d, finishDocument as f, Fact as i, Title as l, useCapturePage as m, CaptureRequest as n, ForHumans as o, messageText as p, DocumentProvider as r, Section as s, CaptureAnchor as t, Visual as u };
378
+
379
+ //# sourceMappingURL=document-Dvemcv7V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-Dvemcv7V.js","names":[],"sources":["../src/react/document.tsx"],"sourcesContent":["import { useRouter } from \"@tanstack/react-router\";\nimport { createContext, isValidElement, useContext, useId, useMemo } from \"react\";\nimport type { ComponentPropsWithRef, ReactElement, ReactNode } from \"react\";\n\nimport type {\n BodyEntry,\n InlineNode,\n Message,\n PageDocument,\n SectionDocument,\n SectionItem,\n} from \"../markdown/document\";\nimport { documentLinkHref, inlineMarkdown, plainText } from \"../markdown/inline\";\nimport { RESERVED_SECTION_ID_PREFIX, hashDocument } from \"../markdown/document\";\nimport { resolveFact } from \"../markdown/facts\";\nimport type { Facts } from \"../markdown/facts\";\nimport { contentHash } from \"../markdown/hash\";\nimport type { Register } from \"../core/index\";\nimport type { SectionKind } from \"../markdown/markdown\";\n\n/** Augment with `facts: typeof facts` to check Fact ids across the application. */\n\nexport type FactId = Register extends { facts: infer F extends Facts }\n ? Extract<keyof F, string>\n : string;\ntype Audience = Message[\"audience\"];\ntype MutableSection = Omit<SectionDocument, \"title\" | \"body\" | \"items\"> & {\n title?: Message;\n body: Array<BodyEntry>;\n items: Array<MutableItem>;\n};\ntype MutableItem = Omit<SectionItem, \"title\" | \"href\" | \"body\" | \"cells\"> & {\n title?: Message;\n href?: string;\n body: Array<BodyEntry>;\n cells: Array<Message>;\n};\nexport interface Collector {\n path: string;\n site: string;\n facts?: Facts;\n sectionCount: number;\n sections: Array<MutableSection>;\n messages: Array<Message>;\n records: Map<string, () => void>;\n links: Set<MutableItem>;\n completed: boolean;\n}\ninterface CaptureContext {\n collector: Collector;\n section?: MutableSection;\n item?: MutableItem;\n audience: Audience;\n suppress: boolean;\n link?: string | undefined;\n}\nexport const CaptureRequest = createContext<Collector | undefined>(undefined);\nconst Capture = createContext<CaptureContext | undefined>(undefined);\n\nfunction CaptureProvider({\n collector,\n section,\n item,\n audience,\n suppress,\n link,\n children,\n}: CaptureContext & { children?: ReactNode }) {\n const value = useMemo(\n () => ({\n collector,\n ...(section === undefined ? {} : { section }),\n ...(item === undefined ? {} : { item }),\n audience,\n suppress,\n ...(link === undefined ? {} : { link }),\n }),\n [collector, section, item, audience, suppress, link],\n );\n return <Capture.Provider value={value}>{children}</Capture.Provider>;\n}\n\ninterface ChildrenProps {\n children?: ReactNode;\n source?: string;\n}\ninterface FactProps {\n id: FactId;\n list?: boolean;\n}\ninterface InlineProps extends ChildrenProps {\n href?: string;\n}\n\nexport function createCollector(options: { path: string; site: string; facts?: Facts }): Collector {\n return {\n ...options,\n sectionCount: 0,\n sections: [],\n messages: [],\n records: new Map(),\n links: new Set(),\n completed: false,\n };\n}\n\n/** Mark the page body; ancestor layouts remain outside the captured document. */\nexport function DocumentProvider({\n collector: supplied,\n children,\n}: {\n collector?: Collector;\n children: ReactNode;\n}) {\n const request = useContext(CaptureRequest);\n const router = useRouter({ warn: false });\n if (import.meta.env?.DEV && router !== null && router !== undefined) {\n const match = router.stores.matches.get().at(-1);\n if (match !== undefined && match.staticData.markdown !== \"rendered\")\n throw new Error(\n `DocumentProvider on ${match.pathname} requires staticData.markdown: \"rendered\"; declare it on the page route.`,\n );\n }\n const collector = supplied ?? request;\n if (collector === undefined) return <>{children}</>;\n return (\n <CaptureProvider collector={collector} audience=\"all\" suppress={false}>\n {children}\n </CaptureProvider>\n );\n}\n\nfunction record(context: CaptureContext, id: string, apply: () => void) {\n context.collector.records.set(id, apply);\n return <template data-document-record={id} />;\n}\n\nconst sourceOf = (source: string | undefined): string => source ?? \"<inline>:1\";\n\nfunction elementProps(node: ReactElement<InlineProps>): InlineProps {\n return node.props;\n}\nfunction factProps(node: ReactElement): { id: string; list?: boolean } {\n const props = node.props;\n if ((typeof props !== \"object\" || props === null) || !(\"id\" in props) || typeof props.id !== \"string\") {\n throw new Error(\"Fact requires an id\");\n }\n return { id: props.id, ...(\"list\" in props && props.list === true ? { list: true } : {}) };\n}\n\n/** Sanitize without executing components: identity is authored text, inline marks and fact ids. */\nexport function inlineTree(\n node: ReactNode,\n options: { facts?: Facts; site?: string; path?: string } = {},\n): Array<InlineNode> {\n if (node === undefined || node === null || typeof node === \"boolean\") return [];\n if (typeof node === \"string\" || typeof node === \"number\") return [String(node)];\n if (Array.isArray(node)) return node.flatMap((child) => inlineTree(child, options));\n if (!isValidElement<InlineProps>(node))\n throw new Error(\"T only accepts text, em, strong, a, code, br, and Fact\");\n if (node.type === T) return inlineTree(elementProps(node).children, options);\n if (node.type === Fact) {\n const { id, list } = factProps(node);\n const definition = resolveFact(id, options.facts);\n if (list && definition.kind !== \"list\")\n throw new Error(`Fact \"${id}\" is not a list`);\n return [{ fact: id, text: definition.text }];\n }\n const tag = node.type;\n if (tag !== \"em\" && tag !== \"strong\" && tag !== \"a\" && tag !== \"code\" && tag !== \"br\") {\n throw new Error(\n `T only accepts text, em, strong, a, code, br, and Fact; found ${typeof tag === \"string\" ? tag : \"a component\"}`,\n );\n }\n const props = elementProps(node);\n const href = tag === \"a\" ? props.href : undefined;\n if (tag === \"a\" && typeof href !== \"string\")\n throw new Error(\"An anchor in T needs a string href\");\n return [\n {\n tag,\n ...(href === undefined\n ? {}\n : {\n href: documentLinkHref(\n href,\n options.site === undefined ? undefined : new URL(options.path ?? \"/\", options.site),\n ),\n }),\n children: inlineTree(props.children, options),\n },\n ];\n}\n\nfunction authoredTree(tree: ReadonlyArray<InlineNode>): unknown {\n return tree.map((node) =>\n typeof node === \"string\"\n ? node\n : \"fact\" in node\n ? { fact: node.fact }\n : {\n tag: node.tag,\n ...(node.href === undefined ? {} : { href: node.href }),\n children: authoredTree(node.children),\n },\n );\n}\n/** Static text for head()/JSON-LD; use format: \"markdown\" to retain inline marks. */\nexport function messageText(\n node: ReactNode,\n options: { format?: \"text\" | \"markdown\"; facts?: Facts; site?: string; path?: string } = {},\n): string {\n const content =\n isValidElement<ChildrenProps>(node) && node.type === Title ? node.props.children : node;\n const tree = inlineTree(content, options);\n return options.format === \"markdown\" ? inlineMarkdown(tree) : plainText(tree);\n}\n\nfunction messageFor(node: ReactNode, source: string | undefined, context: CaptureContext): Message {\n const options = context.collector;\n // A whole-card destination is serialized on the item, rather than repeated on every message.\n const linkedContent =\n context.link === undefined || context.link === context.item?.href ? (\n node\n ) : (\n <a href={context.link}>{node}</a>\n );\n const tree = inlineTree(linkedContent, options);\n const authored = inlineTree(linkedContent, options.facts === undefined ? {} : { facts: options.facts });\n const refs = new Set<string>();\n const visit = (nodes: ReadonlyArray<InlineNode>): void => {\n for (const child of nodes) {\n if (typeof child !== \"string\") {\n if (\"fact\" in child) refs.add(child.fact);\n else visit(child.children);\n }\n }\n };\n visit(tree);\n const message: Message = {\n hash: contentHash(authoredTree(authored)).slice(0, 16),\n tree,\n text: plainText(tree),\n source: sourceOf(source),\n facts: [...refs],\n audience: context.audience,\n };\n return message;\n}\nfunction append(context: CaptureContext, entry: BodyEntry): void {\n if (context.item !== undefined) {\n context.item.body.push(entry);\n if (entry.type === \"message\") context.item.cells.push(entry.message);\n } else if (context.section !== undefined) context.section.body.push(entry);\n else {\n let section = context.collector.sections.at(-1);\n if (section?.kind !== `for-${context.audience}`) {\n section = {\n kind: `for-${context.audience}`,\n id: `for-${context.audience}-${context.collector.sections.length}`,\n body: [],\n items: [],\n source: entry.type === \"message\" ? entry.message.source : entry.source,\n audience: context.audience,\n };\n context.collector.sections.push(section);\n }\n section.body.push(entry);\n }\n}\n\nexport function T({ children, source }: ChildrenProps) {\n const id = useId();\n const context = useContext(Capture);\n if (context === undefined || context.suppress) return <>{children}</>;\n const message = messageFor(children, source, context);\n const marker = record(context, id, () => {\n context.collector.messages.push(message);\n append(context, { type: \"message\", message });\n });\n return (\n <>\n {marker}\n {children}\n </>\n );\n}\n/**\n * Mark an inline heading in place without adding markup. Capture assigns it to the nearest\n * Section.Item, otherwise Section, and records one title message instead of body text.\n * Accepts the same inline children as T. A title prop or another Title on that owner is an error.\n */\nexport function Title({ children, source }: ChildrenProps) {\n const id = useId();\n const context = useContext(Capture);\n if (context === undefined || context.suppress) return <>{children}</>;\n const title = messageFor(children, source, context);\n const marker = record(context, id, () => {\n if (context.section === undefined)\n throw new Error(`Title outside Section on ${context.collector.path}`);\n const owner = context.item ?? context.section;\n if (owner.title !== undefined)\n throw new Error(\n `Duplicate document title for ${context.item === undefined ? `Section \"${context.section.id}\"` : `Section.Item at ${context.item.source}`} on ${context.collector.path}; use a title prop or one Title`,\n );\n owner.title = title;\n context.collector.messages.push(title);\n if (context.item !== undefined) context.item.cells.unshift(title);\n });\n return (\n <CaptureProvider {...context} suppress>\n {marker}\n {children}\n </CaptureProvider>\n );\n}\nexport function Fact({ id, list }: FactProps) {\n const context = useContext(Capture);\n const definition = resolveFact(id, context?.collector.facts);\n if (list && definition.kind !== \"list\")\n throw new Error(`Fact \"${id}\" is not a list`);\n return <>{definition.text}</>;\n}\nfunction ItemRoot(\n props: ChildrenProps & {\n /** Capture-only heading; use Title to mark a visible heading in place. */\n title?: ReactNode;\n },\n) {\n const key = useId();\n const { title, children, source } = props;\n const context = useContext(Capture);\n if (context === undefined || context.suppress) return <>{children}</>;\n if (\"href\" in props)\n throw new Error(\n `Section.Item does not accept href on ${context.collector.path}; render Section.Item.Link instead`,\n );\n if (context.section === undefined)\n throw new Error(`Section.Item outside Section on ${context.collector.path}`);\n const item: MutableItem = {\n body: [],\n cells: [],\n source: sourceOf(source),\n audience: context.audience,\n };\n const heading =\n title === undefined\n ? undefined\n : messageFor(\n title,\n isValidElement<ChildrenProps>(title) ? (title.props.source ?? source) : source,\n { ...context, item },\n );\n if (heading !== undefined) {\n item.title = heading;\n item.cells.push(heading);\n }\n const marker = record(context, key, () => {\n context.section?.items.push(item);\n if (heading !== undefined) context.collector.messages.push(heading);\n });\n return (\n <CaptureProvider {...context} item={item}>\n {marker}\n {children}\n </CaptureProvider>\n );\n}\nfunction SectionRoot({\n evidence,\n kind,\n id,\n title,\n language,\n children,\n source,\n}: ChildrenProps & {\n kind: string | SectionKind;\n id: string;\n evidence?: boolean;\n /** Capture-only heading; use Title to mark a visible heading in place. */\n title?: ReactNode;\n language?: string;\n}) {\n const key = useId();\n const context = useContext(Capture);\n if (context === undefined || context.suppress) return <>{children}</>;\n const heading =\n title === undefined\n ? undefined\n : messageFor(\n title,\n isValidElement<ChildrenProps>(title) ? (title.props.source ?? source) : source,\n context,\n );\n const section: MutableSection = {\n ...(evidence === undefined ? {} : { evidence }),\n kind: typeof kind === \"string\" ? kind : kind.kind,\n id,\n ...(heading === undefined ? {} : { title: heading }),\n ...(language === undefined ? {} : { language }),\n body: [],\n items: [],\n source: sourceOf(source),\n audience: context.audience,\n };\n const marker = record(context, key, () => {\n if (id.startsWith(RESERVED_SECTION_ID_PREFIX))\n throw new Error(`Document Section id \"${id}\" on ${context.collector.path} uses reserved prefix \"${RESERVED_SECTION_ID_PREFIX}\"`);\n if (context.collector.sections.some((entry) => entry.id === id))\n throw new Error(`Duplicate document Section id \"${id}\" on ${context.collector.path}`);\n context.collector.sectionCount++;\n context.collector.sections.push(section);\n if (heading !== undefined) context.collector.messages.push(heading);\n });\n return (\n <CaptureProvider\n collector={context.collector}\n section={section}\n audience={context.audience}\n suppress={false}\n >\n {marker}\n {children}\n </CaptureProvider>\n );\n}\n/**\n * Render the card's anchor and record its destination on the enclosing Section.Item.\n * Use `createLink(Section.Item.Link)` for TanStack navigation: Router supplies the resolved href,\n * including params, search and hash, so the page and twin share one destination.\n * Anchor props and refs pass through. An item may contain only one such link;\n * capture rejects missing or disabled destinations.\n */\nfunction ItemLink(props: ComponentPropsWithRef<\"a\">) {\n return <CapturedAnchor {...props} itemLink />;\n}\nconst Item = Object.assign(ItemRoot, { Link: ItemLink });\nexport const Section = Object.assign(SectionRoot, { Item });\n/**\n * Render children unchanged outside capture. Under DocumentProvider, children never render or record;\n * describe is the only twin output, and omitting it contributes nothing to the twin.\n */\nexport function Visual({ describe, children, source }: ChildrenProps & { describe?: string }) {\n const id = useId();\n const context = useContext(Capture);\n if (context === undefined) return <>{children}</>;\n if (context.suppress || describe === undefined) return null;\n return record(context, id, () =>\n append(context, {\n type: \"visual\",\n text: describe,\n source: sourceOf(source),\n audience: context.audience,\n }),\n );\n}\nfunction AudienceContent({\n audience,\n children,\n}: ChildrenProps & { audience: \"agents\" | \"humans\" }) {\n const context = useContext(Capture);\n if (context === undefined) return audience === \"agents\" ? null : <>{children}</>;\n return (\n <CaptureProvider {...context} audience={audience}>\n {children}\n </CaptureProvider>\n );\n}\nexport function ForAgents(props: ChildrenProps) {\n return <AudienceContent {...props} audience=\"agents\" />;\n}\nexport function ForHumans(props: ChildrenProps) {\n return <AudienceContent {...props} audience=\"humans\" />;\n}\n\nexport function finishDocument(\n collector: Collector,\n metadata: { title: string; description: string },\n html: string,\n): PageDocument {\n if (collector.completed) throw new Error(`Document capture already completed for ${collector.path}`);\n collector.completed = true;\n // Only completed SSR output decides which attempted renders belong to the document and their order.\n collector.sections.length = 0;\n collector.messages.length = 0;\n collector.sectionCount = 0;\n collector.links.clear();\n for (const marker of html.matchAll(/<template data-document-record=\"([^\"]+)\"><\\/template>/g)) {\n const apply = collector.records.get(marker[1] ?? \"\");\n if (apply === undefined) throw new Error(`Unknown document record on ${collector.path}`);\n apply();\n }\n if (collector.sectionCount === 0)\n throw new Error(`Document page ${collector.path} recorded no <Section>`);\n // Validate completed public rows after replay; abandoned renders and human-only rows do not count.\n for (const section of collector.sections) {\n if (section.kind !== \"table\" || section.audience === \"humans\") continue;\n const rows = section.items\n .filter((item) => item.audience !== \"humans\")\n .map((item) => ({\n source: item.source,\n width: item.cells.filter((cell) => cell.audience !== \"humans\").length,\n }));\n const expected = rows[0]?.width;\n const invalid = rows.find((row) => row.width === 0 || row.width !== expected);\n if (invalid !== undefined)\n throw new Error(\n `Table Section \"${section.id}\" on ${collector.path} needs equal, nonempty visible cell counts after excluding ForHumans; row at ${invalid.source} has ${invalid.width}, expected ${expected}`,\n );\n }\n const document = {\n path: collector.path,\n ...metadata,\n sections: collector.sections,\n messages: collector.messages,\n facts: [...new Set(collector.messages.flatMap((message) => message.facts))],\n };\n return { ...document, hash: hashDocument(document) };\n}\n\nexport function useCapturePage(): string | undefined {\n return useContext(Capture)?.collector.path;\n}\n\nfunction CapturedAnchor({\n itemLink = false,\n ...props\n}: ComponentPropsWithRef<\"a\"> & { itemLink?: boolean }) {\n const key = useId();\n const context = useContext(Capture);\n if (context === undefined || context.suppress) return <a {...props} />;\n if (itemLink && context.item === undefined)\n throw new Error(`Section.Item.Link outside Section.Item on ${context.collector.path}`);\n if (typeof props.href !== \"string\")\n throw new Error(`Document page ${context.collector.path}: Link requires a resolved href`);\n const href = documentLinkHref(props.href, new URL(context.collector.path, context.collector.site));\n const item = context.item;\n const marker =\n itemLink && item !== undefined\n ? record(context, key, () => {\n if (context.collector.links.has(item))\n throw new Error(\n `Duplicate Section.Item.Link at ${item.source} on ${context.collector.path}`,\n );\n context.collector.links.add(item);\n item.href = href;\n })\n : null;\n return (\n <CaptureProvider {...context} link={itemLink ? undefined : href}>\n {marker}\n <a {...props} />\n </CaptureProvider>\n );\n}\n\n/** Host for TanStack createLink: capture receives the same resolved anchor props as normal SSR. */\nexport function CaptureAnchor(props: ComponentPropsWithRef<\"a\">) {\n return <CapturedAnchor {...props} />;\n}\n"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ //#region src/markdown/facts.ts
2
+ const registeredFacts = /* @__PURE__ */ new Map();
3
+ function isJson(value, parents = /* @__PURE__ */ new Set()) {
4
+ if (value === null || typeof value === "string" || typeof value === "boolean") return true;
5
+ if (typeof value === "number") return Number.isFinite(value);
6
+ if (typeof value !== "object" || parents.has(value)) return false;
7
+ const prototype = Object.getPrototypeOf(value);
8
+ if (!Array.isArray(value) && prototype !== null && prototype !== Object.prototype) return false;
9
+ parents.add(value);
10
+ const valid = (Array.isArray(value) ? Array.from(value) : Object.values(value)).every((entry) => isJson(entry, parents));
11
+ parents.delete(value);
12
+ return valid;
13
+ }
14
+ function validateDefinition(value) {
15
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("Expected object");
16
+ for (const key of [
17
+ "kind",
18
+ "value",
19
+ "text"
20
+ ]) if (!(key in value)) throw new Error(`Missing key\n at ["${key}"]`);
21
+ if (!("kind" in value) || ![
22
+ "number",
23
+ "money",
24
+ "list",
25
+ "text"
26
+ ].includes(String(value.kind))) throw new Error("Expected \"number\" | \"money\" | \"list\" | \"text\"\n at [\"kind\"]");
27
+ if (!("value" in value) || !isJson(value.value)) throw new Error("Expected JSON value\n at [\"value\"]");
28
+ if (!("text" in value) || typeof value.text !== "string") throw new Error("Expected string\n at [\"text\"]");
29
+ let items;
30
+ if ("items" in value) {
31
+ if (!Array.isArray(value.items)) throw new Error("Expected array\n at [\"items\"]");
32
+ items = Array.from(value.items, (item, index) => {
33
+ if (typeof item !== "string") throw new Error(`Expected string\n at ["items"][${index}]`);
34
+ return item;
35
+ });
36
+ }
37
+ const kind = value.kind;
38
+ if (kind !== "number" && kind !== "money" && kind !== "list" && kind !== "text") throw new Error("Expected \"number\" | \"money\" | \"list\" | \"text\"\n at [\"kind\"]");
39
+ return {
40
+ kind,
41
+ value: value.value,
42
+ text: value.text,
43
+ ...items === void 0 ? {} : { items }
44
+ };
45
+ }
46
+ /** Decode facts loaded from an application module before shipping them to the runtime. */
47
+ function decodeFacts(input) {
48
+ if (typeof input !== "object" || input === null || Array.isArray(input)) throw new Error("Document facts must be an object");
49
+ return Object.fromEntries(Object.entries(input).map(([id, definition]) => {
50
+ if (!id) throw new Error("A document fact needs a nonempty id");
51
+ return [id, validateDefinition(definition)];
52
+ }));
53
+ }
54
+ /** Register code-owned values for ordinary React rendering as well as capture. */
55
+ function defineFacts(facts) {
56
+ for (const [id, definition] of Object.entries(facts)) {
57
+ if (!id) throw new Error("A document fact needs a nonempty id");
58
+ registeredFacts.set(id, validateDefinition(definition));
59
+ }
60
+ return facts;
61
+ }
62
+ function finite(value) {
63
+ if (!Number.isFinite(value)) throw new Error(`Document fact must be finite: ${value}`);
64
+ return value;
65
+ }
66
+ const fact = {
67
+ number(value, options) {
68
+ const validated = finite(value);
69
+ return {
70
+ kind: "number",
71
+ value: validated,
72
+ text: new Intl.NumberFormat("en-US", options).format(validated)
73
+ };
74
+ },
75
+ money(value, options = {}) {
76
+ const validated = finite(value);
77
+ const text = new Intl.NumberFormat("en-US", {
78
+ style: "currency",
79
+ currency: options.currency ?? "USD"
80
+ }).format(validated);
81
+ return {
82
+ kind: "money",
83
+ value: validated,
84
+ text: options.per === void 0 ? text : `${text} per ${options.per}`
85
+ };
86
+ },
87
+ list(values, options) {
88
+ const items = values.map((value) => options === void 0 ? String(value) : options.format(value));
89
+ return {
90
+ kind: "list",
91
+ value: [...values],
92
+ items,
93
+ text: new Intl.ListFormat("en-US", {
94
+ style: "long",
95
+ type: "conjunction"
96
+ }).format(items)
97
+ };
98
+ },
99
+ text(value) {
100
+ return {
101
+ kind: "text",
102
+ value,
103
+ text: value
104
+ };
105
+ }
106
+ };
107
+ function resolveFact(id, facts) {
108
+ const value = facts === void 0 ? registeredFacts.get(id) : facts[id];
109
+ if (value === void 0) throw new Error(`Unknown document fact "${id}"; register it with defineFacts`);
110
+ return value;
111
+ }
112
+ //#endregion
113
+ export { resolveFact as i, defineFacts as n, fact as r, decodeFacts as t };
114
+
115
+ //# sourceMappingURL=facts-1OKclPOk.js.map