@stream-mdx/react 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +385 -4
  2. package/README.md +141 -16
  3. package/dist/blocks-renderer-DAOBFBfi.d.ts +29 -0
  4. package/dist/blocks-renderer-DQEL1kJW.d.cts +29 -0
  5. package/dist/components/bottom-stick-scroll-area.cjs +268 -0
  6. package/dist/components/bottom-stick-scroll-area.d.cts +36 -0
  7. package/dist/components/bottom-stick-scroll-area.d.ts +36 -0
  8. package/dist/components/bottom-stick-scroll-area.mjs +249 -0
  9. package/dist/components/diff-renderer.cjs +86 -0
  10. package/dist/components/diff-renderer.d.cts +11 -0
  11. package/dist/components/diff-renderer.d.ts +11 -0
  12. package/dist/components/diff-renderer.mjs +66 -0
  13. package/dist/components/index.cjs +2879 -1295
  14. package/dist/components/index.d.cts +9 -2
  15. package/dist/components/index.d.ts +9 -2
  16. package/dist/components/index.mjs +2842 -1277
  17. package/dist/components/katex-math.cjs +220 -0
  18. package/dist/components/katex-math.d.cts +10 -0
  19. package/dist/components/katex-math.d.ts +10 -0
  20. package/dist/components/katex-math.mjs +188 -0
  21. package/dist/contexts/math-tracker.cjs +240 -521
  22. package/dist/contexts/math-tracker.mjs +235 -513
  23. package/dist/index-Cmne1yUK.d.cts +723 -0
  24. package/dist/index-D7dyyu3q.d.ts +723 -0
  25. package/dist/index.cjs +13180 -5640
  26. package/dist/index.d.cts +72 -40
  27. package/dist/index.d.ts +72 -40
  28. package/dist/index.mjs +12587 -5038
  29. package/dist/math/display-wrapper.cjs +7 -15
  30. package/dist/math/display-wrapper.d.cts +2 -2
  31. package/dist/math/display-wrapper.d.ts +2 -2
  32. package/dist/math/display-wrapper.mjs +2 -6
  33. package/dist/node-views-Bpc6Gkgl.d.cts +13 -0
  34. package/dist/node-views-DpnYdaAS.d.ts +13 -0
  35. package/dist/renderer/hooks.cjs +35 -20
  36. package/dist/renderer/hooks.d.cts +22 -1
  37. package/dist/renderer/hooks.d.ts +22 -1
  38. package/dist/renderer/hooks.mjs +27 -12
  39. package/dist/renderer/patch-batching.cjs +7 -8
  40. package/dist/renderer/patch-batching.d.cts +1 -1
  41. package/dist/renderer/patch-batching.d.ts +1 -1
  42. package/dist/renderer/patch-batching.mjs +2 -1
  43. package/dist/renderer/patch-coalescing.cjs +5 -8
  44. package/dist/renderer/patch-commit-scheduler.cjs +160 -326
  45. package/dist/renderer/patch-commit-scheduler.d.cts +28 -4
  46. package/dist/renderer/patch-commit-scheduler.d.ts +28 -4
  47. package/dist/renderer/patch-commit-scheduler.mjs +157 -318
  48. package/dist/renderer/store.cjs +3847 -1099
  49. package/dist/renderer/store.d.cts +111 -3
  50. package/dist/renderer/store.d.ts +111 -3
  51. package/dist/renderer/store.mjs +3847 -1085
  52. package/dist/renderer/virtualized-code.cjs +415 -71
  53. package/dist/renderer/virtualized-code.d.cts +24 -23
  54. package/dist/renderer/virtualized-code.d.ts +24 -23
  55. package/dist/renderer/virtualized-code.mjs +409 -62
  56. package/dist/renderer.cjs +10939 -3974
  57. package/dist/renderer.d.cts +100 -29
  58. package/dist/renderer.d.ts +100 -29
  59. package/dist/renderer.mjs +10711 -3697
  60. package/dist/server-regions-CPLHGli0.d.cts +32 -0
  61. package/dist/server-regions-mUhyoKi7.d.ts +32 -0
  62. package/dist/server.cjs +10286 -3365
  63. package/dist/server.d.cts +17 -247
  64. package/dist/server.d.ts +17 -247
  65. package/dist/server.mjs +10565 -3619
  66. package/dist/{streaming-markdown-DOc2uLiP.d.ts → streaming-markdown-yELbJxyH.d.ts} +51 -55
  67. package/dist/{streaming-markdown-D-JcByd9.d.cts → streaming-markdown-zVwFuaJG.d.cts} +51 -55
  68. package/dist/streaming-markdown.cjs +11828 -4879
  69. package/dist/streaming-markdown.d.cts +9 -2
  70. package/dist/streaming-markdown.d.ts +9 -2
  71. package/dist/streaming-markdown.mjs +11820 -4821
  72. package/dist/trusted-mdx/index.cjs +833 -0
  73. package/dist/trusted-mdx/index.d.cts +11 -0
  74. package/dist/trusted-mdx/index.d.ts +11 -0
  75. package/dist/trusted-mdx/index.mjs +807 -0
  76. package/dist/trusted-mdx/native-children-slot.cjs +45 -0
  77. package/dist/trusted-mdx/native-children-slot.d.cts +11 -0
  78. package/dist/trusted-mdx/native-children-slot.d.ts +11 -0
  79. package/dist/trusted-mdx/native-children-slot.mjs +24 -0
  80. package/dist/trusted-mdx/server.cjs +752 -0
  81. package/dist/trusted-mdx/server.d.cts +24 -0
  82. package/dist/trusted-mdx/server.d.ts +24 -0
  83. package/dist/trusted-mdx/server.mjs +724 -0
  84. package/dist/trusted-mdx-contract-ElKpkDI5.d.cts +113 -0
  85. package/dist/trusted-mdx-contract-ElKpkDI5.d.ts +113 -0
  86. package/dist/utils/inline-html.cjs +246 -147
  87. package/dist/utils/inline-html.d.cts +39 -6
  88. package/dist/utils/inline-html.d.ts +39 -6
  89. package/dist/utils/inline-html.mjs +237 -134
  90. package/package.json +52 -18
  91. package/shadcn/README.md +28 -0
  92. package/shadcn/bottom-stick-scroll-area.tsx +358 -0
  93. package/dist/index-D2MYusAM.d.cts +0 -248
  94. package/dist/index-D2MYusAM.d.ts +0 -248
  95. package/dist/mdx-client.cjs +0 -408
  96. package/dist/mdx-client.d.cts +0 -113
  97. package/dist/mdx-client.d.ts +0 -113
  98. package/dist/mdx-client.mjs +0 -369
  99. package/dist/mdx-coordinator.cjs +0 -563
  100. package/dist/mdx-coordinator.d.cts +0 -21
  101. package/dist/mdx-coordinator.d.ts +0 -21
  102. package/dist/mdx-coordinator.mjs +0 -529
  103. package/dist/renderer/node-views.cjs +0 -1642
  104. package/dist/renderer/node-views.d.cts +0 -12
  105. package/dist/renderer/node-views.d.ts +0 -12
  106. package/dist/renderer/node-views.mjs +0 -1616
@@ -4,21 +4,14 @@ var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
- };
7
+ var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
12
8
  var __export = (target, all) => {
13
9
  for (var name in all)
14
- __defProp(target, name, { get: all[name], enumerable: true });
15
- };
16
- var __copyProps = (to, from, except, desc) => {
17
- if (from && typeof from === "object" || typeof from === "function") {
10
+ __defProp(target, name, { get: all[name], enumerable: !0 });
11
+ }, __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from == "object" || typeof from == "function")
18
13
  for (let key of __getOwnPropNames(from))
19
- if (!__hasOwnProp.call(to, key) && key !== except)
20
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
- }
14
+ !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
15
  return to;
23
16
  };
24
17
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
@@ -26,591 +19,1397 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
19
  // file that has been converted to a CommonJS file using a Babel-
27
20
  // compatible transform (i.e. "__esModule" has not been set), then set
28
21
  // "default" to the CommonJS "module.exports" for node compatibility.
29
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target,
30
23
  mod
31
- ));
32
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
+ )), __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
33
25
 
34
- // src/mdx-client.ts
35
- var mdx_client_exports = {};
36
- __export(mdx_client_exports, {
37
- MDXClient: () => MDXClient,
38
- MDXComponentFactory: () => MDXComponentFactory,
39
- getMDXClient: () => getMDXClient,
40
- getMDXComponentFactory: () => getMDXComponentFactory,
41
- registerInlineMdxModule: () => registerInlineMdxModule,
42
- registerMDXComponents: () => registerMDXComponents
26
+ // src/components/index.ts
27
+ var components_exports = {};
28
+ __export(components_exports, {
29
+ AnimationTimeline: () => AnimationTimeline,
30
+ BottomStickScrollArea: () => BottomStickScrollArea,
31
+ CodeBlockCopyButton: () => CodeBlockCopyButton,
32
+ CodeBlockDownloadButton: () => CodeBlockDownloadButton,
33
+ CodeControlsBar: () => CodeControlsBar,
34
+ ComponentRegistry: () => ComponentRegistry,
35
+ DEFAULT_ANIMATED_OPTIONS: () => DEFAULT_ANIMATED_OPTIONS,
36
+ DEFAULT_CONTROLS_LABELS: () => DEFAULT_CONTROLS_LABELS,
37
+ DefaultDiffRenderer: () => DefaultDiffRenderer,
38
+ DefaultLinkSafetyModal: () => DefaultLinkSafetyModal,
39
+ DocumentMathMacroScope: () => DocumentMathMacroScope,
40
+ DocumentMathMacroScopeContext: () => DocumentMathMacroScopeContext,
41
+ KaTeXBlockMath: () => KaTeXBlockMath,
42
+ KaTeXInlineMath: () => KaTeXInlineMath,
43
+ LANGUAGE_EXTENSION_MAP: () => LANGUAGE_EXTENSION_MAP,
44
+ MathExpressionCompletenessContext: () => MathExpressionCompletenessContext,
45
+ STREAM_MDX_ANIMATION_CSS: () => STREAM_MDX_ANIMATION_CSS,
46
+ TableControlsBar: () => TableControlsBar,
47
+ copyToClipboard: () => copyToClipboard,
48
+ defaultInlineComponents: () => defaultInlineComponents,
49
+ defaultUrlTransform: () => import_core3.defaultUrlTransform,
50
+ downloadFile: () => downloadFile,
51
+ escapeCsvCell: () => escapeCsvCell,
52
+ escapeTsvCell: () => escapeTsvCell,
53
+ getCodeSnippetFilename: () => getCodeSnippetFilename,
54
+ getExtensionForLanguage: () => getExtensionForLanguage,
55
+ inlineToPlainText: () => inlineToPlainText,
56
+ loadKaTeX: () => loadKaTeX,
57
+ mapHtmlToReact: () => mapHtmlToReact,
58
+ renderInlineNodes: () => renderInlineNodes,
59
+ renderParagraphMixedSegments: () => renderParagraphMixedSegments,
60
+ resolveAnimatedOptions: () => resolveAnimatedOptions,
61
+ resolveCodeControls: () => resolveCodeControls,
62
+ resolveControlsConfig: () => resolveControlsConfig,
63
+ resolveMermaidControls: () => resolveMermaidControls,
64
+ resolveTableControls: () => resolveTableControls,
65
+ splitTextSegments: () => splitTextSegments,
66
+ splitWordSegments: () => splitWordSegments,
67
+ tableToCsv: () => tableToCsv,
68
+ tableToMarkdown: () => tableToMarkdown,
69
+ tableToTsv: () => tableToTsv
43
70
  });
44
- function assignMdxChildKey(child, index) {
45
- if (child == null) return child;
46
- if (Array.isArray(child)) {
47
- return child.map((entry, subIndex) => assignMdxChildKey(entry, `${index}-${subIndex}`));
48
- }
49
- if (import_react2.default.isValidElement(child)) {
50
- if (child.key !== null && child.key !== void 0) {
51
- return child;
52
- }
53
- return import_react2.default.cloneElement(child, { key: index });
54
- }
55
- return child;
71
+ module.exports = __toCommonJS(components_exports);
72
+
73
+ // src/code-fence-streaming.ts
74
+ function trimProvisionalFenceTail(raw) {
75
+ if (raw.endsWith(`
76
+ `)) return raw;
77
+ let opening = raw.match(/^ {0,3}(`{3,}|~{3,})[^\n]*\n/);
78
+ if (!opening) return raw;
79
+ let lastNewline = raw.lastIndexOf(`
80
+ `), tail = raw.slice(lastNewline + 1).match(/^ {0,3}(`+|~+)[\t ]*$/);
81
+ return tail && tail[1][0] === opening[1][0] && tail[1].length < opening[1].length ? raw.slice(0, lastNewline) : raw;
56
82
  }
57
- function getMDXClient(compileEndpoint) {
58
- if (!globalMDXClient) {
59
- globalMDXClient = new MDXClient(compileEndpoint);
60
- }
61
- return globalMDXClient;
83
+
84
+ // src/components/bottom-stick-scroll-area.tsx
85
+ var import_react = require("react"), import_jsx_runtime = require("react/jsx-runtime"), EPS_BOTTOM_PX = 2, EPS_OVERFLOW_PX = 1, DETACH_SCROLL_DELTA_PX = 1, RETURN_MIN_MS = 180, RETURN_MAX_MS = 520, RETURN_PX_PER_MS = 2.2, RETURN_SETTLE_FRAMES = 2;
86
+ function clamp01(value) {
87
+ return value < 0 ? 0 : value > 1 ? 1 : value;
88
+ }
89
+ function easeOutCubic(value) {
90
+ return 1 - (1 - value) ** 3;
91
+ }
92
+ function joinClasses(...parts) {
93
+ return parts.filter(Boolean).join(" ");
94
+ }
95
+ function measure(viewport) {
96
+ let scrollTop = viewport.scrollTop, scrollHeight = viewport.scrollHeight, clientHeight = viewport.clientHeight, maxScrollTop = Math.max(0, scrollHeight - clientHeight), distanceToBottom = Math.max(0, maxScrollTop - scrollTop), isOverflowing = scrollHeight > clientHeight + EPS_OVERFLOW_PX;
97
+ return { scrollTop, scrollHeight, clientHeight, maxScrollTop, distanceToBottom, isOverflowing };
98
+ }
99
+ function isEditableTarget(target) {
100
+ if (!(target instanceof Element)) return !1;
101
+ if (target.closest("input, textarea, select, [role='textbox']")) return !0;
102
+ let contentEditable = target.closest("[contenteditable]");
103
+ return contentEditable !== null && contentEditable.getAttribute("contenteditable")?.toLowerCase() !== "false";
62
104
  }
63
- function getMDXComponentFactory(compileEndpoint) {
64
- if (!globalComponentFactory) {
65
- const client = getMDXClient(compileEndpoint);
66
- globalComponentFactory = new MDXComponentFactory(client);
105
+ function isScrollKeyIntent(event) {
106
+ if (event.defaultPrevented || isEditableTarget(event.target)) return !1;
107
+ switch (event.key) {
108
+ case "ArrowDown":
109
+ case "ArrowUp":
110
+ case "PageDown":
111
+ case "PageUp":
112
+ case "Home":
113
+ case "End":
114
+ return !0;
115
+ case " ":
116
+ case "Spacebar":
117
+ return event.target instanceof Element ? event.target.closest(
118
+ "button, input, summary, [role='button'], [role='checkbox'], [role='switch'], [role='radio'], [role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']"
119
+ ) === null : !0;
120
+ default:
121
+ return !1;
67
122
  }
68
- return globalComponentFactory;
69
123
  }
70
- function registerMDXComponents(components, options) {
71
- const factory = getMDXComponentFactory();
72
- factory.registerComponents(components, options);
124
+ function DefaultJumpButton({ canJump, jumpToBottom }) {
125
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
126
+ "button",
127
+ {
128
+ type: "button",
129
+ onClick: jumpToBottom,
130
+ "aria-label": "Scroll to bottom",
131
+ style: {
132
+ pointerEvents: canJump ? "auto" : "none",
133
+ borderRadius: 9999,
134
+ border: "1px solid color-mix(in srgb, currentColor 20%, transparent)",
135
+ width: 40,
136
+ height: 40,
137
+ display: "grid",
138
+ placeItems: "center",
139
+ boxShadow: "0 8px 20px rgba(0,0,0,0.18)",
140
+ background: "color-mix(in srgb, var(--background, #fff) 92%, transparent)",
141
+ color: "var(--foreground, #111)",
142
+ cursor: canJump ? "pointer" : "default"
143
+ },
144
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": !0, children: "\u2193" })
145
+ }
146
+ );
73
147
  }
74
- function registerInlineMdxModule(compiled) {
75
- const factory = getMDXComponentFactory();
76
- factory.registerInlineModule({
77
- id: compiled.id,
78
- code: compiled.code,
79
- dependencies: compiled.dependencies ?? []
80
- });
148
+ function BottomStickScrollArea({
149
+ children,
150
+ className,
151
+ viewportClassName,
152
+ contentClassName,
153
+ showJumpToBottom = !0,
154
+ onDebugStateChange,
155
+ onModeChange,
156
+ debugDomAttributes = !1,
157
+ renderJumpToBottom,
158
+ jumpContainerClassName
159
+ }) {
160
+ let viewportRef = (0, import_react.useRef)(null), contentRef = (0, import_react.useRef)(null), modeRef = (0, import_react.useRef)("STICKY_INSTANT"), [mode, setMode] = (0, import_react.useState)("STICKY_INSTANT"), [isOverflowing, setIsOverflowing] = (0, import_react.useState)(!1), [distanceToBottom, setDistanceToBottom] = (0, import_react.useState)(0), [prefersReducedMotion, setPrefersReducedMotion] = (0, import_react.useState)(!1), prefersReducedMotionRef = (0, import_react.useRef)(!1), prevScrollTopRef = (0, import_react.useRef)(0), lastProgrammaticWriteRef = (0, import_react.useRef)(null), programmaticWriteCountRef = (0, import_react.useRef)(0), pendingStickRafRef = (0, import_react.useRef)(null), stickRequestedRef = (0, import_react.useRef)(!1), returnRafRef = (0, import_react.useRef)(null), returnAnimRef = (0, import_react.useRef)(null), setModeBoth = (0, import_react.useCallback)(
161
+ (next) => {
162
+ modeRef.current = next, setMode(next), onModeChange?.(next);
163
+ },
164
+ [onModeChange]
165
+ ), updateDebug = (0, import_react.useCallback)(() => {
166
+ let viewport = viewportRef.current;
167
+ if (!viewport) return;
168
+ let m = measure(viewport);
169
+ debugDomAttributes && (viewport.dataset.stickyMode = modeRef.current, viewport.dataset.distanceToBottom = String(m.distanceToBottom), viewport.dataset.isOverflowing = m.isOverflowing ? "1" : "0", viewport.dataset.programmaticWrites = String(programmaticWriteCountRef.current)), onDebugStateChange?.({
170
+ mode: modeRef.current,
171
+ isOverflowing: m.isOverflowing,
172
+ distanceToBottom: m.distanceToBottom,
173
+ scrollTop: m.scrollTop,
174
+ maxScrollTop: m.maxScrollTop,
175
+ scrollHeight: m.scrollHeight,
176
+ clientHeight: m.clientHeight,
177
+ programmaticWrites: programmaticWriteCountRef.current
178
+ }), setDistanceToBottom(
179
+ (previous) => Math.abs(previous - m.distanceToBottom) <= 0.1 ? previous : m.distanceToBottom
180
+ );
181
+ }, [debugDomAttributes, onDebugStateChange]), writeScrollTop = (0, import_react.useCallback)((nextTop) => {
182
+ let viewport = viewportRef.current;
183
+ viewport && (viewport.scrollTop = nextTop, programmaticWriteCountRef.current += 1, lastProgrammaticWriteRef.current = { at: performance.now(), top: nextTop });
184
+ }, []), cancelPendingStick = (0, import_react.useCallback)(() => {
185
+ pendingStickRafRef.current !== null && (cancelAnimationFrame(pendingStickRafRef.current), pendingStickRafRef.current = null), stickRequestedRef.current = !1;
186
+ }, []), cancelReturn = (0, import_react.useCallback)(() => {
187
+ returnRafRef.current !== null && (cancelAnimationFrame(returnRafRef.current), returnRafRef.current = null), returnAnimRef.current = null;
188
+ }, []), handleReducedMotionChange = (0, import_react.useCallback)(
189
+ (matches) => {
190
+ if (prefersReducedMotionRef.current !== matches && (prefersReducedMotionRef.current = matches, setPrefersReducedMotion(matches)), !matches || modeRef.current !== "RETURNING_SMOOTH") return;
191
+ cancelPendingStick(), cancelReturn(), setModeBoth("STICKY_INSTANT");
192
+ let viewport = viewportRef.current;
193
+ viewport && (writeScrollTop(measure(viewport).maxScrollTop), prevScrollTopRef.current = viewport.scrollTop), updateDebug();
194
+ },
195
+ [cancelPendingStick, cancelReturn, setModeBoth, updateDebug, writeScrollTop]
196
+ ), reducedMotionChangeHandlerRef = (0, import_react.useRef)(handleReducedMotionChange);
197
+ reducedMotionChangeHandlerRef.current = handleReducedMotionChange;
198
+ let interruptReturnForUserIntent = (0, import_react.useCallback)(() => {
199
+ modeRef.current === "RETURNING_SMOOTH" && (cancelPendingStick(), cancelReturn(), setModeBoth("DETACHED"), updateDebug());
200
+ }, [cancelPendingStick, cancelReturn, setModeBoth, updateDebug]), onViewportKeyDown = (0, import_react.useCallback)(
201
+ (event) => {
202
+ isScrollKeyIntent(event) && interruptReturnForUserIntent();
203
+ },
204
+ [interruptReturnForUserIntent]
205
+ ), stickToBottomInstant = (0, import_react.useCallback)(() => {
206
+ let viewport = viewportRef.current;
207
+ viewport && (stickRequestedRef.current = !0, pendingStickRafRef.current === null && (pendingStickRafRef.current = requestAnimationFrame(() => {
208
+ if (pendingStickRafRef.current = null, !stickRequestedRef.current || (stickRequestedRef.current = !1, modeRef.current !== "STICKY_INSTANT")) return;
209
+ let m = measure(viewport);
210
+ writeScrollTop(m.maxScrollTop), updateDebug();
211
+ })));
212
+ }, [updateDebug, writeScrollTop]), startReturnToBottomSmooth = (0, import_react.useCallback)(() => {
213
+ let viewport = viewportRef.current;
214
+ if (!viewport) return;
215
+ if (prefersReducedMotionRef.current) {
216
+ cancelPendingStick(), cancelReturn(), setModeBoth("STICKY_INSTANT"), writeScrollTop(measure(viewport).maxScrollTop), prevScrollTopRef.current = viewport.scrollTop, updateDebug();
217
+ return;
218
+ }
219
+ cancelPendingStick(), cancelReturn();
220
+ let initial = measure(viewport);
221
+ if (initial.distanceToBottom <= EPS_BOTTOM_PX) {
222
+ setModeBoth("STICKY_INSTANT"), stickToBottomInstant(), updateDebug();
223
+ return;
224
+ }
225
+ let durationMs = Math.max(
226
+ RETURN_MIN_MS,
227
+ Math.min(RETURN_MAX_MS, initial.distanceToBottom / RETURN_PX_PER_MS)
228
+ );
229
+ returnAnimRef.current = {
230
+ startTime: performance.now(),
231
+ startTop: initial.scrollTop,
232
+ durationMs,
233
+ settleFrames: 0
234
+ }, setModeBoth("RETURNING_SMOOTH");
235
+ let tick = (now) => {
236
+ let viewportCurrent = viewportRef.current, anim = returnAnimRef.current;
237
+ if (!viewportCurrent || !anim || modeRef.current !== "RETURNING_SMOOTH") {
238
+ cancelReturn();
239
+ return;
240
+ }
241
+ let before = measure(viewportCurrent), progress = clamp01((now - anim.startTime) / anim.durationMs), eased = easeOutCubic(progress), targetBottom = before.maxScrollTop, nextTop = anim.startTop + (targetBottom - anim.startTop) * eased;
242
+ nextTop < before.scrollTop && (nextTop = before.scrollTop), writeScrollTop(nextTop), measure(viewportCurrent).distanceToBottom <= EPS_BOTTOM_PX ? anim.settleFrames += 1 : anim.settleFrames = 0;
243
+ let doneByTime = progress >= 1, doneBySettle = anim.settleFrames >= RETURN_SETTLE_FRAMES && progress >= 0.6;
244
+ if (doneByTime && doneBySettle) {
245
+ cancelReturn(), setModeBoth("STICKY_INSTANT"), stickToBottomInstant(), updateDebug();
246
+ return;
247
+ }
248
+ updateDebug(), returnRafRef.current = requestAnimationFrame(tick);
249
+ };
250
+ returnRafRef.current = requestAnimationFrame(tick);
251
+ }, [cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug, writeScrollTop]), onViewportScroll = (0, import_react.useCallback)(
252
+ (event) => {
253
+ let viewport = event.currentTarget, m = measure(viewport);
254
+ setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
255
+ let previousTop = prevScrollTopRef.current, delta = m.scrollTop - previousTop, lastWrite = lastProgrammaticWriteRef.current, isLikelyOwnWrite = lastWrite !== null && performance.now() - lastWrite.at < 60 && lastWrite !== null && Math.abs(m.scrollTop - lastWrite.top) <= 2;
256
+ modeRef.current === "RETURNING_SMOOTH" ? !isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX && (cancelReturn(), setModeBoth("DETACHED")) : modeRef.current === "STICKY_INSTANT" ? !isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX && m.isOverflowing && (cancelPendingStick(), setModeBoth("DETACHED")) : modeRef.current === "DETACHED" && m.distanceToBottom <= EPS_BOTTOM_PX && (setModeBoth("STICKY_INSTANT"), stickToBottomInstant()), prevScrollTopRef.current = m.scrollTop, updateDebug();
257
+ },
258
+ [cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug]
259
+ );
260
+ (0, import_react.useEffect)(() => {
261
+ let viewport = viewportRef.current, content = contentRef.current;
262
+ if (!viewport || !content) return;
263
+ let observer = new ResizeObserver(() => {
264
+ let m = measure(viewport);
265
+ setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing), modeRef.current === "STICKY_INSTANT" && stickToBottomInstant(), updateDebug();
266
+ });
267
+ return observer.observe(content), observer.observe(viewport), () => observer.disconnect();
268
+ }, [stickToBottomInstant, updateDebug]), (0, import_react.useLayoutEffect)(() => {
269
+ let viewport = viewportRef.current;
270
+ if (!viewport) return;
271
+ setModeBoth("STICKY_INSTANT");
272
+ let initial = measure(viewport);
273
+ writeScrollTop(initial.maxScrollTop), prevScrollTopRef.current = viewport.scrollTop, setIsOverflowing(initial.isOverflowing), setDistanceToBottom(initial.distanceToBottom), updateDebug();
274
+ }, [setModeBoth, updateDebug, writeScrollTop]), (0, import_react.useLayoutEffect)(() => {
275
+ if (typeof window > "u" || typeof window.matchMedia != "function") return;
276
+ let mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)"), onChange = () => reducedMotionChangeHandlerRef.current(mediaQuery.matches);
277
+ return onChange(), typeof mediaQuery.addEventListener == "function" ? (mediaQuery.addEventListener("change", onChange), () => mediaQuery.removeEventListener("change", onChange)) : (mediaQuery.addListener(onChange), () => mediaQuery.removeListener(onChange));
278
+ }, []), (0, import_react.useEffect)(() => () => {
279
+ cancelPendingStick(), cancelReturn();
280
+ }, [cancelPendingStick, cancelReturn]);
281
+ let canJump = isOverflowing && mode === "DETACHED", jumpButton = renderJumpToBottom?.({
282
+ mode,
283
+ canJump,
284
+ isOverflowing,
285
+ distanceToBottom,
286
+ jumpToBottom: startReturnToBottomSmooth
287
+ }) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultJumpButton, { canJump, jumpToBottom: startReturnToBottomSmooth }), jumpContainerClassNameBase = "pointer-events-none absolute z-20", jumpContainerStyle = {
288
+ position: "absolute",
289
+ zIndex: 20,
290
+ left: 0,
291
+ right: 0,
292
+ bottom: 12,
293
+ display: "flex",
294
+ justifyContent: "center",
295
+ opacity: canJump ? 1 : 0,
296
+ transform: prefersReducedMotion ? "none" : canJump ? "translateY(0px)" : "translateY(4px)",
297
+ transition: prefersReducedMotion ? "none" : "opacity 150ms ease, transform 150ms ease",
298
+ pointerEvents: "none"
299
+ };
300
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: joinClasses("relative h-full w-full overflow-hidden", className), children: [
301
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
302
+ "div",
303
+ {
304
+ ref: viewportRef,
305
+ className: joinClasses("h-full w-full overflow-auto", viewportClassName),
306
+ onScroll: onViewportScroll,
307
+ onWheel: interruptReturnForUserIntent,
308
+ onTouchStart: interruptReturnForUserIntent,
309
+ onKeyDown: onViewportKeyDown,
310
+ "data-testid": "sticky-scroll-viewport",
311
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: contentRef, className: joinClasses("flex min-h-full w-full flex-col", contentClassName), children })
312
+ }
313
+ ),
314
+ showJumpToBottom ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
315
+ "div",
316
+ {
317
+ className: joinClasses(jumpContainerClassNameBase, jumpContainerClassName),
318
+ style: jumpContainerStyle,
319
+ "aria-hidden": !canJump,
320
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: canJump ? "pointer-events-auto" : "pointer-events-none", children: jumpButton })
321
+ }
322
+ ) : null
323
+ ] });
81
324
  }
82
- var import_react2, ReactJsxRuntime, withClassName, MDXClient, MDXComponentFactory, globalMDXClient, globalComponentFactory;
83
- var init_mdx_client = __esm({
84
- "src/mdx-client.ts"() {
85
- "use strict";
86
- import_react2 = __toESM(require("react"), 1);
87
- ReactJsxRuntime = __toESM(require("react/jsx-runtime"), 1);
88
- withClassName = (tag, className) => {
89
- return (props) => import_react2.default.createElement(tag, { className, ...props });
325
+
326
+ // src/components/diff-renderer.tsx
327
+ var import_jsx_runtime2 = require("react/jsx-runtime"), DefaultDiffRenderer = ({
328
+ meta,
329
+ renderCode,
330
+ className = "",
331
+ style
332
+ }) => {
333
+ let diffBlocks = Array.isArray(meta?.diffBlocks) ? meta.diffBlocks : null;
334
+ return !diffBlocks || diffBlocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: renderCode }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
335
+ "div",
336
+ {
337
+ className: `stream-mdx-diff-container my-4 rounded-md border border-border bg-muted/20 font-mono text-sm overflow-hidden ${className}`.trim(),
338
+ style,
339
+ children: diffBlocks.map((diffBlock, bIdx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "stream-mdx-diff-block", children: [
340
+ (diffBlock.filePath || diffBlock.additions != null || diffBlock.deletions != null) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "stream-mdx-diff-header flex items-center justify-between border-b border-border bg-muted/40 px-4 py-2 text-xs font-semibold text-muted-foreground", children: [
341
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "stream-mdx-diff-filepath", children: diffBlock.filePath ?? "diff" }),
342
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "stream-mdx-diff-stats flex gap-2", children: [
343
+ diffBlock.additions != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "stream-mdx-diff-stat-add text-green-600 dark:text-green-400", children: [
344
+ "+",
345
+ diffBlock.additions
346
+ ] }),
347
+ diffBlock.deletions != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "stream-mdx-diff-stat-del text-red-600 dark:text-red-400", children: [
348
+ "-",
349
+ diffBlock.deletions
350
+ ] })
351
+ ] })
352
+ ] }),
353
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "stream-mdx-diff-lines overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("table", { className: "w-full border-collapse font-mono text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: diffBlock.lines.map((line, lIdx) => {
354
+ let kindClass = `diff-line-${line.kind} ${line.kind === "add" ? "bg-green-500/10 text-green-900 dark:text-green-200" : line.kind === "del" ? "bg-red-500/10 text-red-900 dark:text-red-200" : line.kind === "hunk" ? "bg-blue-500/10 text-blue-800 dark:text-blue-300 font-semibold" : line.kind === "meta" ? "bg-muted/50 text-muted-foreground italic" : "text-foreground"}`;
355
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
356
+ "tr",
357
+ {
358
+ className: `stream-mdx-diff-row ${kindClass}`,
359
+ "data-diff-kind": line.kind,
360
+ children: [
361
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "stream-mdx-diff-old-no select-none px-2 py-0.5 text-right opacity-50 w-10", children: line.oldNo != null ? line.oldNo : "" }),
362
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "stream-mdx-diff-new-no select-none px-2 py-0.5 text-right opacity-50 w-10", children: line.newNo != null ? line.newNo : "" }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "stream-mdx-diff-prefix select-none px-1 py-0.5 text-center w-4 font-bold", children: line.kind === "add" ? "+" : line.kind === "del" ? "-" : line.kind === "hunk" ? "@" : " " }),
364
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { className: "stream-mdx-diff-content px-2 py-0.5 whitespace-pre", children: line.tokens && line.tokens.length > 0 ? line.tokens.map((token, tIdx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
365
+ "span",
366
+ {
367
+ style: {
368
+ color: token.color ?? void 0,
369
+ fontStyle: token.fontStyle === 1 || token.fontStyle === 3 ? "italic" : void 0,
370
+ fontWeight: token.fontStyle === 2 || token.fontStyle === 3 ? "bold" : void 0
371
+ },
372
+ children: token.content
373
+ },
374
+ tIdx
375
+ )) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: line.raw.replace(/^[+\- ]/, "") }) })
376
+ ]
377
+ },
378
+ lIdx
379
+ );
380
+ }) }) }) })
381
+ ] }, bIdx))
382
+ }
383
+ );
384
+ };
385
+ DefaultDiffRenderer.displayName = "DefaultDiffRenderer";
386
+
387
+ // src/components/katex-math.tsx
388
+ var import_react2 = require("react"), import_jsx_runtime3 = require("react/jsx-runtime"), katexPromise = null;
389
+ async function loadKaTeX() {
390
+ return katexPromise || (katexPromise = import("katex").then((mod) => mod && typeof mod == "object" && "default" in mod && mod.default ? mod.default : mod)), katexPromise;
391
+ }
392
+ var DOCUMENT_POSITION_PRECEDING = 2, DOCUMENT_POSITION_FOLLOWING = 4, DocumentMathMacroScope = class {
393
+ constructor() {
394
+ this.entries = /* @__PURE__ */ new Set();
395
+ this.orderedEntries = [];
396
+ this.macroSnapshots = [];
397
+ this.katex = null;
398
+ this.loadError = null;
399
+ this.loading = !1;
400
+ this.disposed = !1;
401
+ }
402
+ register(element, tex, displayMode, complete, publish) {
403
+ let entry = { element, tex, displayMode, complete, publish };
404
+ return this.entries.add(entry), this.refresh(), () => {
405
+ this.entries.delete(entry) && this.refresh();
90
406
  };
91
- MDXClient = class {
92
- constructor(compileEndpoint = "/api/mdx-compile-v2") {
93
- this.cache = /* @__PURE__ */ new Map();
94
- this.inlineModules = /* @__PURE__ */ new Map();
95
- this.compiledCache = /* @__PURE__ */ new Map();
96
- this.compiledInflight = /* @__PURE__ */ new Map();
97
- this.compileEndpoint = compileEndpoint;
407
+ }
408
+ dispose() {
409
+ this.disposed = !0, this.entries.clear(), this.orderedEntries = [], this.macroSnapshots = [];
410
+ }
411
+ refresh() {
412
+ if (!this.disposed) {
413
+ if (this.loadError) {
414
+ for (let entry of this.entries)
415
+ entry.publish({ tex: entry.tex, displayMode: entry.displayMode, scope: this, error: this.loadError });
416
+ return;
98
417
  }
99
- /**
100
- * Compile MDX block on server
101
- */
102
- async compile(block) {
103
- if (block.type !== "mdx") {
104
- throw new Error("Block is not MDX type");
105
- }
106
- const cacheKey = block.id;
107
- const cachedPromise = this.cache.get(cacheKey);
108
- if (cachedPromise) {
109
- return cachedPromise;
110
- }
111
- const compilationPromise = this.doCompile(block);
112
- this.cache.set(cacheKey, compilationPromise);
113
- try {
114
- const result = await compilationPromise;
115
- return result;
116
- } catch (error) {
117
- this.cache.delete(cacheKey);
118
- throw error;
119
- }
418
+ if (this.katex) {
419
+ this.recompute(this.katex);
420
+ return;
120
421
  }
121
- async getCompiledInternal(ref) {
122
- const inline = this.inlineModules.get(ref.id);
123
- if (inline) {
124
- return this.cloneCompiled(inline);
422
+ this.loading || (this.loading = !0, loadKaTeX().then((katex) => {
423
+ this.disposed || (this.katex = katex, this.refresh());
424
+ }).catch((reason) => {
425
+ if (!this.disposed) {
426
+ this.loadError = reason instanceof Error ? reason : new Error(String(reason));
427
+ for (let entry of this.entries)
428
+ entry.publish({ tex: entry.tex, displayMode: entry.displayMode, scope: this, error: this.loadError });
125
429
  }
126
- const cached = this.compiledCache.get(ref.id);
127
- if (cached) {
128
- return this.cloneCompiled(cached);
129
- }
130
- const inflight = this.compiledInflight.get(ref.id);
131
- if (inflight) {
132
- const resolved = await inflight;
133
- return this.cloneCompiled(resolved);
134
- }
135
- const fetchPromise = this.fetchCompiled(ref);
136
- this.compiledInflight.set(ref.id, fetchPromise);
430
+ }).finally(() => {
431
+ this.loading = !1;
432
+ }));
433
+ }
434
+ }
435
+ recompute(katex) {
436
+ let nextEntries = [...this.entries].sort((left, right) => {
437
+ let position = left.element.compareDocumentPosition(right.element);
438
+ return position & DOCUMENT_POSITION_FOLLOWING ? -1 : position & DOCUMENT_POSITION_PRECEDING ? 1 : 0;
439
+ }), unchangedPrefix = 0;
440
+ for (; unchangedPrefix < this.orderedEntries.length && unchangedPrefix < nextEntries.length && this.orderedEntries[unchangedPrefix] === nextEntries[unchangedPrefix]; )
441
+ unchangedPrefix += 1;
442
+ let macros = unchangedPrefix > 0 ? { ...this.macroSnapshots[unchangedPrefix - 1] } : {};
443
+ this.orderedEntries = nextEntries, this.macroSnapshots.length = unchangedPrefix;
444
+ for (let index = unchangedPrefix; index < nextEntries.length; index += 1) {
445
+ let entry = nextEntries[index], preparation = null;
446
+ if (entry.complete) {
447
+ let nextMacros = { ...macros };
137
448
  try {
138
- const data = await fetchPromise;
139
- this.compiledCache.set(ref.id, data);
140
- return this.cloneCompiled(data);
141
- } finally {
142
- this.compiledInflight.delete(ref.id);
143
- }
144
- }
145
- async getCompiled(ref, options) {
146
- if (options?.signal) {
147
- const inline = this.inlineModules.get(ref.id);
148
- if (inline) {
149
- return this.cloneCompiled(inline);
150
- }
151
- const cached = this.compiledCache.get(ref.id);
152
- if (cached) {
153
- return this.cloneCompiled(cached);
154
- }
155
- const data = await this.fetchCompiled(ref, options);
156
- this.compiledCache.set(ref.id, data);
157
- return this.cloneCompiled(data);
449
+ let html = katex.renderToString(entry.tex, {
450
+ displayMode: entry.displayMode,
451
+ throwOnError: !1,
452
+ trust: !1,
453
+ maxExpand: 1e3,
454
+ macros: nextMacros
455
+ });
456
+ macros = nextMacros, preparation = { tex: entry.tex, displayMode: entry.displayMode, scope: this, html };
457
+ } catch (reason) {
458
+ preparation = {
459
+ tex: entry.tex,
460
+ displayMode: entry.displayMode,
461
+ scope: this,
462
+ error: reason instanceof Error ? reason : new Error(String(reason))
463
+ };
158
464
  }
159
- return this.getCompiledInternal(ref);
160
- }
161
- /**
162
- * Clear compilation cache
163
- */
164
- clearCache() {
165
- this.cache.clear();
166
- this.compiledCache.clear();
167
- this.compiledInflight.clear();
168
465
  }
169
- registerInlineModule(compiled) {
170
- this.inlineModules.set(compiled.id, {
171
- ...compiled,
172
- dependencies: Array.isArray(compiled.dependencies) ? [...compiled.dependencies] : []
466
+ this.macroSnapshots[index] = { ...macros }, entry.publish(preparation);
467
+ }
468
+ }
469
+ }, DocumentMathMacroScopeContext = (0, import_react2.createContext)(null), MathExpressionCompletenessContext = (0, import_react2.createContext)(!0), MathEngineOutputView = ({ engine, tex, displayMode }) => {
470
+ let output = (0, import_react2.useMemo)(
471
+ () => engine.render(tex, { displayMode }),
472
+ [engine, engine.id, tex, displayMode]
473
+ );
474
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: output });
475
+ };
476
+ function useMathPreparation(tex, displayMode, elementRef, enabled) {
477
+ let scope = (0, import_react2.useContext)(DocumentMathMacroScopeContext), complete = (0, import_react2.useContext)(MathExpressionCompletenessContext), [preparation, setPreparation] = (0, import_react2.useState)(null);
478
+ return (0, import_react2.useEffect)(() => {
479
+ if (!enabled) return;
480
+ let active = !0;
481
+ if (scope) {
482
+ let element = elementRef.current;
483
+ return element ? scope.register(element, tex, displayMode, complete, (result) => {
484
+ active && setPreparation(result);
485
+ }) : () => {
486
+ active = !1;
487
+ };
488
+ }
489
+ return (async () => {
490
+ try {
491
+ let html = (await loadKaTeX()).renderToString(tex, {
492
+ displayMode,
493
+ throwOnError: !1,
494
+ trust: !1,
495
+ maxExpand: 1e3
173
496
  });
174
- }
175
- clearInlineModules() {
176
- this.inlineModules.clear();
177
- }
178
- /**
179
- * Actual compilation implementation
180
- */
181
- async doCompile(block) {
182
- const response = await fetch(this.compileEndpoint, {
183
- method: "POST",
184
- headers: {
185
- "Content-Type": "application/json"
186
- },
187
- body: JSON.stringify({
188
- content: block.payload.raw,
189
- blockId: block.id
190
- })
497
+ active && setPreparation({ tex, displayMode, scope: null, html });
498
+ } catch (reason) {
499
+ active && setPreparation({
500
+ tex,
501
+ displayMode,
502
+ scope: null,
503
+ error: reason instanceof Error ? reason : new Error(String(reason))
191
504
  });
192
- if (!response.ok) {
193
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
194
- throw new Error(`MDX compilation failed: ${error.error || response.statusText}`);
195
- }
196
- const data = await response.json();
197
- return {
198
- id: data.id,
199
- code: data.code,
200
- dependencies: data.dependencies || [],
201
- cached: data.cached || false
202
- };
203
- }
204
- async fetchCompiled(ref, options) {
205
- const response = await fetch(`${this.compileEndpoint}?id=${ref.id}`, {
206
- signal: options?.signal
207
- });
208
- if (!response.ok) {
209
- throw new Error(`Failed to get compiled MDX: ${response.statusText}`);
210
- }
211
- const data = await response.json();
212
- return {
213
- id: data.id,
214
- code: data.code,
215
- dependencies: data.dependencies || [],
216
- timestamp: data.timestamp
217
- };
218
- }
219
- cloneCompiled(compiled) {
220
- return {
221
- ...compiled,
222
- dependencies: Array.isArray(compiled.dependencies) ? [...compiled.dependencies] : []
223
- };
224
505
  }
506
+ })(), () => {
507
+ active = !1;
225
508
  };
226
- MDXComponentFactory = class {
227
- constructor(mdxClient) {
228
- this.components = /* @__PURE__ */ new Map();
229
- this.customComponents = /* @__PURE__ */ new Map();
230
- this.mdxClient = mdxClient;
231
- this.baseComponents = this.createBaseComponents();
232
- }
233
- registerInlineModule(module2) {
234
- this.mdxClient.registerInlineModule(module2);
235
- this.components.delete(module2.id);
236
- }
237
- /**
238
- * Create React component from compiled MDX
239
- */
240
- async createComponent(ref) {
241
- const cached = this.components.get(ref.id);
242
- if (cached) {
243
- return cached;
244
- }
245
- const compiled = await this.mdxClient.getCompiled(ref);
246
- const component = this.evaluateCompiledMDX(compiled);
247
- this.components.set(ref.id, component);
248
- return component;
509
+ }, [tex, displayMode, scope, complete, elementRef, enabled]), scope && !complete ? null : preparation?.tex === tex && preparation.displayMode === displayMode && preparation.scope === scope ? preparation : null;
510
+ }
511
+ var KaTeXInlineMath = ({ tex, className = "", fallback, engine }) => {
512
+ let elementRef = (0, import_react2.useRef)(null), preparation = useMathPreparation(tex, !1, elementRef, !engine);
513
+ return engine ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `math-inline ${className}`.trim(), "data-tex": tex, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MathEngineOutputView, { engine, tex, displayMode: !1 }) }) : preparation && "error" in preparation && fallback ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback(tex, preparation.error) }) : preparation && "html" in preparation ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
514
+ "span",
515
+ {
516
+ ref: elementRef,
517
+ className: `math-inline katex-inline ${className}`.trim(),
518
+ "data-tex": tex,
519
+ dangerouslySetInnerHTML: { __html: preparation.html }
520
+ }
521
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { ref: elementRef, className: `math-inline ${className}`.trim(), "data-tex": tex, children: [
522
+ "$",
523
+ tex,
524
+ "$"
525
+ ] });
526
+ };
527
+ KaTeXInlineMath.displayName = "KaTeXInlineMath";
528
+ var KaTeXBlockMath = ({ tex, className = "", fallback, engine }) => {
529
+ let elementRef = (0, import_react2.useRef)(null), preparation = useMathPreparation(tex, !0, elementRef, !engine);
530
+ return engine ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
531
+ "div",
532
+ {
533
+ className: `math-display markdown-math-display ${className}`.trim(),
534
+ "data-tex": tex,
535
+ style: { overflowX: "auto" },
536
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MathEngineOutputView, { engine, tex, displayMode: !0 })
537
+ }
538
+ ) : preparation && "error" in preparation && fallback ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback(tex, preparation.error) }) : preparation && "html" in preparation ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
539
+ "div",
540
+ {
541
+ ref: elementRef,
542
+ className: `math-display katex-block markdown-math-display ${className}`.trim(),
543
+ "data-tex": tex,
544
+ style: { overflowX: "auto" },
545
+ dangerouslySetInnerHTML: { __html: preparation.html }
546
+ }
547
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
548
+ "div",
549
+ {
550
+ ref: elementRef,
551
+ className: `math-display markdown-math-display ${className}`.trim(),
552
+ "data-tex": tex,
553
+ style: { overflowX: "auto" },
554
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "math-display-content", children: [
555
+ "$$",
556
+ tex,
557
+ "$$"
558
+ ] })
559
+ }
560
+ );
561
+ };
562
+ KaTeXBlockMath.displayName = "KaTeXBlockMath";
563
+
564
+ // src/components/controls.tsx
565
+ var import_react3 = __toESM(require("react"), 1), import_jsx_runtime4 = require("react/jsx-runtime"), DEFAULT_CONTROLS_LABELS = {
566
+ copy: "Copy code",
567
+ copied: "Copied!",
568
+ copyError: "Failed to copy",
569
+ download: "Download snippet",
570
+ downloadCsv: "Download CSV",
571
+ downloadTsv: "Download TSV",
572
+ downloadMarkdown: "Download Markdown",
573
+ copyTsv: "Copy TSV",
574
+ copyMarkdown: "Copy Markdown",
575
+ copyTable: "Copy table",
576
+ fullscreen: "Enter fullscreen",
577
+ exitFullscreen: "Exit fullscreen"
578
+ }, LANGUAGE_EXTENSION_MAP = {
579
+ javascript: "js",
580
+ js: "js",
581
+ mjs: "mjs",
582
+ cjs: "cjs",
583
+ typescript: "ts",
584
+ ts: "ts",
585
+ mts: "mts",
586
+ cts: "cts",
587
+ jsx: "jsx",
588
+ tsx: "tsx",
589
+ python: "py",
590
+ py: "py",
591
+ rust: "rs",
592
+ rs: "rs",
593
+ ruby: "rb",
594
+ rb: "rb",
595
+ go: "go",
596
+ golang: "go",
597
+ c: "c",
598
+ cpp: "cpp",
599
+ "c++": "cpp",
600
+ csharp: "cs",
601
+ "c#": "cs",
602
+ cs: "cs",
603
+ java: "java",
604
+ kotlin: "kt",
605
+ kt: "kt",
606
+ swift: "swift",
607
+ php: "php",
608
+ html: "html",
609
+ css: "css",
610
+ scss: "scss",
611
+ sass: "sass",
612
+ less: "less",
613
+ json: "json",
614
+ jsonc: "jsonc",
615
+ yaml: "yaml",
616
+ yml: "yaml",
617
+ toml: "toml",
618
+ xml: "xml",
619
+ svg: "svg",
620
+ markdown: "md",
621
+ md: "md",
622
+ mdx: "mdx",
623
+ sh: "sh",
624
+ bash: "sh",
625
+ shell: "sh",
626
+ zsh: "sh",
627
+ sql: "sql",
628
+ diff: "diff",
629
+ dockerfile: "dockerfile",
630
+ makefile: "makefile",
631
+ graphql: "graphql",
632
+ gql: "graphql",
633
+ lua: "lua",
634
+ r: "r",
635
+ scala: "scala",
636
+ perl: "pl",
637
+ pl: "pl",
638
+ mermaid: "mmd",
639
+ latex: "tex",
640
+ tex: "tex",
641
+ ini: "ini",
642
+ env: "env",
643
+ text: "txt",
644
+ txt: "txt"
645
+ };
646
+ function getExtensionForLanguage(lang) {
647
+ if (!lang) return "txt";
648
+ let clean = lang.trim().toLowerCase().split(/\s+/)[0] ?? "";
649
+ return clean ? LANGUAGE_EXTENSION_MAP[clean] ? LANGUAGE_EXTENSION_MAP[clean] : /^[a-z0-9]+$/.test(clean) ? clean : "txt" : "txt";
650
+ }
651
+ function getCodeSnippetFilename(lang) {
652
+ return `snippet.${getExtensionForLanguage(lang)}`;
653
+ }
654
+ async function copyToClipboard(text) {
655
+ if (typeof navigator > "u" || !navigator.clipboard?.writeText)
656
+ return !1;
657
+ try {
658
+ return await navigator.clipboard.writeText(text), !0;
659
+ } catch {
660
+ return !1;
661
+ }
662
+ }
663
+ function downloadFile(content, filename, mimeType = "text/plain;charset=utf-8") {
664
+ if (!(typeof window > "u" || typeof document > "u"))
665
+ try {
666
+ let blob = new Blob([content], { type: mimeType }), url = URL.createObjectURL(blob), a = document.createElement("a");
667
+ a.href = url, a.download = filename, a.style.display = "none", document.body.appendChild(a);
668
+ try {
669
+ a.click();
670
+ } finally {
671
+ document.body.removeChild(a), setTimeout(() => {
672
+ try {
673
+ URL.revokeObjectURL(url);
674
+ } catch {
675
+ }
676
+ }, 100);
249
677
  }
250
- /**
251
- * Safely evaluate compiled MDX code
252
- */
253
- evaluateCompiledMDX(compiled) {
254
- try {
255
- const context = this.createEvaluationContext();
256
- const argNames = Object.keys(context);
257
- const argValues = Object.values(context);
258
- const moduleExports = new Function(...argNames, compiled.code)(...argValues);
259
- const MDXComponent = this.resolveEvaluatedModule(moduleExports);
260
- return (props) => {
261
- const registryComponents = this.getComponents();
262
- const incomingComponents = props?.components;
263
- const mergedComponents = incomingComponents ? { ...registryComponents, ...incomingComponents } : registryComponents;
264
- return import_react2.default.createElement(MDXComponent, {
265
- ...props,
266
- components: mergedComponents
267
- });
268
- };
269
- } catch (error) {
270
- console.error("Failed to evaluate MDX:", error);
271
- return () => import_react2.default.createElement(
272
- "div",
273
- {
274
- className: "mdx-error"
275
- },
276
- `MDX Error: ${error instanceof Error ? error.message : "Unknown error"}`
277
- );
678
+ } catch {
679
+ }
680
+ }
681
+ function escapeCsvCell(cell) {
682
+ return /[",\r\n]/.test(cell) ? `"${cell.replace(/"/g, '""')}"` : cell;
683
+ }
684
+ function escapeTsvCell(cell) {
685
+ return cell.replace(/\t/g, " ").replace(/\r?\n/g, " ");
686
+ }
687
+ function tableToCsv(headers, rows) {
688
+ let lines = [];
689
+ headers.length > 0 && lines.push(headers.map(escapeCsvCell).join(","));
690
+ for (let row of rows)
691
+ lines.push(row.map(escapeCsvCell).join(","));
692
+ return lines.join(`
693
+ `);
694
+ }
695
+ function tableToTsv(headers, rows) {
696
+ let lines = [];
697
+ headers.length > 0 && lines.push(headers.map(escapeTsvCell).join(" "));
698
+ for (let row of rows)
699
+ lines.push(row.map(escapeTsvCell).join(" "));
700
+ return lines.join(`
701
+ `);
702
+ }
703
+ function tableToMarkdown(headers, rows, align) {
704
+ if (headers.length === 0 && rows.length === 0) return "";
705
+ let columnCount = Math.max(headers.length, ...rows.map((r) => r.length));
706
+ if (columnCount === 0) return "";
707
+ let padRow = (row) => {
708
+ let padded = [...row];
709
+ for (; padded.length < columnCount; ) padded.push("");
710
+ return padded.map((cell) => cell.replace(/\r?\n/g, " ").replace(/\|/g, "\\|"));
711
+ }, headerLine = `| ${padRow(headers.length > 0 ? headers : Array(columnCount).fill("")).join(" | ")} |`, separatorLine = `| ${Array.from({ length: columnCount }, (_, i) => {
712
+ let a = align?.[i];
713
+ return a === "center" ? ":---:" : a === "right" ? "---:" : a === "left" ? ":---" : "---";
714
+ }).join(" | ")} |`, dataLines = rows.map((row) => `| ${padRow(row).join(" | ")} |`);
715
+ return [headerLine, separatorLine, ...dataLines].join(`
716
+ `);
717
+ }
718
+ function inlineToPlainText(nodes) {
719
+ if (!Array.isArray(nodes) || nodes.length === 0) return "";
720
+ let out = "";
721
+ for (let node of nodes)
722
+ if (node)
723
+ switch (node.kind) {
724
+ case "text":
725
+ case "code":
726
+ out += node.text ?? "";
727
+ break;
728
+ case "strong":
729
+ case "em":
730
+ case "strike":
731
+ out += inlineToPlainText(node.children);
732
+ break;
733
+ case "link":
734
+ out += inlineToPlainText(node.children) || node.title || node.href || "";
735
+ break;
736
+ case "image":
737
+ out += node.alt || node.title || "";
738
+ break;
739
+ case "br":
740
+ out += `
741
+ `;
742
+ break;
743
+ case "html":
744
+ Array.isArray(node.children) && node.children.length > 0 ? out += inlineToPlainText(node.children) : node.raw && (/<br\s*\/?>/i.test(node.raw) ? out += `
745
+ ` : out += node.raw.replace(/<[^>]*>/g, ""));
746
+ break;
747
+ case "math-inline":
748
+ case "math-display":
749
+ out += node.tex ?? "";
750
+ break;
751
+ case "mention":
752
+ out += `@${node.handle ?? ""}`;
753
+ break;
754
+ case "citation":
755
+ out += `[${node.id ?? ""}]`;
756
+ break;
757
+ case "footnote-ref":
758
+ out += `[${node.label ?? ""}]`;
759
+ break;
760
+ case "plugin":
761
+ Array.isArray(node.children) ? out += inlineToPlainText(node.children) : out += node.raw ?? "";
762
+ break;
763
+ default: {
764
+ let generic = node;
765
+ generic && typeof generic == "object" && ("text" in generic && typeof generic.text == "string" ? out += generic.text : "children" in generic && Array.isArray(generic.children) && (out += inlineToPlainText(generic.children)));
766
+ break;
278
767
  }
279
768
  }
280
- /**
281
- * Create safe evaluation context for MDX
282
- */
283
- createEvaluationContext() {
284
- const runtime = ReactJsxRuntime;
285
- const createElementWithChildren = (type, props, key) => {
286
- const baseProps = props ?? {};
287
- const finalProps = key === void 0 || key === null ? baseProps : { ...baseProps, key };
288
- if (Array.isArray(finalProps.children)) {
289
- finalProps.children = finalProps.children.map((child, index) => assignMdxChildKey(child, index));
769
+ return out;
770
+ }
771
+ function resolveCodeControls(config) {
772
+ if (!config)
773
+ return { enabled: !1, copy: !1, download: !1, labels: DEFAULT_CONTROLS_LABELS };
774
+ let labels = {
775
+ ...DEFAULT_CONTROLS_LABELS,
776
+ ...typeof config == "object" ? config.labels : void 0
777
+ };
778
+ if (config === !0)
779
+ return { enabled: !0, copy: !0, download: !0, labels };
780
+ let codeOpt = config.code;
781
+ if (!codeOpt)
782
+ return { enabled: !1, copy: !1, download: !1, labels };
783
+ if (codeOpt === !0)
784
+ return { enabled: !0, copy: !0, download: !0, labels };
785
+ let copy = !!codeOpt.copy, download = !!codeOpt.download;
786
+ return { enabled: copy || download, copy, download, labels };
787
+ }
788
+ function resolveTableControls(config) {
789
+ if (!config)
790
+ return {
791
+ enabled: !1,
792
+ copy: !1,
793
+ copyFormats: [],
794
+ download: !1,
795
+ downloadFormats: [],
796
+ labels: DEFAULT_CONTROLS_LABELS
797
+ };
798
+ let labels = {
799
+ ...DEFAULT_CONTROLS_LABELS,
800
+ ...typeof config == "object" ? config.labels : void 0
801
+ };
802
+ if (config === !0)
803
+ return {
804
+ enabled: !0,
805
+ copy: !0,
806
+ copyFormats: ["tsv", "markdown"],
807
+ download: !0,
808
+ downloadFormats: ["csv"],
809
+ labels
810
+ };
811
+ let tableOpt = config.table;
812
+ if (!tableOpt)
813
+ return {
814
+ enabled: !1,
815
+ copy: !1,
816
+ copyFormats: [],
817
+ download: !1,
818
+ downloadFormats: [],
819
+ labels: DEFAULT_CONTROLS_LABELS
820
+ };
821
+ if (tableOpt === !0)
822
+ return {
823
+ enabled: !0,
824
+ copy: !0,
825
+ copyFormats: ["tsv", "markdown"],
826
+ download: !0,
827
+ downloadFormats: ["csv"],
828
+ labels
829
+ };
830
+ let copyVal = tableOpt.copy, copy = !!copyVal, copyFormats = Array.isArray(copyVal) ? copyVal : copyVal ? ["tsv", "markdown"] : [], downloadVal = tableOpt.download, download = !!downloadVal, downloadFormats = Array.isArray(downloadVal) ? downloadVal : downloadVal ? ["csv"] : [];
831
+ return {
832
+ enabled: copy || download,
833
+ copy,
834
+ copyFormats,
835
+ download,
836
+ downloadFormats,
837
+ labels
838
+ };
839
+ }
840
+ function resolveMermaidControls(config) {
841
+ if (!config)
842
+ return { enabled: !1, copy: !1, fullscreen: !1, labels: DEFAULT_CONTROLS_LABELS };
843
+ let labels = {
844
+ ...DEFAULT_CONTROLS_LABELS,
845
+ ...typeof config == "object" ? config.labels : void 0
846
+ };
847
+ if (config === !0)
848
+ return { enabled: !0, copy: !0, fullscreen: !1, labels };
849
+ let mermaidOpt = config.mermaid;
850
+ if (!mermaidOpt)
851
+ return { enabled: !1, copy: !1, fullscreen: !1, labels };
852
+ if (mermaidOpt === !0)
853
+ return { enabled: !0, copy: !0, fullscreen: !1, labels };
854
+ let copy = !!mermaidOpt.copy, fullscreen = !!mermaidOpt.fullscreen;
855
+ return { enabled: copy || fullscreen, copy, fullscreen, labels };
856
+ }
857
+ function resolveControlsConfig(config) {
858
+ return {
859
+ code: resolveCodeControls(config),
860
+ table: resolveTableControls(config),
861
+ mermaid: resolveMermaidControls(config)
862
+ };
863
+ }
864
+ var CodeControlsBar = ({ code, language, config, className }) => {
865
+ let [copied, setCopied] = (0, import_react3.useState)(!1), { labels } = config, handleCopy = (0, import_react3.useCallback)(async () => {
866
+ await copyToClipboard(code) && (setCopied(!0), setTimeout(() => setCopied(!1), 2e3));
867
+ }, [code]), handleDownload = (0, import_react3.useCallback)(() => {
868
+ let filename = getCodeSnippetFilename(language);
869
+ downloadFile(code, filename);
870
+ }, [code, language]);
871
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
872
+ "div",
873
+ {
874
+ className: `stream-mdx-controls stream-mdx-code-controls flex items-center justify-end gap-1 px-2 py-1 text-xs select-none ${className ?? ""}`.trim(),
875
+ "data-stream-mdx-controls": "code",
876
+ children: [
877
+ language ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "stream-mdx-code-language mr-auto text-muted-foreground opacity-60 text-[11px] font-mono", children: language }) : null,
878
+ config.copy ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
879
+ "button",
880
+ {
881
+ type: "button",
882
+ className: "stream-mdx-control stream-mdx-control-copy stream-mdx-control-code-copy inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs hover:bg-muted focus:outline-none",
883
+ "data-stream-mdx-control": "copy",
884
+ "data-stream-mdx-target": "code",
885
+ "data-stream-mdx-action": "copy",
886
+ "aria-label": copied ? labels.copied ?? "Copied!" : labels.copy ?? "Copy code",
887
+ onClick: handleCopy,
888
+ children: copied ? labels.copied ?? "Copied!" : labels.copy ?? "Copy"
290
889
  }
291
- return import_react2.default.createElement(type, finalProps);
292
- };
293
- const runtimeJsx = typeof runtime.jsx === "function" ? runtime.jsx.bind(runtime) : createElementWithChildren;
294
- const runtimeJsxs = typeof runtime.jsxs === "function" ? runtime.jsxs.bind(runtime) : createElementWithChildren;
295
- const runtimeJsxDEV = typeof runtime.jsxDEV === "function" ? runtime.jsxDEV.bind(runtime) : (type, props, key, ..._rest) => createElementWithChildren(type, props, key);
296
- const jsxRuntime = {
297
- jsx: runtimeJsx,
298
- jsxs: runtimeJsxs,
299
- jsxDEV: runtimeJsxDEV,
300
- Fragment: runtime.Fragment ?? import_react2.default.Fragment
301
- };
302
- return {
303
- __mdx_runtime: jsxRuntime,
304
- React: import_react2.default,
305
- Fragment: import_react2.default.Fragment,
306
- useState: import_react2.default.useState,
307
- useEffect: import_react2.default.useEffect,
308
- useMemo: import_react2.default.useMemo,
309
- useCallback: import_react2.default.useCallback,
310
- useRef: import_react2.default.useRef,
311
- useContext: import_react2.default.useContext,
312
- useReducer: import_react2.default.useReducer,
313
- useLayoutEffect: import_react2.default.useLayoutEffect,
314
- console: {
315
- log: console.log,
316
- warn: console.warn,
317
- error: console.error
890
+ ) : null,
891
+ config.download ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
892
+ "button",
893
+ {
894
+ type: "button",
895
+ className: "stream-mdx-control stream-mdx-control-download stream-mdx-control-code-download inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs hover:bg-muted focus:outline-none",
896
+ "data-stream-mdx-control": "download",
897
+ "data-stream-mdx-target": "code",
898
+ "data-stream-mdx-action": "download",
899
+ "aria-label": labels.download ?? "Download snippet",
900
+ onClick: handleDownload,
901
+ children: labels.download ?? "Download"
318
902
  }
319
- };
320
- }
321
- resolveEvaluatedModule(output) {
322
- if (!output) {
323
- throw new Error("Compiled MDX module returned no exports");
324
- }
325
- if (typeof output === "function") {
326
- return output;
327
- }
328
- if (typeof output.default === "function") {
329
- return output.default;
330
- }
331
- if (typeof output.MDXContent === "function") {
332
- return output.MDXContent;
903
+ ) : null
904
+ ]
905
+ }
906
+ );
907
+ }, TableControlsBar = ({
908
+ headers,
909
+ rows,
910
+ align,
911
+ getTableData,
912
+ getMarkdownSource,
913
+ isFinalized,
914
+ config,
915
+ className
916
+ }) => {
917
+ let [copiedFormat, setCopiedFormat] = (0, import_react3.useState)(null), copiedFeedbackTimeout = import_react3.default.useRef(void 0), mounted = import_react3.default.useRef(!0), { labels } = config;
918
+ import_react3.default.useEffect(() => (mounted.current = !0, () => {
919
+ mounted.current = !1, window.clearTimeout(copiedFeedbackTimeout.current);
920
+ }), []);
921
+ let handleCopy = (0, import_react3.useCallback)(
922
+ async (format) => {
923
+ if (!isFinalized) return;
924
+ let text;
925
+ if (format === "markdown") {
926
+ let source = getMarkdownSource?.();
927
+ if (source !== void 0)
928
+ text = source;
929
+ else {
930
+ let data = getTableData?.() ?? { headers, rows, align };
931
+ text = tableToMarkdown(data.headers, data.rows, data.align);
333
932
  }
334
- throw new Error("Compiled MDX module did not export a component");
933
+ } else {
934
+ let data = getTableData?.() ?? { headers, rows, align };
935
+ text = tableToTsv(data.headers, data.rows);
335
936
  }
336
- getComponents() {
337
- if (this.customComponents.size === 0) {
338
- return { ...this.baseComponents };
339
- }
340
- const merged = { ...this.baseComponents };
341
- for (const [key, component] of this.customComponents) {
342
- merged[key] = component;
343
- }
344
- return merged;
937
+ if (await copyToClipboard(text)) {
938
+ if (!mounted.current) return;
939
+ setCopiedFormat(format), window.clearTimeout(copiedFeedbackTimeout.current), copiedFeedbackTimeout.current = window.setTimeout(() => {
940
+ copiedFeedbackTimeout.current = void 0, setCopiedFormat(null);
941
+ }, 2e3);
345
942
  }
346
- /**
347
- * Register or replace custom MDX components
348
- */
349
- registerComponents(components, options) {
350
- if (options?.replace) {
351
- this.customComponents.clear();
352
- }
353
- for (const [key, component] of Object.entries(components)) {
354
- if (!component) continue;
355
- this.customComponents.set(key, component);
943
+ },
944
+ [headers, rows, align, getTableData, getMarkdownSource, isFinalized]
945
+ ), handleDownload = (0, import_react3.useCallback)(
946
+ (format) => {
947
+ if (!isFinalized) return;
948
+ let text = "", filename = "table.csv", mimeType = "text/csv;charset=utf-8";
949
+ if (format === "markdown") {
950
+ let source = getMarkdownSource?.();
951
+ if (source !== void 0)
952
+ text = source;
953
+ else {
954
+ let data = getTableData?.() ?? { headers, rows, align };
955
+ text = tableToMarkdown(data.headers, data.rows, data.align);
356
956
  }
957
+ filename = "table.md", mimeType = "text/markdown;charset=utf-8";
958
+ } else if (format === "tsv") {
959
+ let data = getTableData?.() ?? { headers, rows, align };
960
+ text = tableToTsv(data.headers, data.rows), filename = "table.tsv", mimeType = "text/tab-separated-values;charset=utf-8";
961
+ } else {
962
+ let data = getTableData?.() ?? { headers, rows, align };
963
+ text = tableToCsv(data.headers, data.rows);
357
964
  }
358
- /**
359
- * Get base MDX components
360
- */
361
- createBaseComponents() {
362
- return {
363
- // Standard HTML elements
364
- h1: withClassName("h1", "mdx-h1"),
365
- h2: withClassName("h2", "mdx-h2"),
366
- h3: withClassName("h3", "mdx-h3"),
367
- h4: withClassName("h4", "mdx-h4"),
368
- h5: withClassName("h5", "mdx-h5"),
369
- h6: withClassName("h6", "mdx-h6"),
370
- p: withClassName("p", "mdx-p"),
371
- strong: withClassName("strong", "mdx-strong"),
372
- em: withClassName("em", "mdx-em"),
373
- code: withClassName("code", "mdx-code"),
374
- pre: withClassName("pre", "mdx-pre"),
375
- ul: withClassName("ul", "mdx-ul"),
376
- ol: withClassName("ol", "mdx-ol"),
377
- li: withClassName("li", "mdx-li"),
378
- blockquote: withClassName("blockquote", "mdx-blockquote"),
379
- a: (props) => import_react2.default.createElement("a", {
380
- className: "mdx-link",
381
- target: props.href?.startsWith("http") ? "_blank" : void 0,
382
- rel: props.href?.startsWith("http") ? "noopener noreferrer" : void 0,
383
- ...props
384
- }),
385
- img: (props) => import_react2.default.createElement("img", { className: "mdx-img", ...props }),
386
- table: withClassName("table", "mdx-table"),
387
- thead: withClassName("thead", "mdx-thead"),
388
- tbody: withClassName("tbody", "mdx-tbody"),
389
- tr: withClassName("tr", "mdx-tr"),
390
- th: withClassName("th", "mdx-th"),
391
- td: withClassName("td", "mdx-td")
392
- };
393
- }
394
- /**
395
- * Clear component cache
396
- */
397
- clearCache() {
398
- this.components.clear();
399
- }
400
- clearCustomComponents() {
401
- this.customComponents.clear();
402
- }
403
- };
404
- globalMDXClient = null;
405
- globalComponentFactory = null;
965
+ downloadFile(text, filename, mimeType);
966
+ },
967
+ [headers, rows, align, getTableData, getMarkdownSource, isFinalized]
968
+ );
969
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
970
+ "div",
971
+ {
972
+ className: `stream-mdx-controls stream-mdx-table-controls flex items-center justify-end gap-1 px-2 py-1 text-xs select-none ${className ?? ""}`.trim(),
973
+ "data-stream-mdx-controls": "table",
974
+ children: [
975
+ config.copyFormats.map((format) => {
976
+ let isCopied = copiedFormat === format, defaultLabel = format === "markdown" ? "Copy Markdown" : "Copy TSV", labelText = format === "markdown" ? labels.copyMarkdown ?? defaultLabel : labels.copyTsv ?? defaultLabel;
977
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
978
+ "button",
979
+ {
980
+ type: "button",
981
+ disabled: !isFinalized,
982
+ className: `stream-mdx-control stream-mdx-control-copy stream-mdx-control-table-copy stream-mdx-control-copy-${format} inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs hover:bg-muted focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed`,
983
+ "data-stream-mdx-control": "copy",
984
+ "data-stream-mdx-target": "table",
985
+ "data-stream-mdx-format": format,
986
+ "data-stream-mdx-action": `copy-${format}`,
987
+ "data-format": format,
988
+ "aria-label": isCopied ? labels.copied ?? "Copied!" : labelText,
989
+ onClick: () => handleCopy(format),
990
+ children: isCopied ? labels.copied ?? "Copied!" : labelText
991
+ },
992
+ `copy-${format}`
993
+ );
994
+ }),
995
+ config.downloadFormats.map((format) => {
996
+ let defaultLabel = format === "csv" ? "Download CSV" : format === "tsv" ? "Download TSV" : "Download Markdown", labelText = format === "csv" ? labels.downloadCsv ?? defaultLabel : format === "tsv" ? labels.downloadTsv ?? defaultLabel : labels.downloadMarkdown ?? defaultLabel;
997
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
998
+ "button",
999
+ {
1000
+ type: "button",
1001
+ disabled: !isFinalized,
1002
+ className: `stream-mdx-control stream-mdx-control-download stream-mdx-control-table-download stream-mdx-control-download-${format} inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs hover:bg-muted focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed`,
1003
+ "data-stream-mdx-control": "download",
1004
+ "data-stream-mdx-target": "table",
1005
+ "data-stream-mdx-format": format,
1006
+ "data-stream-mdx-action": `download-${format}`,
1007
+ "data-format": format,
1008
+ "aria-label": labelText,
1009
+ onClick: () => handleDownload(format),
1010
+ children: labelText
1011
+ },
1012
+ `download-${format}`
1013
+ );
1014
+ })
1015
+ ]
1016
+ }
1017
+ );
1018
+ }, CodeBlockCopyButton = ({
1019
+ code,
1020
+ labels,
1021
+ className,
1022
+ ...props
1023
+ }) => {
1024
+ let [copied, setCopied] = (0, import_react3.useState)(!1), copyLabel = labels?.copy ?? DEFAULT_CONTROLS_LABELS.copy ?? "Copy code", copiedLabel = labels?.copied ?? DEFAULT_CONTROLS_LABELS.copied ?? "Copied!", handleCopy = (0, import_react3.useCallback)(
1025
+ async (e) => {
1026
+ if (props.onClick?.(e), e.defaultPrevented) return;
1027
+ await copyToClipboard(code) && (setCopied(!0), setTimeout(() => setCopied(!1), 2e3));
1028
+ },
1029
+ [code, props.onClick]
1030
+ );
1031
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1032
+ "button",
1033
+ {
1034
+ type: "button",
1035
+ className: `stream-mdx-control stream-mdx-control-copy stream-mdx-control-code-copy ${className ?? ""}`.trim(),
1036
+ "data-stream-mdx-control": "copy",
1037
+ "data-stream-mdx-target": "code",
1038
+ "data-stream-mdx-action": "copy",
1039
+ "aria-label": copied ? copiedLabel : copyLabel,
1040
+ ...props,
1041
+ onClick: handleCopy,
1042
+ children: props.children ?? (copied ? copiedLabel : "Copy")
1043
+ }
1044
+ );
1045
+ }, CodeBlockDownloadButton = ({
1046
+ code,
1047
+ language,
1048
+ filename,
1049
+ labels,
1050
+ className,
1051
+ ...props
1052
+ }) => {
1053
+ let downloadLabel = labels?.download ?? DEFAULT_CONTROLS_LABELS.download ?? "Download snippet", handleDownload = (0, import_react3.useCallback)(
1054
+ (e) => {
1055
+ if (props.onClick?.(e), e.defaultPrevented) return;
1056
+ let targetFilename = filename ?? getCodeSnippetFilename(language);
1057
+ downloadFile(code, targetFilename);
1058
+ },
1059
+ [code, language, filename, props.onClick]
1060
+ );
1061
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1062
+ "button",
1063
+ {
1064
+ type: "button",
1065
+ className: `stream-mdx-control stream-mdx-control-download stream-mdx-control-code-download ${className ?? ""}`.trim(),
1066
+ "data-stream-mdx-control": "download",
1067
+ "data-stream-mdx-target": "code",
1068
+ "data-stream-mdx-action": "download",
1069
+ "aria-label": downloadLabel,
1070
+ ...props,
1071
+ onClick: handleDownload,
1072
+ children: props.children ?? labels?.download ?? "Download"
1073
+ }
1074
+ );
1075
+ };
1076
+
1077
+ // src/animation.ts
1078
+ var BUILTIN_ANIMATION_NAMES = {
1079
+ fadeIn: "stream-mdx-fade-in",
1080
+ blurIn: "stream-mdx-blur-in",
1081
+ slideUp: "stream-mdx-slide-up"
1082
+ }, DEFAULT_ANIMATED_OPTIONS = {
1083
+ animation: "fadeIn",
1084
+ animationName: "stream-mdx-fade-in",
1085
+ duration: 150,
1086
+ durationStr: "150ms",
1087
+ easing: "ease-out",
1088
+ sep: "word",
1089
+ stagger: 20,
1090
+ maxBacklogMs: 320
1091
+ };
1092
+ function resolveAnimatedOptions(prop) {
1093
+ if (!prop) return null;
1094
+ if (prop === !0) return DEFAULT_ANIMATED_OPTIONS;
1095
+ let animation = prop.animation ?? DEFAULT_ANIMATED_OPTIONS.animation, duration = typeof prop.duration == "number" ? prop.duration : DEFAULT_ANIMATED_OPTIONS.duration;
1096
+ return {
1097
+ animation,
1098
+ animationName: BUILTIN_ANIMATION_NAMES[animation] ?? animation,
1099
+ duration,
1100
+ durationStr: `${duration}ms`,
1101
+ easing: prop.easing ?? DEFAULT_ANIMATED_OPTIONS.easing,
1102
+ sep: prop.sep ?? DEFAULT_ANIMATED_OPTIONS.sep,
1103
+ stagger: typeof prop.stagger == "number" ? prop.stagger : DEFAULT_ANIMATED_OPTIONS.stagger,
1104
+ maxBacklogMs: typeof prop.maxBacklogMs == "number" ? prop.maxBacklogMs : DEFAULT_ANIMATED_OPTIONS.maxBacklogMs
1105
+ };
1106
+ }
1107
+ var STREAM_MDX_ANIMATION_CSS = `
1108
+ @keyframes stream-mdx-fade-in {
1109
+ from {
1110
+ opacity: 0;
406
1111
  }
407
- });
1112
+ to {
1113
+ opacity: 1;
1114
+ }
1115
+ }
408
1116
 
409
- // src/components/index.ts
410
- var components_exports = {};
411
- __export(components_exports, {
412
- ComponentRegistry: () => ComponentRegistry,
413
- DefaultLinkSafetyModal: () => DefaultLinkSafetyModal,
414
- defaultBlockComponents: () => defaultBlockComponents,
415
- defaultInlineComponents: () => defaultInlineComponents,
416
- mapHtmlToReact: () => mapHtmlToReact,
417
- renderInlineNodes: () => renderInlineNodes,
418
- renderParagraphMixedSegments: () => renderParagraphMixedSegments
419
- });
420
- module.exports = __toCommonJS(components_exports);
421
- var import_core = require("@stream-mdx/core");
1117
+ @keyframes fadeIn {
1118
+ from {
1119
+ opacity: 0;
1120
+ }
1121
+ to {
1122
+ opacity: 1;
1123
+ }
1124
+ }
1125
+
1126
+ @keyframes stream-mdx-blur-in {
1127
+ from {
1128
+ opacity: 0;
1129
+ filter: blur(4px);
1130
+ }
1131
+ to {
1132
+ opacity: 1;
1133
+ filter: blur(0px);
1134
+ }
1135
+ }
422
1136
 
423
- // src/mdx-hydration-metrics.ts
424
- var entries = /* @__PURE__ */ new Map();
425
- var lastHydrationMs = null;
426
- function now() {
427
- if (typeof performance !== "undefined" && typeof performance.now === "function") {
428
- return performance.now();
429
- }
430
- return Date.now();
431
- }
432
- function markMdxHydrationStart(id) {
433
- if (!id) return;
434
- const entry = entries.get(id) ?? { status: "compiled" };
435
- if (entry.startedAt === void 0) {
436
- entry.startedAt = now();
437
- }
438
- entry.status = "compiled";
439
- entries.set(id, entry);
440
- }
441
- function markMdxHydrated(id) {
442
- if (!id) return;
443
- const entry = entries.get(id) ?? { status: "hydrated" };
444
- if (entry.startedAt === void 0) {
445
- entry.startedAt = now();
446
- }
447
- entry.hydratedAt = now();
448
- entry.status = "hydrated";
449
- entries.set(id, entry);
450
- lastHydrationMs = entry.startedAt ? entry.hydratedAt - entry.startedAt : null;
451
- }
452
- function markMdxHydrationError(id) {
453
- if (!id) return;
454
- const entry = entries.get(id) ?? { status: "error" };
455
- entry.status = "error";
456
- entries.set(id, entry);
1137
+ @keyframes blurIn {
1138
+ from {
1139
+ opacity: 0;
1140
+ filter: blur(4px);
1141
+ }
1142
+ to {
1143
+ opacity: 1;
1144
+ filter: blur(0px);
1145
+ }
457
1146
  }
458
1147
 
459
- // src/mdx-hydration-context.ts
460
- var import_react = __toESM(require("react"), 1);
461
- var MdxHydrationContext = import_react.default.createContext({ controller: null });
1148
+ @keyframes stream-mdx-slide-up {
1149
+ from {
1150
+ opacity: 0;
1151
+ transform: translateY(4px);
1152
+ }
1153
+ to {
1154
+ opacity: 1;
1155
+ transform: translateY(0);
1156
+ }
1157
+ }
462
1158
 
463
- // src/mdx-runtime.ts
464
- var mdxRuntimePromise = null;
465
- function loadMdxRuntime() {
466
- if (!mdxRuntimePromise) {
467
- mdxRuntimePromise = Promise.resolve().then(() => (init_mdx_client(), mdx_client_exports));
1159
+ @keyframes slideUp {
1160
+ from {
1161
+ opacity: 0;
1162
+ transform: translateY(4px);
1163
+ }
1164
+ to {
1165
+ opacity: 1;
1166
+ transform: translateY(0);
468
1167
  }
469
- return mdxRuntimePromise;
470
1168
  }
471
1169
 
472
- // src/renderer/use-deferred-render.ts
473
- var import_react3 = require("react");
474
- function useDeferredRender(ref, options) {
475
- const enabled = options?.enabled ?? true;
476
- const [shouldRender, setShouldRender] = (0, import_react3.useState)(!enabled);
477
- (0, import_react3.useEffect)(() => {
478
- if (!enabled) {
479
- setShouldRender(true);
480
- return;
481
- }
482
- const target = ref.current;
483
- if (!target) {
484
- return;
485
- }
486
- let cancelled = false;
487
- let idleId = null;
488
- let timerId = null;
489
- const scheduleRender = () => {
490
- if (cancelled) return;
491
- setShouldRender(true);
492
- };
493
- const runWithIdle = () => {
494
- if (typeof globalThis.requestIdleCallback === "function") {
495
- idleId = globalThis.requestIdleCallback(scheduleRender, { timeout: options?.idleTimeoutMs ?? 200 });
496
- } else {
497
- timerId = window.setTimeout(scheduleRender, options?.idleTimeoutMs ?? 200);
498
- }
499
- };
500
- const observer = new IntersectionObserver(
501
- (entries2) => {
502
- for (const entry of entries2) {
503
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
504
- observer.disconnect();
505
- const debounceMs = options?.debounceMs ?? 80;
506
- timerId = window.setTimeout(runWithIdle, debounceMs);
507
- return;
508
- }
509
- }
510
- },
511
- { rootMargin: options?.rootMargin ?? "200px 0px" }
512
- );
513
- observer.observe(target);
514
- return () => {
515
- cancelled = true;
516
- observer.disconnect();
517
- if (idleId !== null && typeof globalThis.cancelIdleCallback === "function") {
518
- globalThis.cancelIdleCallback(idleId);
519
- }
520
- if (timerId !== null) {
521
- window.clearTimeout(timerId);
1170
+ .stream-mdx-anim {
1171
+ display: inline;
1172
+ animation-name: var(--sm-anim-name, stream-mdx-fade-in);
1173
+ animation-duration: var(--sm-anim-duration, 150ms);
1174
+ animation-timing-function: var(--sm-anim-easing, ease-out);
1175
+ animation-delay: var(--sm-anim-delay, 0ms);
1176
+ animation-fill-mode: both;
1177
+ }
1178
+
1179
+ @media (prefers-reduced-motion: reduce) {
1180
+ .stream-mdx-anim {
1181
+ animation: none !important;
1182
+ }
1183
+ }
1184
+ `.trim(), WHITESPACE_REGEX = /\s/;
1185
+ function splitWordSegments(text) {
1186
+ let result = [], current = "", inWhitespace = !1;
1187
+ for (let char of text) {
1188
+ let isSpace = WHITESPACE_REGEX.test(char);
1189
+ if (isSpace !== inWhitespace && current) {
1190
+ if (isSpace) {
1191
+ current += char, inWhitespace = !0;
1192
+ continue;
522
1193
  }
523
- };
524
- }, [enabled, options?.debounceMs, options?.idleTimeoutMs, options?.rootMargin, ref]);
525
- return shouldRender;
1194
+ result.push(current), current = "";
1195
+ }
1196
+ current += char, inWhitespace = isSpace;
1197
+ }
1198
+ return current && result.push(current), result;
526
1199
  }
1200
+ function splitTextSegments(text, sep) {
1201
+ return sep === "char" ? Array.from(text) : splitWordSegments(text);
1202
+ }
1203
+ var AnimationTimeline = class {
1204
+ constructor(options) {
1205
+ this.committedEndTime = 0;
1206
+ this.cursorEndTime = 0;
1207
+ this.passActive = !1;
1208
+ this.nodeStates = /* @__PURE__ */ new Map();
1209
+ this.now = options?.now ?? (() => typeof performance < "u" ? performance.now() : Date.now()), this.maxBacklogMs = options?.maxBacklogMs ?? 320, this.stagger = options?.stagger ?? 20;
1210
+ }
1211
+ updateOptions(options) {
1212
+ typeof options.maxBacklogMs == "number" && (this.maxBacklogMs = options.maxBacklogMs), typeof options.stagger == "number" && (this.stagger = options.stagger);
1213
+ }
1214
+ beginPass(currentTime = this.now()) {
1215
+ this.passActive || (this.passActive = !0, this.cursorEndTime = Math.min(
1216
+ Math.max(this.committedEndTime, currentTime),
1217
+ currentTime + this.maxBacklogMs
1218
+ ), typeof queueMicrotask == "function" ? queueMicrotask(() => this.commitPass()) : setTimeout(() => this.commitPass(), 0));
1219
+ }
1220
+ commitPass() {
1221
+ this.committedEndTime = this.cursorEndTime, this.passActive = !1;
1222
+ }
1223
+ schedule(count, stagger = this.stagger, currentTime = this.now()) {
1224
+ if (this.beginPass(currentTime), count <= 0) return [];
1225
+ let d = Math.max(0, stagger), maxDeadline = currentTime + this.maxBacklogMs, start = Math.min(Math.max(this.cursorEndTime, currentTime), maxDeadline), step = count > 1 ? Math.min(d, Math.max(0, maxDeadline - start) / (count - 1)) : d, baseDelay = Math.max(0, start - currentTime);
1226
+ this.cursorEndTime = Math.min(start + count * step, maxDeadline);
1227
+ let delays = [];
1228
+ for (let i = 0; i < count; i++)
1229
+ delays.push(Math.min(this.maxBacklogMs, Math.round(baseDelay + i * step)));
1230
+ return delays;
1231
+ }
1232
+ getNodeState(key) {
1233
+ let state = this.nodeStates.get(key);
1234
+ return state || (state = { count: 0, delays: [] }, this.nodeStates.set(key, state)), state;
1235
+ }
1236
+ reset() {
1237
+ this.committedEndTime = 0, this.cursorEndTime = 0, this.passActive = !1, this.nodeStates.clear();
1238
+ }
1239
+ releasePrefix(prefix) {
1240
+ let prefixColon = `${prefix}:`;
1241
+ for (let key of this.nodeStates.keys())
1242
+ (key === prefix || key.startsWith(prefixColon)) && this.nodeStates.delete(key);
1243
+ }
1244
+ };
527
1245
 
528
1246
  // src/components/index.ts
529
- var import_core2 = require("@stream-mdx/core");
530
- var import_react5 = __toESM(require("react"), 1);
1247
+ var import_core3 = require("@stream-mdx/core"), import_core4 = require("@stream-mdx/core"), import_core5 = require("@stream-mdx/core"), import_react11 = __toESM(require("react"), 1);
531
1248
 
532
1249
  // src/utils/inline-html.ts
533
- var import_react4 = __toESM(require("react"), 1);
534
- var BACKTICK_CONTENT = /^`([\s\S]+)`$/;
535
- var DEFAULT_INLINE_HTML_RENDERERS = {
1250
+ var import_react4 = __toESM(require("react"), 1), import_core = require("@stream-mdx/core");
1251
+ function renderHtmlInlineNode(node, children, elements, key, textValue, urlTransform, filterElement, parentTagName, renderPresentation, renderNativeElement) {
1252
+ if (node.isClose || node.tagName === "script" || node.tagName === "style") return null;
1253
+ if (!node.tagName || node.sanitized === "")
1254
+ return import_react4.default.createElement(import_react4.default.Fragment, { key }, children);
1255
+ let tag = node.tagName.toLowerCase(), props = mapAttributesToProps(node.attributes ?? {}, urlTransform);
1256
+ props.key = key;
1257
+ let renderElement = () => {
1258
+ let nativeView;
1259
+ return renderNativeElement ? nativeView = renderNativeElement(
1260
+ tag,
1261
+ props,
1262
+ node.isSelfClosing ? void 0 : children,
1263
+ key ?? tag
1264
+ ) : tag === "textarea" ? (props.defaultValue = textValue ?? "", nativeView = import_react4.default.createElement(elements?.[tag] ?? tag, props)) : nativeView = import_react4.default.createElement(elements?.[tag] ?? tag, props, node.isSelfClosing ? void 0 : children), renderPresentation ? renderPresentation(tag, props, nativeView, children, key ?? tag) : nativeView;
1265
+ };
1266
+ return filterElement ? filterElement(
1267
+ { tagName: tag, properties: props },
1268
+ { source: "html", parentTagName },
1269
+ renderElement,
1270
+ () => children
1271
+ ) : renderElement();
1272
+ }
1273
+ function renderHtmlOwnershipTree(nodes, elements, renderBlock, renderInline, renderInlineElement, renderParagraph, urlTransform, filterElement, parentTagName, contentComponents, renderPresentation, parentPath = "html", renderComponentPresentation) {
1274
+ return nodes.map((node, index) => {
1275
+ let nodeKey = `${parentPath}:${index}`;
1276
+ if (node.kind === "text") return node.inline && renderInline ? renderInline(node.inline, parentTagName) : node.rawSource ?? node.text;
1277
+ if (node.kind === "block") return renderBlock(node.block, parentTagName);
1278
+ if (node.kind === "component") {
1279
+ let reg = contentComponents?.[node.name];
1280
+ if (!reg)
1281
+ return import_react4.default.createElement(import_react4.default.Fragment, { key: nodeKey }, node.rawSource ?? `<${node.name} />`);
1282
+ let result = reg.render({
1283
+ props: node.props,
1284
+ key: index,
1285
+ hasChildren: node.children.length > 0,
1286
+ renderChildren: () => renderHtmlOwnershipTree(
1287
+ node.children,
1288
+ elements,
1289
+ renderBlock,
1290
+ renderInline,
1291
+ renderInlineElement,
1292
+ renderParagraph,
1293
+ urlTransform,
1294
+ filterElement,
1295
+ node.name,
1296
+ contentComponents,
1297
+ renderPresentation,
1298
+ nodeKey,
1299
+ renderComponentPresentation
1300
+ ),
1301
+ status: node.status,
1302
+ diagnostic: node.diagnostic
1303
+ });
1304
+ return result.kind === "invalid" ? import_react4.default.createElement(import_react4.default.Fragment, { key: nodeKey }, node.rawSource ?? `<${node.name} />`) : result.kind === "suppressed" ? null : renderComponentPresentation ? renderComponentPresentation(
1305
+ node.name,
1306
+ result.element,
1307
+ import_react4.default.isValidElement(result.element) ? result.element.props.children : void 0,
1308
+ nodeKey,
1309
+ node.status,
1310
+ node.rawSource
1311
+ ) : result.element;
1312
+ }
1313
+ let tag = node.tagName.toLowerCase(), props = mapAttributesToProps(node.attributes, urlTransform);
1314
+ props.key = nodeKey;
1315
+ let children = renderHtmlOwnershipTree(node.children, elements, renderBlock, renderInline, renderInlineElement, renderParagraph, urlTransform, filterElement, tag, contentComponents, renderPresentation, nodeKey, renderComponentPresentation);
1316
+ if (node.paragraphRoot && renderParagraph) {
1317
+ let paragraph = filterElement ? filterElement(
1318
+ { tagName: "p", properties: props, blockType: "paragraph" },
1319
+ { source: "markdown", parentTagName },
1320
+ () => renderParagraph(children),
1321
+ () => children
1322
+ ) : renderParagraph(children);
1323
+ return import_react4.default.createElement(import_react4.default.Fragment, { key: nodeKey }, paragraph);
1324
+ }
1325
+ if (node.inlineNode && renderInlineElement)
1326
+ return import_react4.default.createElement(import_react4.default.Fragment, { key: nodeKey }, renderInlineElement(node.inlineNode, children, parentTagName, nodeKey));
1327
+ let renderElement = () => {
1328
+ let nativeView;
1329
+ if (tag === "textarea")
1330
+ props.defaultValue = node.children.map((child) => child.kind === "text" ? child.text : "").join(""), nativeView = import_react4.default.createElement(elements[tag] ?? tag, props);
1331
+ else {
1332
+ let content = tag === "pre" && node.children.every((child) => child.kind === "text" && !child.inline) ? node.children.map((child) => child.kind === "text" ? child.text : "").join("") : children;
1333
+ nativeView = import_react4.default.createElement(elements[tag] ?? tag, props, node.children.length ? content : void 0);
1334
+ }
1335
+ return renderPresentation ? renderPresentation(tag, props, nativeView, children, nodeKey) : nativeView;
1336
+ };
1337
+ return filterElement ? filterElement(
1338
+ { tagName: tag, properties: props },
1339
+ { source: "html", parentTagName },
1340
+ renderElement,
1341
+ () => children
1342
+ ) : renderElement();
1343
+ });
1344
+ }
1345
+ var BACKTICK_CONTENT = /^`([\s\S]+)`$/, DEFAULT_INLINE_HTML_RENDERERS = {
536
1346
  kbd: (descriptor, ctx) => {
537
- const trimmed = descriptor.rawInner.trim();
538
- const match = BACKTICK_CONTENT.exec(trimmed);
1347
+ let trimmed = descriptor.rawInner.trim(), match = BACKTICK_CONTENT.exec(trimmed);
539
1348
  if (match) {
540
- const codeText = decodeHtmlEntities(match[1]);
541
- const props = mapAttributesToProps(descriptor.attributes);
542
- if (ctx.key !== void 0 && ctx.key !== null) {
543
- props.key = ctx.key;
544
- }
545
- return import_react4.default.createElement("kbd", props, import_react4.default.createElement("code", { className: "inline-code" }, codeText));
1349
+ let codeText = decodeHtmlEntities(match[1]), props = mapAttributesToProps(descriptor.attributes);
1350
+ return ctx.key !== void 0 && ctx.key !== null && (props.key = ctx.key), import_react4.default.createElement("kbd", props, import_react4.default.createElement("code", { className: "inline-code" }, codeText));
546
1351
  }
547
1352
  return ctx.defaultRender();
548
1353
  }
549
1354
  };
550
1355
  function renderInlineHtmlSegment(raw, sanitized, options = {}) {
551
- const descriptor = parseInlineHtmlDescriptor(raw, sanitized);
552
- if (!descriptor) {
1356
+ let descriptor = parseInlineHtmlDescriptor(raw, sanitized);
1357
+ if (!descriptor)
553
1358
  return null;
554
- }
555
- const className = options.className ?? "markdown-inline-html";
556
- const isInlineTag = INLINE_ELEMENTS.has(descriptor.tagName);
557
- const defaultRender = () => {
558
- if (!descriptor.sanitized || descriptor.sanitized.length === 0) {
559
- if (!descriptor.text) {
560
- return null;
561
- }
562
- if (options.key !== void 0 && options.key !== null) {
563
- return import_react4.default.createElement(import_react4.default.Fragment, { key: options.key }, descriptor.text);
564
- }
565
- return import_react4.default.createElement(import_react4.default.Fragment, {}, descriptor.text);
566
- }
1359
+ let className = options.className ?? "markdown-inline-html", hasCustomElement = !!options.htmlElements?.[descriptor.tagName], isInlineTag = INLINE_ELEMENTS.has(descriptor.tagName) || hasCustomElement, defaultRender = () => {
1360
+ if (!descriptor.sanitized || descriptor.sanitized.length === 0)
1361
+ return descriptor.text ? options.key !== void 0 && options.key !== null ? import_react4.default.createElement(import_react4.default.Fragment, { key: options.key }, descriptor.text) : import_react4.default.createElement(import_react4.default.Fragment, {}, descriptor.text) : null;
567
1362
  if (isInlineTag) {
568
- const parsedElement = renderSanitizedHtmlTree(descriptor.sanitized, options.key);
569
- if (parsedElement) {
1363
+ let parsedElement = renderSanitizedHtmlTree(
1364
+ descriptor.sanitized,
1365
+ options.key,
1366
+ options.htmlElements,
1367
+ options.literalTagContent,
1368
+ options.parseMarkdown
1369
+ );
1370
+ if (parsedElement)
570
1371
  return parsedElement;
571
- }
572
1372
  }
573
- const props = {
1373
+ let customElementComp = options.htmlElements?.[descriptor.tagName];
1374
+ if (customElementComp) {
1375
+ let props2 = mapAttributesToProps(descriptor.attributes, options.urlTransform);
1376
+ return options.key !== void 0 && options.key !== null && (props2.key = options.key), import_react4.default.createElement(customElementComp, props2, descriptor.text || descriptor.sanitizedInner || void 0);
1377
+ }
1378
+ let props = {
574
1379
  className,
575
1380
  dangerouslySetInnerHTML: { __html: descriptor.sanitized }
576
1381
  };
577
- if (options.key !== void 0 && options.key !== null) {
578
- props.key = options.key;
579
- }
580
- return import_react4.default.createElement("span", props);
1382
+ return options.key !== void 0 && options.key !== null && (props.key = options.key), import_react4.default.createElement("span", props);
581
1383
  };
582
- const allRenderers = options.renderers ? { ...DEFAULT_INLINE_HTML_RENDERERS, ...options.renderers } : DEFAULT_INLINE_HTML_RENDERERS;
583
- const renderer = allRenderers[descriptor.tagName];
584
- if (renderer) {
585
- const rendered = renderer(descriptor, { key: options.key, defaultRender });
586
- if (rendered) {
587
- if (options.key !== void 0 && options.key !== null && import_react4.default.isValidElement(rendered) && rendered.key === null) {
588
- return import_react4.default.cloneElement(rendered, { key: options.key });
589
- }
590
- return rendered;
1384
+ if (!hasCustomElement) {
1385
+ let renderer = (options.renderers ? { ...DEFAULT_INLINE_HTML_RENDERERS, ...options.renderers } : DEFAULT_INLINE_HTML_RENDERERS)[descriptor.tagName];
1386
+ if (renderer) {
1387
+ let rendered = renderer(descriptor, { key: options.key, defaultRender });
1388
+ if (rendered)
1389
+ return options.key !== void 0 && options.key !== null && import_react4.default.isValidElement(rendered) && rendered.key === null ? import_react4.default.cloneElement(rendered, { key: options.key }) : rendered;
591
1390
  }
592
1391
  }
593
1392
  return defaultRender();
594
1393
  }
595
1394
  function parseInlineHtmlDescriptor(raw, sanitized) {
596
- const normalizedRaw = typeof raw === "string" ? raw.trim() : "";
597
- const normalizedSanitized = typeof sanitized === "string" && sanitized.length > 0 ? sanitized.trim() : normalizedRaw;
598
- if (!normalizedSanitized) {
599
- return null;
600
- }
601
- const match = normalizedSanitized.match(/^<([A-Za-z][\w:-]*)(\s[^>]*)?>([\s\S]*)<\/\1>$/);
602
- if (!match) {
1395
+ let normalizedRaw = typeof raw == "string" ? raw.trim() : "", normalizedSanitized = typeof sanitized == "string" && sanitized.length > 0 ? sanitized.trim() : normalizedRaw;
1396
+ if (!normalizedSanitized)
603
1397
  return null;
1398
+ let pairedMatch = normalizedSanitized.match(/^<([A-Za-z][\w:-]*)((?:\s+[^>]*)?)>([\s\S]*)<\/\1>$/), tagNameRaw, attrString = "", sanitizedInner = "";
1399
+ if (pairedMatch)
1400
+ tagNameRaw = pairedMatch[1], attrString = pairedMatch[2] ?? "", sanitizedInner = pairedMatch[3] ?? "";
1401
+ else {
1402
+ let selfClosingMatch = normalizedSanitized.match(/^<([A-Za-z][\w:-]*)((?:\s+[^>]*)?)\s*(?:\/?>|>)$/) || normalizedRaw.match(/^<([A-Za-z][\w:-]*)((?:\s+[^>]*)?)\s*(?:\/?>|>)$/);
1403
+ if (!selfClosingMatch)
1404
+ return null;
1405
+ tagNameRaw = selfClosingMatch[1], attrString = selfClosingMatch[2] ?? "", sanitizedInner = "";
604
1406
  }
605
- const [, tagNameRaw, attrString = "", sanitizedInner = ""] = match;
606
- const tagName = tagNameRaw.toLowerCase();
607
- const attributes = parseAttributes(attrString);
608
- let rawInner = "";
1407
+ let tagName = tagNameRaw.toLowerCase(), attributes = parseAttributes(attrString), rawInner = "";
609
1408
  if (normalizedRaw) {
610
- const rawMatch = normalizedRaw.match(/^<([A-Za-z][\w:-]*)(\s[^>]*)?>([\s\S]*)<\/\1>$/);
1409
+ let rawMatch = normalizedRaw.match(/^<([A-Za-z][\w:-]*)(\s[^>]*)?>([\s\S]*)<\/\1>$/);
611
1410
  rawInner = rawMatch ? rawMatch[3] ?? "" : normalizedRaw;
612
1411
  }
613
- const text = extractPlainText(rawInner || sanitizedInner);
1412
+ let text = extractPlainText(rawInner || sanitizedInner);
614
1413
  return {
615
1414
  tagName,
616
1415
  attributes,
@@ -622,52 +1421,91 @@ function parseInlineHtmlDescriptor(raw, sanitized) {
622
1421
  };
623
1422
  }
624
1423
  function parseAttributes(input) {
625
- const attrs = {};
1424
+ let attrs = {};
626
1425
  if (!input) return attrs;
627
- const attrPattern = /([A-Za-z_:][\w:.\-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
628
- let match = attrPattern.exec(input);
629
- while (match !== null) {
630
- const name = match[1];
1426
+ let attrPattern = /([A-Za-z_:][\w:.\-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g, match = attrPattern.exec(input);
1427
+ for (; match !== null; ) {
1428
+ let name = match[1];
631
1429
  if (!name) continue;
632
- const value = match[2] ?? match[3] ?? match[4] ?? "";
633
- attrs[name] = value;
634
- match = attrPattern.exec(input);
1430
+ let value = match[2] ?? match[3] ?? match[4] ?? "";
1431
+ attrs[name] = value, match = attrPattern.exec(input);
635
1432
  }
636
1433
  return attrs;
637
1434
  }
638
- function mapAttributesToProps(attrs) {
639
- const props = {};
640
- for (const [key, value] of Object.entries(attrs)) {
641
- if (key === "class") {
642
- props.className = value;
643
- } else if (key === "style") {
644
- props.style = parseStyleAttribute(value);
645
- } else if (key === "tabindex" || key === "tabIndex") {
646
- const normalized = normalizeTabIndex(value);
647
- if (normalized !== void 0) {
648
- props.tabIndex = normalized;
649
- }
650
- } else {
651
- props[key] = value;
652
- }
1435
+ var BOOLEAN_HTML_PROPS = {
1436
+ allowFullScreen: !0,
1437
+ async: !0,
1438
+ autoFocus: !0,
1439
+ autoPlay: !0,
1440
+ checked: !0,
1441
+ controls: !0,
1442
+ default: !0,
1443
+ defer: !0,
1444
+ disabled: !0,
1445
+ formNoValidate: !0,
1446
+ hidden: !0,
1447
+ inert: !0,
1448
+ loop: !0,
1449
+ multiple: !0,
1450
+ muted: !0,
1451
+ noModule: !0,
1452
+ noValidate: !0,
1453
+ open: !0,
1454
+ playsInline: !0,
1455
+ readOnly: !0,
1456
+ required: !0,
1457
+ reversed: !0,
1458
+ selected: !0,
1459
+ itemScope: !0
1460
+ };
1461
+ function mapAttributesToProps(attrs, urlTransform) {
1462
+ let props = {}, transform = urlTransform ?? import_core.defaultUrlTransform;
1463
+ for (let [key, value] of Object.entries(attrs)) {
1464
+ let lower = key.toLowerCase();
1465
+ if (!(0, import_core.isForbiddenAttribute)(lower))
1466
+ if (key === "class")
1467
+ props.className = value;
1468
+ else if (key === "style")
1469
+ props.style = parseStyleAttribute(value);
1470
+ else if (key === "tabindex" || key === "tabIndex") {
1471
+ let normalized = normalizeTabIndex(value);
1472
+ normalized !== void 0 && (props.tabIndex = normalized);
1473
+ } else if (lower === "href") {
1474
+ let safe = transform(value, "href", { source: "html" });
1475
+ safe != null && (props.href = safe);
1476
+ } else if (lower === "src") {
1477
+ let safe = transform(value, "src", { source: "html" });
1478
+ safe != null && (props.src = safe);
1479
+ } else if (lower === "action") {
1480
+ let safe = transform(value, "href", { source: "html" });
1481
+ safe != null && (props.action = safe);
1482
+ } else if (lower === "formaction") {
1483
+ let safe = transform(value, "href", { source: "html" });
1484
+ safe != null && (props.formAction = safe);
1485
+ } else if (lower === "xlink:href" || lower === "xlinkhref") {
1486
+ let safe = transform(value, "href", { source: "html" });
1487
+ safe != null && (props.xlinkHref = safe);
1488
+ } else /^(?:data|aria)[A-Z]/.test(key) ? props[key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)] = value : BOOLEAN_HTML_PROPS[key] ? props[key] = !0 : props[key] = value;
653
1489
  }
654
1490
  return props;
655
1491
  }
656
1492
  function parseStyleAttribute(value) {
657
- const style = {};
1493
+ let style = {};
658
1494
  if (!value) return style;
659
- const pairs = value.split(";");
660
- for (const pair of pairs) {
1495
+ let pairs = value.split(";");
1496
+ for (let pair of pairs) {
661
1497
  if (!pair.trim()) continue;
662
- const [property, rawVal] = pair.split(":");
663
- if (!property || rawVal === void 0) continue;
664
- const camelProp = property.trim().replace(/-([a-z])/g, (_, char) => char.toUpperCase());
665
- style[camelProp] = rawVal.trim();
1498
+ let separator = pair.indexOf(":");
1499
+ if (separator <= 0) continue;
1500
+ let property = pair.slice(0, separator).trim(), rawVal = pair.slice(separator + 1).trim();
1501
+ if (!(0, import_core.isSafeStyleDeclaration)(property, rawVal)) continue;
1502
+ let camelProp = property.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
1503
+ style[camelProp] = rawVal;
666
1504
  }
667
1505
  return style;
668
1506
  }
669
1507
  function normalizeTabIndex(value) {
670
- const numeric = Number(value);
1508
+ let numeric = Number(value);
671
1509
  return Number.isNaN(numeric) ? void 0 : numeric;
672
1510
  }
673
1511
  function decodeHtmlEntities(value) {
@@ -675,76 +1513,50 @@ function decodeHtmlEntities(value) {
675
1513
  }
676
1514
  function extractPlainText(value) {
677
1515
  if (!value) return "";
678
- const withoutTags = value.replace(/<\/?[^>]+>/g, "");
1516
+ let withoutTags = value.replace(/<\/?[^>]+>/g, "");
679
1517
  return decodeHtmlEntities(withoutTags);
680
1518
  }
681
- function renderSanitizedHtmlTree(html, key) {
682
- if (typeof DOMParser === "undefined") {
1519
+ var DEFAULT_LITERAL_TAGS = /* @__PURE__ */ new Set(["code", "pre", "script", "style", "textarea"]);
1520
+ function renderSanitizedHtmlTree(html, key, htmlElements, literalTagContent, parseMarkdown) {
1521
+ if (typeof DOMParser > "u")
683
1522
  return null;
684
- }
685
1523
  try {
686
- const parser = new DOMParser();
687
- const doc = parser.parseFromString(html, "text/html");
688
- const body = doc.body;
689
- const nodes = Array.from(body.childNodes);
690
- if (nodes.length === 0) {
1524
+ let body = new DOMParser().parseFromString(html, "text/html").body, nodes = Array.from(body.childNodes);
1525
+ if (nodes.length === 0)
691
1526
  return null;
692
- }
693
- const baseKey = typeof key === "string" || typeof key === "number" ? String(key) : "inline-html";
694
- const children = nodes.map((node, index) => convertDomNode(node, `${baseKey}-${index}`)).filter((child) => child !== null && child !== void 0);
695
- if (children.length === 0) {
1527
+ let literalTags = literalTagContent ? /* @__PURE__ */ new Set([...DEFAULT_LITERAL_TAGS, ...literalTagContent.map((t) => t.toLowerCase())]) : DEFAULT_LITERAL_TAGS, baseKey = typeof key == "string" || typeof key == "number" ? String(key) : "inline-html", children = nodes.map((node, index) => convertDomNode(node, `${baseKey}-${index}`, htmlElements, literalTags, !1, parseMarkdown)).filter((child) => child != null);
1528
+ if (children.length === 0)
696
1529
  return null;
697
- }
698
1530
  if (children.length === 1) {
699
- const [child] = children;
700
- if (import_react4.default.isValidElement(child)) {
701
- if (key !== void 0 && key !== null) {
702
- return import_react4.default.cloneElement(child, { key });
703
- }
704
- return child;
705
- }
706
- if (typeof child === "string" || typeof child === "number") {
707
- if (key !== void 0 && key !== null) {
708
- return import_react4.default.createElement(import_react4.default.Fragment, { key }, child);
709
- }
710
- return import_react4.default.createElement(import_react4.default.Fragment, {}, child);
711
- }
712
- return import_react4.default.createElement(import_react4.default.Fragment, { key }, child);
1531
+ let [child] = children;
1532
+ return import_react4.default.isValidElement(child) ? key != null ? import_react4.default.cloneElement(child, { key }) : child : typeof child == "string" || typeof child == "number" ? key != null ? import_react4.default.createElement(import_react4.default.Fragment, { key }, child) : import_react4.default.createElement(import_react4.default.Fragment, {}, child) : import_react4.default.createElement(import_react4.default.Fragment, { key }, child);
713
1533
  }
714
1534
  return import_react4.default.createElement(import_react4.default.Fragment, { key }, ...children);
715
1535
  } catch {
716
1536
  return null;
717
1537
  }
718
1538
  }
719
- function convertDomNode(node, key) {
1539
+ function convertDomNode(node, key, htmlElements, literalTags, parentIsLiteral, parseMarkdown) {
720
1540
  if (node.nodeType === Node.TEXT_NODE) {
721
- return node.textContent ?? "";
1541
+ let rawText = node.textContent ?? "";
1542
+ return parentIsLiteral || !parseMarkdown ? rawText : parseMarkdown(rawText);
722
1543
  }
723
- if (node.nodeType !== Node.ELEMENT_NODE) {
1544
+ if (node.nodeType !== Node.ELEMENT_NODE)
724
1545
  return null;
725
- }
726
- const element = node;
727
- const tagName = element.tagName.toLowerCase();
728
- const attrs = getElementAttributes(element);
729
- const props = mapAttributesToProps(attrs);
1546
+ let element = node, tagName = element.tagName.toLowerCase(), attrs = getElementAttributes(element), props = mapAttributesToProps(attrs);
730
1547
  props.key = key;
731
- const children = [];
1548
+ let isLiteral = parentIsLiteral || (literalTags ? literalTags.has(tagName) : !1), children = [];
732
1549
  element.childNodes.forEach((child, index) => {
733
- const converted = convertDomNode(child, `${key}-${index}`);
734
- if (converted !== null && converted !== void 0) {
735
- children.push(converted);
736
- }
1550
+ let converted = convertDomNode(child, `${key}-${index}`, htmlElements, literalTags, isLiteral, parseMarkdown);
1551
+ converted != null && children.push(converted);
737
1552
  });
738
- if (children.length === 0) {
739
- return import_react4.default.createElement(tagName, props);
740
- }
741
- return import_react4.default.createElement(tagName, props, ...children);
1553
+ let customComponent = htmlElements?.[tagName];
1554
+ return customComponent ? children.length === 0 ? import_react4.default.createElement(customComponent, props) : import_react4.default.createElement(customComponent, props, ...children) : children.length === 0 ? import_react4.default.createElement(tagName, props) : import_react4.default.createElement(tagName, props, ...children);
742
1555
  }
743
1556
  function getElementAttributes(element) {
744
- const attrs = {};
745
- for (const attr of Array.from(element.attributes)) {
1557
+ let attrs = {};
1558
+ for (let attr of Array.from(element.attributes))
746
1559
  attrs[attr.name] = attr.value;
747
- }
748
1560
  return attrs;
749
1561
  }
750
1562
  var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
@@ -754,6 +1566,11 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
754
1566
  "bdi",
755
1567
  "bdo",
756
1568
  "br",
1569
+ "img",
1570
+ "input",
1571
+ "picture",
1572
+ "del",
1573
+ "ins",
757
1574
  "cite",
758
1575
  "code",
759
1576
  "data",
@@ -798,67 +1615,397 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
798
1615
  "mtd"
799
1616
  ]);
800
1617
 
801
- // src/components/link-safety-modal.tsx
802
- var import_jsx_runtime = require("react/jsx-runtime");
803
- var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onCopy }) => {
804
- if (!isOpen) {
805
- return null;
1618
+ // src/components/owned-html.tsx
1619
+ var import_react5 = __toESM(require("react"), 1), import_core2 = require("@stream-mdx/core");
1620
+ function renderOwnedHtmlTree(tree, context) {
1621
+ return renderHtmlOwnershipTree(
1622
+ tree,
1623
+ context.elements,
1624
+ context.renderBlock,
1625
+ context.renderInline,
1626
+ (node, children, parentTagName, key) => {
1627
+ if (node.kind === "strong" || node.kind === "em" || node.kind === "strike" || node.kind === "link") {
1628
+ let component = context.inlineComponents[node.kind], renderElement = () => {
1629
+ let direct;
1630
+ if (node.kind === "link") {
1631
+ if (node.autolink && context.isAutolinkProtocolDisabled(node.href)) return children;
1632
+ let { href, ...linkProps } = node, safeHref = (context.urlTransform ?? import_core2.defaultUrlTransform)(href ?? "", "href", { source: "markdown" });
1633
+ direct = component ? import_react5.default.createElement(component, {
1634
+ ...linkProps,
1635
+ key,
1636
+ ...safeHref != null ? { href: safeHref } : {},
1637
+ children
1638
+ }) : import_react5.default.createElement("a", { key, href: safeHref ?? void 0 }, children);
1639
+ } else {
1640
+ let tag2 = node.kind === "strike" ? "del" : node.kind;
1641
+ direct = component ? import_react5.default.createElement(component, { ...node, key, children }) : import_react5.default.createElement(tag2, { key }, children);
1642
+ }
1643
+ return context.renderInlinePresentation ? context.renderInlinePresentation(node, direct, key) : direct;
1644
+ };
1645
+ if (!context.filterElement) return renderElement();
1646
+ let tag = node.kind === "strike" ? "del" : node.kind === "link" ? "a" : node.kind, properties = node.kind === "link" ? { href: context.urlTransform?.(node.href ?? "", "href", { source: "markdown" }) ?? node.href, title: node.title } : {};
1647
+ return context.filterElement(
1648
+ { tagName: tag, properties },
1649
+ { source: "markdown", parentTagName },
1650
+ renderElement,
1651
+ () => children
1652
+ );
1653
+ }
1654
+ if (node.kind === "plugin") {
1655
+ let component = context.inlineComponents[node.name] ?? context.inlineComponents.plugin, direct = component ? import_react5.default.createElement(component, { ...node.attrs, key, name: node.name, attrs: node.attrs, raw: node.raw, children }) : node.raw;
1656
+ return context.renderInlinePresentation ? context.renderInlinePresentation(node, direct, key, children) : direct;
1657
+ }
1658
+ return context.renderInline([node], parentTagName);
1659
+ },
1660
+ context.renderParagraph,
1661
+ context.urlTransform,
1662
+ context.filterElement,
1663
+ context.parentTagName,
1664
+ context.contentComponents,
1665
+ context.renderHtmlPresentation,
1666
+ void 0,
1667
+ context.renderComponentPresentation
1668
+ );
1669
+ }
1670
+
1671
+ // src/trusted-mdx/native-inline.tsx
1672
+ var import_react7 = __toESM(require("react"), 1), import_trusted_mdx_native_children = require("@stream-mdx/react/_internal/trusted-mdx-native-children");
1673
+
1674
+ // src/trusted-mdx-boundary.tsx
1675
+ var import_react6 = __toESM(require("react"), 1);
1676
+ var import_jsx_runtime5 = require("react/jsx-runtime"), EMPTY_PROJECTIONS = Object.freeze({}), EMPTY_COMPONENTS = Object.freeze({}), EMPTY_DOCUMENT_SNAPSHOT = Object.freeze({
1677
+ requestedRevision: 0,
1678
+ projectionRevision: null,
1679
+ renderedRevision: null,
1680
+ status: "idle",
1681
+ error: null,
1682
+ components: EMPTY_COMPONENTS,
1683
+ layout: null,
1684
+ projections: EMPTY_PROJECTIONS
1685
+ }), EMPTY_FEED_SNAPSHOT = Object.freeze({
1686
+ generation: 0,
1687
+ version: 0,
1688
+ generationCause: "initial",
1689
+ pendingSource: null,
1690
+ revision: null
1691
+ });
1692
+ var TrustedMdxProjectionContext = (0, import_react6.createContext)(null);
1693
+ var TrustedMdxProjectionErrorBoundary = class extends import_react6.default.Component {
1694
+ constructor() {
1695
+ super(...arguments);
1696
+ this.state = { error: null };
806
1697
  }
807
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
808
- "div",
809
- {
810
- className: "stream-mdx-link-modal-backdrop",
811
- role: "dialog",
812
- "aria-modal": "true",
813
- "aria-label": "Link safety confirmation",
814
- style: {
815
- position: "fixed",
816
- inset: 0,
817
- display: "flex",
818
- alignItems: "center",
819
- justifyContent: "center",
820
- background: "rgba(0, 0, 0, 0.4)",
821
- zIndex: 9999,
822
- padding: "24px"
823
- },
824
- onClick: onClose,
825
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
826
- "div",
827
- {
828
- className: "stream-mdx-link-modal",
829
- style: {
830
- width: "min(520px, 100%)",
831
- borderRadius: 12,
832
- background: "var(--background, #fff)",
833
- color: "var(--foreground, #111)",
834
- border: "1px solid var(--border, rgba(0, 0, 0, 0.1))",
835
- boxShadow: "0 20px 60px rgba(0, 0, 0, 0.25)",
836
- padding: 20
837
- },
838
- onClick: (event) => event.stopPropagation(),
839
- children: [
840
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Open external link?" }),
841
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 13, opacity: 0.8, wordBreak: "break-all", marginBottom: 16 }, children: url }),
842
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [
843
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: onCopy, disabled: isChecking, style: buttonStyle, children: "Copy link" }),
844
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: onConfirm, disabled: isChecking, style: primaryButtonStyle, children: "Open link" }),
845
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: onClose, style: buttonStyle, children: "Cancel" })
846
- ] })
847
- ]
848
- }
849
- )
1698
+ static getDerivedStateFromError(error) {
1699
+ return { error: error instanceof Error ? error : new Error(String(error)) };
1700
+ }
1701
+ componentDidCatch(error) {
1702
+ this.props.revision !== null && this.props.document.reportRenderError(this.props.revision, error);
1703
+ }
1704
+ render() {
1705
+ return this.state.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TrustedMdxProjectionContext.Provider, { value: null, children: this.props.fallback }) : this.props.children;
1706
+ }
1707
+ }, CapturedNativeFrameErrorBoundary = class extends import_react6.default.Component {
1708
+ constructor() {
1709
+ super(...arguments);
1710
+ this.state = { error: null };
1711
+ }
1712
+ static getDerivedStateFromError(error) {
1713
+ return { error: error instanceof Error ? error : new Error(String(error)) };
1714
+ }
1715
+ render() {
1716
+ return this.state.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { role: "alert", "data-trusted-mdx-retained-frame-error": "true", children: [
1717
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { children: [
1718
+ "Previously committed trusted MDX source generation ",
1719
+ this.props.sourceGeneration,
1720
+ ", document revision ",
1721
+ this.props.documentRevision,
1722
+ "failed to render: ",
1723
+ this.state.error.message
1724
+ ] }),
1725
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { children: [
1726
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("summary", { children: [
1727
+ "Escaped source for generation ",
1728
+ this.props.sourceGeneration,
1729
+ ", document revision ",
1730
+ this.props.documentRevision
1731
+ ] }),
1732
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { children: this.props.source })
1733
+ ] })
1734
+ ] }) : this.props.children;
1735
+ }
1736
+ };
1737
+
1738
+ // src/trusted-mdx-contract.ts
1739
+ function assertTrustedMdxNativeChildContinuations(owners, flowChildren) {
1740
+ if (owners.length !== flowChildren.length)
1741
+ throw new Error("A trusted MDX native child continuation has misaligned owner and source spans.");
1742
+ let continuationOwnerIndex;
1743
+ for (let index = 0; index < owners.length; index++) {
1744
+ let owner = owners[index];
1745
+ if (owner?.kind !== "continuation") {
1746
+ continuationOwnerIndex = void 0;
1747
+ continue;
850
1748
  }
851
- );
1749
+ let ownerIndex = owner.ownerIndex, ownerForRun = owners[ownerIndex], previousChild = flowChildren[index - 1], child = flowChildren[index];
1750
+ if (!Number.isSafeInteger(ownerIndex) || ownerIndex < 0 || ownerIndex >= index || (continuationOwnerIndex === void 0 ? ownerIndex !== index - 1 : ownerIndex !== continuationOwnerIndex) || ownerForRun === null || ownerForRun === void 0 || ownerForRun.kind === "continuation" || previousChild?.kind !== "inline" || child?.kind !== "inline" || previousChild.to <= previousChild.from || child.to <= child.from || previousChild.to !== child.from)
1751
+ throw new Error("A trusted MDX native child continuation does not cover one exact contiguous inline run.");
1752
+ continuationOwnerIndex = ownerIndex;
1753
+ }
1754
+ }
1755
+
1756
+ // src/trusted-mdx/native-inline.tsx
1757
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1758
+ function renderTrustedMdxOwner(ownerId, snapshot, source, inline, nativeChildren) {
1759
+ let projection = snapshot.projections[ownerId];
1760
+ if (projection?.kind === "native-child") return;
1761
+ if (projection?.kind === "module") return null;
1762
+ if (projection?.kind === "server-content") {
1763
+ if (!projection.nativeChildren) return projection.content;
1764
+ if (nativeChildren === void 0)
1765
+ throw new Error(`Trusted MDX owner "${ownerId}" has no prepared native children.`);
1766
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_trusted_mdx_native_children.TrustedMdxNativeChildrenContext.Provider, { value: nativeChildren, children: projection.content });
1767
+ }
1768
+ if (projection?.kind === "render" && projection.nativeChildren && nativeChildren === void 0)
1769
+ throw new Error(`Trusted MDX owner "${ownerId}" has no prepared native children.`);
1770
+ if (projection?.kind === "render") {
1771
+ let nativeChildrenFactory = projection.rootElementName === void 0 || nativeChildren === void 0 ? void 0 : (fallback) => {
1772
+ let owners = projection.nativeChildOwners, flowChildren = projection.flowChildren;
1773
+ if (!owners || !flowChildren || owners.length !== flowChildren.length || !Array.isArray(nativeChildren) || nativeChildren.length !== owners.length)
1774
+ throw new Error(`Trusted MDX owner "${ownerId}" has misaligned native child owners.`);
1775
+ return assertTrustedMdxNativeChildContinuations(owners, flowChildren), owners.map((owner, index) => {
1776
+ if (owner === null) return fallback(index);
1777
+ if (owner.kind === "continuation") return;
1778
+ let child = nativeChildren[index];
1779
+ if (child === void 0)
1780
+ throw new Error(`Trusted MDX owner "${ownerId}" has no rendered native child "${owner.blockId}".`);
1781
+ return child;
1782
+ });
1783
+ };
1784
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: projection.regions.map((Region, index) => {
1785
+ let regionProps = {
1786
+ components: snapshot.components,
1787
+ ...nativeChildrenFactory === void 0 ? {} : { children: nativeChildrenFactory }
1788
+ };
1789
+ return import_react7.default.createElement(
1790
+ import_react7.default.Fragment,
1791
+ { key: `${ownerId}:${index}` },
1792
+ Region(regionProps)
1793
+ );
1794
+ }) });
1795
+ }
1796
+ let diagnostic = projection?.kind === "unmapped" ? projection.diagnostic : snapshot.error ?? `MDX owner "${ownerId}" has no exact trusted source projection.`, status = projection?.kind === "unmapped" ? "unmapped" : snapshot.status === "error" ? "error" : "pending";
1797
+ return (projection?.kind === "unmapped" && projection.placement !== void 0 ? projection.placement === "inline" : inline) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "markdown-mdx-inline", "data-mdx-status": status, "data-mdx-diagnostic": diagnostic, children: [
1798
+ source,
1799
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "markdown-mdx-diagnostic", role: "note", children: diagnostic })
1800
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "markdown-mdx-inert", "data-mdx-status": status, "data-mdx-diagnostic": diagnostic, children: [
1801
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: source }) }),
1802
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "markdown-mdx-diagnostic", role: "note", children: diagnostic })
1803
+ ] });
1804
+ }
1805
+ function TrustedMdxInlineOwner({ ownerId, source }) {
1806
+ let snapshot = (0, import_react7.useContext)(TrustedMdxProjectionContext);
1807
+ return snapshot ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: renderTrustedMdxOwner(ownerId, snapshot, source, !0) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "markdown-mdx-inline", children: source });
1808
+ }
1809
+
1810
+ // src/renderer/node-presentations.ts
1811
+ var import_react8 = __toESM(require("react"), 1);
1812
+ function renderPresentedNode(presentation, nativeView, context, applyPresentationPropsToCustomElements = !1) {
1813
+ if (!presentation) return nativeView;
1814
+ let prepared = nativeView;
1815
+ return presentation.props && import_react8.default.isValidElement(prepared) && (typeof prepared.type == "string" || applyPresentationPropsToCustomElements) && (prepared = import_react8.default.cloneElement(
1816
+ prepared,
1817
+ mergeNodePresentationProps(prepared.props, presentation.props)
1818
+ )), "view" in presentation && presentation.view ? import_react8.default.createElement(presentation.view, {
1819
+ ...context.viewProps,
1820
+ key: context.key
1821
+ }) : "wrapper" in presentation && presentation.wrapper ? import_react8.default.createElement(presentation.wrapper, {
1822
+ key: context.key,
1823
+ children: prepared,
1824
+ metadata: context.metadata,
1825
+ actions: context.actions
1826
+ }) : prepared;
1827
+ }
1828
+ var PRESENTATION_KEY_PATTERNS = [
1829
+ /^[a-z][a-z0-9-]*$/,
1830
+ /^inline:[a-z][a-z0-9-]*$/,
1831
+ /^html:[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/,
1832
+ /^component:[A-Za-z][A-Za-z0-9_.-]*$/,
1833
+ /^extension:[A-Za-z][A-Za-z0-9_.-]*$/
1834
+ ], RESERVED_PRESENTATION_PROPS = {
1835
+ className: !0,
1836
+ style: !0,
1837
+ title: !0
1838
+ };
1839
+ function resolveNodePresentation(presentations, key) {
1840
+ if (!isNodePresentationKey(key))
1841
+ throw new TypeError(`invalid node presentation key: ${key}`);
1842
+ if (!presentations || !Object.prototype.hasOwnProperty.call(presentations, key)) return;
1843
+ let candidate = presentations[key];
1844
+ return validateNodePresentation(key, candidate), candidate;
1845
+ }
1846
+ function mergeNodePresentationProps(nativeProps, decoration) {
1847
+ if (!decoration) return nativeProps;
1848
+ let merged = {};
1849
+ for (let [property, value] of Object.entries(decoration))
1850
+ if (property === "className") {
1851
+ let nativeClass = nativeProps.className;
1852
+ merged.className = typeof nativeClass == "string" && value ? `${nativeClass} ${value}` : value ?? nativeClass;
1853
+ } else property === "style" ? merged.style = { ...nativeProps.style, ...value } : Object.prototype.hasOwnProperty.call(nativeProps, property) || (merged[property] = value);
1854
+ return merged;
1855
+ }
1856
+ function validateNodePresentations(presentations) {
1857
+ if (presentations !== void 0) {
1858
+ if (presentations === null || typeof presentations != "object" || Array.isArray(presentations))
1859
+ throw new TypeError("node presentations must be an object");
1860
+ for (let key of Object.keys(presentations)) {
1861
+ if (!isNodePresentationKey(key))
1862
+ throw new TypeError(`invalid node presentation key: ${key}`);
1863
+ validateNodePresentation(key, presentations[key]);
1864
+ }
1865
+ }
1866
+ }
1867
+ function isNodePresentationKey(key) {
1868
+ return PRESENTATION_KEY_PATTERNS.some((pattern) => pattern.test(key));
1869
+ }
1870
+ function validateNodePresentation(key, candidate) {
1871
+ if (candidate === null || typeof candidate != "object" || Array.isArray(candidate))
1872
+ throw new TypeError(`node presentation for ${key} must be an object`);
1873
+ let presentation = candidate;
1874
+ if ((key === "table-row" || key === "table-cell") && presentation.view !== void 0)
1875
+ throw new TypeError(
1876
+ `node presentation for ${key}: headless table-part views are not supported; use components.table.view with useTableRows`
1877
+ );
1878
+ if ((key === "table-row" || key === "table-cell") && presentation.slots !== void 0)
1879
+ throw new TypeError(`node presentation for ${key} only supports wrapper and props`);
1880
+ if (key.startsWith("component:") && presentation.view !== void 0)
1881
+ throw new TypeError(`node presentation for ${key}: headless views are not supported for restricted content components`);
1882
+ if (presentation.wrapper !== void 0 && presentation.view !== void 0)
1883
+ throw new TypeError(`node presentation for ${key}: wrapper and view are mutually exclusive`);
1884
+ if (presentation.wrapper !== void 0 && !isComponentType(presentation.wrapper))
1885
+ throw new TypeError(`node presentation for ${key} has an invalid wrapper`);
1886
+ if (presentation.view !== void 0 && !isComponentType(presentation.view))
1887
+ throw new TypeError(`node presentation for ${key} has an invalid view`);
1888
+ presentation.props !== void 0 && validatePresentationProps(key, presentation.props), presentation.slots !== void 0 && validatePresentationSlots(key, presentation.slots);
1889
+ for (let property of Object.keys(presentation))
1890
+ if (property !== "props" && property !== "wrapper" && property !== "view" && property !== "slots")
1891
+ throw new TypeError(`node presentation for ${key} has an unknown field: ${property}`);
1892
+ }
1893
+ function isComponentType(value) {
1894
+ return typeof value == "function" || typeof value == "object" && value !== null;
1895
+ }
1896
+ function validatePresentationProps(key, candidate) {
1897
+ if (candidate === null || typeof candidate != "object" || Array.isArray(candidate))
1898
+ throw new TypeError(`node presentation props for ${key} must be an object`);
1899
+ let props = candidate;
1900
+ for (let [property, value] of Object.entries(props)) {
1901
+ let isDataOrAria = /^(data|aria)-[a-z][a-z0-9_.:-]*$/.test(property);
1902
+ if (RESERVED_PRESENTATION_PROPS[property] !== !0 && !isDataOrAria)
1903
+ throw new TypeError(`presentation prop is not allowed: ${property}`);
1904
+ if (property === "style" && (value === null || typeof value != "object" || Array.isArray(value)))
1905
+ throw new TypeError(`presentation style for ${key} must be an object`);
1906
+ }
1907
+ }
1908
+ function validatePresentationSlots(key, candidate) {
1909
+ if (candidate === null || typeof candidate != "object" || Array.isArray(candidate))
1910
+ throw new TypeError(`node presentation slots for ${key} must be an object`);
1911
+ for (let slot of Object.keys(candidate))
1912
+ if (key !== "code" && key !== "table" || slot !== "actions")
1913
+ throw new TypeError(`presentation slot is not supported for ${key}: ${slot}`);
1914
+ }
1915
+
1916
+ // src/renderer/virtualized-table.ts
1917
+ var import_react9 = require("react"), import_react_dom = require("react-dom"), DEFAULT_TABLE_VIRTUALIZATION_CONFIG = Object.freeze({
1918
+ enabled: !1,
1919
+ minRows: 40,
1920
+ virtualizeThreshold: 40,
1921
+ estimatedRowHeight: 40,
1922
+ overscan: 8,
1923
+ maxHeight: "600px"
1924
+ });
1925
+ function resolveTableVirtualizationConfig(options) {
1926
+ if (options === !0) return { ...DEFAULT_TABLE_VIRTUALIZATION_CONFIG, enabled: !0 };
1927
+ if (!options) return DEFAULT_TABLE_VIRTUALIZATION_CONFIG;
1928
+ let threshold = options.minRows ?? options.virtualizeThreshold ?? 40, minRows = Number.isFinite(threshold) ? Math.max(1, Math.floor(threshold)) : 40, buffer = options.overscan ?? 8, overscan = Number.isFinite(buffer) ? Math.min(50, Math.max(1, Math.floor(buffer))) : 8, estimate = options.estimatedRowHeight ?? 40;
1929
+ return {
1930
+ enabled: options.enabled ?? !0,
1931
+ minRows,
1932
+ virtualizeThreshold: minRows,
1933
+ estimatedRowHeight: Number.isFinite(estimate) && estimate > 0 ? estimate : 40,
1934
+ overscan,
1935
+ maxHeight: options.maxHeight ?? "600px"
1936
+ };
1937
+ }
1938
+
1939
+ // src/renderer/virtualized-code.tsx
1940
+ var import_react10 = require("react"), import_react_dom2 = require("react-dom");
1941
+ var DEFAULT_VIRTUALIZED_CODE_CONFIG = {
1942
+ enabled: !0,
1943
+ windowSize: 100,
1944
+ bufferSize: 50,
1945
+ virtualizeThreshold: 200,
1946
+ followTail: !1
852
1947
  };
853
- var buttonStyle = {
1948
+ function resolveVirtualizedCodeConfig(options) {
1949
+ return {
1950
+ ...DEFAULT_VIRTUALIZED_CODE_CONFIG,
1951
+ ...options,
1952
+ followTail: options?.followTail ?? DEFAULT_VIRTUALIZED_CODE_CONFIG.followTail
1953
+ };
1954
+ }
1955
+
1956
+ // src/components/link-safety-modal.tsx
1957
+ var import_jsx_runtime7 = require("react/jsx-runtime"), DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onCopy }) => isOpen ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1958
+ "div",
1959
+ {
1960
+ className: "stream-mdx-link-modal-backdrop",
1961
+ role: "dialog",
1962
+ "aria-modal": "true",
1963
+ "aria-label": "Link safety confirmation",
1964
+ style: {
1965
+ position: "fixed",
1966
+ inset: 0,
1967
+ display: "flex",
1968
+ alignItems: "center",
1969
+ justifyContent: "center",
1970
+ background: "rgba(0, 0, 0, 0.4)",
1971
+ zIndex: 9999,
1972
+ padding: "24px"
1973
+ },
1974
+ onClick: onClose,
1975
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1976
+ "div",
1977
+ {
1978
+ className: "stream-mdx-link-modal",
1979
+ style: {
1980
+ width: "min(520px, 100%)",
1981
+ borderRadius: 12,
1982
+ background: "var(--background, #fff)",
1983
+ color: "var(--foreground, #111)",
1984
+ border: "1px solid var(--border, rgba(0, 0, 0, 0.1))",
1985
+ boxShadow: "0 20px 60px rgba(0, 0, 0, 0.25)",
1986
+ padding: 20
1987
+ },
1988
+ onClick: (event) => event.stopPropagation(),
1989
+ children: [
1990
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Open external link?" }),
1991
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 13, opacity: 0.8, wordBreak: "break-all", marginBottom: 16 }, children: url }),
1992
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [
1993
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: onCopy, disabled: isChecking, style: buttonStyle, children: "Copy link" }),
1994
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: onConfirm, disabled: isChecking, style: primaryButtonStyle, children: "Open link" }),
1995
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: onClose, style: buttonStyle, children: "Cancel" })
1996
+ ] })
1997
+ ]
1998
+ }
1999
+ )
2000
+ }
2001
+ ) : null, buttonStyle = {
854
2002
  borderRadius: 8,
855
2003
  border: "1px solid var(--border, rgba(0, 0, 0, 0.1))",
856
2004
  padding: "6px 12px",
857
2005
  background: "var(--background, #fff)",
858
2006
  color: "inherit",
859
2007
  fontSize: 13
860
- };
861
- var primaryButtonStyle = {
2008
+ }, primaryButtonStyle = {
862
2009
  ...buttonStyle,
863
2010
  background: "var(--foreground, #111)",
864
2011
  color: "var(--background, #fff)",
@@ -866,120 +2013,295 @@ var primaryButtonStyle = {
866
2013
  };
867
2014
 
868
2015
  // src/components/index.ts
869
- var MdxRuntimeBoundary = class extends import_react5.default.Component {
870
- constructor() {
871
- super(...arguments);
872
- this.state = { hasError: false };
873
- }
874
- static getDerivedStateFromError() {
875
- return { hasError: true };
876
- }
877
- componentDidCatch(error) {
878
- this.props.onError(error);
879
- }
880
- componentDidUpdate(prevProps) {
881
- if (prevProps.resetKey !== this.props.resetKey && this.state.hasError) {
882
- this.setState({ hasError: false });
883
- }
884
- }
885
- render() {
886
- if (this.state.hasError) {
887
- return null;
888
- }
889
- return this.props.children;
890
- }
891
- };
892
- function renderInlineNodes(nodes, components) {
2016
+ function presentationText(node) {
2017
+ return typeof node == "string" || typeof node == "number" ? String(node) : Array.isArray(node) ? node.map(presentationText).join("") : import_react11.default.isValidElement(node) ? presentationText(node.props.children) : "";
2018
+ }
2019
+ function renderInlineNodes(nodes, components, urlTransform, registry, parentTagName, animationContext) {
893
2020
  return nodes.map((node, index) => {
894
- const key = `${node.kind}-${index}`;
2021
+ let key = `${node.kind}-${index}`, itemChildContext = animationContext?.animated && !animationContext.isFinalized ? {
2022
+ ...animationContext,
2023
+ nodeKeyPrefix: animationContext.nodeKeyPrefix ? `${animationContext.nodeKeyPrefix}:${key}` : key
2024
+ } : animationContext, presentInline = (nativeView, renderedChildren) => registry ? registry.renderInlinePresentation(node, nativeView, key, itemChildContext, renderedChildren) : nativeView;
895
2025
  switch (node.kind) {
896
2026
  case "text": {
897
- const textComponent = components.text;
898
- if (textComponent && textComponent !== defaultInlineComponents.text) {
899
- return import_react5.default.createElement(textComponent, { key, text: node.text });
2027
+ let textComponent = components.text;
2028
+ if (textComponent && textComponent !== defaultInlineComponents.text)
2029
+ return presentInline(import_react11.default.createElement(textComponent, { key, text: node.text }));
2030
+ if (animationContext?.animated && !animationContext.isFinalized && animationContext.timeline) {
2031
+ let { animated, timeline, nodeKeyPrefix } = animationContext, nodeKey = nodeKeyPrefix ? `${nodeKeyPrefix}:${key}` : key, segments = splitTextSegments(node.text, animated.sep), state = timeline.getNodeState(nodeKey);
2032
+ if (segments.length > state.count) {
2033
+ let newCount = segments.length - state.count, newDelays = timeline.schedule(newCount, animated.stagger);
2034
+ state.delays.push(...newDelays), state.count = segments.length;
2035
+ } else segments.length < state.count && (state.count = segments.length, state.delays.length = segments.length);
2036
+ let animName = animated.animationName, durationStr = animated.durationStr, spans = segments.map((segment, segmentIndex) => {
2037
+ let delay = state.delays[segmentIndex] ?? 0, animStyle = {
2038
+ "--sm-anim-duration": durationStr,
2039
+ "--sm-anim-easing": animated.easing,
2040
+ "--sm-anim-delay": `${delay}ms`
2041
+ };
2042
+ return animName && (animStyle["--sm-anim-name"] = animName, animStyle.animationName = animName), import_react11.default.createElement(
2043
+ "span",
2044
+ {
2045
+ key: segmentIndex,
2046
+ className: "stream-mdx-anim",
2047
+ style: animStyle
2048
+ },
2049
+ segment
2050
+ );
2051
+ });
2052
+ return presentInline(import_react11.default.createElement(import_react11.default.Fragment, { key }, ...spans));
900
2053
  }
901
- return import_react5.default.createElement(import_react5.default.Fragment, { key, children: node.text });
2054
+ return presentInline(import_react11.default.createElement(import_react11.default.Fragment, { key, children: node.text }));
902
2055
  }
903
- case "strong":
904
- return import_react5.default.createElement(components.strong, {
2056
+ case "strong": {
2057
+ if (!registry?.hasElementFilters())
2058
+ return presentInline(import_react11.default.createElement(components.strong, {
2059
+ key,
2060
+ children: renderInlineNodes(node.children, components, urlTransform, registry, "strong", itemChildContext)
2061
+ }));
2062
+ let renderChildren = () => renderInlineNodes(node.children, components, urlTransform, registry, "strong", itemChildContext), renderElement = () => presentInline(import_react11.default.createElement(components.strong, {
905
2063
  key,
906
- children: renderInlineNodes(node.children, components)
907
- });
908
- case "em":
909
- return import_react5.default.createElement(components.em, {
2064
+ children: renderChildren()
2065
+ }));
2066
+ return registry.filterElement(
2067
+ { tagName: "strong", properties: { key }, blockType: void 0 },
2068
+ { source: "markdown", parentTagName },
2069
+ renderElement,
2070
+ renderChildren
2071
+ );
2072
+ }
2073
+ case "em": {
2074
+ if (!registry?.hasElementFilters())
2075
+ return presentInline(import_react11.default.createElement(components.em, {
2076
+ key,
2077
+ children: renderInlineNodes(node.children, components, urlTransform, registry, "em", itemChildContext)
2078
+ }));
2079
+ let renderChildren = () => renderInlineNodes(node.children, components, urlTransform, registry, "em", itemChildContext), renderElement = () => presentInline(import_react11.default.createElement(components.em, {
910
2080
  key,
911
- children: renderInlineNodes(node.children, components)
912
- });
2081
+ children: renderChildren()
2082
+ }));
2083
+ return registry.filterElement(
2084
+ { tagName: "em", properties: { key }, blockType: void 0 },
2085
+ { source: "markdown", parentTagName },
2086
+ renderElement,
2087
+ renderChildren
2088
+ );
2089
+ }
913
2090
  case "strike": {
914
- const StrikeComponent = components.strike ?? ((props) => import_react5.default.createElement("del", {}, props.children));
915
- return import_react5.default.createElement(StrikeComponent, {
2091
+ let StrikeComponent = components.strike ?? ((props) => import_react11.default.createElement("del", {}, props.children));
2092
+ if (!registry?.hasElementFilters())
2093
+ return presentInline(import_react11.default.createElement(StrikeComponent, {
2094
+ key,
2095
+ children: renderInlineNodes(node.children, components, urlTransform, registry, "del", itemChildContext)
2096
+ }));
2097
+ let renderChildren = () => renderInlineNodes(node.children, components, urlTransform, registry, "del", itemChildContext), renderElement = () => presentInline(import_react11.default.createElement(StrikeComponent, {
916
2098
  key,
917
- children: renderInlineNodes(node.children, components)
918
- });
2099
+ children: renderChildren()
2100
+ }));
2101
+ return registry.filterElement(
2102
+ { tagName: "del", properties: { key }, blockType: void 0 },
2103
+ { source: "markdown", parentTagName },
2104
+ renderElement,
2105
+ renderChildren
2106
+ );
2107
+ }
2108
+ case "code": {
2109
+ if (!registry?.hasElementFilters())
2110
+ return presentInline(import_react11.default.createElement(components.code, { key, text: node.text }));
2111
+ let renderChildren = () => node.text, renderElement = () => presentInline(import_react11.default.createElement(components.code, { key, text: node.text }));
2112
+ return registry.filterElement(
2113
+ { tagName: "code", properties: { key, text: node.text }, blockType: void 0 },
2114
+ { source: "markdown", parentTagName },
2115
+ renderElement,
2116
+ renderChildren
2117
+ );
919
2118
  }
920
- case "code":
921
- return import_react5.default.createElement(components.code, { key, text: node.text });
922
- case "link":
923
- return import_react5.default.createElement(
2119
+ case "link": {
2120
+ if (node.autolink && registry?.isAutolinkProtocolDisabled(node.href))
2121
+ return renderInlineNodes(node.children, components, urlTransform, registry, parentTagName, itemChildContext);
2122
+ let safeHref = (urlTransform ?? import_core4.defaultUrlTransform)(node.href ?? "", "href", { source: "markdown" });
2123
+ if (!registry?.hasElementFilters())
2124
+ return presentInline(import_react11.default.createElement(
2125
+ components.link,
2126
+ {
2127
+ key,
2128
+ ...safeHref != null ? { href: safeHref } : {},
2129
+ title: node.title,
2130
+ children: renderInlineNodes(node.children, components, urlTransform, registry, "a", itemChildContext)
2131
+ }
2132
+ ));
2133
+ let renderChildren = () => renderInlineNodes(node.children, components, urlTransform, registry, "a", itemChildContext), renderElement = () => presentInline(import_react11.default.createElement(
924
2134
  components.link,
925
2135
  {
926
2136
  key,
927
- href: node.href,
2137
+ ...safeHref != null ? { href: safeHref } : {},
928
2138
  title: node.title,
929
- children: renderInlineNodes(node.children, components)
2139
+ children: renderChildren()
930
2140
  }
2141
+ ));
2142
+ return registry.filterElement(
2143
+ { tagName: "a", properties: { key, href: safeHref, title: node.title }, blockType: void 0 },
2144
+ { source: "markdown", parentTagName },
2145
+ renderElement,
2146
+ renderChildren
931
2147
  );
932
- case "image":
933
- return import_react5.default.createElement(components.image, {
2148
+ }
2149
+ case "image": {
2150
+ let safeSrc = (urlTransform ?? import_core4.defaultUrlTransform)(node.src ?? "", "src", { source: "markdown" });
2151
+ if (!registry?.hasElementFilters())
2152
+ return presentInline(import_react11.default.createElement(components.image, {
2153
+ key,
2154
+ ...safeSrc != null ? { src: safeSrc } : {},
2155
+ alt: node.alt ?? "",
2156
+ title: node.title
2157
+ }));
2158
+ let renderElement = () => presentInline(import_react11.default.createElement(components.image, {
934
2159
  key,
935
- src: node.src,
936
- alt: node.alt,
2160
+ ...safeSrc != null ? { src: safeSrc } : {},
2161
+ alt: node.alt ?? "",
937
2162
  title: node.title
938
- });
939
- case "br":
940
- return import_react5.default.createElement(import_react5.default.Fragment, { key }, import_react5.default.createElement(components.br, {}));
2163
+ }));
2164
+ return registry.filterElement(
2165
+ { tagName: "img", properties: { key, src: safeSrc, alt: node.alt ?? "", title: node.title }, blockType: void 0 },
2166
+ { source: "markdown", parentTagName },
2167
+ renderElement,
2168
+ void 0
2169
+ );
2170
+ }
2171
+ case "br": {
2172
+ if (!registry?.hasElementFilters())
2173
+ return presentInline(import_react11.default.createElement(
2174
+ import_react11.default.Fragment,
2175
+ { key },
2176
+ import_react11.default.createElement(components.br, {}),
2177
+ `
2178
+ `
2179
+ ));
2180
+ let renderElement = () => presentInline(import_react11.default.createElement(
2181
+ import_react11.default.Fragment,
2182
+ { key },
2183
+ import_react11.default.createElement(components.br, {}),
2184
+ `
2185
+ `
2186
+ ));
2187
+ return registry.filterElement(
2188
+ { tagName: "br", properties: { key }, blockType: void 0 },
2189
+ { source: "markdown", parentTagName },
2190
+ renderElement,
2191
+ void 0
2192
+ );
2193
+ }
2194
+ case "plugin": {
2195
+ let pluginComponent = components[node.name] ?? components.plugin, hasExtensionPresentation = registry?.getNodePresentation(`extension:${node.name}`) !== void 0, pluginChildren = node.children && (pluginComponent || hasExtensionPresentation) ? renderInlineNodes(node.children, components, urlTransform, registry, parentTagName, itemChildContext) : void 0;
2196
+ return pluginComponent ? presentInline(import_react11.default.createElement(pluginComponent, {
2197
+ key,
2198
+ ...node.attrs,
2199
+ name: node.name,
2200
+ attrs: node.attrs,
2201
+ children: pluginChildren,
2202
+ raw: node.raw
2203
+ }), pluginChildren) : hasExtensionPresentation ? presentInline(import_react11.default.createElement(import_react11.default.Fragment, { key }, pluginChildren ?? node.raw), pluginChildren) : presentInline(import_react11.default.createElement(import_react11.default.Fragment, { key }, node.raw));
2204
+ }
2205
+ case "trusted-mdx-inline":
2206
+ return import_react11.default.createElement(TrustedMdxInlineOwner, { key, ownerId: node.ownerId, source: node.raw });
2207
+ case "html": {
2208
+ let children = node.children ? renderInlineNodes(node.children, components, urlTransform, registry, node.tagName?.toLowerCase(), itemChildContext) : void 0, textValue = node.children?.map((child) => child.kind === "text" ? child.text : "").join(""), htmlRenderer = components.html;
2209
+ return htmlRenderer && !registry?.isDefaultHtmlInlineRenderer(htmlRenderer) ? renderHtmlInlineNode(
2210
+ node,
2211
+ children,
2212
+ void 0,
2213
+ key,
2214
+ textValue,
2215
+ urlTransform,
2216
+ registry?.hasElementFilters() ? (el, ctx, renderElement, renderChildren) => registry.filterElement(el, ctx, renderElement, renderChildren) : void 0,
2217
+ parentTagName,
2218
+ registry ? (tagName, properties, nativeView, htmlChildren, presentationKey) => registry.renderHtmlPresentation(
2219
+ tagName,
2220
+ properties,
2221
+ nativeView,
2222
+ htmlChildren,
2223
+ presentationKey,
2224
+ animationContext?.nodeKeyPrefix,
2225
+ animationContext?.isFinalized,
2226
+ animationContext?.sourceGuard
2227
+ ) : void 0,
2228
+ (tagName, properties, htmlChildren, presentationKey) => import_react11.default.createElement(htmlRenderer, {
2229
+ ...node,
2230
+ key: presentationKey,
2231
+ children: htmlChildren,
2232
+ textValue,
2233
+ properties
2234
+ })
2235
+ ) : renderHtmlInlineNode(
2236
+ node,
2237
+ children,
2238
+ void 0,
2239
+ key,
2240
+ textValue,
2241
+ urlTransform,
2242
+ registry?.hasElementFilters() ? (el, ctx, renderElement, renderChildren) => registry.filterElement(el, ctx, renderElement, renderChildren) : void 0,
2243
+ parentTagName,
2244
+ registry ? (tagName, properties, nativeView, htmlChildren, presentationKey) => registry.renderHtmlPresentation(
2245
+ tagName,
2246
+ properties,
2247
+ nativeView,
2248
+ htmlChildren,
2249
+ presentationKey,
2250
+ animationContext?.nodeKeyPrefix,
2251
+ animationContext?.isFinalized,
2252
+ animationContext?.sourceGuard
2253
+ ) : void 0
2254
+ );
2255
+ }
941
2256
  default: {
942
- const component = components[node.kind];
2257
+ let component = components[node.kind];
943
2258
  if (component) {
944
- return import_react5.default.createElement(component, { key, ...node });
2259
+ let engine = node.kind === "math-inline" || node.kind === "math-display" ? registry?.getMathEngine() : void 0;
2260
+ return presentInline(import_react11.default.createElement(component, { key, ...node, ...engine ? { engine } : {} }));
945
2261
  }
946
- return null;
2262
+ return presentInline(import_react11.default.createElement(import_react11.default.Fragment, { key }, null));
947
2263
  }
948
2264
  }
949
2265
  });
950
2266
  }
951
2267
  var defaultInlineComponents = {
952
- text: ({ text }) => import_react5.default.createElement(import_react5.default.Fragment, {}, text),
953
- strong: ({ children }) => import_react5.default.createElement("strong", {}, children),
954
- em: ({ children }) => import_react5.default.createElement("em", {}, children),
955
- strike: ({ children }) => import_react5.default.createElement("del", {}, children),
956
- code: ({ text }) => import_react5.default.createElement(
2268
+ text: ({ text }) => import_react11.default.createElement(import_react11.default.Fragment, {}, text),
2269
+ strong: ({ children }) => import_react11.default.createElement("strong", {}, children),
2270
+ em: ({ children }) => import_react11.default.createElement("em", {}, children),
2271
+ strike: ({ children }) => import_react11.default.createElement("del", {}, children),
2272
+ code: ({ text }) => import_react11.default.createElement(
957
2273
  "code",
958
2274
  {
959
2275
  className: "inline-code"
960
2276
  },
961
2277
  text
962
2278
  ),
963
- link: ({ href, title, children }) => import_react5.default.createElement(
964
- "a",
965
- {
966
- href,
2279
+ link: ({ href, title, children }) => {
2280
+ let safeHref = href == null ? void 0 : (0, import_core4.defaultUrlTransform)(href, "href", { source: "markdown" });
2281
+ return import_react11.default.createElement(
2282
+ "a",
2283
+ {
2284
+ ...safeHref != null ? { href: safeHref } : {},
2285
+ title,
2286
+ className: "markdown-link",
2287
+ target: safeHref?.startsWith("http") ? "_blank" : void 0,
2288
+ rel: safeHref?.startsWith("http") ? "noopener noreferrer" : void 0
2289
+ },
2290
+ children
2291
+ );
2292
+ },
2293
+ image: ({ src, alt, title }) => {
2294
+ let safeSrc = (0, import_core4.defaultUrlTransform)(src ?? "", "src", { source: "markdown" });
2295
+ return import_react11.default.createElement("img", {
2296
+ ...safeSrc != null ? { src: safeSrc } : {},
2297
+ alt,
967
2298
  title,
968
- className: "markdown-link",
969
- target: href?.startsWith("http") ? "_blank" : void 0,
970
- rel: href?.startsWith("http") ? "noopener noreferrer" : void 0
971
- },
972
- children
973
- ),
974
- image: ({ src, alt, title }) => import_react5.default.createElement("img", {
975
- src,
976
- alt,
977
- title,
978
- className: "markdown-image"
979
- }),
980
- br: () => import_react5.default.createElement("br"),
2299
+ className: "markdown-image"
2300
+ });
2301
+ },
2302
+ br: () => import_react11.default.createElement("br"),
981
2303
  // Custom extensible components
982
- mention: ({ handle }) => import_react5.default.createElement(
2304
+ mention: ({ handle }) => import_react11.default.createElement(
983
2305
  "span",
984
2306
  {
985
2307
  className: "mention",
@@ -987,7 +2309,7 @@ var defaultInlineComponents = {
987
2309
  },
988
2310
  `@${handle}`
989
2311
  ),
990
- citation: ({ id }) => import_react5.default.createElement(
2312
+ citation: ({ id }) => import_react11.default.createElement(
991
2313
  "span",
992
2314
  {
993
2315
  className: "citation",
@@ -995,107 +2317,135 @@ var defaultInlineComponents = {
995
2317
  },
996
2318
  `[${id}]`
997
2319
  ),
998
- "math-inline": ({ tex }) => import_react5.default.createElement(
999
- "span",
1000
- {
1001
- className: "math-inline",
1002
- "data-tex": tex
1003
- },
1004
- `$${tex}$`
1005
- ),
1006
- "math-display": ({ tex }) => import_react5.default.createElement(
1007
- "div",
1008
- {
1009
- className: "math-display markdown-math-display",
1010
- "data-tex": tex,
1011
- style: { overflowX: "auto" }
1012
- },
1013
- import_react5.default.createElement("span", { className: "math-display-content" }, `$$${tex}$$`)
1014
- ),
2320
+ "math-inline": ({ tex, engine }) => import_react11.default.createElement(KaTeXInlineMath, { tex, engine }),
2321
+ "math-display": ({ tex, engine }) => import_react11.default.createElement(KaTeXBlockMath, { tex, engine }),
1015
2322
  // Footnote inline reference (superscript anchor)
1016
- "footnote-ref": ({ label, number }) => {
1017
- const n = number ?? "?";
1018
- const href = number ? `#fn:${n}` : void 0;
1019
- const id = number ? `fnref:${n}` : void 0;
1020
- return import_react5.default.createElement("sup", { className: "footnote-ref" }, import_react5.default.createElement("a", { href, id, "data-label": label }, String(n)));
2323
+ "footnote-ref": ({ label, number, occurrence, defined }) => {
2324
+ if (!number || defined === !1) return import_react11.default.createElement(import_react11.default.Fragment, null, `[^${label}]`);
2325
+ let n = number, href = `#fn:${n}`, id = `fnref:${n}${occurrence && occurrence > 1 ? `:${occurrence}` : ""}`;
2326
+ return import_react11.default.createElement(
2327
+ "sup",
2328
+ { className: "footnote-ref" },
2329
+ import_react11.default.createElement("a", { href, id, "data-label": label, style: { color: "var(--foreground)", textDecoration: "underline" } }, String(n))
2330
+ );
1021
2331
  }
1022
2332
  };
2333
+ function blockPresentationProps(props) {
2334
+ let decoration = {};
2335
+ for (let [property, value] of Object.entries(props))
2336
+ (property === "className" || property === "style" || property === "title" || property.startsWith("data-") || property.startsWith("aria-")) && (decoration[property] = value);
2337
+ return Object.keys(decoration).length > 0 ? decoration : void 0;
2338
+ }
2339
+ function applyBlockPresentationProps(nativeView, decoration) {
2340
+ if (!decoration) return nativeView;
2341
+ if (Array.isArray(nativeView))
2342
+ return nativeView.map((child) => applyBlockPresentationProps(child, decoration));
2343
+ if (!import_react11.default.isValidElement(nativeView)) return nativeView;
2344
+ if (nativeView.type === import_react11.default.Fragment) {
2345
+ let children = import_react11.default.Children.map(
2346
+ nativeView.props.children,
2347
+ (child) => applyBlockPresentationProps(child, decoration)
2348
+ );
2349
+ return import_react11.default.cloneElement(nativeView, void 0, children);
2350
+ }
2351
+ return import_react11.default.cloneElement(
2352
+ nativeView,
2353
+ mergeNodePresentationProps(nativeView.props, decoration)
2354
+ );
2355
+ }
1023
2356
  var defaultBlockComponents = {
1024
- paragraph: ({ inlines, raw, meta, children }) => {
1025
- if (children !== void 0) {
1026
- return import_react5.default.createElement(
1027
- "p",
1028
- {
1029
- className: "markdown-paragraph"
1030
- },
1031
- children
2357
+ paragraph: (props) => {
2358
+ let { inlines, raw, meta, children } = props, decoration = blockPresentationProps(props);
2359
+ if (children !== void 0)
2360
+ return applyBlockPresentationProps(
2361
+ import_react11.default.createElement("p", { className: "markdown-paragraph" }, children),
2362
+ decoration
1032
2363
  );
1033
- }
1034
- const segments = Array.isArray(meta?.mixedSegments) ? meta?.mixedSegments : void 0;
2364
+ let segments = Array.isArray(meta?.mixedSegments) ? meta?.mixedSegments : void 0;
1035
2365
  if (segments && segments.length > 0) {
1036
- const structured = renderParagraphMixedSegments(segments, defaultInlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
1037
- if (structured.length === 1) {
1038
- return structured[0];
1039
- }
1040
- return import_react5.default.createElement(import_react5.default.Fragment, {}, ...structured);
2366
+ let structured = renderParagraphMixedSegments(segments, defaultInlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
2367
+ return structured.length === 1 ? applyBlockPresentationProps(structured[0], decoration) : applyBlockPresentationProps(
2368
+ import_react11.default.createElement(import_react11.default.Fragment, {}, ...structured),
2369
+ decoration
2370
+ );
1041
2371
  }
1042
- const filteredInlines = inlines && raw && inlines.length > 0 ? inlines.filter((node) => !(node.kind === "text" && node.text === raw)) : inlines ?? [];
1043
- const effectiveInlines = filteredInlines.length > 0 ? filteredInlines : raw ? [
2372
+ let filteredInlines = inlines && raw && inlines.length > 0 ? inlines.filter((node) => !(node.kind === "text" && node.text === raw)) : inlines ?? [], effectiveInlines = filteredInlines.length > 0 ? filteredInlines : raw ? [
1044
2373
  {
1045
2374
  kind: "text",
1046
2375
  text: raw
1047
2376
  }
1048
2377
  ] : [];
1049
- return import_react5.default.createElement(
1050
- "p",
1051
- {
1052
- className: "markdown-paragraph"
1053
- },
1054
- effectiveInlines.length > 0 ? renderInlineNodes(effectiveInlines, defaultInlineComponents) : raw ?? ""
2378
+ return applyBlockPresentationProps(
2379
+ import_react11.default.createElement(
2380
+ "p",
2381
+ { className: "markdown-paragraph" },
2382
+ effectiveInlines.length > 0 ? renderInlineNodes(effectiveInlines, defaultInlineComponents) : raw ?? ""
2383
+ ),
2384
+ decoration
1055
2385
  );
1056
2386
  },
1057
- heading: ({ level, inlines, text, meta }) => {
1058
- const tag = `h${level}`;
1059
- const onlyPlainText = Array.isArray(inlines) && inlines.length > 0 && inlines.every((node) => node.kind === "text");
1060
- const children = onlyPlainText ? inlines.map((node) => node.kind === "text" ? node.text : "").join("") : renderInlineNodes(inlines, defaultInlineComponents);
1061
- const headingId = typeof meta?.headingId === "string" && meta.headingId.length > 0 ? meta.headingId : void 0;
1062
- return import_react5.default.createElement(
1063
- tag,
1064
- {
1065
- className: `markdown-heading markdown-h${level}`,
1066
- ...text ? { "data-heading-text": text } : {},
1067
- ...headingId ? { id: headingId, "data-heading-id": headingId } : {}
1068
- },
1069
- children
2387
+ heading: (props) => {
2388
+ let { level, inlines, text, meta, children } = props, decoration = blockPresentationProps(props), tag = `h${level}`, onlyPlainText = Array.isArray(inlines) && inlines.length > 0 && inlines.every((node) => node.kind === "text"), content = children !== void 0 ? children : onlyPlainText ? inlines.map((node) => node.kind === "text" ? node.text : "").join("") : renderInlineNodes(inlines, defaultInlineComponents), headingId = typeof meta?.headingId == "string" && meta.headingId.length > 0 ? meta.headingId : void 0;
2389
+ return applyBlockPresentationProps(
2390
+ import_react11.default.createElement(
2391
+ tag,
2392
+ {
2393
+ className: `markdown-heading markdown-h${level}`,
2394
+ ...text ? { "data-heading-text": text } : {},
2395
+ ...headingId ? { id: headingId, "data-heading-id": headingId } : {}
2396
+ },
2397
+ content
2398
+ ),
2399
+ decoration
1070
2400
  );
1071
2401
  },
1072
- code: ({ html, meta, lines, lang, preAttrs, codeAttrs }) => {
1073
- const language = typeof lang === "string" ? lang : typeof meta?.lang === "string" ? String(meta.lang) : "text";
1074
- if (html) {
1075
- return import_react5.default.createElement("div", {
1076
- className: `markdown-code-block language-${language || "text"}`,
2402
+ code: ({ html, meta, lines, children, lang, preAttrs, codeAttrs }) => {
2403
+ let language = (typeof lang == "string" ? lang : typeof meta?.lang == "string" ? String(meta.lang) : "").trim();
2404
+ if (children !== void 0) {
2405
+ let preAttributes = attrsToProps(preAttrs), codeAttributes = attrsToProps(codeAttrs), preClassName = [preAttributes.className, "markdown-code-block", language ? `language-${language}` : ""].filter(Boolean).join(" "), codeClassName = [codeAttributes.className, language ? `language-${language}` : ""].filter(Boolean).join(" ");
2406
+ return import_react11.default.createElement(
2407
+ "div",
2408
+ { className: language ? `markdown-code-block language-${language}` : "markdown-code-block" },
2409
+ import_react11.default.createElement(
2410
+ "pre",
2411
+ {
2412
+ ...preAttributes,
2413
+ className: preClassName
2414
+ },
2415
+ import_react11.default.createElement(
2416
+ "code",
2417
+ {
2418
+ ...codeAttributes,
2419
+ ...codeClassName ? { className: codeClassName } : {}
2420
+ },
2421
+ children
2422
+ )
2423
+ )
2424
+ );
2425
+ }
2426
+ if (html)
2427
+ return import_react11.default.createElement("div", {
2428
+ className: language ? `markdown-code-block language-${language}` : "markdown-code-block",
1077
2429
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: highlighted HTML is generated by our sanitizer */
1078
2430
  dangerouslySetInnerHTML: { __html: html }
1079
2431
  });
1080
- }
1081
- const code = meta?.code || "";
2432
+ let code = meta?.code || "";
1082
2433
  if (lines && lines.length > 0) {
1083
- const preAttributes = attrsToProps(preAttrs);
1084
- const codeAttributes = attrsToProps(codeAttrs);
1085
- return import_react5.default.createElement(
2434
+ let preAttributes = attrsToProps(preAttrs), codeAttributes = attrsToProps(codeAttrs), preClassName = [preAttributes.className, "markdown-code-block", language ? `language-${language}` : ""].filter(Boolean).join(" "), codeClassName = [codeAttributes.className, language ? `language-${language}` : ""].filter(Boolean).join(" ");
2435
+ return import_react11.default.createElement(
1086
2436
  "pre",
1087
2437
  {
1088
2438
  ...preAttributes,
1089
- className: preAttributes.className ? `${preAttributes.className} markdown-code-block language-${language || "text"}` : `markdown-code-block language-${language || "text"}`
2439
+ className: preClassName
1090
2440
  },
1091
- import_react5.default.createElement(
2441
+ import_react11.default.createElement(
1092
2442
  "code",
1093
2443
  {
1094
2444
  ...codeAttributes,
1095
- className: codeAttributes.className ? `${codeAttributes.className} language-${language || "text"}` : `language-${language || "text"}`
2445
+ ...codeClassName ? { className: codeClassName } : {}
1096
2446
  },
1097
2447
  lines.map(
1098
- (line) => import_react5.default.createElement("span", {
2448
+ (line) => import_react11.default.createElement("span", {
1099
2449
  key: line.id,
1100
2450
  className: "line",
1101
2451
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: line HTML is sanitized server-side */
@@ -1105,29 +2455,26 @@ var defaultBlockComponents = {
1105
2455
  )
1106
2456
  );
1107
2457
  }
1108
- return import_react5.default.createElement("pre", {
1109
- className: `markdown-code-block language-${language || "text"}`,
2458
+ return import_react11.default.createElement("pre", {
2459
+ className: language ? `markdown-code-block language-${language}` : "markdown-code-block",
1110
2460
  children: code
1111
2461
  });
1112
2462
  },
1113
- blockquote: ({ inlines, renderedContent }) => import_react5.default.createElement(
2463
+ blockquote: ({ inlines, renderedContent }) => import_react11.default.createElement(
1114
2464
  "blockquote",
1115
2465
  {
1116
2466
  className: "markdown-blockquote"
1117
2467
  },
1118
2468
  renderedContent ?? renderInlineNodes(inlines, defaultInlineComponents)
1119
2469
  ),
1120
- hr: (props) => import_react5.default.createElement("hr", props),
2470
+ hr: (props) => import_react11.default.createElement("hr", props),
1121
2471
  list: ({ ordered, items }) => {
1122
- if (items.length === 0) {
2472
+ if (items.length === 0)
1123
2473
  return null;
1124
- }
1125
- const tag = ordered ? "ol" : "ul";
1126
- const listStyle = ordered ? {
1127
- ["--list-indent"]: `calc(2.5rem + ${String(items.length).length}ch)`
1128
- } : void 0;
1129
- const listItems = items.map(
1130
- (item, index) => import_react5.default.createElement(
2474
+ let tag = ordered ? "ol" : "ul", listStyle = ordered ? {
2475
+ "--list-indent": `calc(2.5rem + ${String(items.length).length}ch)`
2476
+ } : void 0, listItems = items.map(
2477
+ (item, index) => import_react11.default.createElement(
1131
2478
  "li",
1132
2479
  {
1133
2480
  key: index,
@@ -1138,7 +2485,7 @@ var defaultBlockComponents = {
1138
2485
  renderInlineNodes(item, defaultInlineComponents)
1139
2486
  )
1140
2487
  );
1141
- return import_react5.default.createElement(
2488
+ return import_react11.default.createElement(
1142
2489
  tag,
1143
2490
  {
1144
2491
  className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
@@ -1147,206 +2494,69 @@ var defaultBlockComponents = {
1147
2494
  listItems
1148
2495
  );
1149
2496
  },
1150
- html: ({ __trustedHtml, elements }) => {
1151
- const raw = typeof __trustedHtml === "string" ? __trustedHtml : __trustedHtml.toString();
1152
- const htmlString = typeof window === "undefined" ? raw : (0, import_core.sanitizeHTML)(raw);
1153
- if (typeof window !== "undefined" && elements) {
1154
- const content = mapHtmlToReact(htmlString, elements);
1155
- return import_react5.default.createElement("div", { className: "markdown-html" }, content);
2497
+ html: ({ __trustedHtml, elements, isSanitized, literalTagContent, children }) => {
2498
+ if (children !== void 0)
2499
+ return import_react11.default.createElement("div", { className: "markdown-html" }, children);
2500
+ let raw = typeof __trustedHtml == "string" ? __trustedHtml : __trustedHtml.toString(), htmlString = isSanitized || typeof window > "u" ? raw : (0, import_core4.sanitizeHTML)(raw);
2501
+ if (typeof window < "u" && elements) {
2502
+ let content = mapHtmlToReact(htmlString, elements, literalTagContent);
2503
+ return import_react11.default.createElement("div", { className: "markdown-html" }, content);
1156
2504
  }
1157
- return import_react5.default.createElement("div", {
2505
+ return import_react11.default.createElement("div", {
1158
2506
  className: "markdown-html",
1159
2507
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: htmlString is sanitized before injection */
1160
2508
  dangerouslySetInnerHTML: { __html: htmlString }
1161
2509
  });
1162
2510
  },
1163
- mdx: ({ compiledRef, compiledModule, status, errorMessage, raw }) => {
1164
- const [Comp, setComp] = import_react5.default.useState(null);
1165
- const [internalError, setInternalError] = import_react5.default.useState(null);
1166
- const [renderError, setRenderError] = import_react5.default.useState(null);
1167
- const [retryKey, setRetryKey] = import_react5.default.useState(0);
1168
- const hydrationContext = import_react5.default.useContext(MdxHydrationContext);
1169
- const hydrationController = hydrationContext?.controller ?? null;
1170
- const hydrationOptions = hydrationContext?.options;
1171
- const containerRef = import_react5.default.useRef(null);
1172
- const deferHydration = hydrationOptions?.strategy === "visible";
1173
- const shouldHydrate = useDeferredRender(
1174
- containerRef,
1175
- deferHydration ? {
1176
- enabled: true,
1177
- rootMargin: hydrationOptions?.rootMargin,
1178
- idleTimeoutMs: hydrationOptions?.idleTimeoutMs,
1179
- debounceMs: hydrationOptions?.debounceMs
1180
- } : { enabled: false }
1181
- );
1182
- const resolvedId = compiledModule?.id ?? (compiledRef?.id && compiledRef.id !== "pending" ? compiledRef.id : void 0);
1183
- const handleRetry = import_react5.default.useCallback(() => {
1184
- setInternalError(null);
1185
- setRenderError(null);
1186
- setComp(null);
1187
- setRetryKey((prev) => prev + 1);
1188
- }, []);
1189
- const handleRuntimeError = import_react5.default.useCallback(
1190
- (error) => {
1191
- const message2 = error instanceof Error ? error.message : String(error);
1192
- setRenderError(message2);
1193
- markMdxHydrationError(resolvedId ?? compiledRef?.id);
1194
- },
1195
- [resolvedId, compiledRef?.id]
1196
- );
1197
- const effectiveStatus = status ? status : resolvedId ? "compiled" : "pending";
1198
- const failureMessage = errorMessage ?? internalError ?? renderError ?? null;
1199
- const moduleDependencies = compiledModule?.dependencies;
1200
- import_react5.default.useEffect(() => {
1201
- if (!shouldHydrate) {
1202
- return;
1203
- }
1204
- if (status === "error") {
1205
- markMdxHydrationError(resolvedId ?? compiledRef?.id);
1206
- return;
1207
- }
1208
- let cancelled = false;
1209
- async function ensure() {
1210
- let permit = null;
1211
- try {
1212
- if (status === "error" || !resolvedId || resolvedId === "pending") {
1213
- if (!cancelled) {
1214
- setComp(null);
1215
- setInternalError(null);
1216
- }
1217
- return;
1218
- }
1219
- if (hydrationController) {
1220
- permit = await hydrationController.acquire();
1221
- if (cancelled) {
1222
- permit.release();
1223
- return;
1224
- }
1225
- }
1226
- setInternalError(null);
1227
- setRenderError(null);
1228
- markMdxHydrationStart(resolvedId);
1229
- const { getMDXComponentFactory: getMDXComponentFactory2, registerInlineMdxModule: registerInlineMdxModule2 } = await loadMdxRuntime();
1230
- if (compiledModule?.code) {
1231
- registerInlineMdxModule2({
1232
- id: compiledModule.id,
1233
- code: compiledModule.code,
1234
- dependencies: moduleDependencies ?? []
1235
- });
1236
- }
1237
- const factory = getMDXComponentFactory2();
1238
- const C = await factory.createComponent({ id: resolvedId });
1239
- if (!cancelled) {
1240
- setComp(() => C);
1241
- setInternalError(null);
1242
- markMdxHydrated(resolvedId);
1243
- }
1244
- } catch (error) {
1245
- if (!cancelled) {
1246
- const message2 = error instanceof Error ? error.message : String(error);
1247
- setInternalError(message2);
1248
- markMdxHydrationError(resolvedId);
1249
- }
1250
- } finally {
1251
- permit?.release();
1252
- }
1253
- }
1254
- ensure();
1255
- return () => {
1256
- cancelled = true;
1257
- };
1258
- }, [compiledModule?.id, compiledModule?.code, moduleDependencies, resolvedId, status, shouldHydrate, retryKey]);
1259
- const compileMode = compiledModule?.source === "worker" || compiledRef?.id?.startsWith("worker:") ? "worker" : "server";
1260
- const pendingId = resolvedId && resolvedId !== "pending" ? resolvedId : compiledRef?.id ?? "pending";
1261
- const waitingForVisibility = deferHydration && !shouldHydrate && Boolean(resolvedId);
1262
- const pendingLabel = waitingForVisibility ? "MDX ready (hydrate on view)\u2026" : compileMode === "worker" ? "Compiling MDX (client)\u2026" : "Compiling MDX (server)\u2026";
1263
- const message = failureMessage ?? (compileMode === "worker" ? "MDX compilation failed in client mode. Try switching back to server rendering or restarting the stream." : "MDX compilation failed. Try restarting the stream.");
1264
- const rawFallback = typeof raw === "string" && raw.trim().length > 0 ? import_react5.default.createElement("pre", { className: "markdown-mdx-fallback" }, raw) : null;
1265
- const allowRetry = Boolean(internalError || renderError);
1266
- const retryButton = allowRetry ? import_react5.default.createElement(
1267
- "button",
1268
- {
1269
- type: "button",
1270
- className: "markdown-mdx-retry",
1271
- onClick: handleRetry
1272
- },
1273
- "Retry hydration"
1274
- ) : null;
1275
- const errorPanel = import_react5.default.createElement(
2511
+ mdx: ({ raw, meta }) => {
2512
+ let originalType = typeof meta?.originalType == "string" ? String(meta.originalType) : void 0, mixedSegments = Array.isArray(meta?.mixedSegments) ? meta.mixedSegments : void 0;
2513
+ if (originalType === "paragraph" && !meta?.mdxStandalone && mixedSegments && mixedSegments.length > 0) {
2514
+ let structured = renderParagraphMixedSegments(mixedSegments, defaultInlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
2515
+ return structured.length === 1 ? structured[0] : import_react11.default.createElement(import_react11.default.Fragment, {}, ...structured);
2516
+ }
2517
+ return import_react11.default.createElement(
1276
2518
  "div",
1277
- { className: "markdown-mdx-error" },
1278
- import_react5.default.createElement(import_react5.default.Fragment, null, import_react5.default.createElement("strong", null, "MDX failed"), import_react5.default.createElement("div", null, message))
2519
+ { className: "markdown-mdx-inert", "data-diagnostic": "MDX requires explicit engines.mdx in trusted-mdx mode" },
2520
+ import_react11.default.createElement("pre", null, import_react11.default.createElement("code", null, raw ?? ""))
1279
2521
  );
1280
- if (Comp && !failureMessage) {
1281
- return import_react5.default.createElement(
1282
- "div",
1283
- {
1284
- className: "markdown-mdx",
1285
- ref: containerRef,
1286
- "data-mdx-ref": resolvedId ?? compiledRef?.id ?? "compiled",
1287
- "data-mdx-status": failureMessage ? "error" : "compiled",
1288
- "data-mdx-mode": compileMode
1289
- },
1290
- import_react5.default.createElement(
1291
- MdxRuntimeBoundary,
1292
- { resetKey: retryKey, onError: handleRuntimeError },
1293
- import_react5.default.createElement(Comp, {})
1294
- )
1295
- );
1296
- }
1297
- if (failureMessage) {
1298
- return import_react5.default.createElement(
1299
- "div",
1300
- {
1301
- className: "markdown-mdx",
1302
- ref: containerRef,
1303
- "data-mdx-ref": pendingId,
1304
- "data-mdx-status": "error",
1305
- "data-mdx-mode": compileMode
1306
- },
1307
- errorPanel,
1308
- rawFallback,
1309
- retryButton
1310
- );
1311
- }
1312
- if (!Comp) {
1313
- return import_react5.default.createElement(
1314
- "div",
1315
- {
1316
- className: "markdown-mdx",
1317
- ref: containerRef,
1318
- "data-mdx-ref": pendingId,
1319
- "data-mdx-status": "pending",
1320
- "data-mdx-mode": compileMode
1321
- },
1322
- pendingLabel
1323
- );
1324
- }
1325
2522
  },
1326
2523
  // Footnotes block rendered at page end
1327
2524
  footnotes: ({ items }) => {
1328
- if (!items || items.length === 0) return import_react5.default.createElement(import_react5.default.Fragment, null);
1329
- const listItems = items.map(
1330
- (item) => import_react5.default.createElement(
2525
+ if (!items || items.length === 0) return import_react11.default.createElement(import_react11.default.Fragment, null);
2526
+ let listItems = items.map(
2527
+ (item) => import_react11.default.createElement(
1331
2528
  "li",
1332
2529
  { key: item.number, id: `fn:${item.number}` },
1333
2530
  renderInlineNodes(item.inlines, defaultInlineComponents),
1334
- " ",
1335
- import_react5.default.createElement("a", { href: `#fnref:${item.number}`, className: "footnote-backref", "aria-label": "Back to content" }, "\u21A9")
2531
+ ...Array.from({ length: item.refCount ?? 1 }, (_, index) => import_react11.default.createElement(
2532
+ import_react11.default.Fragment,
2533
+ { key: index },
2534
+ " ",
2535
+ import_react11.default.createElement(
2536
+ "a",
2537
+ {
2538
+ href: `#fnref:${item.number}${index > 0 ? `:${index + 1}` : ""}`,
2539
+ className: "footnote-backref",
2540
+ "aria-label": index > 0 ? `Back to content (reference ${index + 1})` : "Back to content",
2541
+ style: { color: "var(--foreground)", textDecoration: "underline" }
2542
+ },
2543
+ "\u21A9",
2544
+ index > 0 ? import_react11.default.createElement("sup", null, String(index + 1)) : null
2545
+ )
2546
+ ))
1336
2547
  )
1337
2548
  );
1338
- return import_react5.default.createElement("section", { className: "footnotes" }, import_react5.default.createElement("hr", {}), import_react5.default.createElement("ol", {}, listItems));
2549
+ return import_react11.default.createElement("section", { className: "footnotes" }, import_react11.default.createElement("hr", {}), import_react11.default.createElement("ol", {}, listItems));
1339
2550
  },
1340
2551
  // Footnote definition placeholders (render nothing)
1341
- "footnote-def": () => import_react5.default.createElement(import_react5.default.Fragment, null),
2552
+ "footnote-def": () => import_react11.default.createElement(import_react11.default.Fragment, null),
1342
2553
  // Callouts block
1343
2554
  callout: ({ kind, inlines = [] }) => {
1344
- const tone = (kind || "NOTE").toUpperCase();
1345
- const title = tone.charAt(0) + tone.slice(1).toLowerCase();
1346
- return import_react5.default.createElement(
2555
+ let tone = (kind || "NOTE").toUpperCase(), title = tone.charAt(0) + tone.slice(1).toLowerCase();
2556
+ return import_react11.default.createElement(
1347
2557
  "div",
1348
2558
  { className: `markdown-callout markdown-callout-${tone.toLowerCase()} border rounded p-3 my-3` },
1349
- import_react5.default.createElement("div", { className: "font-semibold mb-1" }, title),
2559
+ import_react11.default.createElement("div", { className: "font-semibold mb-1" }, title),
1350
2560
  inlines.length > 0 ? renderInlineNodes(inlines, defaultInlineComponents) : null
1351
2561
  );
1352
2562
  },
@@ -1357,11 +2567,9 @@ var defaultBlockComponents = {
1357
2567
  align,
1358
2568
  elements
1359
2569
  }) => {
1360
- const El = getDefaultTableElements(elements);
1361
- const renderCells = (cells, tag, rowIdx) => cells.map((cell, i) => {
1362
- const columnAlign = align?.[i] ?? void 0;
1363
- const cellStyle = columnAlign ? { textAlign: columnAlign } : void 0;
1364
- return import_react5.default.createElement(
2570
+ let El = getDefaultTableElements(elements), renderCells = (cells, tag, rowIdx) => cells.map((cell, i) => {
2571
+ let columnAlign = align?.[i] ?? void 0, cellStyle = columnAlign ? { textAlign: columnAlign } : void 0;
2572
+ return import_react11.default.createElement(
1365
2573
  tag === "th" ? El.Th : El.Td,
1366
2574
  {
1367
2575
  key: `${rowIdx}-${i}`,
@@ -1372,54 +2580,228 @@ var defaultBlockComponents = {
1372
2580
  renderInlineNodes(cell, defaultInlineComponents)
1373
2581
  );
1374
2582
  });
1375
- return import_react5.default.createElement(
2583
+ return import_react11.default.createElement(
1376
2584
  El.Table,
1377
2585
  { className: "markdown-table" },
1378
- header && header.length > 0 ? import_react5.default.createElement(El.Thead, {}, import_react5.default.createElement(El.Tr, {}, renderCells(header, "th", -1))) : null,
1379
- import_react5.default.createElement(
2586
+ header && header.length > 0 ? import_react11.default.createElement(El.Thead, {}, import_react11.default.createElement(El.Tr, {}, renderCells(header, "th", -1))) : null,
2587
+ rows && rows.length > 0 ? import_react11.default.createElement(
1380
2588
  El.Tbody,
1381
2589
  {},
1382
- rows.map((row, r) => import_react5.default.createElement(El.Tr, { key: r }, renderCells(row, "td", r)))
1383
- )
2590
+ rows.map((row, r) => import_react11.default.createElement(El.Tr, { key: r }, renderCells(row, "td", r)))
2591
+ ) : null
1384
2592
  );
1385
2593
  }
1386
- };
1387
- var ComponentRegistry = class {
1388
- constructor(blockComponents = {}, inlineComponents = {}) {
1389
- this.blockComponentMapCache = null;
2594
+ }, ComponentRegistry = class {
2595
+ constructor(options) {
2596
+ this.nodePresentations = {};
2597
+ this.tableVirtualization = DEFAULT_TABLE_VIRTUALIZATION_CONFIG;
2598
+ this.tableVirtualizationListeners = /* @__PURE__ */ new Set();
2599
+ this.codeVirtualization = DEFAULT_VIRTUALIZED_CODE_CONFIG;
2600
+ this.codeVirtualizationListeners = /* @__PURE__ */ new Set();
1390
2601
  this.inlineComponentMapCache = null;
1391
- this.blockComponents = { ...defaultBlockComponents, ...blockComponents };
1392
- this.inlineComponents = { ...defaultInlineComponents, ...inlineComponents };
1393
- this.htmlElements = getDefaultHtmlElements();
1394
- this.tableElements = getDefaultTableElements();
2602
+ this.controls = !1;
2603
+ this.animatedOptions = null;
2604
+ this.animationTimeline = null;
2605
+ this.hasFilterConfig = !1;
2606
+ this.mathEngine = options?.engines?.math, this.mermaidEngine = options?.engines?.mermaid, this.inlineComponents = { ...defaultInlineComponents }, this.htmlElements = getDefaultHtmlElements(), options?.urlTransform && (this.urlTransform = options.urlTransform), options?.contentComponents && (this.contentComponents = options.contentComponents);
2607
+ let defaultHtmlInlineRenderer = (node) => renderHtmlInlineNode(node, node.children, this.htmlElements, void 0, node.textValue, this.urlTransform);
2608
+ this.defaultHtmlInlineRenderer = defaultHtmlInlineRenderer, this.inlineComponents.html = defaultHtmlInlineRenderer, this.tableElements = getDefaultTableElements(), this.setNodePresentations(options?.components), options?.tableVirtualization !== void 0 && this.setTableVirtualization(options.tableVirtualization), options?.codeVirtualization !== void 0 && this.setCodeVirtualization(options.codeVirtualization), options?.controls !== void 0 && this.setControls(options.controls), options?.controlsComponent !== void 0 && this.setControlsComponent(options.controlsComponent), options?.animated !== void 0 && this.setAnimated(options.animated), options && this.setElementFilters(options);
1395
2609
  }
1396
- /**
1397
- * Update block components
1398
- */
1399
- setBlockComponents(components) {
1400
- this.blockComponents = { ...this.blockComponents, ...components };
1401
- this.blockComponentMapCache = null;
2610
+ setLinkSafetyRenderer(renderer) {
2611
+ this.inlineComponents = {
2612
+ ...this.inlineComponents,
2613
+ link: renderer ?? defaultInlineComponents.link
2614
+ }, this.inlineComponentMapCache = null;
1402
2615
  }
1403
- /**
1404
- * Update inline components
1405
- */
1406
- setInlineComponents(components) {
1407
- this.inlineComponents = { ...this.inlineComponents, ...components };
1408
- this.inlineComponentMapCache = null;
2616
+ hasElementFilters() {
2617
+ return this.hasFilterConfig;
2618
+ }
2619
+ /** Replaces the whole filter configuration at once so prop swaps (allowed -> disallowed) never trip the exclusivity check. */
2620
+ setElementFilters(options) {
2621
+ let { allowedElements, disallowedElements, allowElement, unwrapDisallowed, disableAutolinkProtocols } = options;
2622
+ if (allowedElements && disallowedElements)
2623
+ throw new Error("Cannot specify both allowedElements and disallowedElements; expected one or the other");
2624
+ let toTagSet = (tags) => tags ? new Set(tags.map((tag) => tag.trim().toLowerCase())) : void 0;
2625
+ this.allowedElements = toTagSet(allowedElements), this.disallowedElements = toTagSet(disallowedElements), this.allowElement = allowElement, this.unwrapDisallowed = unwrapDisallowed, this.disableAutolinkProtocols = disableAutolinkProtocols ? new Set(disableAutolinkProtocols.map((protocol) => protocol.trim().toLowerCase().replace(/:$/, ""))) : void 0, this.hasFilterConfig = !!(this.allowedElements || this.disallowedElements || this.allowElement);
2626
+ }
2627
+ isAutolinkProtocolDisabled(href) {
2628
+ if (!this.disableAutolinkProtocols || !href) return !1;
2629
+ let match = /^[a-zA-Z][a-zA-Z0-9+.-]*(?=:)/.exec(href.trim());
2630
+ return match ? this.disableAutolinkProtocols.has(match[0].toLowerCase()) : !1;
2631
+ }
2632
+ isElementAllowed(element, context) {
2633
+ let tag = element.tagName.toLowerCase();
2634
+ return !(this.allowedElements && !this.allowedElements.has(tag) || this.disallowedElements && this.disallowedElements.has(tag) || this.allowElement && !this.allowElement(
2635
+ { tagName: tag, properties: element.properties ?? {}, blockType: element.blockType },
2636
+ context
2637
+ ));
2638
+ }
2639
+ filterElement(element, context, renderElement, renderChildren) {
2640
+ if (!this.hasFilterConfig || this.isElementAllowed(element, context))
2641
+ return renderElement();
2642
+ if (this.unwrapDisallowed && renderChildren) {
2643
+ let children = renderChildren();
2644
+ if (children == null) return null;
2645
+ let key = element.properties?.key;
2646
+ return import_react11.default.createElement(import_react11.default.Fragment, key !== void 0 ? { key } : null, children);
2647
+ }
2648
+ return null;
2649
+ }
2650
+ setUrlTransform(transform) {
2651
+ this.urlTransform = transform;
1409
2652
  }
1410
- /** Update HTML element mapping for html blocks */
1411
- setHtmlElements(map) {
1412
- this.htmlElements = { ...this.htmlElements, ...map };
2653
+ setAnimated(animated) {
2654
+ this.animated = animated, this.animatedOptions = resolveAnimatedOptions(animated), this.animatedOptions ? this.animationTimeline ? this.animationTimeline.updateOptions({
2655
+ maxBacklogMs: this.animatedOptions.maxBacklogMs,
2656
+ stagger: this.animatedOptions.stagger
2657
+ }) : this.animationTimeline = new AnimationTimeline({
2658
+ maxBacklogMs: this.animatedOptions.maxBacklogMs,
2659
+ stagger: this.animatedOptions.stagger
2660
+ }) : (this.animationTimeline && this.animationTimeline.reset(), this.animationTimeline = null);
1413
2661
  }
1414
- /** Update table element mapping for table blocks */
1415
- setTableElements(map) {
1416
- this.tableElements = { ...this.tableElements, ...map };
2662
+ getAnimated() {
2663
+ return this.animated;
2664
+ }
2665
+ getAnimatedOptions() {
2666
+ return this.animatedOptions;
2667
+ }
2668
+ getAnimationTimeline() {
2669
+ return this.animationTimeline;
2670
+ }
2671
+ getRenderInlineContext(isFinalized, blockId, sourceGuard) {
2672
+ let context;
2673
+ return isFinalized ? (blockId && this.animationTimeline && this.animationTimeline.releasePrefix(blockId), context = blockId ? { isFinalized: !0, nodeKeyPrefix: blockId } : void 0) : this.animatedOptions && this.animationTimeline && (context = {
2674
+ isFinalized: !1,
2675
+ animated: this.animatedOptions,
2676
+ timeline: this.animationTimeline,
2677
+ nodeKeyPrefix: blockId
2678
+ }), sourceGuard ? { ...context ?? { isFinalized: isFinalized ?? !1 }, sourceGuard } : context;
2679
+ }
2680
+ resetAnimationTimeline() {
2681
+ this.animationTimeline?.reset();
2682
+ }
2683
+ getUrlTransform() {
2684
+ return this.urlTransform;
2685
+ }
2686
+ releaseFinalizedBlockAnimations(blockId) {
2687
+ this.animationTimeline?.releasePrefix(blockId);
2688
+ }
2689
+ setNodePresentations(presentations) {
2690
+ validateNodePresentations(presentations), this.nodePresentations = presentations ?? {};
2691
+ }
2692
+ getNodePresentation(key) {
2693
+ return resolveNodePresentation(this.nodePresentations, key);
2694
+ }
2695
+ isDefaultHtmlInlineRenderer(renderer) {
2696
+ return !renderer || !this.defaultHtmlInlineRenderer ? !1 : renderer === this.defaultHtmlInlineRenderer;
2697
+ }
2698
+ renderInlinePresentation(node, nativeView, key, context, renderedChildren) {
2699
+ let keyName = node.kind === "plugin" ? `extension:${node.name}` : node.kind === "math-inline" || node.kind === "math-display" ? "inline:math" : `inline:${node.kind}`, presentation = this.getNodePresentation(keyName);
2700
+ if (!presentation) return nativeView;
2701
+ let hasPluginComponent = node.kind === "plugin" && (this.inlineComponents[node.name] !== void 0 || this.inlineComponents.plugin !== void 0), preparedNativeView = node.kind === "plugin" && !hasPluginComponent && renderedChildren !== void 0 ? import_react11.default.createElement(import_react11.default.Fragment, { key }, renderedChildren) : nativeView, presentedNode = node;
2702
+ if ("view" in presentation && presentation.view) {
2703
+ let transform = this.urlTransform ?? import_core4.defaultUrlTransform;
2704
+ node.kind === "link" ? presentedNode = {
2705
+ ...node,
2706
+ href: transform(node.href ?? "", "href", { source: "markdown" }) ?? void 0
2707
+ } : node.kind === "image" && (presentedNode = {
2708
+ ...node,
2709
+ src: transform(node.src ?? "", "src", { source: "markdown" }) ?? ""
2710
+ });
2711
+ }
2712
+ let metadata = Object.freeze({
2713
+ id: `${context?.nodeKeyPrefix ?? "inline"}:${String(key)}`,
2714
+ type: keyName,
2715
+ isFinalized: context?.isFinalized ?? !1
2716
+ }), source = () => (context?.sourceGuard?.(), inlineToPlainText([node])), actions = Object.freeze({
2717
+ readSource: source,
2718
+ copy: () => copyToClipboard(source()),
2719
+ download: () => downloadFile(source(), `${node.kind}.txt`)
2720
+ }), children = node.kind === "math-inline" || node.kind === "math-display" ? nativeView : renderedChildren ?? (import_react11.default.isValidElement(preparedNativeView) ? preparedNativeView.props.children : void 0);
2721
+ return renderPresentedNode(presentation, preparedNativeView, {
2722
+ key,
2723
+ metadata,
2724
+ actions,
2725
+ viewProps: { node: presentedNode, children, metadata, actions }
2726
+ });
2727
+ }
2728
+ renderHtmlPresentation(tagName, properties, nativeView, children, key, ownerId, isFinalized = !1, sourceGuard) {
2729
+ let keyName = `html:${tagName.toLowerCase()}`, presentation = this.getNodePresentation(keyName);
2730
+ if (!presentation) return nativeView;
2731
+ let viewProperties = {};
2732
+ for (let [property, value] of Object.entries(properties))
2733
+ property !== "key" && (viewProperties[property] = value);
2734
+ let source = () => (sourceGuard?.(), presentationText(children)), metadata = Object.freeze({
2735
+ id: `${ownerId ?? "html"}:${String(key)}`,
2736
+ type: keyName,
2737
+ isFinalized
2738
+ }), actions = Object.freeze({
2739
+ readSource: source,
2740
+ copy: () => copyToClipboard(source()),
2741
+ download: () => downloadFile(source(), `${tagName.toLowerCase()}.txt`)
2742
+ });
2743
+ return renderPresentedNode(presentation, nativeView, {
2744
+ key,
2745
+ metadata,
2746
+ actions,
2747
+ viewProps: { tagName: tagName.toLowerCase(), properties: viewProperties, children, metadata, actions }
2748
+ });
2749
+ }
2750
+ renderComponentPresentation(name, nativeView, children, key, status, rawSource, ownerId, sourceGuard) {
2751
+ let keyName = `component:${name}`, presentation = this.getNodePresentation(keyName);
2752
+ if (!presentation) return nativeView;
2753
+ if ("view" in presentation && presentation.view)
2754
+ throw new TypeError(`node presentation for ${keyName}: headless views are not supported for restricted content components`);
2755
+ let preparedNativeView = presentation.props ? import_react11.default.cloneElement(
2756
+ nativeView,
2757
+ mergeNodePresentationProps(nativeView.props, presentation.props)
2758
+ ) : nativeView;
2759
+ if (!("wrapper" in presentation) || !presentation.wrapper) return preparedNativeView;
2760
+ let source = () => (sourceGuard?.(), rawSource ?? presentationText(children)), metadata = Object.freeze({
2761
+ id: `${ownerId ?? "component"}:${String(key)}`,
2762
+ type: keyName,
2763
+ isFinalized: status === "closed"
2764
+ }), actions = Object.freeze({
2765
+ readSource: source,
2766
+ copy: () => copyToClipboard(source()),
2767
+ download: () => downloadFile(source(), `${name}.txt`)
2768
+ });
2769
+ return import_react11.default.createElement(presentation.wrapper, { key, children: preparedNativeView, metadata, actions });
2770
+ }
2771
+ /** Get HTML element mapping */
2772
+ getHtmlElements() {
2773
+ return this.htmlElements;
2774
+ }
2775
+ /** Update literal tag content list */
2776
+ setLiteralTagContent(tags) {
2777
+ this.literalTagContent = tags;
2778
+ }
2779
+ /** Get literal tag content list */
2780
+ getLiteralTagContent() {
2781
+ return this.literalTagContent;
2782
+ }
2783
+ setControls(controls) {
2784
+ this.controls = controls ?? !1;
2785
+ }
2786
+ getControls() {
2787
+ return this.controls;
2788
+ }
2789
+ setControlsComponent(component) {
2790
+ this.controlsComponent = component;
2791
+ }
2792
+ getControlsComponent() {
2793
+ if (this.controlsComponent)
2794
+ return this.controlsComponent;
1417
2795
  }
1418
2796
  /**
1419
2797
  * Get block component
1420
2798
  */
1421
2799
  getBlockComponent(type) {
1422
- return this.blockComponents[type] || this.blockComponents.paragraph;
2800
+ return defaultBlockComponents[type] ?? defaultBlockComponents.paragraph;
2801
+ }
2802
+ getCodeNodeView() {
2803
+ let presentation = this.getNodePresentation("code");
2804
+ return presentation && "view" in presentation ? presentation.view : void 0;
1423
2805
  }
1424
2806
  /**
1425
2807
  * Get inline components
@@ -1427,112 +2809,309 @@ var ComponentRegistry = class {
1427
2809
  getInlineComponents() {
1428
2810
  return this.inlineComponents;
1429
2811
  }
1430
- getBlockComponentMap() {
1431
- if (!this.blockComponentMapCache) {
1432
- this.blockComponentMapCache = { ...this.blockComponents };
1433
- }
1434
- return this.blockComponentMapCache;
2812
+ getMathEngine() {
2813
+ return this.mathEngine;
1435
2814
  }
1436
- getInlineComponentMap() {
1437
- if (!this.inlineComponentMapCache) {
1438
- this.inlineComponentMapCache = { ...this.inlineComponents };
1439
- }
1440
- return this.inlineComponentMapCache;
2815
+ setMermaidEngine(engine) {
2816
+ this.mermaidEngine = engine;
2817
+ }
2818
+ getMermaidEngine() {
2819
+ return this.mermaidEngine;
2820
+ }
2821
+ setContentComponents(contentComponents) {
2822
+ this.contentComponents = contentComponents;
2823
+ }
2824
+ getContentComponents() {
2825
+ return this.contentComponents;
2826
+ }
2827
+ renderHtmlTree(tree, renderBlock = (block) => this.renderBlock(block), paragraph, parentTagName, renderParagraphPresentation, sourceGuard) {
2828
+ return renderOwnedHtmlTree(
2829
+ tree,
2830
+ this.ownedHtmlRenderContext(renderBlock, paragraph, parentTagName, void 0, renderParagraphPresentation, sourceGuard)
2831
+ );
2832
+ }
2833
+ ownedHtmlRenderContext(renderBlock = (block) => this.renderBlock(block), paragraph, parentTagName, inlineContext, renderParagraphPresentation, sourceGuard) {
2834
+ let renderContext = inlineContext ?? (paragraph ? this.getRenderInlineContext(paragraph.isFinalized, paragraph.id, sourceGuard) : void 0);
2835
+ return {
2836
+ elements: this.htmlElements,
2837
+ renderBlock,
2838
+ renderInline: (nodes, parentTagName2) => renderInlineNodes(nodes, this.inlineComponents, this.urlTransform, this, parentTagName2, renderContext),
2839
+ renderInlinePresentation: (node, nativeView, key, children) => this.renderInlinePresentation(node, nativeView, key, renderContext, children),
2840
+ renderHtmlPresentation: (tagName, properties, nativeView, children, key) => this.renderHtmlPresentation(
2841
+ tagName,
2842
+ properties,
2843
+ nativeView,
2844
+ children,
2845
+ key,
2846
+ renderContext?.nodeKeyPrefix ?? String(paragraph?.id ?? parentTagName ?? "html"),
2847
+ renderContext?.isFinalized ?? paragraph?.isFinalized ?? !1,
2848
+ renderContext?.sourceGuard
2849
+ ),
2850
+ renderComponentPresentation: (name, nativeView, children, key, status, rawSource) => this.renderComponentPresentation(
2851
+ name,
2852
+ nativeView,
2853
+ children,
2854
+ key,
2855
+ status,
2856
+ rawSource,
2857
+ renderContext?.nodeKeyPrefix ?? String(paragraph?.id ?? parentTagName ?? "html"),
2858
+ renderContext?.sourceGuard
2859
+ ),
2860
+ inlineComponents: this.inlineComponents,
2861
+ urlTransform: this.urlTransform,
2862
+ isAutolinkProtocolDisabled: (href) => this.isAutolinkProtocolDisabled(href),
2863
+ filterElement: this.hasElementFilters() ? (element, context, renderElement, renderChildren) => this.filterElement(element, context, renderElement, renderChildren) : void 0,
2864
+ parentTagName,
2865
+ contentComponents: this.contentComponents,
2866
+ renderParagraph: paragraph ? (children) => {
2867
+ let nativeView = import_react11.default.createElement(this.getBlockComponent("paragraph"), {
2868
+ ...this.getBlockProps(paragraph, sourceGuard),
2869
+ children
2870
+ });
2871
+ return renderParagraphPresentation ? renderParagraphPresentation(nativeView) : nativeView;
2872
+ } : void 0
2873
+ };
1441
2874
  }
1442
2875
  getTableElements() {
1443
2876
  return this.tableElements;
1444
2877
  }
2878
+ subscribeTableVirtualization(listener) {
2879
+ return this.tableVirtualizationListeners.add(listener), () => {
2880
+ this.tableVirtualizationListeners.delete(listener);
2881
+ };
2882
+ }
2883
+ setTableVirtualization(options) {
2884
+ this.tableVirtualization = resolveTableVirtualizationConfig(options);
2885
+ for (let listener of this.tableVirtualizationListeners)
2886
+ listener();
2887
+ }
2888
+ getTableVirtualization() {
2889
+ return this.tableVirtualization;
2890
+ }
2891
+ subscribeCodeVirtualization(listener) {
2892
+ return this.codeVirtualizationListeners.add(listener), () => {
2893
+ this.codeVirtualizationListeners.delete(listener);
2894
+ };
2895
+ }
2896
+ setCodeVirtualization(options) {
2897
+ this.codeVirtualization = resolveVirtualizedCodeConfig(options);
2898
+ for (let listener of this.codeVirtualizationListeners)
2899
+ listener();
2900
+ }
2901
+ getCodeVirtualization() {
2902
+ return this.codeVirtualization;
2903
+ }
1445
2904
  /**
1446
2905
  * Render a block
1447
2906
  */
1448
- renderBlock(block) {
1449
- const Component = this.getBlockComponent(block.type);
1450
- const props = this.getBlockProps(block);
1451
- return import_react5.default.createElement(Component, {
1452
- key: block.id,
1453
- ...props
1454
- });
2907
+ renderBlock(block, renderPresentation, sourceGuard) {
2908
+ let meta = block.payload.meta, sourceOwnedHtmlTree = meta?.htmlOwnership === !0 && Array.isArray(meta.htmlTree) ? meta.htmlTree : void 0;
2909
+ if (block.type === "paragraph" && sourceOwnedHtmlTree)
2910
+ return import_react11.default.createElement(
2911
+ import_react11.default.Fragment,
2912
+ {},
2913
+ this.renderHtmlTree(sourceOwnedHtmlTree, void 0, block, void 0, renderPresentation, sourceGuard)
2914
+ );
2915
+ if (block.type === "paragraph" && meta?.htmlParagraphTree)
2916
+ return import_react11.default.createElement(
2917
+ import_react11.default.Fragment,
2918
+ {},
2919
+ this.renderHtmlTree(meta.htmlParagraphTree, void 0, block, void 0, renderPresentation, sourceGuard)
2920
+ );
2921
+ let Component = this.getBlockComponent(block.type), props = this.getBlockProps(block, sourceGuard), paragraphGroups = block.type === "paragraph" && Array.isArray(block.payload.meta?.mixedSegments) && Array.isArray(props.children) ? props.children : void 0;
2922
+ paragraphGroups && (props.children = paragraphGroups.flatMap(
2923
+ (group) => import_react11.default.isValidElement(group) && group.type === "p" ? import_react11.default.Children.toArray(group.props.children) : [group]
2924
+ ));
2925
+ let element = paragraphGroups ? import_react11.default.createElement(import_react11.default.Fragment, { key: block.id }, ...paragraphGroups.map(
2926
+ (group, index) => import_react11.default.isValidElement(group) && group.type === "p" ? import_react11.default.createElement(Component, { ...props, key: `${block.id}-${index}`, children: group.props.children }) : group
2927
+ )) : import_react11.default.createElement(Component, { key: block.id, ...props }), finalElement = (() => {
2928
+ if (block.type === "code") {
2929
+ let meta2 = block.payload.meta ?? {}, lang = typeof meta2.lang == "string" ? String(meta2.lang) : "", raw = typeof block.payload.raw == "string" ? block.payload.raw : "", metaCode = typeof meta2.code == "string" ? meta2.code : null, normalizedRaw = raw.replace(/\r\n?/g, `
2930
+ `), fenced = (0, import_core4.stripCodeFence)(block.isFinalized ? normalizedRaw : trimProvisionalFenceTail(normalizedRaw)), codeText = metaCode !== null ? metaCode.replace(/\r\n?/g, `
2931
+ `) : fenced.hadFence ? fenced.code : normalizedRaw, codeControls = resolveCodeControls(this.getControls());
2932
+ if (Array.isArray(meta2.diffBlocks) && meta2.diffBlocks.length > 0)
2933
+ return import_react11.default.createElement(DefaultDiffRenderer, {
2934
+ key: block.id,
2935
+ meta: meta2,
2936
+ renderCode: element
2937
+ });
2938
+ if (codeControls.enabled) {
2939
+ let ControlsComponent = this.getControlsComponent(), controlsElement = ControlsComponent ? import_react11.default.createElement(ControlsComponent, {
2940
+ type: "code",
2941
+ blockId: block.id,
2942
+ code: codeText,
2943
+ language: lang,
2944
+ isFinalized: block.isFinalized,
2945
+ onCopy: () => copyToClipboard(codeText),
2946
+ onDownload: () => downloadFile(codeText, getCodeSnippetFilename(lang)),
2947
+ labels: codeControls.labels
2948
+ }) : import_react11.default.createElement(CodeControlsBar, {
2949
+ code: codeText,
2950
+ language: lang,
2951
+ config: codeControls
2952
+ });
2953
+ return import_react11.default.createElement("div", { className: "stream-mdx-code-wrapper relative", key: block.id }, controlsElement, element);
2954
+ }
2955
+ }
2956
+ if (block.type === "table") {
2957
+ let tableControls = resolveTableControls(this.getControls());
2958
+ if (tableControls.enabled) {
2959
+ let meta2 = block.payload.meta ?? {}, header = Array.isArray(meta2.header) ? meta2.header.map((cell) => inlineToPlainText(cell)) : [], rows = Array.isArray(meta2.rows) ? meta2.rows.map((r) => r.map((cell) => inlineToPlainText(cell))) : [], align = Array.isArray(meta2.align) ? meta2.align : void 0, isFinalized = !!block.isFinalized, ControlsComponent = this.getControlsComponent(), controlsElement = ControlsComponent ? import_react11.default.createElement(ControlsComponent, {
2960
+ type: "table",
2961
+ blockId: block.id,
2962
+ headers: header,
2963
+ rows,
2964
+ align,
2965
+ isFinalized,
2966
+ onCopy: (format) => {
2967
+ if (!isFinalized) return;
2968
+ let text = format === "markdown" ? tableToMarkdown(header, rows, align) : tableToTsv(header, rows);
2969
+ return copyToClipboard(text);
2970
+ },
2971
+ onDownload: (format) => {
2972
+ isFinalized && (format === "tsv" ? downloadFile(tableToTsv(header, rows), "table.tsv", "text/tab-separated-values;charset=utf-8") : format === "markdown" ? downloadFile(tableToMarkdown(header, rows, align), "table.md", "text/markdown;charset=utf-8") : downloadFile(tableToCsv(header, rows), "table.csv", "text/csv;charset=utf-8"));
2973
+ },
2974
+ labels: tableControls.labels
2975
+ }) : import_react11.default.createElement(TableControlsBar, {
2976
+ headers: header,
2977
+ rows,
2978
+ align,
2979
+ isFinalized,
2980
+ config: tableControls
2981
+ });
2982
+ return import_react11.default.createElement("div", { className: "stream-mdx-table-wrapper relative", key: block.id }, controlsElement, element);
2983
+ }
2984
+ }
2985
+ return element;
2986
+ })();
2987
+ if (this.hasFilterConfig) {
2988
+ let blockTagName = "";
2989
+ switch (block.type) {
2990
+ case "paragraph":
2991
+ blockTagName = "p";
2992
+ break;
2993
+ case "heading": {
2994
+ let meta2 = block.payload.meta ?? {}, levelFromMeta = typeof meta2.headingLevel == "number" ? meta2.headingLevel : void 0, normalizedLevel = Number.isFinite(levelFromMeta) ? Math.min(Math.max(levelFromMeta, 1), 6) : void 0, rawHeading = typeof block.payload.raw == "string" ? block.payload.raw : "";
2995
+ blockTagName = `h${normalizedLevel ?? this.extractHeadingLevel(rawHeading)}`;
2996
+ break;
2997
+ }
2998
+ case "code":
2999
+ blockTagName = "pre";
3000
+ break;
3001
+ case "blockquote":
3002
+ blockTagName = "blockquote";
3003
+ break;
3004
+ case "hr":
3005
+ blockTagName = "hr";
3006
+ break;
3007
+ case "list":
3008
+ blockTagName = block.payload.meta?.ordered ? "ol" : "ul";
3009
+ break;
3010
+ case "table":
3011
+ blockTagName = "table";
3012
+ break;
3013
+ }
3014
+ if (blockTagName) {
3015
+ let renderChildren = () => {
3016
+ if (block.type === "paragraph" || block.type === "heading")
3017
+ return "children" in props ? props.children : void 0;
3018
+ if (block.type === "blockquote")
3019
+ return "renderedContent" in props ? props.renderedContent : void 0;
3020
+ if (block.type === "code") {
3021
+ let meta2 = block.payload.meta;
3022
+ return (meta2 && typeof meta2 == "object" && "code" in meta2 && typeof meta2.code == "string" ? meta2.code : void 0) || block.payload.raw || "";
3023
+ }
3024
+ }, filtered = this.filterElement(
3025
+ { tagName: blockTagName, properties: props, blockType: block.type },
3026
+ { source: "markdown" },
3027
+ () => renderPresentation ? renderPresentation(finalElement) : finalElement,
3028
+ renderChildren
3029
+ );
3030
+ return filtered == null ? import_react11.default.createElement(import_react11.default.Fragment, { key: block.id }) : import_react11.default.isValidElement(filtered) ? filtered : import_react11.default.createElement(import_react11.default.Fragment, { key: block.id }, filtered);
3031
+ }
3032
+ }
3033
+ let presented = renderPresentation ? renderPresentation(finalElement) : finalElement;
3034
+ return import_react11.default.isValidElement(presented) ? presented : import_react11.default.createElement(import_react11.default.Fragment, { key: block.id }, presented);
1455
3035
  }
1456
3036
  /**
1457
3037
  * Get props for a block based on its type
1458
3038
  */
1459
- getBlockProps(block) {
3039
+ getBlockProps(block, sourceGuard) {
3040
+ let animCtx = this.getRenderInlineContext(block.isFinalized, block.id, sourceGuard);
1460
3041
  switch (block.type) {
1461
3042
  case "heading": {
1462
- const meta = block.payload.meta ?? {};
1463
- const inlineNodes = Array.isArray(block.payload.inline) ? block.payload.inline : [];
1464
- const levelFromMeta = typeof meta.headingLevel === "number" ? meta.headingLevel : void 0;
1465
- const normalizedLevel = Number.isFinite(levelFromMeta) ? Math.min(Math.max(levelFromMeta, 1), 6) : void 0;
1466
- const rawHeading = typeof block.payload.raw === "string" ? block.payload.raw : "";
1467
- const headingText = typeof meta.headingText === "string" && meta.headingText.trim().length > 0 ? meta.headingText : (0, import_core2.removeHeadingMarkers)(rawHeading).trim();
1468
- const level = normalizedLevel ?? this.extractHeadingLevel(rawHeading);
3043
+ let meta = block.payload.meta ?? {}, inlineNodes = Array.isArray(block.payload.inline) ? block.payload.inline : [], levelFromMeta = typeof meta.headingLevel == "number" ? meta.headingLevel : void 0, normalizedLevel = Number.isFinite(levelFromMeta) ? Math.min(Math.max(levelFromMeta, 1), 6) : void 0, rawHeading = typeof block.payload.raw == "string" ? block.payload.raw : "", headingText = typeof meta.headingText == "string" && meta.headingText.trim().length > 0 ? meta.headingText : (0, import_core5.removeHeadingMarkers)(rawHeading).trim(), level = normalizedLevel ?? this.extractHeadingLevel(rawHeading), ownedTree = block.payload.meta?.htmlOwnership === !0 ? block.payload.meta.htmlTree : void 0, ownedRoot = ownedTree?.length === 1 ? ownedTree[0] : void 0, ownedChildren = ownedRoot?.kind === "element" && ownedRoot.tagName === `h${level}` ? ownedRoot.children : void 0, renderedChildren = ownedChildren ? renderOwnedHtmlTree(ownedChildren, this.ownedHtmlRenderContext(void 0, void 0, `h${level}`, animCtx)) : renderInlineNodes(inlineNodes, this.inlineComponents, this.urlTransform, this, `h${level}`, animCtx);
1469
3044
  return {
1470
3045
  level,
1471
3046
  inlines: inlineNodes,
1472
3047
  text: headingText,
1473
- meta
3048
+ meta,
3049
+ children: renderedChildren
1474
3050
  };
1475
3051
  }
1476
- case "paragraph":
3052
+ case "paragraph": {
3053
+ let segments = block.payload.meta?.mixedSegments;
1477
3054
  return {
1478
3055
  inlines: block.payload.inline || [],
1479
3056
  raw: block.payload.raw,
1480
- meta: block.payload.meta
3057
+ meta: block.payload.meta,
3058
+ children: Array.isArray(segments) && segments.length > 0 ? renderMixedParagraphSegments(
3059
+ segments,
3060
+ this.inlineComponents,
3061
+ DEFAULT_INLINE_HTML_RENDERERS,
3062
+ this.htmlElements,
3063
+ this.literalTagContent,
3064
+ this.urlTransform,
3065
+ this,
3066
+ animCtx,
3067
+ block.payload.meta?.mixedHtmlTrees,
3068
+ (tree) => renderOwnedHtmlTree(tree, this.ownedHtmlRenderContext(void 0, void 0, "p", animCtx))
3069
+ ) : renderInlineNodes(block.payload.inline ?? [], this.inlineComponents, this.urlTransform, this, "p", animCtx)
1481
3070
  };
3071
+ }
1482
3072
  case "blockquote":
1483
3073
  return {
1484
- inlines: block.payload.inline || []
3074
+ inlines: block.payload.inline || [],
3075
+ renderedContent: renderInlineNodes(block.payload.inline || [], this.inlineComponents, this.urlTransform, this, "blockquote", animCtx)
1485
3076
  };
1486
3077
  case "hr": {
1487
- const range = block.payload.range;
3078
+ let range = block.payload.range;
1488
3079
  return {
1489
3080
  className: "markdown-hr",
1490
- "data-start": typeof range?.from === "number" ? range.from : void 0,
1491
- "data-end": typeof range?.to === "number" ? range.to : void 0
3081
+ "data-start": typeof range?.from == "number" ? range.from : void 0,
3082
+ "data-end": typeof range?.to == "number" ? range.to : void 0
1492
3083
  };
1493
3084
  }
1494
3085
  case "code":
1495
3086
  return {
1496
3087
  html: block.payload.highlightedHtml,
1497
3088
  meta: block.payload.meta,
1498
- lang: typeof block.payload.meta?.lang === "string" ? String(block.payload.meta?.lang) : void 0
3089
+ lang: typeof block.payload.meta?.lang == "string" ? String(block.payload.meta?.lang) : void 0
1499
3090
  };
1500
3091
  case "list": {
1501
- const items = Array.isArray(block.payload.meta?.items) ? block.payload.meta?.items : [];
3092
+ let items = Array.isArray(block.payload.meta?.items) ? block.payload.meta?.items : [];
1502
3093
  return {
1503
- ordered: Boolean(block.payload.meta?.ordered),
3094
+ ordered: !!block.payload.meta?.ordered,
1504
3095
  items
1505
3096
  };
1506
3097
  }
1507
3098
  case "html": {
1508
- const trusted = block.payload.sanitizedHtml ?? block.payload.raw;
3099
+ let isWorkerSanitized = !!(block.payload.sanitizedHtml || block.payload.meta?.sanitized), content = block.payload.sanitizedHtml ?? block.payload.raw ?? "", htmlTree = block.payload.meta?.htmlTree;
1509
3100
  return {
1510
- // Server render should not depend on DOMPurify (which requires a DOM `window`).
1511
- // In worker-compiled flows, `sanitizedHtml` is already sanitized at the source.
1512
- __trustedHtml: typeof window === "undefined" ? String(trusted ?? "") : (0, import_core.createTrustedHTML)(String(trusted ?? "")),
1513
- elements: this.htmlElements
3101
+ __trustedHtml: isWorkerSanitized || typeof window > "u" ? String(content) : (0, import_core4.createTrustedHTML)(String(content)),
3102
+ elements: this.htmlElements,
3103
+ isSanitized: isWorkerSanitized,
3104
+ literalTagContent: this.literalTagContent,
3105
+ children: htmlTree ? this.renderHtmlTree(htmlTree, void 0, block) : void 0
1514
3106
  };
1515
3107
  }
1516
3108
  case "mdx":
1517
- return (() => {
1518
- const meta = block.payload.meta;
1519
- const rawStatus = typeof meta?.mdxStatus === "string" ? meta.mdxStatus : void 0;
1520
- const status = rawStatus === "pending" || rawStatus === "compiled" || rawStatus === "error" ? rawStatus : void 0;
1521
- const errorMessage = typeof meta?.mdxError === "string" ? String(meta.mdxError) : void 0;
1522
- const compiledModule = block.payload.compiledMdxModule ?? null;
1523
- const compiledRef = block.payload.compiledMdxRef ?? (compiledModule ? { id: compiledModule.id } : void 0);
1524
- return {
1525
- compiledRef: compiledRef ?? { id: "pending" },
1526
- compiledModule,
1527
- status,
1528
- errorMessage,
1529
- raw: typeof block.payload.raw === "string" ? block.payload.raw : void 0
1530
- };
1531
- })();
3109
+ return {
3110
+ raw: typeof block.payload.raw == "string" ? block.payload.raw : void 0,
3111
+ meta: block.payload.meta
3112
+ };
1532
3113
  case "table": {
1533
- const header = Array.isArray(block.payload.meta?.header) ? block.payload.meta?.header : void 0;
1534
- const rows = Array.isArray(block.payload.meta?.rows) ? block.payload.meta?.rows : [];
1535
- const align = Array.isArray(block.payload.meta?.align) ? block.payload.meta?.align : void 0;
3114
+ let header = Array.isArray(block.payload.meta?.header) ? block.payload.meta?.header : void 0, rows = Array.isArray(block.payload.meta?.rows) ? block.payload.meta?.rows : [], align = Array.isArray(block.payload.meta?.align) ? block.payload.meta?.align : void 0;
1536
3115
  return {
1537
3116
  header,
1538
3117
  rows,
@@ -1540,17 +3119,14 @@ var ComponentRegistry = class {
1540
3119
  elements: this.tableElements
1541
3120
  };
1542
3121
  }
1543
- case "footnotes": {
1544
- const items = Array.isArray(block.payload.meta?.items) ? block.payload.meta?.items : [];
3122
+ case "footnotes":
1545
3123
  return {
1546
- items
3124
+ items: Array.isArray(block.payload.meta?.items) ? block.payload.meta?.items : []
1547
3125
  };
1548
- }
1549
3126
  case "footnote-def":
1550
3127
  return {};
1551
3128
  case "callout": {
1552
- const kind = typeof block.payload.meta?.kind === "string" ? String(block.payload.meta.kind) : void 0;
1553
- const inlineNodes = Array.isArray(block.payload.inline) ? block.payload.inline : [];
3129
+ let kind = typeof block.payload.meta?.kind == "string" ? String(block.payload.meta.kind) : void 0, inlineNodes = Array.isArray(block.payload.inline) ? block.payload.inline : [];
1554
3130
  return {
1555
3131
  kind,
1556
3132
  inlines: inlineNodes
@@ -1567,112 +3143,117 @@ var ComponentRegistry = class {
1567
3143
  * Extract heading level from raw markdown
1568
3144
  */
1569
3145
  extractHeadingLevel(raw) {
1570
- const match = raw.match(/^(#{1,6})\s/);
1571
- if (match) {
1572
- return Math.min(match[1].length, 6);
1573
- }
1574
- return 1;
3146
+ let match = raw.match(/^(#{1,6})\s/);
3147
+ return match ? Math.min(match[1].length, 6) : 1;
1575
3148
  }
1576
3149
  };
1577
3150
  function getDefaultHtmlElements() {
1578
3151
  return {
1579
3152
  // Text semantics
1580
- p: (props) => import_react5.default.createElement("p", props),
1581
- strong: (props) => import_react5.default.createElement("strong", props),
1582
- em: (props) => import_react5.default.createElement("em", props),
1583
- code: (props) => import_react5.default.createElement("code", props),
1584
- pre: (props) => import_react5.default.createElement("pre", props),
1585
- span: (props) => import_react5.default.createElement("span", props),
1586
- br: (props) => import_react5.default.createElement("br", props),
1587
- hr: (props) => import_react5.default.createElement("hr", props),
3153
+ p: (props) => import_react11.default.createElement("p", props),
3154
+ strong: (props) => import_react11.default.createElement("strong", props),
3155
+ em: (props) => import_react11.default.createElement("em", props),
3156
+ code: (props) => import_react11.default.createElement("code", props),
3157
+ pre: (props) => import_react11.default.createElement("pre", props),
3158
+ span: (props) => import_react11.default.createElement("span", props),
3159
+ br: (props) => import_react11.default.createElement("br", props),
3160
+ hr: (props) => import_react11.default.createElement("hr", props),
1588
3161
  // Lists
1589
- ul: (props) => import_react5.default.createElement("ul", props),
1590
- ol: (props) => import_react5.default.createElement("ol", props),
1591
- li: (props) => import_react5.default.createElement("li", props),
3162
+ ul: (props) => import_react11.default.createElement("ul", props),
3163
+ ol: (props) => import_react11.default.createElement("ol", props),
3164
+ li: (props) => import_react11.default.createElement("li", props),
1592
3165
  // Links & media
1593
- a: (props) => import_react5.default.createElement("a", props),
1594
- img: (props) => import_react5.default.createElement("img", props),
3166
+ a: (props) => import_react11.default.createElement("a", props),
3167
+ img: (props) => import_react11.default.createElement("img", props),
1595
3168
  // Blockquotes
1596
- blockquote: (props) => import_react5.default.createElement("blockquote", props),
3169
+ blockquote: (props) => import_react11.default.createElement("blockquote", props),
1597
3170
  // Tables
1598
- table: (props) => import_react5.default.createElement("table", props),
1599
- thead: (props) => import_react5.default.createElement("thead", props),
1600
- tbody: (props) => import_react5.default.createElement("tbody", props),
1601
- tr: (props) => import_react5.default.createElement("tr", props),
1602
- th: (props) => import_react5.default.createElement("th", props),
1603
- td: (props) => import_react5.default.createElement("td", props),
3171
+ table: (props) => import_react11.default.createElement("table", props),
3172
+ thead: (props) => import_react11.default.createElement("thead", props),
3173
+ tbody: (props) => import_react11.default.createElement("tbody", props),
3174
+ tr: (props) => import_react11.default.createElement("tr", props),
3175
+ th: (props) => import_react11.default.createElement("th", props),
3176
+ td: (props) => import_react11.default.createElement("td", props),
1604
3177
  // Generic
1605
- div: (props) => import_react5.default.createElement("div", props)
3178
+ div: (props) => import_react11.default.createElement("div", props)
1606
3179
  };
1607
3180
  }
1608
3181
  function getDefaultTableElements(overrides) {
1609
- const base = {
1610
- Table: (props) => import_react5.default.createElement("table", props),
1611
- Thead: (props) => import_react5.default.createElement("thead", props),
1612
- Tbody: (props) => import_react5.default.createElement("tbody", props),
1613
- Tr: (props) => import_react5.default.createElement("tr", props),
1614
- Th: (props) => import_react5.default.createElement("th", props),
1615
- Td: (props) => import_react5.default.createElement("td", props)
1616
- };
1617
- return { ...base, ...overrides || {} };
1618
- }
1619
- function mapHtmlToReact(html, elements) {
1620
- const parser = new DOMParser();
1621
- const doc = parser.parseFromString(html, "text/html");
1622
- const children = [];
1623
- doc.body.childNodes.forEach((node, index) => {
1624
- const element = toReact(node, elements, `root-${index}`);
1625
- if (element) {
1626
- children.push(element);
1627
- }
1628
- });
1629
- return import_react5.default.createElement(import_react5.default.Fragment, {}, ...children);
3182
+ return { ...{
3183
+ Table: (props) => import_react11.default.createElement("table", props),
3184
+ Thead: (props) => import_react11.default.createElement("thead", props),
3185
+ Tbody: (props) => import_react11.default.createElement("tbody", props),
3186
+ Tr: (props) => import_react11.default.createElement("tr", props),
3187
+ Th: (props) => import_react11.default.createElement("th", props),
3188
+ Td: (props) => import_react11.default.createElement("td", props)
3189
+ }, ...overrides || {} };
3190
+ }
3191
+ var DEFAULT_LITERAL_TAGS2 = /* @__PURE__ */ new Set(["code", "pre", "script", "style", "textarea"]);
3192
+ function mapHtmlToReact(html, elements, literalTagContent, parseMarkdown) {
3193
+ let ParserClass = typeof DOMParser < "u" ? DOMParser : typeof window < "u" ? window.DOMParser : void 0;
3194
+ if (!ParserClass) return null;
3195
+ let doc = new ParserClass().parseFromString(html, "text/html"), children = [], literalTags = literalTagContent ? /* @__PURE__ */ new Set([...DEFAULT_LITERAL_TAGS2, ...literalTagContent.map((t) => t.toLowerCase())]) : DEFAULT_LITERAL_TAGS2;
3196
+ return doc.body.childNodes.forEach((node, index) => {
3197
+ let element = toReact(node, elements, `root-${index}`, void 0, literalTags, !1, parseMarkdown);
3198
+ element && children.push(element);
3199
+ }), import_react11.default.createElement(import_react11.default.Fragment, {}, ...children);
1630
3200
  }
1631
- function toReact(node, elements, key) {
3201
+ var TABLE_TEXT_FORBIDDEN_PARENTS = /* @__PURE__ */ new Set(["table", "thead", "tbody", "tfoot", "tr", "colgroup"]);
3202
+ function toReact(node, elements, key, parentTag, literalTags, parentIsLiteral, parseMarkdown) {
1632
3203
  if (node.nodeType === Node.TEXT_NODE) {
1633
- const text = node.textContent ?? "";
1634
- return import_react5.default.createElement(import_react5.default.Fragment, { key }, text);
3204
+ let text = node.textContent ?? "";
3205
+ if (parentTag && TABLE_TEXT_FORBIDDEN_PARENTS.has(parentTag) && text.trim().length === 0)
3206
+ return null;
3207
+ let content = parentIsLiteral || !parseMarkdown ? text : parseMarkdown(text);
3208
+ return import_react11.default.createElement(import_react11.default.Fragment, { key }, content);
1635
3209
  }
1636
- if (node.nodeType !== Node.ELEMENT_NODE) {
3210
+ if (node.nodeType !== Node.ELEMENT_NODE)
1637
3211
  return null;
1638
- }
1639
- const el = node;
1640
- const tag = el.tagName.toLowerCase();
1641
- const props = {};
1642
- for (const attr of Array.from(el.attributes)) {
1643
- const name = attr.name === "class" ? "className" : attr.name;
3212
+ let el = node, tag = el.tagName.toLowerCase(), isLiteral = parentIsLiteral || (literalTags ? literalTags.has(tag) : !1), props = {};
3213
+ for (let attr of Array.from(el.attributes)) {
3214
+ let name = attr.name === "class" ? "className" : attr.name;
1644
3215
  props[name] = attr.value;
1645
3216
  }
1646
- const children = [];
3217
+ if (tag === "textarea")
3218
+ return import_react11.default.createElement(elements[tag] ?? tag, { ...props, key, defaultValue: el.textContent ?? "" });
3219
+ let children = [];
1647
3220
  el.childNodes.forEach((childNode, childIndex) => {
1648
- const child = toReact(childNode, elements, `${key}-${childIndex}`);
1649
- if (child) {
1650
- children.push(child);
1651
- }
3221
+ let child = toReact(childNode, elements, `${key}-${childIndex}`, tag, literalTags, isLiteral, parseMarkdown);
3222
+ child && children.push(child);
1652
3223
  });
1653
- const component = elements[tag];
1654
- const elementChildren = children.length > 0 ? children : void 0;
1655
- if (component) {
1656
- return import_react5.default.createElement(component, { ...props, key }, elementChildren);
1657
- }
1658
- return import_react5.default.createElement(tag, { ...props, key }, elementChildren);
3224
+ let component = elements[tag], elementChildren = children.length > 0 ? children : void 0;
3225
+ return component ? import_react11.default.createElement(component, { ...props, key }, elementChildren) : import_react11.default.createElement(tag, { ...props, key }, elementChildren);
1659
3226
  }
1660
3227
  function attrsToProps(attrs) {
1661
3228
  if (!attrs) return {};
1662
- const result = {};
1663
- for (const [key, value] of Object.entries(attrs)) {
1664
- if (key === "class") {
1665
- result.className = value;
1666
- } else if (key === "style") {
1667
- result.style = parseStyleAttribute2(value);
1668
- } else if (key === "tabindex" || key === "tabIndex") {
1669
- const numericValue = Number(value);
1670
- if (!Number.isNaN(numericValue)) {
1671
- result.tabIndex = numericValue;
1672
- }
1673
- } else {
1674
- result[key] = value;
1675
- }
3229
+ let result = {};
3230
+ for (let [key, value] of Object.entries(attrs)) {
3231
+ let lower = key.toLowerCase();
3232
+ if (!(0, import_core4.isForbiddenAttribute)(lower))
3233
+ if (key === "class")
3234
+ result.className = value;
3235
+ else if (key === "style")
3236
+ result.style = parseStyleAttribute2(value);
3237
+ else if (key === "tabindex" || key === "tabIndex") {
3238
+ let numericValue = Number(value);
3239
+ Number.isNaN(numericValue) || (result.tabIndex = numericValue);
3240
+ } else if (lower === "href") {
3241
+ let safe = (0, import_core4.defaultUrlTransform)(value, "href", { source: "html" });
3242
+ safe != null && (result.href = safe);
3243
+ } else if (lower === "src") {
3244
+ let safe = (0, import_core4.defaultUrlTransform)(value, "src", { source: "html" });
3245
+ safe != null && (result.src = safe);
3246
+ } else if (lower === "action") {
3247
+ let safe = (0, import_core4.defaultUrlTransform)(value, "href", { source: "html" });
3248
+ safe != null && (result.action = safe);
3249
+ } else if (lower === "formaction") {
3250
+ let safe = (0, import_core4.defaultUrlTransform)(value, "href", { source: "html" });
3251
+ safe != null && (result.formAction = safe);
3252
+ } else if (lower === "xlink:href" || lower === "xlinkhref") {
3253
+ let safe = (0, import_core4.defaultUrlTransform)(value, "href", { source: "html" });
3254
+ safe != null && (result.xlinkHref = safe);
3255
+ } else
3256
+ result[key] = value;
1676
3257
  }
1677
3258
  return result;
1678
3259
  }
@@ -1680,48 +3261,36 @@ function escapeHtml(value) {
1680
3261
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1681
3262
  }
1682
3263
  function parseStyleAttribute2(value) {
1683
- const style = {};
3264
+ let style = {};
1684
3265
  if (!value) return style;
1685
- const parts = value.split(";");
1686
- for (const part of parts) {
3266
+ let parts = value.split(";");
3267
+ for (let part of parts) {
1687
3268
  if (!part.trim()) continue;
1688
- const [prop, val] = part.split(":");
1689
- if (!prop || !val) continue;
1690
- const camelProp = prop.trim().replace(/-([a-z])/g, (_, char) => char.toUpperCase());
1691
- style[camelProp] = val.trim();
3269
+ let separator = part.indexOf(":");
3270
+ if (separator <= 0) continue;
3271
+ let prop = part.slice(0, separator).trim(), val = part.slice(separator + 1).trim();
3272
+ if (!(0, import_core4.isSafeStyleDeclaration)(prop, val)) continue;
3273
+ let cssProperty = prop.startsWith("--") ? prop : prop.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
3274
+ style[cssProperty] = val;
1692
3275
  }
1693
3276
  return style;
1694
3277
  }
1695
- function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRenderers) {
1696
- const result = [];
1697
- let inlineBuffer = [];
1698
- let inlineGroupIndex = 0;
1699
- const pushRenderedNodes = (nodes, target, baseKey) => {
3278
+ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRenderers, htmlElements, literalTagContent, urlTransform) {
3279
+ return renderMixedParagraphSegments(segments, inlineComponents, inlineHtmlRenderers, htmlElements, literalTagContent, urlTransform);
3280
+ }
3281
+ function renderMixedParagraphSegments(segments, inlineComponents, inlineHtmlRenderers, htmlElements, literalTagContent, urlTransform, registry, animationContext, htmlTrees, renderOwnedHtml) {
3282
+ let result = [], inlineBuffer = [], inlineGroupIndex = 0, pushRenderedNodes = (nodes, target, baseKey) => {
1700
3283
  nodes.forEach((node, idx) => {
1701
- if (node === null || node === void 0) return;
1702
- const key = `${baseKey}-${idx}`;
1703
- if (import_react5.default.isValidElement(node)) {
1704
- target.push(node.key === key ? node : import_react5.default.cloneElement(node, { key }));
1705
- } else if (typeof node === "string" || typeof node === "number") {
1706
- target.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, node));
1707
- } else {
1708
- target.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, node));
1709
- }
3284
+ if (node == null) return;
3285
+ let key = `${baseKey}-${idx}`;
3286
+ import_react11.default.isValidElement(node) ? target.push(node.key === key ? node : import_react11.default.cloneElement(node, { key })) : typeof node == "string" || typeof node == "number" ? target.push(import_react11.default.createElement(import_react11.default.Fragment, { key }, node)) : target.push(import_react11.default.createElement(import_react11.default.Fragment, { key }, node));
1710
3287
  });
1711
- };
1712
- const ensureArray = (value) => {
1713
- if (value === null || value === void 0) {
1714
- return [];
1715
- }
1716
- return Array.isArray(value) ? value : [value];
1717
- };
1718
- const flushInline = () => {
1719
- if (inlineBuffer.length === 0) {
3288
+ }, ensureArray = (value) => value == null ? [] : Array.isArray(value) ? value : [value], flushInline = () => {
3289
+ if (inlineBuffer.length === 0)
1720
3290
  return;
1721
- }
1722
- const key = `paragraph-inline-group-${inlineGroupIndex++}`;
3291
+ let key = `paragraph-inline-group-${inlineGroupIndex++}`;
1723
3292
  result.push(
1724
- import_react5.default.createElement(
3293
+ import_react11.default.createElement(
1725
3294
  "p",
1726
3295
  {
1727
3296
  key,
@@ -1729,109 +3298,90 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
1729
3298
  },
1730
3299
  inlineBuffer
1731
3300
  )
1732
- );
1733
- inlineBuffer = [];
3301
+ ), inlineBuffer = [];
1734
3302
  };
1735
- segments.forEach((segment, index) => {
1736
- const key = `paragraph-segment-${index}`;
3303
+ return segments.forEach((segment, index) => {
3304
+ let key = `paragraph-segment-${index}`;
1737
3305
  switch (segment.kind) {
1738
3306
  case "text": {
1739
- const inlineNodes = Array.isArray(segment.inline) ? segment.inline : [];
3307
+ let inlineNodes = Array.isArray(segment.inline) ? segment.inline : [];
1740
3308
  if (inlineNodes.length === 0) {
1741
- if (segment.value) {
1742
- inlineBuffer.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, segment.value));
1743
- }
3309
+ segment.value && inlineBuffer.push(import_react11.default.createElement(import_react11.default.Fragment, { key }, segment.value));
1744
3310
  break;
1745
3311
  }
1746
- let chunk = [];
1747
- const pushChunk = (chunkNodes, chunkKey) => {
3312
+ let chunk = [], pushChunk = (chunkNodes, chunkKey) => {
1748
3313
  if (chunkNodes.length === 0) return;
1749
- const rendered = renderInlineNodes(chunkNodes, inlineComponents);
3314
+ let rendered = renderInlineNodes(chunkNodes, inlineComponents, urlTransform, registry, "p", animationContext);
1750
3315
  pushRenderedNodes(ensureArray(rendered), inlineBuffer, chunkKey);
1751
3316
  };
1752
3317
  inlineNodes.forEach((inlineNode, inlineIdx) => {
1753
3318
  if (inlineNode.kind === "math-display") {
1754
- pushChunk(chunk, `${key}-chunk-${inlineIdx}`);
1755
- chunk = [];
1756
- flushInline();
1757
- const rendered = renderInlineNodes([inlineNode], inlineComponents);
3319
+ pushChunk(chunk, `${key}-chunk-${inlineIdx}`), chunk = [], flushInline();
3320
+ let rendered = renderInlineNodes([inlineNode], inlineComponents, urlTransform, registry, "p", animationContext);
1758
3321
  pushRenderedNodes(ensureArray(rendered), result, `${key}-math-${inlineIdx}`);
1759
- } else {
3322
+ } else
1760
3323
  chunk.push(inlineNode);
1761
- }
1762
- });
1763
- pushChunk(chunk, `${key}-chunk-tail`);
3324
+ }), pushChunk(chunk, `${key}-chunk-tail`);
1764
3325
  break;
1765
3326
  }
1766
3327
  case "mdx": {
1767
- const status = segment.status ?? "pending";
1768
- let element;
1769
- if (status === "compiled") {
1770
- element = import_react5.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
1771
- } else if (status === "error") {
1772
- const message = segment.value || "MDX error";
1773
- element = import_react5.default.createElement("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error" }, message);
1774
- } else {
1775
- element = import_react5.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": status }, segment.value);
1776
- }
1777
- inlineBuffer.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, element));
3328
+ let element = import_react11.default.createElement("span", { className: "markdown-mdx-inline" }, segment.value);
3329
+ inlineBuffer.push(import_react11.default.createElement(import_react11.default.Fragment, { key }, element));
1778
3330
  break;
1779
3331
  }
1780
3332
  case "html": {
1781
- const html = segment.sanitized ?? segment.value;
1782
- const isBlockLevel = isBlockLevelHtml(html);
1783
- const element = renderInlineHtmlSegment(segment.value, segment.sanitized, {
3333
+ let html = segment.sanitized ?? segment.value, isBlockLevel = isBlockLevelHtml(html);
3334
+ if (registry && htmlTrees?.[index] !== void 0) {
3335
+ let rendered = renderOwnedHtml ? renderOwnedHtml(htmlTrees[index]) : registry.renderHtmlTree(htmlTrees[index]);
3336
+ isBlockLevel ? (flushInline(), pushRenderedNodes(ensureArray(rendered), result, key)) : pushRenderedNodes(ensureArray(rendered), inlineBuffer, key);
3337
+ break;
3338
+ }
3339
+ let parseMarkdown = (text) => !text || !text.includes("*") && !text.includes("_") && !text.includes("[") && !text.includes("`") && !text.includes("#") ? text : renderInlineNodes(new import_core4.InlineParser().parse(text), inlineComponents, urlTransform, registry, "p", animationContext), element = renderInlineHtmlSegment(segment.value, segment.sanitized, {
1784
3340
  key,
1785
- renderers: inlineHtmlRenderers
3341
+ renderers: inlineHtmlRenderers,
3342
+ htmlElements,
3343
+ literalTagContent,
3344
+ urlTransform,
3345
+ parseMarkdown
1786
3346
  });
1787
- if (isBlockLevel) {
1788
- flushInline();
1789
- if (element) {
1790
- result.push(element);
1791
- } else if (html) {
1792
- result.push(
1793
- import_react5.default.createElement("div", {
1794
- key,
1795
- className: "markdown-inline-html-block",
1796
- dangerouslySetInnerHTML: { __html: html }
1797
- })
1798
- );
1799
- }
1800
- } else if (element) {
1801
- inlineBuffer.push(element);
1802
- }
3347
+ isBlockLevel ? (flushInline(), element ? result.push(element) : html && result.push(
3348
+ import_react11.default.createElement("div", {
3349
+ key,
3350
+ className: "markdown-inline-html-block",
3351
+ dangerouslySetInnerHTML: { __html: html }
3352
+ })
3353
+ )) : element ? inlineBuffer.push(element) : html && inlineBuffer.push(
3354
+ import_react11.default.createElement("span", {
3355
+ key,
3356
+ className: "markdown-inline-html",
3357
+ dangerouslySetInnerHTML: { __html: html }
3358
+ })
3359
+ );
1803
3360
  break;
1804
3361
  }
1805
3362
  default:
1806
3363
  break;
1807
3364
  }
1808
- });
1809
- flushInline();
1810
- if (result.length === 0) {
1811
- return [
1812
- import_react5.default.createElement(
1813
- "p",
1814
- {
1815
- key: "paragraph-inline-group-0",
1816
- className: "markdown-paragraph"
1817
- },
1818
- inlineBuffer
1819
- )
1820
- ];
1821
- }
1822
- return result;
3365
+ }), flushInline(), result.length === 0 ? [
3366
+ import_react11.default.createElement(
3367
+ "p",
3368
+ {
3369
+ key: "paragraph-inline-group-0",
3370
+ className: "markdown-paragraph"
3371
+ },
3372
+ inlineBuffer
3373
+ )
3374
+ ] : result;
1823
3375
  }
1824
3376
  function isBlockLevelHtml(html) {
1825
- if (!html) return false;
1826
- const trimmed = html.trim();
1827
- if (!trimmed.startsWith("<")) {
1828
- return false;
1829
- }
1830
- const match = trimmed.match(/^<([A-Za-z][\w:-]*)\b/);
1831
- if (!match) {
1832
- return false;
1833
- }
1834
- const tag = match[1].toLowerCase();
3377
+ if (!html) return !1;
3378
+ let trimmed = html.trim();
3379
+ if (!trimmed.startsWith("<"))
3380
+ return !1;
3381
+ let match = trimmed.match(/^<([A-Za-z][\w:-]*)\b/);
3382
+ if (!match)
3383
+ return !1;
3384
+ let tag = match[1].toLowerCase();
1835
3385
  return BLOCK_LEVEL_TAGS.has(tag);
1836
3386
  }
1837
3387
  var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
@@ -1868,11 +3418,45 @@ var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
1868
3418
  ]);
1869
3419
  // Annotate the CommonJS export names for ESM import in node:
1870
3420
  0 && (module.exports = {
3421
+ AnimationTimeline,
3422
+ BottomStickScrollArea,
3423
+ CodeBlockCopyButton,
3424
+ CodeBlockDownloadButton,
3425
+ CodeControlsBar,
1871
3426
  ComponentRegistry,
3427
+ DEFAULT_ANIMATED_OPTIONS,
3428
+ DEFAULT_CONTROLS_LABELS,
3429
+ DefaultDiffRenderer,
1872
3430
  DefaultLinkSafetyModal,
1873
- defaultBlockComponents,
3431
+ DocumentMathMacroScope,
3432
+ DocumentMathMacroScopeContext,
3433
+ KaTeXBlockMath,
3434
+ KaTeXInlineMath,
3435
+ LANGUAGE_EXTENSION_MAP,
3436
+ MathExpressionCompletenessContext,
3437
+ STREAM_MDX_ANIMATION_CSS,
3438
+ TableControlsBar,
3439
+ copyToClipboard,
1874
3440
  defaultInlineComponents,
3441
+ defaultUrlTransform,
3442
+ downloadFile,
3443
+ escapeCsvCell,
3444
+ escapeTsvCell,
3445
+ getCodeSnippetFilename,
3446
+ getExtensionForLanguage,
3447
+ inlineToPlainText,
3448
+ loadKaTeX,
1875
3449
  mapHtmlToReact,
1876
3450
  renderInlineNodes,
1877
- renderParagraphMixedSegments
3451
+ renderParagraphMixedSegments,
3452
+ resolveAnimatedOptions,
3453
+ resolveCodeControls,
3454
+ resolveControlsConfig,
3455
+ resolveMermaidControls,
3456
+ resolveTableControls,
3457
+ splitTextSegments,
3458
+ splitWordSegments,
3459
+ tableToCsv,
3460
+ tableToMarkdown,
3461
+ tableToTsv
1878
3462
  });