@stream-mdx/react 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -4
- package/README.md +65 -15
- package/dist/components/bottom-stick-scroll-area.cjs +344 -0
- package/dist/components/bottom-stick-scroll-area.d.cts +36 -0
- package/dist/components/bottom-stick-scroll-area.d.ts +36 -0
- package/dist/components/bottom-stick-scroll-area.mjs +320 -0
- package/dist/components/index.cjs +503 -172
- package/dist/components/index.d.cts +3 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.mjs +350 -22
- package/dist/{index-D2MYusAM.d.cts → index-BVhp_pcF.d.ts} +3 -0
- package/dist/{index-D2MYusAM.d.ts → index-EaeouYp2.d.cts} +3 -0
- package/dist/index.cjs +1472 -486
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +1256 -272
- package/dist/mdx-client.cjs +1 -1
- package/dist/mdx-client.mjs +1 -1
- package/dist/mdx-coordinator.cjs +28 -7
- package/dist/mdx-coordinator.d.cts +2 -2
- package/dist/mdx-coordinator.d.ts +2 -2
- package/dist/mdx-coordinator.mjs +28 -7
- package/dist/renderer/node-views.cjs +271 -26
- package/dist/renderer/node-views.d.cts +3 -1
- package/dist/renderer/node-views.d.ts +3 -1
- package/dist/renderer/node-views.mjs +272 -27
- package/dist/renderer/patch-batching.cjs +2 -0
- package/dist/renderer/patch-batching.d.cts +1 -1
- package/dist/renderer/patch-batching.d.ts +1 -1
- package/dist/renderer/patch-batching.mjs +2 -1
- package/dist/renderer/patch-commit-scheduler.cjs +82 -30
- package/dist/renderer/patch-commit-scheduler.d.cts +15 -3
- package/dist/renderer/patch-commit-scheduler.d.ts +15 -3
- package/dist/renderer/patch-commit-scheduler.mjs +84 -30
- package/dist/renderer/store.cjs +382 -36
- package/dist/renderer/store.d.cts +3 -0
- package/dist/renderer/store.d.ts +3 -0
- package/dist/renderer/store.mjs +382 -36
- package/dist/renderer.cjs +758 -114
- package/dist/renderer.d.cts +3 -1
- package/dist/renderer.d.ts +3 -1
- package/dist/renderer.mjs +760 -116
- package/dist/server.cjs +669 -71
- package/dist/server.d.cts +5 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.mjs +670 -72
- package/dist/{streaming-markdown-DOc2uLiP.d.ts → streaming-markdown-CEI9eDZm.d.ts} +3 -1
- package/dist/{streaming-markdown-D-JcByd9.d.cts → streaming-markdown-DRisClXb.d.cts} +3 -1
- package/dist/streaming-markdown.cjs +788 -121
- package/dist/streaming-markdown.d.cts +4 -2
- package/dist/streaming-markdown.d.ts +4 -2
- package/dist/streaming-markdown.mjs +790 -123
- package/dist/utils/inline-html.d.cts +3 -1
- package/dist/utils/inline-html.d.ts +3 -1
- package/package.json +14 -3
- package/shadcn/README.md +28 -0
- package/shadcn/bottom-stick-scroll-area.tsx +358 -0
package/dist/index.cjs
CHANGED
|
@@ -46,11 +46,11 @@ function assignMdxChildKey(child, index) {
|
|
|
46
46
|
if (Array.isArray(child)) {
|
|
47
47
|
return child.map((entry, subIndex) => assignMdxChildKey(entry, `${index}-${subIndex}`));
|
|
48
48
|
}
|
|
49
|
-
if (
|
|
49
|
+
if (import_react3.default.isValidElement(child)) {
|
|
50
50
|
if (child.key !== null && child.key !== void 0) {
|
|
51
51
|
return child;
|
|
52
52
|
}
|
|
53
|
-
return
|
|
53
|
+
return import_react3.default.cloneElement(child, { key: index });
|
|
54
54
|
}
|
|
55
55
|
return child;
|
|
56
56
|
}
|
|
@@ -79,14 +79,14 @@ function registerInlineMdxModule(compiled) {
|
|
|
79
79
|
dependencies: compiled.dependencies ?? []
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
-
var
|
|
82
|
+
var import_react3, ReactJsxRuntime, withClassName, MDXClient, MDXComponentFactory, globalMDXClient, globalComponentFactory;
|
|
83
83
|
var init_mdx_client = __esm({
|
|
84
84
|
"src/mdx-client.ts"() {
|
|
85
85
|
"use strict";
|
|
86
|
-
|
|
86
|
+
import_react3 = __toESM(require("react"), 1);
|
|
87
87
|
ReactJsxRuntime = __toESM(require("react/jsx-runtime"), 1);
|
|
88
88
|
withClassName = (tag, className) => {
|
|
89
|
-
return (props) =>
|
|
89
|
+
return (props) => import_react3.default.createElement(tag, { className, ...props });
|
|
90
90
|
};
|
|
91
91
|
MDXClient = class {
|
|
92
92
|
constructor(compileEndpoint = "/api/mdx-compile-v2") {
|
|
@@ -103,7 +103,7 @@ var init_mdx_client = __esm({
|
|
|
103
103
|
if (block.type !== "mdx") {
|
|
104
104
|
throw new Error("Block is not MDX type");
|
|
105
105
|
}
|
|
106
|
-
const cacheKey = block.id
|
|
106
|
+
const cacheKey = `${block.id}\0${block.payload.raw ?? ""}`;
|
|
107
107
|
const cachedPromise = this.cache.get(cacheKey);
|
|
108
108
|
if (cachedPromise) {
|
|
109
109
|
return cachedPromise;
|
|
@@ -261,14 +261,14 @@ var init_mdx_client = __esm({
|
|
|
261
261
|
const registryComponents = this.getComponents();
|
|
262
262
|
const incomingComponents = props?.components;
|
|
263
263
|
const mergedComponents = incomingComponents ? { ...registryComponents, ...incomingComponents } : registryComponents;
|
|
264
|
-
return
|
|
264
|
+
return import_react3.default.createElement(MDXComponent, {
|
|
265
265
|
...props,
|
|
266
266
|
components: mergedComponents
|
|
267
267
|
});
|
|
268
268
|
};
|
|
269
269
|
} catch (error) {
|
|
270
270
|
console.error("Failed to evaluate MDX:", error);
|
|
271
|
-
return () =>
|
|
271
|
+
return () => import_react3.default.createElement(
|
|
272
272
|
"div",
|
|
273
273
|
{
|
|
274
274
|
className: "mdx-error"
|
|
@@ -288,7 +288,7 @@ var init_mdx_client = __esm({
|
|
|
288
288
|
if (Array.isArray(finalProps.children)) {
|
|
289
289
|
finalProps.children = finalProps.children.map((child, index) => assignMdxChildKey(child, index));
|
|
290
290
|
}
|
|
291
|
-
return
|
|
291
|
+
return import_react3.default.createElement(type, finalProps);
|
|
292
292
|
};
|
|
293
293
|
const runtimeJsx = typeof runtime.jsx === "function" ? runtime.jsx.bind(runtime) : createElementWithChildren;
|
|
294
294
|
const runtimeJsxs = typeof runtime.jsxs === "function" ? runtime.jsxs.bind(runtime) : createElementWithChildren;
|
|
@@ -297,20 +297,20 @@ var init_mdx_client = __esm({
|
|
|
297
297
|
jsx: runtimeJsx,
|
|
298
298
|
jsxs: runtimeJsxs,
|
|
299
299
|
jsxDEV: runtimeJsxDEV,
|
|
300
|
-
Fragment: runtime.Fragment ??
|
|
300
|
+
Fragment: runtime.Fragment ?? import_react3.default.Fragment
|
|
301
301
|
};
|
|
302
302
|
return {
|
|
303
303
|
__mdx_runtime: jsxRuntime,
|
|
304
|
-
React:
|
|
305
|
-
Fragment:
|
|
306
|
-
useState:
|
|
307
|
-
useEffect:
|
|
308
|
-
useMemo:
|
|
309
|
-
useCallback:
|
|
310
|
-
useRef:
|
|
311
|
-
useContext:
|
|
312
|
-
useReducer:
|
|
313
|
-
useLayoutEffect:
|
|
304
|
+
React: import_react3.default,
|
|
305
|
+
Fragment: import_react3.default.Fragment,
|
|
306
|
+
useState: import_react3.default.useState,
|
|
307
|
+
useEffect: import_react3.default.useEffect,
|
|
308
|
+
useMemo: import_react3.default.useMemo,
|
|
309
|
+
useCallback: import_react3.default.useCallback,
|
|
310
|
+
useRef: import_react3.default.useRef,
|
|
311
|
+
useContext: import_react3.default.useContext,
|
|
312
|
+
useReducer: import_react3.default.useReducer,
|
|
313
|
+
useLayoutEffect: import_react3.default.useLayoutEffect,
|
|
314
314
|
console: {
|
|
315
315
|
log: console.log,
|
|
316
316
|
warn: console.warn,
|
|
@@ -376,13 +376,13 @@ var init_mdx_client = __esm({
|
|
|
376
376
|
ol: withClassName("ol", "mdx-ol"),
|
|
377
377
|
li: withClassName("li", "mdx-li"),
|
|
378
378
|
blockquote: withClassName("blockquote", "mdx-blockquote"),
|
|
379
|
-
a: (props) =>
|
|
379
|
+
a: (props) => import_react3.default.createElement("a", {
|
|
380
380
|
className: "mdx-link",
|
|
381
381
|
target: props.href?.startsWith("http") ? "_blank" : void 0,
|
|
382
382
|
rel: props.href?.startsWith("http") ? "noopener noreferrer" : void 0,
|
|
383
383
|
...props
|
|
384
384
|
}),
|
|
385
|
-
img: (props) =>
|
|
385
|
+
img: (props) => import_react3.default.createElement("img", { className: "mdx-img", ...props }),
|
|
386
386
|
table: withClassName("table", "mdx-table"),
|
|
387
387
|
thead: withClassName("thead", "mdx-thead"),
|
|
388
388
|
tbody: withClassName("tbody", "mdx-tbody"),
|
|
@@ -409,6 +409,7 @@ var init_mdx_client = __esm({
|
|
|
409
409
|
// src/index.ts
|
|
410
410
|
var index_exports = {};
|
|
411
411
|
__export(index_exports, {
|
|
412
|
+
BottomStickScrollArea: () => BottomStickScrollArea,
|
|
412
413
|
ComponentRegistry: () => ComponentRegistry,
|
|
413
414
|
DEFAULT_COALESCE_CONFIG: () => import_core3.DEFAULT_COALESCE_CONFIG,
|
|
414
415
|
DEFAULT_VIRTUALIZED_CODE_CONFIG: () => DEFAULT_VIRTUALIZED_CODE_CONFIG,
|
|
@@ -434,6 +435,7 @@ __export(index_exports, {
|
|
|
434
435
|
defaultInlineComponents: () => defaultInlineComponents,
|
|
435
436
|
getMDXClient: () => getMDXClient,
|
|
436
437
|
getMDXComponentFactory: () => getMDXComponentFactory,
|
|
438
|
+
getPatchKind: () => import_patch_batching.getPatchKind,
|
|
437
439
|
isHeavyPatch: () => import_patch_batching.isHeavyPatch,
|
|
438
440
|
isListPatchDebugEnabled: () => isListPatchDebugEnabled,
|
|
439
441
|
mapHtmlToReact: () => mapHtmlToReact,
|
|
@@ -454,6 +456,321 @@ __export(index_exports, {
|
|
|
454
456
|
});
|
|
455
457
|
module.exports = __toCommonJS(index_exports);
|
|
456
458
|
|
|
459
|
+
// src/components/bottom-stick-scroll-area.tsx
|
|
460
|
+
var import_react = require("react");
|
|
461
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
462
|
+
var EPS_BOTTOM_PX = 2;
|
|
463
|
+
var EPS_OVERFLOW_PX = 1;
|
|
464
|
+
var DETACH_SCROLL_DELTA_PX = 1;
|
|
465
|
+
var RETURN_MIN_MS = 180;
|
|
466
|
+
var RETURN_MAX_MS = 520;
|
|
467
|
+
var RETURN_PX_PER_MS = 2.2;
|
|
468
|
+
var RETURN_SETTLE_FRAMES = 2;
|
|
469
|
+
function clamp01(value) {
|
|
470
|
+
if (value < 0) return 0;
|
|
471
|
+
if (value > 1) return 1;
|
|
472
|
+
return value;
|
|
473
|
+
}
|
|
474
|
+
function easeOutCubic(value) {
|
|
475
|
+
return 1 - (1 - value) ** 3;
|
|
476
|
+
}
|
|
477
|
+
function joinClasses(...parts) {
|
|
478
|
+
return parts.filter(Boolean).join(" ");
|
|
479
|
+
}
|
|
480
|
+
function measure(viewport) {
|
|
481
|
+
const scrollTop = viewport.scrollTop;
|
|
482
|
+
const scrollHeight = viewport.scrollHeight;
|
|
483
|
+
const clientHeight = viewport.clientHeight;
|
|
484
|
+
const maxScrollTop = Math.max(0, scrollHeight - clientHeight);
|
|
485
|
+
const distanceToBottom = Math.max(0, maxScrollTop - scrollTop);
|
|
486
|
+
const isOverflowing = scrollHeight > clientHeight + EPS_OVERFLOW_PX;
|
|
487
|
+
return { scrollTop, scrollHeight, clientHeight, maxScrollTop, distanceToBottom, isOverflowing };
|
|
488
|
+
}
|
|
489
|
+
function DefaultJumpButton({ canJump, jumpToBottom }) {
|
|
490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
491
|
+
"button",
|
|
492
|
+
{
|
|
493
|
+
type: "button",
|
|
494
|
+
onClick: jumpToBottom,
|
|
495
|
+
"aria-label": "Scroll to bottom",
|
|
496
|
+
style: {
|
|
497
|
+
pointerEvents: canJump ? "auto" : "none",
|
|
498
|
+
borderRadius: 9999,
|
|
499
|
+
border: "1px solid color-mix(in srgb, currentColor 20%, transparent)",
|
|
500
|
+
width: 40,
|
|
501
|
+
height: 40,
|
|
502
|
+
display: "grid",
|
|
503
|
+
placeItems: "center",
|
|
504
|
+
boxShadow: "0 8px 20px rgba(0,0,0,0.18)",
|
|
505
|
+
background: "color-mix(in srgb, var(--background, #fff) 92%, transparent)",
|
|
506
|
+
color: "var(--foreground, #111)",
|
|
507
|
+
cursor: canJump ? "pointer" : "default"
|
|
508
|
+
},
|
|
509
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": true, children: "\u2193" })
|
|
510
|
+
}
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
function BottomStickScrollArea({
|
|
514
|
+
children,
|
|
515
|
+
className,
|
|
516
|
+
viewportClassName,
|
|
517
|
+
contentClassName,
|
|
518
|
+
showJumpToBottom = true,
|
|
519
|
+
onDebugStateChange,
|
|
520
|
+
onModeChange,
|
|
521
|
+
debugDomAttributes = false,
|
|
522
|
+
renderJumpToBottom,
|
|
523
|
+
jumpContainerClassName
|
|
524
|
+
}) {
|
|
525
|
+
const viewportRef = (0, import_react.useRef)(null);
|
|
526
|
+
const contentRef = (0, import_react.useRef)(null);
|
|
527
|
+
const modeRef = (0, import_react.useRef)("STICKY_INSTANT");
|
|
528
|
+
const [mode, setMode] = (0, import_react.useState)("STICKY_INSTANT");
|
|
529
|
+
const [isOverflowing, setIsOverflowing] = (0, import_react.useState)(false);
|
|
530
|
+
const [distanceToBottom, setDistanceToBottom] = (0, import_react.useState)(0);
|
|
531
|
+
const prevScrollTopRef = (0, import_react.useRef)(0);
|
|
532
|
+
const lastProgrammaticWriteRef = (0, import_react.useRef)(null);
|
|
533
|
+
const programmaticWriteCountRef = (0, import_react.useRef)(0);
|
|
534
|
+
const pendingStickRafRef = (0, import_react.useRef)(null);
|
|
535
|
+
const stickRequestedRef = (0, import_react.useRef)(false);
|
|
536
|
+
const returnRafRef = (0, import_react.useRef)(null);
|
|
537
|
+
const returnAnimRef = (0, import_react.useRef)(null);
|
|
538
|
+
const setModeBoth = (0, import_react.useCallback)(
|
|
539
|
+
(next) => {
|
|
540
|
+
modeRef.current = next;
|
|
541
|
+
setMode(next);
|
|
542
|
+
onModeChange?.(next);
|
|
543
|
+
},
|
|
544
|
+
[onModeChange]
|
|
545
|
+
);
|
|
546
|
+
const updateDebug = (0, import_react.useCallback)(() => {
|
|
547
|
+
const viewport = viewportRef.current;
|
|
548
|
+
if (!viewport) return;
|
|
549
|
+
const m = measure(viewport);
|
|
550
|
+
if (debugDomAttributes) {
|
|
551
|
+
viewport.dataset.stickyMode = modeRef.current;
|
|
552
|
+
viewport.dataset.distanceToBottom = String(m.distanceToBottom);
|
|
553
|
+
viewport.dataset.isOverflowing = m.isOverflowing ? "1" : "0";
|
|
554
|
+
viewport.dataset.programmaticWrites = String(programmaticWriteCountRef.current);
|
|
555
|
+
}
|
|
556
|
+
onDebugStateChange?.({
|
|
557
|
+
mode: modeRef.current,
|
|
558
|
+
isOverflowing: m.isOverflowing,
|
|
559
|
+
distanceToBottom: m.distanceToBottom,
|
|
560
|
+
scrollTop: m.scrollTop,
|
|
561
|
+
maxScrollTop: m.maxScrollTop,
|
|
562
|
+
scrollHeight: m.scrollHeight,
|
|
563
|
+
clientHeight: m.clientHeight,
|
|
564
|
+
programmaticWrites: programmaticWriteCountRef.current
|
|
565
|
+
});
|
|
566
|
+
setDistanceToBottom(
|
|
567
|
+
(previous) => Math.abs(previous - m.distanceToBottom) <= 0.1 ? previous : m.distanceToBottom
|
|
568
|
+
);
|
|
569
|
+
}, [debugDomAttributes, onDebugStateChange]);
|
|
570
|
+
const writeScrollTop = (0, import_react.useCallback)((nextTop) => {
|
|
571
|
+
const viewport = viewportRef.current;
|
|
572
|
+
if (!viewport) return;
|
|
573
|
+
viewport.scrollTop = nextTop;
|
|
574
|
+
programmaticWriteCountRef.current += 1;
|
|
575
|
+
lastProgrammaticWriteRef.current = { at: performance.now(), top: nextTop };
|
|
576
|
+
}, []);
|
|
577
|
+
const cancelPendingStick = (0, import_react.useCallback)(() => {
|
|
578
|
+
if (pendingStickRafRef.current !== null) {
|
|
579
|
+
cancelAnimationFrame(pendingStickRafRef.current);
|
|
580
|
+
pendingStickRafRef.current = null;
|
|
581
|
+
}
|
|
582
|
+
stickRequestedRef.current = false;
|
|
583
|
+
}, []);
|
|
584
|
+
const cancelReturn = (0, import_react.useCallback)(() => {
|
|
585
|
+
if (returnRafRef.current !== null) {
|
|
586
|
+
cancelAnimationFrame(returnRafRef.current);
|
|
587
|
+
returnRafRef.current = null;
|
|
588
|
+
}
|
|
589
|
+
returnAnimRef.current = null;
|
|
590
|
+
}, []);
|
|
591
|
+
const stickToBottomInstant = (0, import_react.useCallback)(() => {
|
|
592
|
+
const viewport = viewportRef.current;
|
|
593
|
+
if (!viewport) return;
|
|
594
|
+
stickRequestedRef.current = true;
|
|
595
|
+
if (pendingStickRafRef.current !== null) return;
|
|
596
|
+
pendingStickRafRef.current = requestAnimationFrame(() => {
|
|
597
|
+
pendingStickRafRef.current = null;
|
|
598
|
+
if (!stickRequestedRef.current) return;
|
|
599
|
+
stickRequestedRef.current = false;
|
|
600
|
+
if (modeRef.current !== "STICKY_INSTANT") return;
|
|
601
|
+
const m = measure(viewport);
|
|
602
|
+
writeScrollTop(m.maxScrollTop);
|
|
603
|
+
updateDebug();
|
|
604
|
+
});
|
|
605
|
+
}, [updateDebug, writeScrollTop]);
|
|
606
|
+
const startReturnToBottomSmooth = (0, import_react.useCallback)(() => {
|
|
607
|
+
const viewport = viewportRef.current;
|
|
608
|
+
if (!viewport) return;
|
|
609
|
+
cancelPendingStick();
|
|
610
|
+
cancelReturn();
|
|
611
|
+
const initial = measure(viewport);
|
|
612
|
+
if (initial.distanceToBottom <= EPS_BOTTOM_PX) {
|
|
613
|
+
setModeBoth("STICKY_INSTANT");
|
|
614
|
+
stickToBottomInstant();
|
|
615
|
+
updateDebug();
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
const durationMs = Math.max(
|
|
619
|
+
RETURN_MIN_MS,
|
|
620
|
+
Math.min(RETURN_MAX_MS, initial.distanceToBottom / RETURN_PX_PER_MS)
|
|
621
|
+
);
|
|
622
|
+
returnAnimRef.current = {
|
|
623
|
+
startTime: performance.now(),
|
|
624
|
+
startTop: initial.scrollTop,
|
|
625
|
+
durationMs,
|
|
626
|
+
settleFrames: 0
|
|
627
|
+
};
|
|
628
|
+
setModeBoth("RETURNING_SMOOTH");
|
|
629
|
+
const tick = (now2) => {
|
|
630
|
+
const viewportCurrent = viewportRef.current;
|
|
631
|
+
const anim = returnAnimRef.current;
|
|
632
|
+
if (!viewportCurrent || !anim || modeRef.current !== "RETURNING_SMOOTH") {
|
|
633
|
+
cancelReturn();
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
const before = measure(viewportCurrent);
|
|
637
|
+
const progress = clamp01((now2 - anim.startTime) / anim.durationMs);
|
|
638
|
+
const eased = easeOutCubic(progress);
|
|
639
|
+
const targetBottom = before.maxScrollTop;
|
|
640
|
+
let nextTop = anim.startTop + (targetBottom - anim.startTop) * eased;
|
|
641
|
+
if (nextTop < before.scrollTop) {
|
|
642
|
+
nextTop = before.scrollTop;
|
|
643
|
+
}
|
|
644
|
+
writeScrollTop(nextTop);
|
|
645
|
+
const after = measure(viewportCurrent);
|
|
646
|
+
if (after.distanceToBottom <= EPS_BOTTOM_PX) {
|
|
647
|
+
anim.settleFrames += 1;
|
|
648
|
+
} else {
|
|
649
|
+
anim.settleFrames = 0;
|
|
650
|
+
}
|
|
651
|
+
const doneByTime = progress >= 1;
|
|
652
|
+
const doneBySettle = anim.settleFrames >= RETURN_SETTLE_FRAMES && progress >= 0.6;
|
|
653
|
+
if (doneByTime && doneBySettle) {
|
|
654
|
+
cancelReturn();
|
|
655
|
+
setModeBoth("STICKY_INSTANT");
|
|
656
|
+
stickToBottomInstant();
|
|
657
|
+
updateDebug();
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
updateDebug();
|
|
661
|
+
returnRafRef.current = requestAnimationFrame(tick);
|
|
662
|
+
};
|
|
663
|
+
returnRafRef.current = requestAnimationFrame(tick);
|
|
664
|
+
}, [cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug, writeScrollTop]);
|
|
665
|
+
const onViewportScroll = (0, import_react.useCallback)(
|
|
666
|
+
(event) => {
|
|
667
|
+
const viewport = event.currentTarget;
|
|
668
|
+
const m = measure(viewport);
|
|
669
|
+
setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
|
|
670
|
+
const previousTop = prevScrollTopRef.current;
|
|
671
|
+
const delta = m.scrollTop - previousTop;
|
|
672
|
+
const lastWrite = lastProgrammaticWriteRef.current;
|
|
673
|
+
const wroteRecently = lastWrite !== null && performance.now() - lastWrite.at < 60;
|
|
674
|
+
const isLikelyOwnWrite = wroteRecently && lastWrite !== null && Math.abs(m.scrollTop - lastWrite.top) <= 2;
|
|
675
|
+
if (modeRef.current === "RETURNING_SMOOTH") {
|
|
676
|
+
if (!isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX) {
|
|
677
|
+
cancelReturn();
|
|
678
|
+
setModeBoth("DETACHED");
|
|
679
|
+
}
|
|
680
|
+
} else if (modeRef.current === "STICKY_INSTANT") {
|
|
681
|
+
if (!isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX && m.isOverflowing) {
|
|
682
|
+
cancelPendingStick();
|
|
683
|
+
setModeBoth("DETACHED");
|
|
684
|
+
}
|
|
685
|
+
} else if (modeRef.current === "DETACHED") {
|
|
686
|
+
if (m.distanceToBottom <= EPS_BOTTOM_PX) {
|
|
687
|
+
setModeBoth("STICKY_INSTANT");
|
|
688
|
+
stickToBottomInstant();
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
prevScrollTopRef.current = m.scrollTop;
|
|
692
|
+
updateDebug();
|
|
693
|
+
},
|
|
694
|
+
[cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug]
|
|
695
|
+
);
|
|
696
|
+
(0, import_react.useEffect)(() => {
|
|
697
|
+
const viewport = viewportRef.current;
|
|
698
|
+
const content = contentRef.current;
|
|
699
|
+
if (!viewport || !content) return;
|
|
700
|
+
const observer = new ResizeObserver(() => {
|
|
701
|
+
const m = measure(viewport);
|
|
702
|
+
setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
|
|
703
|
+
if (modeRef.current === "STICKY_INSTANT") {
|
|
704
|
+
stickToBottomInstant();
|
|
705
|
+
}
|
|
706
|
+
updateDebug();
|
|
707
|
+
});
|
|
708
|
+
observer.observe(content);
|
|
709
|
+
observer.observe(viewport);
|
|
710
|
+
return () => observer.disconnect();
|
|
711
|
+
}, [stickToBottomInstant, updateDebug]);
|
|
712
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
713
|
+
const viewport = viewportRef.current;
|
|
714
|
+
if (!viewport) return;
|
|
715
|
+
setModeBoth("STICKY_INSTANT");
|
|
716
|
+
const initial = measure(viewport);
|
|
717
|
+
writeScrollTop(initial.maxScrollTop);
|
|
718
|
+
prevScrollTopRef.current = viewport.scrollTop;
|
|
719
|
+
setIsOverflowing(initial.isOverflowing);
|
|
720
|
+
setDistanceToBottom(initial.distanceToBottom);
|
|
721
|
+
updateDebug();
|
|
722
|
+
}, [setModeBoth, updateDebug, writeScrollTop]);
|
|
723
|
+
(0, import_react.useEffect)(() => {
|
|
724
|
+
return () => {
|
|
725
|
+
cancelPendingStick();
|
|
726
|
+
cancelReturn();
|
|
727
|
+
};
|
|
728
|
+
}, [cancelPendingStick, cancelReturn]);
|
|
729
|
+
const canJump = isOverflowing && mode === "DETACHED";
|
|
730
|
+
const jumpButton = renderJumpToBottom?.({
|
|
731
|
+
mode,
|
|
732
|
+
canJump,
|
|
733
|
+
isOverflowing,
|
|
734
|
+
distanceToBottom,
|
|
735
|
+
jumpToBottom: startReturnToBottomSmooth
|
|
736
|
+
}) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultJumpButton, { canJump, jumpToBottom: startReturnToBottomSmooth });
|
|
737
|
+
const jumpContainerClassNameBase = "pointer-events-none absolute z-20";
|
|
738
|
+
const jumpContainerStyle = {
|
|
739
|
+
position: "absolute",
|
|
740
|
+
zIndex: 20,
|
|
741
|
+
left: 0,
|
|
742
|
+
right: 0,
|
|
743
|
+
bottom: 12,
|
|
744
|
+
display: "flex",
|
|
745
|
+
justifyContent: "center",
|
|
746
|
+
opacity: canJump ? 1 : 0,
|
|
747
|
+
transform: canJump ? "translateY(0px)" : "translateY(4px)",
|
|
748
|
+
transition: "opacity 150ms ease, transform 150ms ease",
|
|
749
|
+
pointerEvents: "none"
|
|
750
|
+
};
|
|
751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: joinClasses("relative h-full w-full overflow-hidden", className), children: [
|
|
752
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
753
|
+
"div",
|
|
754
|
+
{
|
|
755
|
+
ref: viewportRef,
|
|
756
|
+
className: joinClasses("h-full w-full overflow-auto", viewportClassName),
|
|
757
|
+
onScroll: onViewportScroll,
|
|
758
|
+
"data-testid": "sticky-scroll-viewport",
|
|
759
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: contentRef, className: joinClasses("flex min-h-full w-full flex-col", contentClassName), children })
|
|
760
|
+
}
|
|
761
|
+
),
|
|
762
|
+
showJumpToBottom ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
763
|
+
"div",
|
|
764
|
+
{
|
|
765
|
+
className: joinClasses(jumpContainerClassNameBase, jumpContainerClassName),
|
|
766
|
+
style: jumpContainerStyle,
|
|
767
|
+
"aria-hidden": !canJump,
|
|
768
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: canJump ? "pointer-events-auto" : "pointer-events-none", children: jumpButton })
|
|
769
|
+
}
|
|
770
|
+
) : null
|
|
771
|
+
] });
|
|
772
|
+
}
|
|
773
|
+
|
|
457
774
|
// src/components/index.ts
|
|
458
775
|
var import_core = require("@stream-mdx/core");
|
|
459
776
|
|
|
@@ -630,7 +947,7 @@ function percentile(values, ratio) {
|
|
|
630
947
|
}
|
|
631
948
|
|
|
632
949
|
// src/mdx-hydration-context.ts
|
|
633
|
-
var
|
|
950
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
634
951
|
var MdxHydrationController = class {
|
|
635
952
|
constructor(options) {
|
|
636
953
|
this.active = 0;
|
|
@@ -668,7 +985,7 @@ var MdxHydrationController = class {
|
|
|
668
985
|
next();
|
|
669
986
|
}
|
|
670
987
|
};
|
|
671
|
-
var MdxHydrationContext =
|
|
988
|
+
var MdxHydrationContext = import_react2.default.createContext({ controller: null });
|
|
672
989
|
function createMdxHydrationController(options) {
|
|
673
990
|
if (!options || options.strategy === "immediate") {
|
|
674
991
|
return null;
|
|
@@ -689,11 +1006,11 @@ function prefetchMdxRuntime() {
|
|
|
689
1006
|
}
|
|
690
1007
|
|
|
691
1008
|
// src/renderer/use-deferred-render.ts
|
|
692
|
-
var
|
|
1009
|
+
var import_react4 = require("react");
|
|
693
1010
|
function useDeferredRender(ref, options) {
|
|
694
1011
|
const enabled = options?.enabled ?? true;
|
|
695
|
-
const [shouldRender, setShouldRender] = (0,
|
|
696
|
-
(0,
|
|
1012
|
+
const [shouldRender, setShouldRender] = (0, import_react4.useState)(!enabled);
|
|
1013
|
+
(0, import_react4.useEffect)(() => {
|
|
697
1014
|
if (!enabled) {
|
|
698
1015
|
setShouldRender(true);
|
|
699
1016
|
return;
|
|
@@ -746,10 +1063,10 @@ function useDeferredRender(ref, options) {
|
|
|
746
1063
|
|
|
747
1064
|
// src/components/index.ts
|
|
748
1065
|
var import_core2 = require("@stream-mdx/core");
|
|
749
|
-
var
|
|
1066
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
750
1067
|
|
|
751
1068
|
// src/utils/inline-html.ts
|
|
752
|
-
var
|
|
1069
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
753
1070
|
var BACKTICK_CONTENT = /^`([\s\S]+)`$/;
|
|
754
1071
|
var DEFAULT_INLINE_HTML_RENDERERS = {
|
|
755
1072
|
kbd: (descriptor, ctx) => {
|
|
@@ -761,7 +1078,7 @@ var DEFAULT_INLINE_HTML_RENDERERS = {
|
|
|
761
1078
|
if (ctx.key !== void 0 && ctx.key !== null) {
|
|
762
1079
|
props.key = ctx.key;
|
|
763
1080
|
}
|
|
764
|
-
return
|
|
1081
|
+
return import_react5.default.createElement("kbd", props, import_react5.default.createElement("code", { className: "inline-code" }, codeText));
|
|
765
1082
|
}
|
|
766
1083
|
return ctx.defaultRender();
|
|
767
1084
|
}
|
|
@@ -779,9 +1096,9 @@ function renderInlineHtmlSegment(raw, sanitized, options = {}) {
|
|
|
779
1096
|
return null;
|
|
780
1097
|
}
|
|
781
1098
|
if (options.key !== void 0 && options.key !== null) {
|
|
782
|
-
return
|
|
1099
|
+
return import_react5.default.createElement(import_react5.default.Fragment, { key: options.key }, descriptor.text);
|
|
783
1100
|
}
|
|
784
|
-
return
|
|
1101
|
+
return import_react5.default.createElement(import_react5.default.Fragment, {}, descriptor.text);
|
|
785
1102
|
}
|
|
786
1103
|
if (isInlineTag) {
|
|
787
1104
|
const parsedElement = renderSanitizedHtmlTree(descriptor.sanitized, options.key);
|
|
@@ -796,15 +1113,15 @@ function renderInlineHtmlSegment(raw, sanitized, options = {}) {
|
|
|
796
1113
|
if (options.key !== void 0 && options.key !== null) {
|
|
797
1114
|
props.key = options.key;
|
|
798
1115
|
}
|
|
799
|
-
return
|
|
1116
|
+
return import_react5.default.createElement("span", props);
|
|
800
1117
|
};
|
|
801
1118
|
const allRenderers = options.renderers ? { ...DEFAULT_INLINE_HTML_RENDERERS, ...options.renderers } : DEFAULT_INLINE_HTML_RENDERERS;
|
|
802
1119
|
const renderer = allRenderers[descriptor.tagName];
|
|
803
1120
|
if (renderer) {
|
|
804
1121
|
const rendered = renderer(descriptor, { key: options.key, defaultRender });
|
|
805
1122
|
if (rendered) {
|
|
806
|
-
if (options.key !== void 0 && options.key !== null &&
|
|
807
|
-
return
|
|
1123
|
+
if (options.key !== void 0 && options.key !== null && import_react5.default.isValidElement(rendered) && rendered.key === null) {
|
|
1124
|
+
return import_react5.default.cloneElement(rendered, { key: options.key });
|
|
808
1125
|
}
|
|
809
1126
|
return rendered;
|
|
810
1127
|
}
|
|
@@ -916,21 +1233,21 @@ function renderSanitizedHtmlTree(html, key) {
|
|
|
916
1233
|
}
|
|
917
1234
|
if (children.length === 1) {
|
|
918
1235
|
const [child] = children;
|
|
919
|
-
if (
|
|
1236
|
+
if (import_react5.default.isValidElement(child)) {
|
|
920
1237
|
if (key !== void 0 && key !== null) {
|
|
921
|
-
return
|
|
1238
|
+
return import_react5.default.cloneElement(child, { key });
|
|
922
1239
|
}
|
|
923
1240
|
return child;
|
|
924
1241
|
}
|
|
925
1242
|
if (typeof child === "string" || typeof child === "number") {
|
|
926
1243
|
if (key !== void 0 && key !== null) {
|
|
927
|
-
return
|
|
1244
|
+
return import_react5.default.createElement(import_react5.default.Fragment, { key }, child);
|
|
928
1245
|
}
|
|
929
|
-
return
|
|
1246
|
+
return import_react5.default.createElement(import_react5.default.Fragment, {}, child);
|
|
930
1247
|
}
|
|
931
|
-
return
|
|
1248
|
+
return import_react5.default.createElement(import_react5.default.Fragment, { key }, child);
|
|
932
1249
|
}
|
|
933
|
-
return
|
|
1250
|
+
return import_react5.default.createElement(import_react5.default.Fragment, { key }, ...children);
|
|
934
1251
|
} catch {
|
|
935
1252
|
return null;
|
|
936
1253
|
}
|
|
@@ -955,9 +1272,9 @@ function convertDomNode(node, key) {
|
|
|
955
1272
|
}
|
|
956
1273
|
});
|
|
957
1274
|
if (children.length === 0) {
|
|
958
|
-
return
|
|
1275
|
+
return import_react5.default.createElement(tagName, props);
|
|
959
1276
|
}
|
|
960
|
-
return
|
|
1277
|
+
return import_react5.default.createElement(tagName, props, ...children);
|
|
961
1278
|
}
|
|
962
1279
|
function getElementAttributes(element) {
|
|
963
1280
|
const attrs = {};
|
|
@@ -1018,12 +1335,12 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
1018
1335
|
]);
|
|
1019
1336
|
|
|
1020
1337
|
// src/components/link-safety-modal.tsx
|
|
1021
|
-
var
|
|
1338
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1022
1339
|
var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onCopy }) => {
|
|
1023
1340
|
if (!isOpen) {
|
|
1024
1341
|
return null;
|
|
1025
1342
|
}
|
|
1026
|
-
return /* @__PURE__ */ (0,
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1027
1344
|
"div",
|
|
1028
1345
|
{
|
|
1029
1346
|
className: "stream-mdx-link-modal-backdrop",
|
|
@@ -1041,7 +1358,7 @@ var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onC
|
|
|
1041
1358
|
padding: "24px"
|
|
1042
1359
|
},
|
|
1043
1360
|
onClick: onClose,
|
|
1044
|
-
children: /* @__PURE__ */ (0,
|
|
1361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1045
1362
|
"div",
|
|
1046
1363
|
{
|
|
1047
1364
|
className: "stream-mdx-link-modal",
|
|
@@ -1056,12 +1373,12 @@ var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onC
|
|
|
1056
1373
|
},
|
|
1057
1374
|
onClick: (event) => event.stopPropagation(),
|
|
1058
1375
|
children: [
|
|
1059
|
-
/* @__PURE__ */ (0,
|
|
1060
|
-
/* @__PURE__ */ (0,
|
|
1061
|
-
/* @__PURE__ */ (0,
|
|
1062
|
-
/* @__PURE__ */ (0,
|
|
1063
|
-
/* @__PURE__ */ (0,
|
|
1064
|
-
/* @__PURE__ */ (0,
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Open external link?" }),
|
|
1377
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 13, opacity: 0.8, wordBreak: "break-all", marginBottom: 16 }, children: url }),
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [
|
|
1379
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: onCopy, disabled: isChecking, style: buttonStyle, children: "Copy link" }),
|
|
1380
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: onConfirm, disabled: isChecking, style: primaryButtonStyle, children: "Open link" }),
|
|
1381
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: onClose, style: buttonStyle, children: "Cancel" })
|
|
1065
1382
|
] })
|
|
1066
1383
|
]
|
|
1067
1384
|
}
|
|
@@ -1085,7 +1402,7 @@ var primaryButtonStyle = {
|
|
|
1085
1402
|
};
|
|
1086
1403
|
|
|
1087
1404
|
// src/components/index.ts
|
|
1088
|
-
var MdxRuntimeBoundary = class extends
|
|
1405
|
+
var MdxRuntimeBoundary = class extends import_react6.default.Component {
|
|
1089
1406
|
constructor() {
|
|
1090
1407
|
super(...arguments);
|
|
1091
1408
|
this.state = { hasError: false };
|
|
@@ -1115,31 +1432,31 @@ function renderInlineNodes(nodes, components) {
|
|
|
1115
1432
|
case "text": {
|
|
1116
1433
|
const textComponent = components.text;
|
|
1117
1434
|
if (textComponent && textComponent !== defaultInlineComponents.text) {
|
|
1118
|
-
return
|
|
1435
|
+
return import_react6.default.createElement(textComponent, { key, text: node.text });
|
|
1119
1436
|
}
|
|
1120
|
-
return
|
|
1437
|
+
return import_react6.default.createElement(import_react6.default.Fragment, { key, children: node.text });
|
|
1121
1438
|
}
|
|
1122
1439
|
case "strong":
|
|
1123
|
-
return
|
|
1440
|
+
return import_react6.default.createElement(components.strong, {
|
|
1124
1441
|
key,
|
|
1125
1442
|
children: renderInlineNodes(node.children, components)
|
|
1126
1443
|
});
|
|
1127
1444
|
case "em":
|
|
1128
|
-
return
|
|
1445
|
+
return import_react6.default.createElement(components.em, {
|
|
1129
1446
|
key,
|
|
1130
1447
|
children: renderInlineNodes(node.children, components)
|
|
1131
1448
|
});
|
|
1132
1449
|
case "strike": {
|
|
1133
|
-
const StrikeComponent = components.strike ?? ((props) =>
|
|
1134
|
-
return
|
|
1450
|
+
const StrikeComponent = components.strike ?? ((props) => import_react6.default.createElement("del", {}, props.children));
|
|
1451
|
+
return import_react6.default.createElement(StrikeComponent, {
|
|
1135
1452
|
key,
|
|
1136
1453
|
children: renderInlineNodes(node.children, components)
|
|
1137
1454
|
});
|
|
1138
1455
|
}
|
|
1139
1456
|
case "code":
|
|
1140
|
-
return
|
|
1457
|
+
return import_react6.default.createElement(components.code, { key, text: node.text });
|
|
1141
1458
|
case "link":
|
|
1142
|
-
return
|
|
1459
|
+
return import_react6.default.createElement(
|
|
1143
1460
|
components.link,
|
|
1144
1461
|
{
|
|
1145
1462
|
key,
|
|
@@ -1149,18 +1466,18 @@ function renderInlineNodes(nodes, components) {
|
|
|
1149
1466
|
}
|
|
1150
1467
|
);
|
|
1151
1468
|
case "image":
|
|
1152
|
-
return
|
|
1469
|
+
return import_react6.default.createElement(components.image, {
|
|
1153
1470
|
key,
|
|
1154
1471
|
src: node.src,
|
|
1155
1472
|
alt: node.alt,
|
|
1156
1473
|
title: node.title
|
|
1157
1474
|
});
|
|
1158
1475
|
case "br":
|
|
1159
|
-
return
|
|
1476
|
+
return import_react6.default.createElement(import_react6.default.Fragment, { key }, import_react6.default.createElement(components.br, {}));
|
|
1160
1477
|
default: {
|
|
1161
1478
|
const component = components[node.kind];
|
|
1162
1479
|
if (component) {
|
|
1163
|
-
return
|
|
1480
|
+
return import_react6.default.createElement(component, { key, ...node });
|
|
1164
1481
|
}
|
|
1165
1482
|
return null;
|
|
1166
1483
|
}
|
|
@@ -1168,18 +1485,18 @@ function renderInlineNodes(nodes, components) {
|
|
|
1168
1485
|
});
|
|
1169
1486
|
}
|
|
1170
1487
|
var defaultInlineComponents = {
|
|
1171
|
-
text: ({ text }) =>
|
|
1172
|
-
strong: ({ children }) =>
|
|
1173
|
-
em: ({ children }) =>
|
|
1174
|
-
strike: ({ children }) =>
|
|
1175
|
-
code: ({ text }) =>
|
|
1488
|
+
text: ({ text }) => import_react6.default.createElement(import_react6.default.Fragment, {}, text),
|
|
1489
|
+
strong: ({ children }) => import_react6.default.createElement("strong", {}, children),
|
|
1490
|
+
em: ({ children }) => import_react6.default.createElement("em", {}, children),
|
|
1491
|
+
strike: ({ children }) => import_react6.default.createElement("del", {}, children),
|
|
1492
|
+
code: ({ text }) => import_react6.default.createElement(
|
|
1176
1493
|
"code",
|
|
1177
1494
|
{
|
|
1178
1495
|
className: "inline-code"
|
|
1179
1496
|
},
|
|
1180
1497
|
text
|
|
1181
1498
|
),
|
|
1182
|
-
link: ({ href, title, children }) =>
|
|
1499
|
+
link: ({ href, title, children }) => import_react6.default.createElement(
|
|
1183
1500
|
"a",
|
|
1184
1501
|
{
|
|
1185
1502
|
href,
|
|
@@ -1190,15 +1507,15 @@ var defaultInlineComponents = {
|
|
|
1190
1507
|
},
|
|
1191
1508
|
children
|
|
1192
1509
|
),
|
|
1193
|
-
image: ({ src, alt, title }) =>
|
|
1510
|
+
image: ({ src, alt, title }) => import_react6.default.createElement("img", {
|
|
1194
1511
|
src,
|
|
1195
1512
|
alt,
|
|
1196
1513
|
title,
|
|
1197
1514
|
className: "markdown-image"
|
|
1198
1515
|
}),
|
|
1199
|
-
br: () =>
|
|
1516
|
+
br: () => import_react6.default.createElement("br"),
|
|
1200
1517
|
// Custom extensible components
|
|
1201
|
-
mention: ({ handle }) =>
|
|
1518
|
+
mention: ({ handle }) => import_react6.default.createElement(
|
|
1202
1519
|
"span",
|
|
1203
1520
|
{
|
|
1204
1521
|
className: "mention",
|
|
@@ -1206,7 +1523,7 @@ var defaultInlineComponents = {
|
|
|
1206
1523
|
},
|
|
1207
1524
|
`@${handle}`
|
|
1208
1525
|
),
|
|
1209
|
-
citation: ({ id }) =>
|
|
1526
|
+
citation: ({ id }) => import_react6.default.createElement(
|
|
1210
1527
|
"span",
|
|
1211
1528
|
{
|
|
1212
1529
|
className: "citation",
|
|
@@ -1214,7 +1531,7 @@ var defaultInlineComponents = {
|
|
|
1214
1531
|
},
|
|
1215
1532
|
`[${id}]`
|
|
1216
1533
|
),
|
|
1217
|
-
"math-inline": ({ tex }) =>
|
|
1534
|
+
"math-inline": ({ tex }) => import_react6.default.createElement(
|
|
1218
1535
|
"span",
|
|
1219
1536
|
{
|
|
1220
1537
|
className: "math-inline",
|
|
@@ -1222,27 +1539,31 @@ var defaultInlineComponents = {
|
|
|
1222
1539
|
},
|
|
1223
1540
|
`$${tex}$`
|
|
1224
1541
|
),
|
|
1225
|
-
"math-display": ({ tex }) =>
|
|
1542
|
+
"math-display": ({ tex }) => import_react6.default.createElement(
|
|
1226
1543
|
"div",
|
|
1227
1544
|
{
|
|
1228
1545
|
className: "math-display markdown-math-display",
|
|
1229
1546
|
"data-tex": tex,
|
|
1230
1547
|
style: { overflowX: "auto" }
|
|
1231
1548
|
},
|
|
1232
|
-
|
|
1549
|
+
import_react6.default.createElement("span", { className: "math-display-content" }, `$$${tex}$$`)
|
|
1233
1550
|
),
|
|
1234
1551
|
// Footnote inline reference (superscript anchor)
|
|
1235
1552
|
"footnote-ref": ({ label, number }) => {
|
|
1236
1553
|
const n = number ?? "?";
|
|
1237
1554
|
const href = number ? `#fn:${n}` : void 0;
|
|
1238
1555
|
const id = number ? `fnref:${n}` : void 0;
|
|
1239
|
-
return
|
|
1556
|
+
return import_react6.default.createElement(
|
|
1557
|
+
"sup",
|
|
1558
|
+
{ className: "footnote-ref" },
|
|
1559
|
+
import_react6.default.createElement("a", { href, id, "data-label": label, style: { color: "var(--foreground)", textDecoration: "underline" } }, String(n))
|
|
1560
|
+
);
|
|
1240
1561
|
}
|
|
1241
1562
|
};
|
|
1242
1563
|
var defaultBlockComponents = {
|
|
1243
1564
|
paragraph: ({ inlines, raw, meta, children }) => {
|
|
1244
1565
|
if (children !== void 0) {
|
|
1245
|
-
return
|
|
1566
|
+
return import_react6.default.createElement(
|
|
1246
1567
|
"p",
|
|
1247
1568
|
{
|
|
1248
1569
|
className: "markdown-paragraph"
|
|
@@ -1256,7 +1577,7 @@ var defaultBlockComponents = {
|
|
|
1256
1577
|
if (structured.length === 1) {
|
|
1257
1578
|
return structured[0];
|
|
1258
1579
|
}
|
|
1259
|
-
return
|
|
1580
|
+
return import_react6.default.createElement(import_react6.default.Fragment, {}, ...structured);
|
|
1260
1581
|
}
|
|
1261
1582
|
const filteredInlines = inlines && raw && inlines.length > 0 ? inlines.filter((node) => !(node.kind === "text" && node.text === raw)) : inlines ?? [];
|
|
1262
1583
|
const effectiveInlines = filteredInlines.length > 0 ? filteredInlines : raw ? [
|
|
@@ -1265,7 +1586,7 @@ var defaultBlockComponents = {
|
|
|
1265
1586
|
text: raw
|
|
1266
1587
|
}
|
|
1267
1588
|
] : [];
|
|
1268
|
-
return
|
|
1589
|
+
return import_react6.default.createElement(
|
|
1269
1590
|
"p",
|
|
1270
1591
|
{
|
|
1271
1592
|
className: "markdown-paragraph"
|
|
@@ -1278,7 +1599,7 @@ var defaultBlockComponents = {
|
|
|
1278
1599
|
const onlyPlainText = Array.isArray(inlines) && inlines.length > 0 && inlines.every((node) => node.kind === "text");
|
|
1279
1600
|
const children = onlyPlainText ? inlines.map((node) => node.kind === "text" ? node.text : "").join("") : renderInlineNodes(inlines, defaultInlineComponents);
|
|
1280
1601
|
const headingId = typeof meta?.headingId === "string" && meta.headingId.length > 0 ? meta.headingId : void 0;
|
|
1281
|
-
return
|
|
1602
|
+
return import_react6.default.createElement(
|
|
1282
1603
|
tag,
|
|
1283
1604
|
{
|
|
1284
1605
|
className: `markdown-heading markdown-h${level}`,
|
|
@@ -1291,7 +1612,7 @@ var defaultBlockComponents = {
|
|
|
1291
1612
|
code: ({ html, meta, lines, lang, preAttrs, codeAttrs }) => {
|
|
1292
1613
|
const language = typeof lang === "string" ? lang : typeof meta?.lang === "string" ? String(meta.lang) : "text";
|
|
1293
1614
|
if (html) {
|
|
1294
|
-
return
|
|
1615
|
+
return import_react6.default.createElement("div", {
|
|
1295
1616
|
className: `markdown-code-block language-${language || "text"}`,
|
|
1296
1617
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: highlighted HTML is generated by our sanitizer */
|
|
1297
1618
|
dangerouslySetInnerHTML: { __html: html }
|
|
@@ -1301,20 +1622,20 @@ var defaultBlockComponents = {
|
|
|
1301
1622
|
if (lines && lines.length > 0) {
|
|
1302
1623
|
const preAttributes = attrsToProps(preAttrs);
|
|
1303
1624
|
const codeAttributes = attrsToProps(codeAttrs);
|
|
1304
|
-
return
|
|
1625
|
+
return import_react6.default.createElement(
|
|
1305
1626
|
"pre",
|
|
1306
1627
|
{
|
|
1307
1628
|
...preAttributes,
|
|
1308
1629
|
className: preAttributes.className ? `${preAttributes.className} markdown-code-block language-${language || "text"}` : `markdown-code-block language-${language || "text"}`
|
|
1309
1630
|
},
|
|
1310
|
-
|
|
1631
|
+
import_react6.default.createElement(
|
|
1311
1632
|
"code",
|
|
1312
1633
|
{
|
|
1313
1634
|
...codeAttributes,
|
|
1314
1635
|
className: codeAttributes.className ? `${codeAttributes.className} language-${language || "text"}` : `language-${language || "text"}`
|
|
1315
1636
|
},
|
|
1316
1637
|
lines.map(
|
|
1317
|
-
(line) =>
|
|
1638
|
+
(line) => import_react6.default.createElement("span", {
|
|
1318
1639
|
key: line.id,
|
|
1319
1640
|
className: "line",
|
|
1320
1641
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: line HTML is sanitized server-side */
|
|
@@ -1324,19 +1645,19 @@ var defaultBlockComponents = {
|
|
|
1324
1645
|
)
|
|
1325
1646
|
);
|
|
1326
1647
|
}
|
|
1327
|
-
return
|
|
1648
|
+
return import_react6.default.createElement("pre", {
|
|
1328
1649
|
className: `markdown-code-block language-${language || "text"}`,
|
|
1329
1650
|
children: code
|
|
1330
1651
|
});
|
|
1331
1652
|
},
|
|
1332
|
-
blockquote: ({ inlines, renderedContent }) =>
|
|
1653
|
+
blockquote: ({ inlines, renderedContent }) => import_react6.default.createElement(
|
|
1333
1654
|
"blockquote",
|
|
1334
1655
|
{
|
|
1335
1656
|
className: "markdown-blockquote"
|
|
1336
1657
|
},
|
|
1337
1658
|
renderedContent ?? renderInlineNodes(inlines, defaultInlineComponents)
|
|
1338
1659
|
),
|
|
1339
|
-
hr: (props) =>
|
|
1660
|
+
hr: (props) => import_react6.default.createElement("hr", props),
|
|
1340
1661
|
list: ({ ordered, items }) => {
|
|
1341
1662
|
if (items.length === 0) {
|
|
1342
1663
|
return null;
|
|
@@ -1346,7 +1667,7 @@ var defaultBlockComponents = {
|
|
|
1346
1667
|
["--list-indent"]: `calc(2.5rem + ${String(items.length).length}ch)`
|
|
1347
1668
|
} : void 0;
|
|
1348
1669
|
const listItems = items.map(
|
|
1349
|
-
(item, index) =>
|
|
1670
|
+
(item, index) => import_react6.default.createElement(
|
|
1350
1671
|
"li",
|
|
1351
1672
|
{
|
|
1352
1673
|
key: index,
|
|
@@ -1357,7 +1678,7 @@ var defaultBlockComponents = {
|
|
|
1357
1678
|
renderInlineNodes(item, defaultInlineComponents)
|
|
1358
1679
|
)
|
|
1359
1680
|
);
|
|
1360
|
-
return
|
|
1681
|
+
return import_react6.default.createElement(
|
|
1361
1682
|
tag,
|
|
1362
1683
|
{
|
|
1363
1684
|
className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
|
|
@@ -1371,23 +1692,23 @@ var defaultBlockComponents = {
|
|
|
1371
1692
|
const htmlString = typeof window === "undefined" ? raw : (0, import_core.sanitizeHTML)(raw);
|
|
1372
1693
|
if (typeof window !== "undefined" && elements) {
|
|
1373
1694
|
const content = mapHtmlToReact(htmlString, elements);
|
|
1374
|
-
return
|
|
1695
|
+
return import_react6.default.createElement("div", { className: "markdown-html" }, content);
|
|
1375
1696
|
}
|
|
1376
|
-
return
|
|
1697
|
+
return import_react6.default.createElement("div", {
|
|
1377
1698
|
className: "markdown-html",
|
|
1378
1699
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: htmlString is sanitized before injection */
|
|
1379
1700
|
dangerouslySetInnerHTML: { __html: htmlString }
|
|
1380
1701
|
});
|
|
1381
1702
|
},
|
|
1382
|
-
mdx: ({ compiledRef, compiledModule, status, errorMessage
|
|
1383
|
-
const [Comp, setComp] =
|
|
1384
|
-
const [internalError, setInternalError] =
|
|
1385
|
-
const [renderError, setRenderError] =
|
|
1386
|
-
const [retryKey, setRetryKey] =
|
|
1387
|
-
const hydrationContext =
|
|
1703
|
+
mdx: ({ compiledRef, compiledModule, status, errorMessage }) => {
|
|
1704
|
+
const [Comp, setComp] = import_react6.default.useState(null);
|
|
1705
|
+
const [internalError, setInternalError] = import_react6.default.useState(null);
|
|
1706
|
+
const [renderError, setRenderError] = import_react6.default.useState(null);
|
|
1707
|
+
const [retryKey, setRetryKey] = import_react6.default.useState(0);
|
|
1708
|
+
const hydrationContext = import_react6.default.useContext(MdxHydrationContext);
|
|
1388
1709
|
const hydrationController = hydrationContext?.controller ?? null;
|
|
1389
1710
|
const hydrationOptions = hydrationContext?.options;
|
|
1390
|
-
const containerRef =
|
|
1711
|
+
const containerRef = import_react6.default.useRef(null);
|
|
1391
1712
|
const deferHydration = hydrationOptions?.strategy === "visible";
|
|
1392
1713
|
const shouldHydrate = useDeferredRender(
|
|
1393
1714
|
containerRef,
|
|
@@ -1399,13 +1720,13 @@ var defaultBlockComponents = {
|
|
|
1399
1720
|
} : { enabled: false }
|
|
1400
1721
|
);
|
|
1401
1722
|
const resolvedId = compiledModule?.id ?? (compiledRef?.id && compiledRef.id !== "pending" ? compiledRef.id : void 0);
|
|
1402
|
-
const handleRetry =
|
|
1723
|
+
const handleRetry = import_react6.default.useCallback(() => {
|
|
1403
1724
|
setInternalError(null);
|
|
1404
1725
|
setRenderError(null);
|
|
1405
1726
|
setComp(null);
|
|
1406
1727
|
setRetryKey((prev) => prev + 1);
|
|
1407
1728
|
}, []);
|
|
1408
|
-
const handleRuntimeError =
|
|
1729
|
+
const handleRuntimeError = import_react6.default.useCallback(
|
|
1409
1730
|
(error) => {
|
|
1410
1731
|
const message2 = error instanceof Error ? error.message : String(error);
|
|
1411
1732
|
setRenderError(message2);
|
|
@@ -1416,7 +1737,7 @@ var defaultBlockComponents = {
|
|
|
1416
1737
|
const effectiveStatus = status ? status : resolvedId ? "compiled" : "pending";
|
|
1417
1738
|
const failureMessage = errorMessage ?? internalError ?? renderError ?? null;
|
|
1418
1739
|
const moduleDependencies = compiledModule?.dependencies;
|
|
1419
|
-
|
|
1740
|
+
import_react6.default.useEffect(() => {
|
|
1420
1741
|
if (!shouldHydrate) {
|
|
1421
1742
|
return;
|
|
1422
1743
|
}
|
|
@@ -1480,9 +1801,8 @@ var defaultBlockComponents = {
|
|
|
1480
1801
|
const waitingForVisibility = deferHydration && !shouldHydrate && Boolean(resolvedId);
|
|
1481
1802
|
const pendingLabel = waitingForVisibility ? "MDX ready (hydrate on view)\u2026" : compileMode === "worker" ? "Compiling MDX (client)\u2026" : "Compiling MDX (server)\u2026";
|
|
1482
1803
|
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.");
|
|
1483
|
-
const rawFallback = typeof raw === "string" && raw.trim().length > 0 ? import_react5.default.createElement("pre", { className: "markdown-mdx-fallback" }, raw) : null;
|
|
1484
1804
|
const allowRetry = Boolean(internalError || renderError);
|
|
1485
|
-
const retryButton = allowRetry ?
|
|
1805
|
+
const retryButton = allowRetry ? import_react6.default.createElement(
|
|
1486
1806
|
"button",
|
|
1487
1807
|
{
|
|
1488
1808
|
type: "button",
|
|
@@ -1491,13 +1811,14 @@ var defaultBlockComponents = {
|
|
|
1491
1811
|
},
|
|
1492
1812
|
"Retry hydration"
|
|
1493
1813
|
) : null;
|
|
1494
|
-
const errorPanel =
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1814
|
+
const errorPanel = import_react6.default.createElement(
|
|
1815
|
+
import_react6.default.Fragment,
|
|
1816
|
+
null,
|
|
1817
|
+
import_react6.default.createElement("strong", null, "MDX failed"),
|
|
1818
|
+
import_react6.default.createElement("div", null, message)
|
|
1498
1819
|
);
|
|
1499
1820
|
if (Comp && !failureMessage) {
|
|
1500
|
-
return
|
|
1821
|
+
return import_react6.default.createElement(
|
|
1501
1822
|
"div",
|
|
1502
1823
|
{
|
|
1503
1824
|
className: "markdown-mdx",
|
|
@@ -1506,30 +1827,29 @@ var defaultBlockComponents = {
|
|
|
1506
1827
|
"data-mdx-status": failureMessage ? "error" : "compiled",
|
|
1507
1828
|
"data-mdx-mode": compileMode
|
|
1508
1829
|
},
|
|
1509
|
-
|
|
1830
|
+
import_react6.default.createElement(
|
|
1510
1831
|
MdxRuntimeBoundary,
|
|
1511
1832
|
{ resetKey: retryKey, onError: handleRuntimeError },
|
|
1512
|
-
|
|
1833
|
+
import_react6.default.createElement(Comp, {})
|
|
1513
1834
|
)
|
|
1514
1835
|
);
|
|
1515
1836
|
}
|
|
1516
1837
|
if (failureMessage) {
|
|
1517
|
-
return
|
|
1838
|
+
return import_react6.default.createElement(
|
|
1518
1839
|
"div",
|
|
1519
1840
|
{
|
|
1520
|
-
className: "markdown-mdx",
|
|
1841
|
+
className: "markdown-mdx error",
|
|
1521
1842
|
ref: containerRef,
|
|
1522
1843
|
"data-mdx-ref": pendingId,
|
|
1523
1844
|
"data-mdx-status": "error",
|
|
1524
1845
|
"data-mdx-mode": compileMode
|
|
1525
1846
|
},
|
|
1526
1847
|
errorPanel,
|
|
1527
|
-
rawFallback,
|
|
1528
1848
|
retryButton
|
|
1529
1849
|
);
|
|
1530
1850
|
}
|
|
1531
1851
|
if (!Comp) {
|
|
1532
|
-
return
|
|
1852
|
+
return import_react6.default.createElement(
|
|
1533
1853
|
"div",
|
|
1534
1854
|
{
|
|
1535
1855
|
className: "markdown-mdx",
|
|
@@ -1544,28 +1864,37 @@ var defaultBlockComponents = {
|
|
|
1544
1864
|
},
|
|
1545
1865
|
// Footnotes block rendered at page end
|
|
1546
1866
|
footnotes: ({ items }) => {
|
|
1547
|
-
if (!items || items.length === 0) return
|
|
1867
|
+
if (!items || items.length === 0) return import_react6.default.createElement(import_react6.default.Fragment, null);
|
|
1548
1868
|
const listItems = items.map(
|
|
1549
|
-
(item) =>
|
|
1869
|
+
(item) => import_react6.default.createElement(
|
|
1550
1870
|
"li",
|
|
1551
1871
|
{ key: item.number, id: `fn:${item.number}` },
|
|
1552
1872
|
renderInlineNodes(item.inlines, defaultInlineComponents),
|
|
1553
1873
|
" ",
|
|
1554
|
-
|
|
1874
|
+
import_react6.default.createElement(
|
|
1875
|
+
"a",
|
|
1876
|
+
{
|
|
1877
|
+
href: `#fnref:${item.number}`,
|
|
1878
|
+
className: "footnote-backref",
|
|
1879
|
+
"aria-label": "Back to content",
|
|
1880
|
+
style: { color: "var(--foreground)", textDecoration: "underline" }
|
|
1881
|
+
},
|
|
1882
|
+
"\u21A9"
|
|
1883
|
+
)
|
|
1555
1884
|
)
|
|
1556
1885
|
);
|
|
1557
|
-
return
|
|
1886
|
+
return import_react6.default.createElement("section", { className: "footnotes" }, import_react6.default.createElement("hr", {}), import_react6.default.createElement("ol", {}, listItems));
|
|
1558
1887
|
},
|
|
1559
1888
|
// Footnote definition placeholders (render nothing)
|
|
1560
|
-
"footnote-def": () =>
|
|
1889
|
+
"footnote-def": () => import_react6.default.createElement(import_react6.default.Fragment, null),
|
|
1561
1890
|
// Callouts block
|
|
1562
1891
|
callout: ({ kind, inlines = [] }) => {
|
|
1563
1892
|
const tone = (kind || "NOTE").toUpperCase();
|
|
1564
1893
|
const title = tone.charAt(0) + tone.slice(1).toLowerCase();
|
|
1565
|
-
return
|
|
1894
|
+
return import_react6.default.createElement(
|
|
1566
1895
|
"div",
|
|
1567
1896
|
{ className: `markdown-callout markdown-callout-${tone.toLowerCase()} border rounded p-3 my-3` },
|
|
1568
|
-
|
|
1897
|
+
import_react6.default.createElement("div", { className: "font-semibold mb-1" }, title),
|
|
1569
1898
|
inlines.length > 0 ? renderInlineNodes(inlines, defaultInlineComponents) : null
|
|
1570
1899
|
);
|
|
1571
1900
|
},
|
|
@@ -1580,7 +1909,7 @@ var defaultBlockComponents = {
|
|
|
1580
1909
|
const renderCells = (cells, tag, rowIdx) => cells.map((cell, i) => {
|
|
1581
1910
|
const columnAlign = align?.[i] ?? void 0;
|
|
1582
1911
|
const cellStyle = columnAlign ? { textAlign: columnAlign } : void 0;
|
|
1583
|
-
return
|
|
1912
|
+
return import_react6.default.createElement(
|
|
1584
1913
|
tag === "th" ? El.Th : El.Td,
|
|
1585
1914
|
{
|
|
1586
1915
|
key: `${rowIdx}-${i}`,
|
|
@@ -1591,14 +1920,14 @@ var defaultBlockComponents = {
|
|
|
1591
1920
|
renderInlineNodes(cell, defaultInlineComponents)
|
|
1592
1921
|
);
|
|
1593
1922
|
});
|
|
1594
|
-
return
|
|
1923
|
+
return import_react6.default.createElement(
|
|
1595
1924
|
El.Table,
|
|
1596
1925
|
{ className: "markdown-table" },
|
|
1597
|
-
header && header.length > 0 ?
|
|
1598
|
-
|
|
1926
|
+
header && header.length > 0 ? import_react6.default.createElement(El.Thead, {}, import_react6.default.createElement(El.Tr, {}, renderCells(header, "th", -1))) : null,
|
|
1927
|
+
import_react6.default.createElement(
|
|
1599
1928
|
El.Tbody,
|
|
1600
1929
|
{},
|
|
1601
|
-
rows.map((row, r) =>
|
|
1930
|
+
rows.map((row, r) => import_react6.default.createElement(El.Tr, { key: r }, renderCells(row, "td", r)))
|
|
1602
1931
|
)
|
|
1603
1932
|
);
|
|
1604
1933
|
}
|
|
@@ -1667,7 +1996,7 @@ var ComponentRegistry = class {
|
|
|
1667
1996
|
renderBlock(block) {
|
|
1668
1997
|
const Component = this.getBlockComponent(block.type);
|
|
1669
1998
|
const props = this.getBlockProps(block);
|
|
1670
|
-
return
|
|
1999
|
+
return import_react6.default.createElement(Component, {
|
|
1671
2000
|
key: block.id,
|
|
1672
2001
|
...props
|
|
1673
2002
|
});
|
|
@@ -1796,42 +2125,42 @@ var ComponentRegistry = class {
|
|
|
1796
2125
|
function getDefaultHtmlElements() {
|
|
1797
2126
|
return {
|
|
1798
2127
|
// Text semantics
|
|
1799
|
-
p: (props) =>
|
|
1800
|
-
strong: (props) =>
|
|
1801
|
-
em: (props) =>
|
|
1802
|
-
code: (props) =>
|
|
1803
|
-
pre: (props) =>
|
|
1804
|
-
span: (props) =>
|
|
1805
|
-
br: (props) =>
|
|
1806
|
-
hr: (props) =>
|
|
2128
|
+
p: (props) => import_react6.default.createElement("p", props),
|
|
2129
|
+
strong: (props) => import_react6.default.createElement("strong", props),
|
|
2130
|
+
em: (props) => import_react6.default.createElement("em", props),
|
|
2131
|
+
code: (props) => import_react6.default.createElement("code", props),
|
|
2132
|
+
pre: (props) => import_react6.default.createElement("pre", props),
|
|
2133
|
+
span: (props) => import_react6.default.createElement("span", props),
|
|
2134
|
+
br: (props) => import_react6.default.createElement("br", props),
|
|
2135
|
+
hr: (props) => import_react6.default.createElement("hr", props),
|
|
1807
2136
|
// Lists
|
|
1808
|
-
ul: (props) =>
|
|
1809
|
-
ol: (props) =>
|
|
1810
|
-
li: (props) =>
|
|
2137
|
+
ul: (props) => import_react6.default.createElement("ul", props),
|
|
2138
|
+
ol: (props) => import_react6.default.createElement("ol", props),
|
|
2139
|
+
li: (props) => import_react6.default.createElement("li", props),
|
|
1811
2140
|
// Links & media
|
|
1812
|
-
a: (props) =>
|
|
1813
|
-
img: (props) =>
|
|
2141
|
+
a: (props) => import_react6.default.createElement("a", props),
|
|
2142
|
+
img: (props) => import_react6.default.createElement("img", props),
|
|
1814
2143
|
// Blockquotes
|
|
1815
|
-
blockquote: (props) =>
|
|
2144
|
+
blockquote: (props) => import_react6.default.createElement("blockquote", props),
|
|
1816
2145
|
// Tables
|
|
1817
|
-
table: (props) =>
|
|
1818
|
-
thead: (props) =>
|
|
1819
|
-
tbody: (props) =>
|
|
1820
|
-
tr: (props) =>
|
|
1821
|
-
th: (props) =>
|
|
1822
|
-
td: (props) =>
|
|
2146
|
+
table: (props) => import_react6.default.createElement("table", props),
|
|
2147
|
+
thead: (props) => import_react6.default.createElement("thead", props),
|
|
2148
|
+
tbody: (props) => import_react6.default.createElement("tbody", props),
|
|
2149
|
+
tr: (props) => import_react6.default.createElement("tr", props),
|
|
2150
|
+
th: (props) => import_react6.default.createElement("th", props),
|
|
2151
|
+
td: (props) => import_react6.default.createElement("td", props),
|
|
1823
2152
|
// Generic
|
|
1824
|
-
div: (props) =>
|
|
2153
|
+
div: (props) => import_react6.default.createElement("div", props)
|
|
1825
2154
|
};
|
|
1826
2155
|
}
|
|
1827
2156
|
function getDefaultTableElements(overrides) {
|
|
1828
2157
|
const base = {
|
|
1829
|
-
Table: (props) =>
|
|
1830
|
-
Thead: (props) =>
|
|
1831
|
-
Tbody: (props) =>
|
|
1832
|
-
Tr: (props) =>
|
|
1833
|
-
Th: (props) =>
|
|
1834
|
-
Td: (props) =>
|
|
2158
|
+
Table: (props) => import_react6.default.createElement("table", props),
|
|
2159
|
+
Thead: (props) => import_react6.default.createElement("thead", props),
|
|
2160
|
+
Tbody: (props) => import_react6.default.createElement("tbody", props),
|
|
2161
|
+
Tr: (props) => import_react6.default.createElement("tr", props),
|
|
2162
|
+
Th: (props) => import_react6.default.createElement("th", props),
|
|
2163
|
+
Td: (props) => import_react6.default.createElement("td", props)
|
|
1835
2164
|
};
|
|
1836
2165
|
return { ...base, ...overrides || {} };
|
|
1837
2166
|
}
|
|
@@ -1845,12 +2174,12 @@ function mapHtmlToReact(html, elements) {
|
|
|
1845
2174
|
children.push(element);
|
|
1846
2175
|
}
|
|
1847
2176
|
});
|
|
1848
|
-
return
|
|
2177
|
+
return import_react6.default.createElement(import_react6.default.Fragment, {}, ...children);
|
|
1849
2178
|
}
|
|
1850
2179
|
function toReact(node, elements, key) {
|
|
1851
2180
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
1852
2181
|
const text = node.textContent ?? "";
|
|
1853
|
-
return
|
|
2182
|
+
return import_react6.default.createElement(import_react6.default.Fragment, { key }, text);
|
|
1854
2183
|
}
|
|
1855
2184
|
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
1856
2185
|
return null;
|
|
@@ -1872,9 +2201,9 @@ function toReact(node, elements, key) {
|
|
|
1872
2201
|
const component = elements[tag];
|
|
1873
2202
|
const elementChildren = children.length > 0 ? children : void 0;
|
|
1874
2203
|
if (component) {
|
|
1875
|
-
return
|
|
2204
|
+
return import_react6.default.createElement(component, { ...props, key }, elementChildren);
|
|
1876
2205
|
}
|
|
1877
|
-
return
|
|
2206
|
+
return import_react6.default.createElement(tag, { ...props, key }, elementChildren);
|
|
1878
2207
|
}
|
|
1879
2208
|
function attrsToProps(attrs) {
|
|
1880
2209
|
if (!attrs) return {};
|
|
@@ -1919,12 +2248,12 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
1919
2248
|
nodes.forEach((node, idx) => {
|
|
1920
2249
|
if (node === null || node === void 0) return;
|
|
1921
2250
|
const key = `${baseKey}-${idx}`;
|
|
1922
|
-
if (
|
|
1923
|
-
target.push(node.key === key ? node :
|
|
2251
|
+
if (import_react6.default.isValidElement(node)) {
|
|
2252
|
+
target.push(node.key === key ? node : import_react6.default.cloneElement(node, { key }));
|
|
1924
2253
|
} else if (typeof node === "string" || typeof node === "number") {
|
|
1925
|
-
target.push(
|
|
2254
|
+
target.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, node));
|
|
1926
2255
|
} else {
|
|
1927
|
-
target.push(
|
|
2256
|
+
target.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, node));
|
|
1928
2257
|
}
|
|
1929
2258
|
});
|
|
1930
2259
|
};
|
|
@@ -1940,7 +2269,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
1940
2269
|
}
|
|
1941
2270
|
const key = `paragraph-inline-group-${inlineGroupIndex++}`;
|
|
1942
2271
|
result.push(
|
|
1943
|
-
|
|
2272
|
+
import_react6.default.createElement(
|
|
1944
2273
|
"p",
|
|
1945
2274
|
{
|
|
1946
2275
|
key,
|
|
@@ -1958,7 +2287,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
1958
2287
|
const inlineNodes = Array.isArray(segment.inline) ? segment.inline : [];
|
|
1959
2288
|
if (inlineNodes.length === 0) {
|
|
1960
2289
|
if (segment.value) {
|
|
1961
|
-
inlineBuffer.push(
|
|
2290
|
+
inlineBuffer.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, segment.value));
|
|
1962
2291
|
}
|
|
1963
2292
|
break;
|
|
1964
2293
|
}
|
|
@@ -1986,14 +2315,14 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
1986
2315
|
const status = segment.status ?? "pending";
|
|
1987
2316
|
let element;
|
|
1988
2317
|
if (status === "compiled") {
|
|
1989
|
-
element =
|
|
2318
|
+
element = import_react6.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
|
|
1990
2319
|
} else if (status === "error") {
|
|
1991
2320
|
const message = segment.value || "MDX error";
|
|
1992
|
-
element =
|
|
2321
|
+
element = import_react6.default.createElement("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error" }, message);
|
|
1993
2322
|
} else {
|
|
1994
|
-
element =
|
|
2323
|
+
element = import_react6.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": status }, segment.value);
|
|
1995
2324
|
}
|
|
1996
|
-
inlineBuffer.push(
|
|
2325
|
+
inlineBuffer.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, element));
|
|
1997
2326
|
break;
|
|
1998
2327
|
}
|
|
1999
2328
|
case "html": {
|
|
@@ -2009,7 +2338,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
2009
2338
|
result.push(element);
|
|
2010
2339
|
} else if (html) {
|
|
2011
2340
|
result.push(
|
|
2012
|
-
|
|
2341
|
+
import_react6.default.createElement("div", {
|
|
2013
2342
|
key,
|
|
2014
2343
|
className: "markdown-inline-html-block",
|
|
2015
2344
|
dangerouslySetInnerHTML: { __html: html }
|
|
@@ -2028,7 +2357,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
2028
2357
|
flushInline();
|
|
2029
2358
|
if (result.length === 0) {
|
|
2030
2359
|
return [
|
|
2031
|
-
|
|
2360
|
+
import_react6.default.createElement(
|
|
2032
2361
|
"p",
|
|
2033
2362
|
{
|
|
2034
2363
|
key: "paragraph-inline-group-0",
|
|
@@ -2090,20 +2419,21 @@ var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
|
2090
2419
|
init_mdx_client();
|
|
2091
2420
|
|
|
2092
2421
|
// src/mdx-coordinator.ts
|
|
2093
|
-
var
|
|
2422
|
+
var import_react7 = require("react");
|
|
2094
2423
|
init_mdx_client();
|
|
2095
2424
|
function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
2096
|
-
const mdxClientRef = (0,
|
|
2425
|
+
const mdxClientRef = (0, import_react7.useRef)(getMDXClient(compileEndpoint));
|
|
2097
2426
|
const mode = options?.mode ?? "server";
|
|
2098
|
-
const [compiledMap, setCompiledMap] = (0,
|
|
2099
|
-
const blockSignatureRef = (0,
|
|
2100
|
-
const
|
|
2427
|
+
const [compiledMap, setCompiledMap] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
|
|
2428
|
+
const blockSignatureRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
|
|
2429
|
+
const failedSignatureRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
|
|
2430
|
+
const applyCompiledRef = (0, import_react7.useCallback)(
|
|
2101
2431
|
(block, compiledId) => {
|
|
2102
2432
|
if (mode === "worker") {
|
|
2103
2433
|
return;
|
|
2104
2434
|
}
|
|
2105
2435
|
if (options?.workerClient) {
|
|
2106
|
-
options.workerClient.setMdxCompiled(block.id, compiledId);
|
|
2436
|
+
options.workerClient.setMdxCompiled(block.id, compiledId, block.payload.raw ?? "");
|
|
2107
2437
|
return;
|
|
2108
2438
|
}
|
|
2109
2439
|
const store = options?.store;
|
|
@@ -2114,6 +2444,9 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
|
2114
2444
|
const index = currentBlocks.findIndex((candidate) => candidate.id === block.id);
|
|
2115
2445
|
if (index === -1) return;
|
|
2116
2446
|
const current = currentBlocks[index];
|
|
2447
|
+
if ((current.payload.raw ?? "") !== (block.payload.raw ?? "")) {
|
|
2448
|
+
return;
|
|
2449
|
+
}
|
|
2117
2450
|
if (current.payload.compiledMdxRef?.id === compiledId) {
|
|
2118
2451
|
return;
|
|
2119
2452
|
}
|
|
@@ -2139,11 +2472,17 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
|
2139
2472
|
},
|
|
2140
2473
|
[options?.workerClient, options?.store, mode]
|
|
2141
2474
|
);
|
|
2142
|
-
(0,
|
|
2475
|
+
(0, import_react7.useEffect)(() => {
|
|
2143
2476
|
if (mode === "worker") {
|
|
2144
2477
|
return;
|
|
2145
2478
|
}
|
|
2146
|
-
const targets = blocks.filter((b) =>
|
|
2479
|
+
const targets = blocks.filter((b) => {
|
|
2480
|
+
if (b.type !== "mdx" || !b.isFinalized || b.payload.compiledMdxRef || compiledMap.has(b.id)) {
|
|
2481
|
+
return false;
|
|
2482
|
+
}
|
|
2483
|
+
const raw = b.payload.raw ?? "";
|
|
2484
|
+
return failedSignatureRef.current.get(b.id) !== raw;
|
|
2485
|
+
});
|
|
2147
2486
|
if (targets.length === 0) return;
|
|
2148
2487
|
let cancelled = false;
|
|
2149
2488
|
(async () => {
|
|
@@ -2162,22 +2501,29 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
|
2162
2501
|
next.set(block.id, compiled.id);
|
|
2163
2502
|
return next;
|
|
2164
2503
|
});
|
|
2504
|
+
failedSignatureRef.current.delete(block.id);
|
|
2165
2505
|
applyCompiledRef(block, compiled.id);
|
|
2166
2506
|
} catch (e) {
|
|
2167
2507
|
console.warn("MDX compile failed for block", block.id, e);
|
|
2508
|
+
failedSignatureRef.current.set(block.id, block.payload.raw ?? "");
|
|
2168
2509
|
if (options?.workerClient) {
|
|
2169
|
-
options.workerClient.setMdxError(block.id, e instanceof Error ? e.message : String(e));
|
|
2510
|
+
options.workerClient.setMdxError(block.id, e instanceof Error ? e.message : String(e), block.payload.raw ?? "");
|
|
2170
2511
|
} else if (options?.store) {
|
|
2512
|
+
const currentBlocks = options.store.getBlocks();
|
|
2513
|
+
const current = currentBlocks.find((candidate) => candidate.id === block.id);
|
|
2514
|
+
if (!current || (current.payload.raw ?? "") !== (block.payload.raw ?? "")) {
|
|
2515
|
+
continue;
|
|
2516
|
+
}
|
|
2171
2517
|
options.store.applyPatches([
|
|
2172
2518
|
{
|
|
2173
2519
|
op: "setProps",
|
|
2174
2520
|
at: { blockId: block.id, nodeId: block.id },
|
|
2175
2521
|
props: {
|
|
2176
2522
|
block: {
|
|
2177
|
-
...
|
|
2523
|
+
...current,
|
|
2178
2524
|
payload: {
|
|
2179
|
-
...
|
|
2180
|
-
meta: { ...
|
|
2525
|
+
...current.payload,
|
|
2526
|
+
meta: { ...current.payload.meta ?? {}, mdxStatus: "error", mdxError: e instanceof Error ? e.message : String(e) }
|
|
2181
2527
|
}
|
|
2182
2528
|
}
|
|
2183
2529
|
}
|
|
@@ -2191,7 +2537,7 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
|
2191
2537
|
cancelled = true;
|
|
2192
2538
|
};
|
|
2193
2539
|
}, [blocks, compiledMap, applyCompiledRef, options?.workerClient, options?.store, mode]);
|
|
2194
|
-
(0,
|
|
2540
|
+
(0, import_react7.useEffect)(() => {
|
|
2195
2541
|
if (mode === "worker") {
|
|
2196
2542
|
return;
|
|
2197
2543
|
}
|
|
@@ -2210,6 +2556,7 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
|
2210
2556
|
const currentSignature = candidate.payload.raw ?? "";
|
|
2211
2557
|
if (previousSignature !== void 0 && previousSignature !== currentSignature) {
|
|
2212
2558
|
next.delete(blockId);
|
|
2559
|
+
failedSignatureRef.current.delete(blockId);
|
|
2213
2560
|
mutated = true;
|
|
2214
2561
|
}
|
|
2215
2562
|
}
|
|
@@ -2219,11 +2566,14 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
|
|
|
2219
2566
|
for (const block of blocks) {
|
|
2220
2567
|
if (block.type === "mdx") {
|
|
2221
2568
|
signatureMap.set(block.id, block.payload.raw ?? "");
|
|
2569
|
+
if (!block.isFinalized || block.payload.compiledMdxRef) {
|
|
2570
|
+
failedSignatureRef.current.delete(block.id);
|
|
2571
|
+
}
|
|
2222
2572
|
}
|
|
2223
2573
|
}
|
|
2224
2574
|
blockSignatureRef.current = signatureMap;
|
|
2225
2575
|
}, [blocks, mode]);
|
|
2226
|
-
const derivedBlocks = (0,
|
|
2576
|
+
const derivedBlocks = (0, import_react7.useMemo)(() => {
|
|
2227
2577
|
if (mode === "worker") {
|
|
2228
2578
|
return blocks;
|
|
2229
2579
|
}
|
|
@@ -2406,7 +2756,7 @@ async function prefetchMdxBundle(request) {
|
|
|
2406
2756
|
}
|
|
2407
2757
|
|
|
2408
2758
|
// src/math/display-wrapper.tsx
|
|
2409
|
-
var
|
|
2759
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
2410
2760
|
var BASE_CLASS = "katex-block-wrapper my-2";
|
|
2411
2761
|
var SCROLL_ROOT_CLASS = "katex-scroll relative overflow-x-hidden w-full max-w-full";
|
|
2412
2762
|
var VIEWPORT_CLASS = "katex-scroll-viewport h-full w-full rounded-[inherit]";
|
|
@@ -2421,27 +2771,30 @@ function combineClassNames(base, extra) {
|
|
|
2421
2771
|
}
|
|
2422
2772
|
function DisplayMathWrapper({ children, className = "" }) {
|
|
2423
2773
|
const wrapperClass = combineClassNames(BASE_CLASS, className);
|
|
2424
|
-
return /* @__PURE__ */ (0,
|
|
2774
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: wrapperClass, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { dir: "ltr", className: SCROLL_ROOT_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: VIEWPORT_CLASS, style: VIEWPORT_STYLE, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: SHIM_STYLE, children }) }) }) });
|
|
2425
2775
|
}
|
|
2426
2776
|
function renderDisplayMathWithHtml(html, className) {
|
|
2427
|
-
return /* @__PURE__ */ (0,
|
|
2777
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DisplayMathWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "katex-block", dangerouslySetInnerHTML: { __html: html } }) });
|
|
2428
2778
|
}
|
|
2429
2779
|
|
|
2430
2780
|
// src/renderer.tsx
|
|
2431
|
-
var
|
|
2781
|
+
var import_react14 = __toESM(require("react"), 1);
|
|
2432
2782
|
var import_worker = require("@stream-mdx/worker");
|
|
2433
2783
|
init_mdx_client();
|
|
2434
2784
|
|
|
2435
2785
|
// src/renderer/code-highlight-context.tsx
|
|
2436
|
-
var
|
|
2437
|
-
var CodeHighlightRequestContext =
|
|
2786
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
2787
|
+
var CodeHighlightRequestContext = import_react8.default.createContext(null);
|
|
2438
2788
|
function useCodeHighlightRequester() {
|
|
2439
|
-
return
|
|
2789
|
+
return import_react8.default.useContext(CodeHighlightRequestContext);
|
|
2440
2790
|
}
|
|
2441
2791
|
|
|
2442
2792
|
// src/renderer/patch-batching.ts
|
|
2443
2793
|
var import_patch_batching = require("@stream-mdx/core/perf/patch-batching");
|
|
2444
2794
|
|
|
2795
|
+
// src/renderer/patch-commit-scheduler.ts
|
|
2796
|
+
var import_patch_batching2 = require("@stream-mdx/core/perf/patch-batching");
|
|
2797
|
+
|
|
2445
2798
|
// src/renderer/patch-coalescing.ts
|
|
2446
2799
|
var import_core3 = require("@stream-mdx/core");
|
|
2447
2800
|
|
|
@@ -2452,6 +2805,9 @@ var COALESCING_DURATION_ACTIVATE_MS = 6;
|
|
|
2452
2805
|
var COALESCING_DURATION_DEACTIVATE_MS = 4;
|
|
2453
2806
|
var RETAIN_TOUCHED_IN_HISTORY = typeof process !== "undefined" && process.env ? process.env.NODE_ENV !== "production" : true;
|
|
2454
2807
|
var EMPTY_TOUCHED_SET = /* @__PURE__ */ new Set();
|
|
2808
|
+
function shouldSkipCoalescing(patches) {
|
|
2809
|
+
return patches.length <= 1;
|
|
2810
|
+
}
|
|
2455
2811
|
function getDefaultNow() {
|
|
2456
2812
|
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
2457
2813
|
return () => performance.now();
|
|
@@ -2478,8 +2834,9 @@ function getDefaultCancelRaf() {
|
|
|
2478
2834
|
}
|
|
2479
2835
|
var PatchCommitScheduler = class {
|
|
2480
2836
|
constructor(params) {
|
|
2481
|
-
this.
|
|
2482
|
-
this.
|
|
2837
|
+
this.semanticQueue = [];
|
|
2838
|
+
this.enrichmentHighQueue = [];
|
|
2839
|
+
this.enrichmentLowQueue = [];
|
|
2483
2840
|
this.scheduled = false;
|
|
2484
2841
|
this.flushing = false;
|
|
2485
2842
|
this.scheduledHandle = null;
|
|
@@ -2491,6 +2848,7 @@ var PatchCommitScheduler = class {
|
|
|
2491
2848
|
this.scheduleToken = 0;
|
|
2492
2849
|
this.coalescingDurationSamples = [];
|
|
2493
2850
|
this.adaptiveBudgetActive = false;
|
|
2851
|
+
this.flushCount = 0;
|
|
2494
2852
|
this.store = params.store;
|
|
2495
2853
|
this.onFlush = params.onFlush;
|
|
2496
2854
|
this.frameBudgetMs = Math.max(1, params.options?.frameBudgetMs ?? 10);
|
|
@@ -2506,6 +2864,8 @@ var PatchCommitScheduler = class {
|
|
|
2506
2864
|
this.maxLowPriorityBatchesPerFlush = params.options?.maxLowPriorityBatchesPerFlush ?? 2;
|
|
2507
2865
|
this.urgentQueueThreshold = Math.max(1, params.options?.urgentQueueThreshold ?? 4);
|
|
2508
2866
|
this.historyLimit = Math.max(1, params.options?.historyLimit ?? 200);
|
|
2867
|
+
this.startupMicrotaskFlushes = Math.max(0, Math.floor(params.options?.startupMicrotaskFlushes ?? 0));
|
|
2868
|
+
this.adaptiveBudgeting = params.options?.adaptiveBudgeting ?? true;
|
|
2509
2869
|
const requestedBatch = params.options?.batch;
|
|
2510
2870
|
if (requestedBatch === "microtask") {
|
|
2511
2871
|
this.batchStrategy = "microtask";
|
|
@@ -2532,19 +2892,23 @@ var PatchCommitScheduler = class {
|
|
|
2532
2892
|
patches: input.patches,
|
|
2533
2893
|
meta: input.meta ?? {},
|
|
2534
2894
|
receivedAt: input.meta?.receivedAt ?? this.now(),
|
|
2895
|
+
kind: input.meta?.kind === "semantic" || input.meta?.kind === "enrichment" ? input.meta.kind : input.patches.some((patch) => (0, import_patch_batching2.getPatchKind)(patch) === "semantic") ? "semantic" : "enrichment",
|
|
2535
2896
|
priority: input.meta?.priority === "low" ? "low" : "high"
|
|
2536
2897
|
};
|
|
2537
|
-
if (batch.
|
|
2538
|
-
|
|
2898
|
+
if (batch.kind === "semantic") {
|
|
2899
|
+
batch.priority = "high";
|
|
2900
|
+
this.semanticQueue.push(batch);
|
|
2901
|
+
} else if (batch.priority === "low") {
|
|
2902
|
+
this.enrichmentLowQueue.push(batch);
|
|
2539
2903
|
} else {
|
|
2540
|
-
this.
|
|
2904
|
+
this.enrichmentHighQueue.push(batch);
|
|
2541
2905
|
}
|
|
2542
2906
|
if (!this.paused) {
|
|
2543
2907
|
this.schedule();
|
|
2544
2908
|
}
|
|
2545
2909
|
}
|
|
2546
2910
|
flushAll() {
|
|
2547
|
-
if (this.
|
|
2911
|
+
if (this.semanticQueue.length === 0 && this.enrichmentHighQueue.length === 0 && this.enrichmentLowQueue.length === 0 && !this.flushing) {
|
|
2548
2912
|
return null;
|
|
2549
2913
|
}
|
|
2550
2914
|
this.cancelScheduled();
|
|
@@ -2554,9 +2918,11 @@ var PatchCommitScheduler = class {
|
|
|
2554
2918
|
}
|
|
2555
2919
|
clear() {
|
|
2556
2920
|
this.cancelScheduled();
|
|
2557
|
-
this.
|
|
2558
|
-
this.
|
|
2921
|
+
this.semanticQueue = [];
|
|
2922
|
+
this.enrichmentHighQueue = [];
|
|
2923
|
+
this.enrichmentLowQueue = [];
|
|
2559
2924
|
this.flushing = false;
|
|
2925
|
+
this.flushCount = 0;
|
|
2560
2926
|
this.coalescingDurationSamples = [];
|
|
2561
2927
|
this.adaptiveBudgetActive = false;
|
|
2562
2928
|
this.adaptiveHighBatchCap = void 0;
|
|
@@ -2564,10 +2930,10 @@ var PatchCommitScheduler = class {
|
|
|
2564
2930
|
this.maybeResolveIdle();
|
|
2565
2931
|
}
|
|
2566
2932
|
getPendingCount() {
|
|
2567
|
-
return this.
|
|
2933
|
+
return this.semanticQueue.length + this.enrichmentHighQueue.length + this.enrichmentLowQueue.length;
|
|
2568
2934
|
}
|
|
2569
2935
|
isIdle() {
|
|
2570
|
-
return !this.flushing && !this.scheduled && this.
|
|
2936
|
+
return !this.flushing && !this.scheduled && this.semanticQueue.length === 0 && this.enrichmentHighQueue.length === 0 && this.enrichmentLowQueue.length === 0;
|
|
2571
2937
|
}
|
|
2572
2938
|
awaitIdle() {
|
|
2573
2939
|
if (this.isIdle()) {
|
|
@@ -2607,7 +2973,8 @@ var PatchCommitScheduler = class {
|
|
|
2607
2973
|
this.runFlush(this.frameBudgetMs, false);
|
|
2608
2974
|
this.maybeResolveIdle();
|
|
2609
2975
|
};
|
|
2610
|
-
|
|
2976
|
+
const useStartupMicrotask = this.batchStrategy !== "microtask" && this.startupMicrotaskFlushes > 0 && this.flushCount < this.startupMicrotaskFlushes && typeof queueMicrotask === "function";
|
|
2977
|
+
if ((this.batchStrategy === "microtask" || useStartupMicrotask) && typeof queueMicrotask === "function") {
|
|
2611
2978
|
this.scheduledViaRaf = false;
|
|
2612
2979
|
this.scheduledHandle = token;
|
|
2613
2980
|
queueMicrotask(execute);
|
|
@@ -2637,12 +3004,14 @@ var PatchCommitScheduler = class {
|
|
|
2637
3004
|
if (this.paused && !manual) {
|
|
2638
3005
|
return null;
|
|
2639
3006
|
}
|
|
2640
|
-
if (this.
|
|
3007
|
+
if (this.semanticQueue.length === 0 && this.enrichmentHighQueue.length === 0 && this.enrichmentLowQueue.length === 0) {
|
|
2641
3008
|
return null;
|
|
2642
3009
|
}
|
|
2643
3010
|
this.flushing = true;
|
|
2644
3011
|
const startedAt = this.now();
|
|
2645
|
-
const
|
|
3012
|
+
const initialSemanticQueueSize = this.semanticQueue.length;
|
|
3013
|
+
const initialEnrichmentQueueSize = this.enrichmentHighQueue.length + this.enrichmentLowQueue.length;
|
|
3014
|
+
const initialQueueSize = initialSemanticQueueSize + initialEnrichmentQueueSize;
|
|
2646
3015
|
const batches = [];
|
|
2647
3016
|
let totalInputPatches = 0;
|
|
2648
3017
|
let totalAppliedPatches = 0;
|
|
@@ -2657,7 +3026,15 @@ var PatchCommitScheduler = class {
|
|
|
2657
3026
|
consumed += 1;
|
|
2658
3027
|
const applyStart = this.now();
|
|
2659
3028
|
const queueDelayMs = Math.max(0, applyStart - next.receivedAt);
|
|
2660
|
-
|
|
3029
|
+
let coalesced;
|
|
3030
|
+
let coalescingMetrics;
|
|
3031
|
+
if (shouldSkipCoalescing(next.patches)) {
|
|
3032
|
+
coalesced = next.patches;
|
|
3033
|
+
} else {
|
|
3034
|
+
const result = (0, import_core3.coalescePatchesWithMetrics)(next.patches, import_core3.DEFAULT_COALESCE_CONFIG);
|
|
3035
|
+
coalesced = result.patches;
|
|
3036
|
+
coalescingMetrics = result.metrics;
|
|
3037
|
+
}
|
|
2661
3038
|
const touched = this.store.applyPatches(coalesced, {
|
|
2662
3039
|
coalesced: true,
|
|
2663
3040
|
metrics: coalescingMetrics
|
|
@@ -2677,6 +3054,7 @@ var PatchCommitScheduler = class {
|
|
|
2677
3054
|
receivedAt: next.receivedAt,
|
|
2678
3055
|
appliedAt: applyStart,
|
|
2679
3056
|
priority: next.priority,
|
|
3057
|
+
kind: next.kind,
|
|
2680
3058
|
coalescing: coalescingMetrics
|
|
2681
3059
|
});
|
|
2682
3060
|
if (maxBatches && batches.length - startingBatchCount >= maxBatches) {
|
|
@@ -2693,27 +3071,32 @@ var PatchCommitScheduler = class {
|
|
|
2693
3071
|
queue.splice(0, consumed);
|
|
2694
3072
|
}
|
|
2695
3073
|
};
|
|
2696
|
-
|
|
3074
|
+
processQueue(this.semanticQueue, void 0, Number.POSITIVE_INFINITY);
|
|
3075
|
+
const initialHighQueueSize = this.enrichmentHighQueue.length;
|
|
2697
3076
|
const configuredHighLimit = manual || !this.maxBatchesPerFlush ? void 0 : initialHighQueueSize > this.maxBatchesPerFlush ? void 0 : this.maxBatchesPerFlush;
|
|
2698
|
-
const highBatchLimit = this.adaptiveHighBatchCap ?? configuredHighLimit;
|
|
2699
|
-
processQueue(this.
|
|
3077
|
+
const highBatchLimit = this.adaptiveBudgeting ? this.adaptiveHighBatchCap ?? configuredHighLimit : configuredHighLimit;
|
|
3078
|
+
processQueue(this.enrichmentHighQueue, highBatchLimit, budgetMs);
|
|
2700
3079
|
if (manual) {
|
|
2701
|
-
processQueue(this.
|
|
2702
|
-
} else if (this.
|
|
3080
|
+
processQueue(this.enrichmentLowQueue, void 0, Number.POSITIVE_INFINITY);
|
|
3081
|
+
} else if (this.enrichmentLowQueue.length > 0) {
|
|
2703
3082
|
elapsed = this.now() - startedAt;
|
|
2704
3083
|
const budgetForLow = Math.max(0, this.lowPriorityFrameBudgetMs - elapsed);
|
|
2705
|
-
|
|
2706
|
-
|
|
3084
|
+
const processedHigherPriorityWork = batches.length > 0;
|
|
3085
|
+
if (budgetForLow > 0 || !processedHigherPriorityWork) {
|
|
3086
|
+
const initialLowQueueSize = this.enrichmentLowQueue.length;
|
|
2707
3087
|
const configuredLowLimit = manual || !this.maxLowPriorityBatchesPerFlush ? void 0 : initialLowQueueSize > this.maxLowPriorityBatchesPerFlush ? void 0 : this.maxLowPriorityBatchesPerFlush;
|
|
2708
|
-
const lowBatchLimit = this.adaptiveLowBatchCap ?? configuredLowLimit;
|
|
2709
|
-
processQueue(this.
|
|
3088
|
+
const lowBatchLimit = this.adaptiveBudgeting ? this.adaptiveLowBatchCap ?? configuredLowLimit : configuredLowLimit;
|
|
3089
|
+
processQueue(this.enrichmentLowQueue, lowBatchLimit, budgetForLow);
|
|
2710
3090
|
}
|
|
2711
3091
|
}
|
|
2712
3092
|
this.flushing = false;
|
|
2713
3093
|
const completedAt = this.now();
|
|
2714
3094
|
const totalDurationMs = completedAt - startedAt;
|
|
2715
|
-
const
|
|
3095
|
+
const remainingSemantic = this.semanticQueue.length;
|
|
3096
|
+
const remainingEnrichment = this.enrichmentHighQueue.length + this.enrichmentLowQueue.length;
|
|
3097
|
+
const remaining = remainingSemantic + remainingEnrichment;
|
|
2716
3098
|
if (batches.length > 0) {
|
|
3099
|
+
this.flushCount += 1;
|
|
2717
3100
|
try {
|
|
2718
3101
|
this.onFlush({
|
|
2719
3102
|
batches,
|
|
@@ -2721,7 +3104,11 @@ var PatchCommitScheduler = class {
|
|
|
2721
3104
|
totalAppliedPatches,
|
|
2722
3105
|
totalDurationMs,
|
|
2723
3106
|
remainingQueueSize: remaining,
|
|
3107
|
+
remainingSemanticQueueSize: remainingSemantic,
|
|
3108
|
+
remainingEnrichmentQueueSize: remainingEnrichment,
|
|
2724
3109
|
queueDepthBefore: initialQueueSize,
|
|
3110
|
+
semanticQueueDepthBefore: initialSemanticQueueSize,
|
|
3111
|
+
enrichmentQueueDepthBefore: initialEnrichmentQueueSize,
|
|
2725
3112
|
flushStartedAt: startedAt,
|
|
2726
3113
|
flushCompletedAt: completedAt
|
|
2727
3114
|
});
|
|
@@ -2732,21 +3119,27 @@ var PatchCommitScheduler = class {
|
|
|
2732
3119
|
if (remaining > 0 && !this.paused) {
|
|
2733
3120
|
this.schedule();
|
|
2734
3121
|
}
|
|
2735
|
-
const coalescingStats = this.computeCoalescingDurationStats();
|
|
2736
|
-
this.
|
|
2737
|
-
|
|
3122
|
+
const coalescingStats = this.adaptiveBudgeting ? this.computeCoalescingDurationStats() : { sampleCount: this.coalescingDurationSamples.length, p95: null };
|
|
3123
|
+
if (this.adaptiveBudgeting) {
|
|
3124
|
+
this.updateAdaptiveBudget(coalescingStats.p95);
|
|
3125
|
+
}
|
|
3126
|
+
const adaptiveState = this.adaptiveBudgeting ? this.snapshotAdaptiveBudget(coalescingStats.p95 ?? null) : void 0;
|
|
2738
3127
|
const flushResult = batches.length > 0 ? {
|
|
2739
3128
|
batches,
|
|
2740
3129
|
totalPatches: totalInputPatches,
|
|
2741
3130
|
totalAppliedPatches,
|
|
2742
3131
|
totalDurationMs,
|
|
2743
3132
|
remainingQueueSize: remaining,
|
|
3133
|
+
remainingSemanticQueueSize: remainingSemantic,
|
|
3134
|
+
remainingEnrichmentQueueSize: remainingEnrichment,
|
|
2744
3135
|
queueDepthBefore: initialQueueSize,
|
|
3136
|
+
semanticQueueDepthBefore: initialSemanticQueueSize,
|
|
3137
|
+
enrichmentQueueDepthBefore: initialEnrichmentQueueSize,
|
|
2745
3138
|
flushStartedAt: startedAt,
|
|
2746
3139
|
flushCompletedAt: completedAt,
|
|
2747
3140
|
coalescingDurationP95: coalescingStats.p95 ?? void 0,
|
|
2748
3141
|
coalescingDurationSampleCount: coalescingStats.sampleCount,
|
|
2749
|
-
adaptiveBudgetActive: adaptiveState
|
|
3142
|
+
adaptiveBudgetActive: adaptiveState?.active,
|
|
2750
3143
|
adaptiveBudgetState: adaptiveState
|
|
2751
3144
|
} : null;
|
|
2752
3145
|
if (flushResult) {
|
|
@@ -2782,6 +3175,9 @@ var PatchCommitScheduler = class {
|
|
|
2782
3175
|
};
|
|
2783
3176
|
}
|
|
2784
3177
|
updateAdaptiveBudget(p95) {
|
|
3178
|
+
if (!this.adaptiveBudgeting) {
|
|
3179
|
+
return;
|
|
3180
|
+
}
|
|
2785
3181
|
if (p95 !== null && p95 > COALESCING_DURATION_ACTIVATE_MS) {
|
|
2786
3182
|
if (!this.adaptiveBudgetActive) {
|
|
2787
3183
|
this.adaptiveBudgetActive = true;
|
|
@@ -2855,11 +3251,13 @@ var PatchCommitScheduler = class {
|
|
|
2855
3251
|
}
|
|
2856
3252
|
restart() {
|
|
2857
3253
|
this.cancelScheduled();
|
|
2858
|
-
this.
|
|
2859
|
-
this.
|
|
3254
|
+
this.semanticQueue = [];
|
|
3255
|
+
this.enrichmentHighQueue = [];
|
|
3256
|
+
this.enrichmentLowQueue = [];
|
|
2860
3257
|
this.flushing = false;
|
|
2861
3258
|
this.sequence = 0;
|
|
2862
3259
|
this.history = [];
|
|
3260
|
+
this.flushCount = 0;
|
|
2863
3261
|
this.scheduleToken++;
|
|
2864
3262
|
this.paused = false;
|
|
2865
3263
|
this.coalescingDurationSamples = [];
|
|
@@ -2906,6 +3304,12 @@ var PatchCommitScheduler = class {
|
|
|
2906
3304
|
if (typeof options.historyLimit !== "undefined") {
|
|
2907
3305
|
this.setHistoryLimit(options.historyLimit);
|
|
2908
3306
|
}
|
|
3307
|
+
if (typeof options.startupMicrotaskFlushes !== "undefined") {
|
|
3308
|
+
this.startupMicrotaskFlushes = Math.max(0, Math.floor(options.startupMicrotaskFlushes));
|
|
3309
|
+
}
|
|
3310
|
+
if (typeof options.adaptiveBudgeting !== "undefined") {
|
|
3311
|
+
this.adaptiveBudgeting = options.adaptiveBudgeting;
|
|
3312
|
+
}
|
|
2909
3313
|
if (typeof options.batch !== "undefined") {
|
|
2910
3314
|
const requestedBatch = options.batch;
|
|
2911
3315
|
if (requestedBatch === "microtask") {
|
|
@@ -2932,6 +3336,7 @@ var PatchCommitScheduler = class {
|
|
|
2932
3336
|
|
|
2933
3337
|
// src/renderer/store.ts
|
|
2934
3338
|
var import_core4 = require("@stream-mdx/core");
|
|
3339
|
+
var import_patch_batching3 = require("@stream-mdx/core/perf/patch-batching");
|
|
2935
3340
|
|
|
2936
3341
|
// src/renderer/list-utils.ts
|
|
2937
3342
|
function updateNodeDepth(node, depth) {
|
|
@@ -3027,12 +3432,28 @@ function snapshotToBlock(node) {
|
|
|
3027
3432
|
}
|
|
3028
3433
|
return null;
|
|
3029
3434
|
}
|
|
3030
|
-
var
|
|
3031
|
-
var
|
|
3435
|
+
var nodeSnapshotCacheByMap = /* @__PURE__ */ new WeakMap();
|
|
3436
|
+
var childrenSnapshotCacheByMap = /* @__PURE__ */ new WeakMap();
|
|
3032
3437
|
var NODE_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
3033
3438
|
var CHILDREN_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
3034
3439
|
var NODE_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(NODE_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
3035
3440
|
var CHILDREN_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(CHILDREN_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
3441
|
+
function getNodeSnapshotCacheForMap(map) {
|
|
3442
|
+
let cache = nodeSnapshotCacheByMap.get(map);
|
|
3443
|
+
if (!cache) {
|
|
3444
|
+
cache = /* @__PURE__ */ new Map();
|
|
3445
|
+
nodeSnapshotCacheByMap.set(map, cache);
|
|
3446
|
+
}
|
|
3447
|
+
return cache;
|
|
3448
|
+
}
|
|
3449
|
+
function getChildrenSnapshotCacheForMap(map) {
|
|
3450
|
+
let cache = childrenSnapshotCacheByMap.get(map);
|
|
3451
|
+
if (!cache) {
|
|
3452
|
+
cache = /* @__PURE__ */ new Map();
|
|
3453
|
+
childrenSnapshotCacheByMap.set(map, cache);
|
|
3454
|
+
}
|
|
3455
|
+
return cache;
|
|
3456
|
+
}
|
|
3036
3457
|
function pruneCache(cache, max, buffer) {
|
|
3037
3458
|
if (cache.size <= max + buffer) return;
|
|
3038
3459
|
let remaining = cache.size - max;
|
|
@@ -3042,6 +3463,14 @@ function pruneCache(cache, max, buffer) {
|
|
|
3042
3463
|
if (remaining <= 0) break;
|
|
3043
3464
|
}
|
|
3044
3465
|
}
|
|
3466
|
+
function deleteSnapshotCacheEntry(map, id) {
|
|
3467
|
+
getNodeSnapshotCacheForMap(map).delete(id);
|
|
3468
|
+
getChildrenSnapshotCacheForMap(map).delete(id);
|
|
3469
|
+
}
|
|
3470
|
+
function clearSnapshotCaches(map) {
|
|
3471
|
+
getNodeSnapshotCacheForMap(map).clear();
|
|
3472
|
+
getChildrenSnapshotCacheForMap(map).clear();
|
|
3473
|
+
}
|
|
3045
3474
|
var EMPTY_CHILDREN = Object.freeze([]);
|
|
3046
3475
|
var EMPTY_NODE_SNAPSHOT = Object.freeze({ version: -1, node: void 0 });
|
|
3047
3476
|
var EMPTY_CHILDREN_SNAPSHOT = Object.freeze({
|
|
@@ -3209,9 +3638,57 @@ function createRootRecord() {
|
|
|
3209
3638
|
parentId: null,
|
|
3210
3639
|
children: [],
|
|
3211
3640
|
props: {},
|
|
3212
|
-
version: 0
|
|
3641
|
+
version: 0,
|
|
3642
|
+
blockEpoch: 0
|
|
3213
3643
|
};
|
|
3214
3644
|
}
|
|
3645
|
+
function readNumericEpoch(value) {
|
|
3646
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
3647
|
+
return void 0;
|
|
3648
|
+
}
|
|
3649
|
+
return value;
|
|
3650
|
+
}
|
|
3651
|
+
function readSnapshotBlockEpoch(snapshot) {
|
|
3652
|
+
return readNumericEpoch(snapshot.meta?.blockEpoch);
|
|
3653
|
+
}
|
|
3654
|
+
function readPatchBlockEpoch(patch) {
|
|
3655
|
+
if (patch.op === "setHTML") {
|
|
3656
|
+
return readNumericEpoch(patch.patchMeta?.blockEpoch);
|
|
3657
|
+
}
|
|
3658
|
+
return readNumericEpoch(patch.meta?.blockEpoch);
|
|
3659
|
+
}
|
|
3660
|
+
function readPatchParseEpoch(patch) {
|
|
3661
|
+
if (patch.op === "setHTML") {
|
|
3662
|
+
return readNumericEpoch(patch.patchMeta?.parseEpoch);
|
|
3663
|
+
}
|
|
3664
|
+
return readNumericEpoch(patch.meta?.parseEpoch);
|
|
3665
|
+
}
|
|
3666
|
+
function readPatchTx(patch) {
|
|
3667
|
+
if (patch.op === "setHTML") {
|
|
3668
|
+
return readNumericEpoch(patch.patchMeta?.tx);
|
|
3669
|
+
}
|
|
3670
|
+
return readNumericEpoch(patch.meta?.tx);
|
|
3671
|
+
}
|
|
3672
|
+
function assignSubtreeBlockEpoch(map, rootId, blockEpoch, touched) {
|
|
3673
|
+
const root = map.get(rootId);
|
|
3674
|
+
if (!root) return;
|
|
3675
|
+
const stack = [root];
|
|
3676
|
+
while (stack.length > 0) {
|
|
3677
|
+
const node = stack.pop();
|
|
3678
|
+
if (!node) continue;
|
|
3679
|
+
if (node.blockEpoch !== blockEpoch) {
|
|
3680
|
+
node.blockEpoch = blockEpoch;
|
|
3681
|
+
node.version += 1;
|
|
3682
|
+
touched?.add(node.id);
|
|
3683
|
+
}
|
|
3684
|
+
for (const childId of node.children) {
|
|
3685
|
+
const child = map.get(childId);
|
|
3686
|
+
if (child) {
|
|
3687
|
+
stack.push(child);
|
|
3688
|
+
}
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3215
3692
|
function ensureArray(value) {
|
|
3216
3693
|
return Array.isArray(value) ? value : [];
|
|
3217
3694
|
}
|
|
@@ -3271,7 +3748,7 @@ function escapeHtml2(value) {
|
|
|
3271
3748
|
}
|
|
3272
3749
|
function stripOuterLineSpan(html) {
|
|
3273
3750
|
if (!html) return null;
|
|
3274
|
-
const openTagMatch = html.match(/<span[^>]*>/i);
|
|
3751
|
+
const openTagMatch = html.match(/<span[^>]*class="[^"]*\bline\b[^"]*"[^>]*>/i);
|
|
3275
3752
|
if (!openTagMatch) {
|
|
3276
3753
|
return null;
|
|
3277
3754
|
}
|
|
@@ -3320,8 +3797,7 @@ function normalizeCodeBlockChildren(nodes, parent, touched) {
|
|
|
3320
3797
|
if (node.type !== "code-line") {
|
|
3321
3798
|
anomalies.push(`type-mismatch:${node.id}:${node.type}`);
|
|
3322
3799
|
nodes.delete(node.id);
|
|
3323
|
-
|
|
3324
|
-
childrenSnapshotCache.delete(node.id);
|
|
3800
|
+
deleteSnapshotCacheEntry(nodes, node.id);
|
|
3325
3801
|
touched.add(node.id);
|
|
3326
3802
|
continue;
|
|
3327
3803
|
}
|
|
@@ -3365,16 +3841,14 @@ function normalizeCodeBlockChildren(nodes, parent, touched) {
|
|
|
3365
3841
|
const existing = nodes.get(desiredId);
|
|
3366
3842
|
if (existing && existing !== node) {
|
|
3367
3843
|
nodes.delete(desiredId);
|
|
3368
|
-
|
|
3369
|
-
childrenSnapshotCache.delete(desiredId);
|
|
3844
|
+
deleteSnapshotCacheEntry(nodes, desiredId);
|
|
3370
3845
|
touched.add(desiredId);
|
|
3371
3846
|
mutated = true;
|
|
3372
3847
|
}
|
|
3373
3848
|
if (node.id !== desiredId) {
|
|
3374
3849
|
const previousId = node.id;
|
|
3375
3850
|
nodes.delete(node.id);
|
|
3376
|
-
|
|
3377
|
-
childrenSnapshotCache.delete(previousId);
|
|
3851
|
+
deleteSnapshotCacheEntry(nodes, previousId);
|
|
3378
3852
|
node.id = desiredId;
|
|
3379
3853
|
nodes.set(desiredId, node);
|
|
3380
3854
|
touched.add(desiredId);
|
|
@@ -3405,8 +3879,7 @@ function normalizeCodeBlockChildren(nodes, parent, touched) {
|
|
|
3405
3879
|
for (const [id, record] of nodes) {
|
|
3406
3880
|
if (record.parentId === parent.id && record.type === "code-line" && !allowed.has(id)) {
|
|
3407
3881
|
nodes.delete(id);
|
|
3408
|
-
|
|
3409
|
-
childrenSnapshotCache.delete(id);
|
|
3882
|
+
deleteSnapshotCacheEntry(nodes, id);
|
|
3410
3883
|
touched.add(id);
|
|
3411
3884
|
mutated = true;
|
|
3412
3885
|
}
|
|
@@ -3490,8 +3963,10 @@ function normalizeCodeLineProps(incoming, previous) {
|
|
|
3490
3963
|
}
|
|
3491
3964
|
function createCodeLineProps(index, text, highlight, tokens) {
|
|
3492
3965
|
const safeText = typeof text === "string" ? text : "";
|
|
3493
|
-
const
|
|
3494
|
-
const
|
|
3966
|
+
const hasIncomingHighlight = typeof highlight === "string" && highlight.trim().length > 0;
|
|
3967
|
+
const sanitized = hasIncomingHighlight ? sanitizeLineInnerHtml(highlight, safeText) : null;
|
|
3968
|
+
const hasRenderableTokens = tokens !== void 0 && tokens !== null;
|
|
3969
|
+
const html = sanitized && sanitized.length >= safeText.length ? sanitized : hasRenderableTokens ? null : escapeHtml2(safeText);
|
|
3495
3970
|
const props = {
|
|
3496
3971
|
index,
|
|
3497
3972
|
text: safeText,
|
|
@@ -3602,6 +4077,18 @@ function validateCodeBlockChildren(nodes, parent) {
|
|
|
3602
4077
|
issues.push({ kind: "dangling-node", id });
|
|
3603
4078
|
}
|
|
3604
4079
|
}
|
|
4080
|
+
if (parent.block?.isFinalized) {
|
|
4081
|
+
const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(parent.block));
|
|
4082
|
+
const expectedChildren = ensureArray(snapshot.children).filter((child) => child.type === "code-line");
|
|
4083
|
+
if (expectedChildren.length !== parent.children.length) {
|
|
4084
|
+
issues.push({
|
|
4085
|
+
kind: "line-count-mismatch",
|
|
4086
|
+
id: parent.id,
|
|
4087
|
+
expected: expectedChildren.length,
|
|
4088
|
+
actual: parent.children.length
|
|
4089
|
+
});
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
3605
4092
|
return { ok: issues.length === 0, issues };
|
|
3606
4093
|
}
|
|
3607
4094
|
function rebuildCodeBlockFromSnapshot(nodes, parent, touched, issues) {
|
|
@@ -3618,7 +4105,7 @@ function rebuildCodeBlockFromSnapshot(nodes, parent, touched, issues) {
|
|
|
3618
4105
|
}
|
|
3619
4106
|
const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(parent.block));
|
|
3620
4107
|
removeSubtree(nodes, parent.id, touched);
|
|
3621
|
-
const inserted = insertSnapshotAt(nodes, ancestor, index, snapshot);
|
|
4108
|
+
const inserted = insertSnapshotAt(nodes, ancestor, index, snapshot, touched, parent.blockEpoch);
|
|
3622
4109
|
if (!inserted) {
|
|
3623
4110
|
return false;
|
|
3624
4111
|
}
|
|
@@ -3641,7 +4128,55 @@ function arraysEqual(a, b) {
|
|
|
3641
4128
|
}
|
|
3642
4129
|
return true;
|
|
3643
4130
|
}
|
|
3644
|
-
function
|
|
4131
|
+
function expectedCodeLineId(parentId, index) {
|
|
4132
|
+
return `${parentId}::line:${index}`;
|
|
4133
|
+
}
|
|
4134
|
+
function collectStoreInvariantViolations(nodes) {
|
|
4135
|
+
const violations = [];
|
|
4136
|
+
for (const [id, node] of nodes) {
|
|
4137
|
+
if (node.type === "__root__") continue;
|
|
4138
|
+
if (node.children.length > 1) {
|
|
4139
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4140
|
+
for (const childId of node.children) {
|
|
4141
|
+
if (seen.has(childId)) {
|
|
4142
|
+
violations.push(`duplicate child id:${id}:${childId}`);
|
|
4143
|
+
} else {
|
|
4144
|
+
seen.add(childId);
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
}
|
|
4148
|
+
if (node.type === "list") {
|
|
4149
|
+
const parent = node.parentId ? nodes.get(node.parentId) : void 0;
|
|
4150
|
+
if (parent?.type === "list-item" && node.children.length === 0) {
|
|
4151
|
+
violations.push(`empty nested list:${id}`);
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
if (node.type === "code") {
|
|
4155
|
+
for (let index = 0; index < node.children.length; index += 1) {
|
|
4156
|
+
const childId = node.children[index];
|
|
4157
|
+
const child = nodes.get(childId);
|
|
4158
|
+
if (!child) {
|
|
4159
|
+
violations.push(`missing code-line node:${node.id}:${childId}`);
|
|
4160
|
+
continue;
|
|
4161
|
+
}
|
|
4162
|
+
if (child.type !== "code-line") {
|
|
4163
|
+
violations.push(`non-code child in code block:${node.id}:${child.id}:${child.type}`);
|
|
4164
|
+
continue;
|
|
4165
|
+
}
|
|
4166
|
+
const expectedId = expectedCodeLineId(node.id, index);
|
|
4167
|
+
if (child.id !== expectedId) {
|
|
4168
|
+
violations.push(`code-line id mismatch:${node.id}:${child.id}:${expectedId}`);
|
|
4169
|
+
}
|
|
4170
|
+
const indexProp = typeof child.props?.index === "number" ? child.props.index : null;
|
|
4171
|
+
if (indexProp !== index) {
|
|
4172
|
+
violations.push(`code-line index mismatch:${node.id}:${child.id}:${indexProp}:${index}`);
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
return violations;
|
|
4178
|
+
}
|
|
4179
|
+
function buildNodeFromSnapshot(map, snapshot, parentId, blockEpoch) {
|
|
3645
4180
|
const record = {
|
|
3646
4181
|
id: snapshot.id,
|
|
3647
4182
|
type: snapshot.type,
|
|
@@ -3651,6 +4186,7 @@ function buildNodeFromSnapshot(map, snapshot, parentId) {
|
|
|
3651
4186
|
meta: snapshot.meta ? { ...snapshot.meta } : void 0,
|
|
3652
4187
|
range: snapshot.range ? { ...snapshot.range } : void 0,
|
|
3653
4188
|
version: 0,
|
|
4189
|
+
blockEpoch,
|
|
3654
4190
|
block: snapshotToBlock(snapshot) ?? void 0
|
|
3655
4191
|
};
|
|
3656
4192
|
if (record.type === "code") {
|
|
@@ -3659,7 +4195,7 @@ function buildNodeFromSnapshot(map, snapshot, parentId) {
|
|
|
3659
4195
|
map.set(record.id, record);
|
|
3660
4196
|
const childSnapshots = ensureArray(snapshot.children);
|
|
3661
4197
|
for (const child of childSnapshots) {
|
|
3662
|
-
const childRecord = buildNodeFromSnapshot(map, child, record.id);
|
|
4198
|
+
const childRecord = buildNodeFromSnapshot(map, child, record.id, blockEpoch);
|
|
3663
4199
|
record.children.push(childRecord.id);
|
|
3664
4200
|
}
|
|
3665
4201
|
return record;
|
|
@@ -3687,8 +4223,7 @@ function removeSubtree(map, id, touched) {
|
|
|
3687
4223
|
}
|
|
3688
4224
|
}
|
|
3689
4225
|
map.delete(node.id);
|
|
3690
|
-
|
|
3691
|
-
childrenSnapshotCache.delete(node.id);
|
|
4226
|
+
deleteSnapshotCacheEntry(map, node.id);
|
|
3692
4227
|
touched.add(node.id);
|
|
3693
4228
|
for (const childId of node.children) {
|
|
3694
4229
|
const child = map.get(childId);
|
|
@@ -3720,13 +4255,13 @@ function resolveParent(map, path) {
|
|
|
3720
4255
|
}
|
|
3721
4256
|
return map.get(path.blockId);
|
|
3722
4257
|
}
|
|
3723
|
-
function insertSnapshotAt(map, parent, index, snapshot, touched) {
|
|
4258
|
+
function insertSnapshotAt(map, parent, index, snapshot, touched, blockEpoch) {
|
|
3724
4259
|
if (!parent) return null;
|
|
3725
4260
|
const existingIndex = parent.children.indexOf(snapshot.id);
|
|
3726
4261
|
if (existingIndex !== -1) {
|
|
3727
4262
|
removeSubtree(map, parent.children[existingIndex], touched ?? /* @__PURE__ */ new Set());
|
|
3728
4263
|
}
|
|
3729
|
-
const record = buildNodeFromSnapshot(map, snapshot, parent.id);
|
|
4264
|
+
const record = buildNodeFromSnapshot(map, snapshot, parent.id, blockEpoch ?? readSnapshotBlockEpoch(snapshot) ?? parent.blockEpoch);
|
|
3730
4265
|
const insertedIds = [];
|
|
3731
4266
|
const queue = [record];
|
|
3732
4267
|
while (queue.length > 0) {
|
|
@@ -3744,13 +4279,13 @@ function insertSnapshotAt(map, parent, index, snapshot, touched) {
|
|
|
3744
4279
|
ensureUniqueChildren(parent, touched);
|
|
3745
4280
|
return { record, insertedIds };
|
|
3746
4281
|
}
|
|
3747
|
-
function replaceSnapshotAt(map, parent, index, snapshot, touched) {
|
|
4282
|
+
function replaceSnapshotAt(map, parent, index, snapshot, touched, blockEpoch) {
|
|
3748
4283
|
if (!parent) return;
|
|
3749
4284
|
if (index < 0 || index >= parent.children.length) return;
|
|
3750
4285
|
const targetId = parent.children[index];
|
|
3751
4286
|
parent.children.splice(index, 1);
|
|
3752
4287
|
removeSubtree(map, targetId, touched);
|
|
3753
|
-
const inserted = insertSnapshotAt(map, parent, index, snapshot, touched);
|
|
4288
|
+
const inserted = insertSnapshotAt(map, parent, index, snapshot, touched, blockEpoch);
|
|
3754
4289
|
if (inserted) {
|
|
3755
4290
|
for (const id of inserted.insertedIds) {
|
|
3756
4291
|
touched.add(id);
|
|
@@ -3770,6 +4305,24 @@ function createRendererStore(initialBlocks = []) {
|
|
|
3770
4305
|
const listeners = /* @__PURE__ */ new Set();
|
|
3771
4306
|
let notifyScheduled = false;
|
|
3772
4307
|
let lastCoalescingMetrics = null;
|
|
4308
|
+
let invariantViolations = [];
|
|
4309
|
+
let transientDiagnostics = [];
|
|
4310
|
+
let nextBlockEpoch = 1;
|
|
4311
|
+
const debugCounters = {
|
|
4312
|
+
appendLineGuardRejected: 0,
|
|
4313
|
+
staleEpochRejected: 0,
|
|
4314
|
+
storeInvariantViolationCount: 0
|
|
4315
|
+
};
|
|
4316
|
+
const allocateBlockEpoch = (preferred) => {
|
|
4317
|
+
const resolved = readNumericEpoch(preferred);
|
|
4318
|
+
if (resolved !== void 0) {
|
|
4319
|
+
nextBlockEpoch = Math.max(nextBlockEpoch, resolved + 1);
|
|
4320
|
+
return resolved;
|
|
4321
|
+
}
|
|
4322
|
+
const epoch = nextBlockEpoch;
|
|
4323
|
+
nextBlockEpoch += 1;
|
|
4324
|
+
return epoch;
|
|
4325
|
+
};
|
|
3773
4326
|
const getRaf = () => {
|
|
3774
4327
|
if (typeof globalThis !== "undefined" && typeof globalThis.requestAnimationFrame === "function") {
|
|
3775
4328
|
return globalThis.requestAnimationFrame;
|
|
@@ -3801,9 +4354,12 @@ function createRendererStore(initialBlocks = []) {
|
|
|
3801
4354
|
}
|
|
3802
4355
|
}
|
|
3803
4356
|
}
|
|
4357
|
+
function appendDiagnostic(message) {
|
|
4358
|
+
transientDiagnostics = [...transientDiagnostics, message];
|
|
4359
|
+
invariantViolations = [...invariantViolations, message];
|
|
4360
|
+
}
|
|
3804
4361
|
function rebuildFromBlocks(blocks) {
|
|
3805
|
-
|
|
3806
|
-
childrenSnapshotCache.clear();
|
|
4362
|
+
clearSnapshotCaches(nodes);
|
|
3807
4363
|
nodes = /* @__PURE__ */ new Map();
|
|
3808
4364
|
const root = createRootRecord();
|
|
3809
4365
|
nodes.set(root.id, root);
|
|
@@ -3812,9 +4368,12 @@ function createRendererStore(initialBlocks = []) {
|
|
|
3812
4368
|
for (let i = 0; i < blocks.length; i++) {
|
|
3813
4369
|
const block = (0, import_core4.cloneBlock)(blocks[i]);
|
|
3814
4370
|
const snapshot = (0, import_core4.createBlockSnapshot)(block);
|
|
3815
|
-
insertSnapshotAt(nodes, root, root.children.length, snapshot);
|
|
4371
|
+
insertSnapshotAt(nodes, root, root.children.length, snapshot, void 0, allocateBlockEpoch(readSnapshotBlockEpoch(snapshot)));
|
|
3816
4372
|
}
|
|
3817
4373
|
normalizeAllListDepths(nodes, /* @__PURE__ */ new Set(), import_core4.PATCH_ROOT_ID);
|
|
4374
|
+
transientDiagnostics = [];
|
|
4375
|
+
invariantViolations = collectStoreInvariantViolations(nodes);
|
|
4376
|
+
debugCounters.storeInvariantViolationCount += invariantViolations.length;
|
|
3818
4377
|
version++;
|
|
3819
4378
|
blocksDirty = true;
|
|
3820
4379
|
scheduleNotify();
|
|
@@ -3879,11 +4438,57 @@ function createRendererStore(initialBlocks = []) {
|
|
|
3879
4438
|
listDepthDirty = true;
|
|
3880
4439
|
}
|
|
3881
4440
|
};
|
|
3882
|
-
const
|
|
4441
|
+
const semanticTxEpochs = /* @__PURE__ */ new Map();
|
|
4442
|
+
const resolveBlockEpochTarget = (patch, at) => {
|
|
4443
|
+
if ((patch.op === "insertChild" || patch.op === "replaceChild") && at.blockId === import_core4.PATCH_ROOT_ID) {
|
|
4444
|
+
const nodeId = patch.node?.id;
|
|
4445
|
+
return nodeId ? nodes.get(nodeId) : void 0;
|
|
4446
|
+
}
|
|
4447
|
+
return nodes.get(at.blockId) ?? (at.nodeId ? nodes.get(at.nodeId) : void 0);
|
|
4448
|
+
};
|
|
4449
|
+
const rejectStaleEpochPatch = (patch, at) => {
|
|
4450
|
+
const expectedBlockEpoch = readPatchBlockEpoch(patch);
|
|
4451
|
+
const patchTx = readPatchTx(patch);
|
|
4452
|
+
if (expectedBlockEpoch === void 0) {
|
|
4453
|
+
return false;
|
|
4454
|
+
}
|
|
4455
|
+
if ((0, import_patch_batching3.getPatchKind)(patch) !== "semantic" || !at) {
|
|
4456
|
+
return false;
|
|
4457
|
+
}
|
|
4458
|
+
const target = resolveBlockEpochTarget(patch, at);
|
|
4459
|
+
if (!target || target.blockEpoch === expectedBlockEpoch) {
|
|
4460
|
+
return false;
|
|
4461
|
+
}
|
|
4462
|
+
const txEpoch = at.blockId && patchTx !== void 0 ? semanticTxEpochs.get(at.blockId) : void 0;
|
|
4463
|
+
if (txEpoch && txEpoch.tx === patchTx && txEpoch.blockEpoch === target.blockEpoch) {
|
|
4464
|
+
return false;
|
|
4465
|
+
}
|
|
4466
|
+
debugCounters.staleEpochRejected += 1;
|
|
4467
|
+
appendDiagnostic(
|
|
4468
|
+
`stale epoch rejected:${patch.op}:${target.id}:expected=${expectedBlockEpoch}:actual=${target.blockEpoch}`
|
|
4469
|
+
);
|
|
4470
|
+
return true;
|
|
4471
|
+
};
|
|
4472
|
+
const advanceBlockEpoch = (blockId, touchedSet, preferredEpoch, tx) => {
|
|
4473
|
+
if (!blockId || blockId === import_core4.PATCH_ROOT_ID) {
|
|
4474
|
+
return null;
|
|
4475
|
+
}
|
|
4476
|
+
const blockRoot = nodes.get(blockId);
|
|
4477
|
+
if (!blockRoot) {
|
|
4478
|
+
return null;
|
|
4479
|
+
}
|
|
4480
|
+
const nextEpoch = allocateBlockEpoch(preferredEpoch);
|
|
4481
|
+
assignSubtreeBlockEpoch(nodes, blockRoot.id, nextEpoch, touchedSet);
|
|
4482
|
+
if (tx !== void 0) {
|
|
4483
|
+
semanticTxEpochs.set(blockRoot.id, { tx, blockEpoch: nextEpoch });
|
|
4484
|
+
}
|
|
4485
|
+
return nextEpoch;
|
|
4486
|
+
};
|
|
4487
|
+
const applyPropsUpdate = (at, props, preferredEpoch, tx, semanticUpdate = false) => {
|
|
3883
4488
|
const perfStartLocal = perfEnabled ? getPerfNow() : 0;
|
|
3884
4489
|
const targetId = at.nodeId ?? at.blockId;
|
|
3885
4490
|
if (!targetId) return;
|
|
3886
|
-
|
|
4491
|
+
let target = nodes.get(targetId);
|
|
3887
4492
|
if (!target) return;
|
|
3888
4493
|
const parentType = target.parentId ? nodes.get(target.parentId)?.type : void 0;
|
|
3889
4494
|
if (debugListPatches && (isListRelated(target.type) || isListRelated(parentType))) {
|
|
@@ -3910,6 +4515,9 @@ function createRendererStore(initialBlocks = []) {
|
|
|
3910
4515
|
propsChanged = true;
|
|
3911
4516
|
}
|
|
3912
4517
|
if (propsChanged) {
|
|
4518
|
+
if (semanticUpdate) {
|
|
4519
|
+
advanceBlockEpoch(at.blockId, touched, preferredEpoch, tx);
|
|
4520
|
+
}
|
|
3913
4521
|
target.version++;
|
|
3914
4522
|
touched.add(target.id);
|
|
3915
4523
|
const parent = target.parentId ? nodes.get(target.parentId) : void 0;
|
|
@@ -3973,16 +4581,56 @@ function createRendererStore(initialBlocks = []) {
|
|
|
3973
4581
|
}
|
|
3974
4582
|
}
|
|
3975
4583
|
let blockChanged = false;
|
|
4584
|
+
let typeChanged = false;
|
|
4585
|
+
let rebuiltFromFinalizedBlock = false;
|
|
4586
|
+
let blockEpochAdvanced = false;
|
|
3976
4587
|
const incomingBlock = props?.block;
|
|
3977
4588
|
if (incomingBlock && typeof incomingBlock === "object") {
|
|
3978
4589
|
target.block = (0, import_core4.cloneBlock)(incomingBlock);
|
|
4590
|
+
const previousType = target.type;
|
|
4591
|
+
const incomingType = typeof target.block.type === "string" ? target.block.type : target.type;
|
|
4592
|
+
if (incomingType !== target.type) {
|
|
4593
|
+
target.type = incomingType;
|
|
4594
|
+
typeChanged = true;
|
|
4595
|
+
if (isListRelated(previousType) || isListRelated(target.type)) {
|
|
4596
|
+
markListDepthDirty(target.id);
|
|
4597
|
+
}
|
|
4598
|
+
}
|
|
3979
4599
|
if (target.type === "code") {
|
|
3980
4600
|
applyCodeBlockMetadata(target);
|
|
3981
4601
|
}
|
|
4602
|
+
if (semanticUpdate) {
|
|
4603
|
+
advanceBlockEpoch(at.blockId, touched, preferredEpoch, tx);
|
|
4604
|
+
blockEpochAdvanced = true;
|
|
4605
|
+
}
|
|
4606
|
+
const shouldRebuildFinalizedTree = !at.nodeId && target.id === at.blockId && Boolean(target.block?.isFinalized) && target.type !== "code" && Boolean(target.parentId);
|
|
4607
|
+
if (shouldRebuildFinalizedTree) {
|
|
4608
|
+
const parent = target.parentId ? nodes.get(target.parentId) : void 0;
|
|
4609
|
+
const index = parent ? parent.children.indexOf(target.id) : -1;
|
|
4610
|
+
if (parent && index !== -1) {
|
|
4611
|
+
const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(target.block));
|
|
4612
|
+
replaceSnapshotAt(nodes, parent, index, snapshot, touched, target.blockEpoch);
|
|
4613
|
+
mutatedBlocks = true;
|
|
4614
|
+
blockChanged = true;
|
|
4615
|
+
rebuiltFromFinalizedBlock = true;
|
|
4616
|
+
const rebuilt = nodes.get(target.id);
|
|
4617
|
+
if (isListRelated(previousType) || isListRelated(rebuilt?.type)) {
|
|
4618
|
+
markListDepthDirty(target.id);
|
|
4619
|
+
}
|
|
4620
|
+
target = rebuilt ?? target;
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
3982
4623
|
mutatedBlocks = true;
|
|
3983
4624
|
blockChanged = true;
|
|
3984
4625
|
}
|
|
3985
|
-
if (
|
|
4626
|
+
if (rebuiltFromFinalizedBlock) {
|
|
4627
|
+
return;
|
|
4628
|
+
}
|
|
4629
|
+
if (propsChanged || blockChanged || typeChanged) {
|
|
4630
|
+
if (semanticUpdate && !blockEpochAdvanced) {
|
|
4631
|
+
advanceBlockEpoch(at.blockId, touched, preferredEpoch, tx);
|
|
4632
|
+
blockEpochAdvanced = true;
|
|
4633
|
+
}
|
|
3986
4634
|
target.version++;
|
|
3987
4635
|
touched.add(target.id);
|
|
3988
4636
|
let parentForNormalization;
|
|
@@ -4025,13 +4673,22 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4025
4673
|
const applyPatch = (patch) => {
|
|
4026
4674
|
switch (patch.op) {
|
|
4027
4675
|
case "insertChild": {
|
|
4676
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4028
4677
|
const parent = resolveParent(nodes, patch.at);
|
|
4029
|
-
const inserted = insertSnapshotAt(
|
|
4678
|
+
const inserted = insertSnapshotAt(
|
|
4679
|
+
nodes,
|
|
4680
|
+
parent,
|
|
4681
|
+
patch.index,
|
|
4682
|
+
patch.node,
|
|
4683
|
+
touched,
|
|
4684
|
+
allocateBlockEpoch(readPatchParseEpoch(patch) ?? readSnapshotBlockEpoch(patch.node))
|
|
4685
|
+
);
|
|
4030
4686
|
if (inserted) {
|
|
4031
4687
|
for (const id of inserted.insertedIds) {
|
|
4032
4688
|
touched.add(id);
|
|
4033
4689
|
}
|
|
4034
4690
|
mutatedBlocks = true;
|
|
4691
|
+
advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
|
|
4035
4692
|
if (isListRelated(inserted.record.type) || isListRelated(parent?.type)) {
|
|
4036
4693
|
markListDepthDirty(inserted.record.id);
|
|
4037
4694
|
if (parent) {
|
|
@@ -4051,6 +4708,7 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4051
4708
|
break;
|
|
4052
4709
|
}
|
|
4053
4710
|
case "deleteChild": {
|
|
4711
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4054
4712
|
const parent = resolveParent(nodes, patch.at);
|
|
4055
4713
|
if (!parent) break;
|
|
4056
4714
|
if (patch.index < 0 || patch.index >= parent.children.length) break;
|
|
@@ -4062,6 +4720,7 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4062
4720
|
touched.add(parent.id);
|
|
4063
4721
|
ensureUniqueChildren(parent, touched);
|
|
4064
4722
|
mutatedBlocks = true;
|
|
4723
|
+
advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
|
|
4065
4724
|
if (isListRelated(parent.type) || isListRelated(removedNode?.type)) {
|
|
4066
4725
|
markListDepthDirty(parent.id);
|
|
4067
4726
|
}
|
|
@@ -4078,11 +4737,20 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4078
4737
|
break;
|
|
4079
4738
|
}
|
|
4080
4739
|
case "replaceChild": {
|
|
4740
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4081
4741
|
const parent = resolveParent(nodes, patch.at);
|
|
4082
4742
|
if (!parent) break;
|
|
4083
|
-
replaceSnapshotAt(
|
|
4743
|
+
replaceSnapshotAt(
|
|
4744
|
+
nodes,
|
|
4745
|
+
parent,
|
|
4746
|
+
patch.index,
|
|
4747
|
+
patch.node,
|
|
4748
|
+
touched,
|
|
4749
|
+
allocateBlockEpoch(readPatchParseEpoch(patch) ?? readSnapshotBlockEpoch(patch.node))
|
|
4750
|
+
);
|
|
4084
4751
|
touched.add(parent.id);
|
|
4085
4752
|
mutatedBlocks = true;
|
|
4753
|
+
advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
|
|
4086
4754
|
if (isListRelated(parent.type)) {
|
|
4087
4755
|
markListDepthDirty(parent.id);
|
|
4088
4756
|
}
|
|
@@ -4096,18 +4764,33 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4096
4764
|
break;
|
|
4097
4765
|
}
|
|
4098
4766
|
case "setProps": {
|
|
4099
|
-
|
|
4767
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4768
|
+
applyPropsUpdate(patch.at, patch.props, readPatchParseEpoch(patch), readPatchTx(patch), (0, import_patch_batching3.getPatchKind)(patch) === "semantic");
|
|
4100
4769
|
break;
|
|
4101
4770
|
}
|
|
4102
4771
|
case "setPropsBatch": {
|
|
4103
4772
|
const entries2 = Array.isArray(patch.entries) ? patch.entries : [];
|
|
4104
4773
|
for (const entry of entries2) {
|
|
4105
4774
|
if (!entry || !entry.at) continue;
|
|
4106
|
-
|
|
4775
|
+
const entryPatch = {
|
|
4776
|
+
op: "setProps",
|
|
4777
|
+
at: entry.at,
|
|
4778
|
+
props: entry.props,
|
|
4779
|
+
meta: entry.meta ?? patch.meta
|
|
4780
|
+
};
|
|
4781
|
+
if (rejectStaleEpochPatch(entryPatch, entry.at)) continue;
|
|
4782
|
+
applyPropsUpdate(
|
|
4783
|
+
entry.at,
|
|
4784
|
+
entry.props,
|
|
4785
|
+
readPatchParseEpoch(entryPatch),
|
|
4786
|
+
readPatchTx(entryPatch),
|
|
4787
|
+
(0, import_patch_batching3.getPatchKind)(entryPatch) === "semantic"
|
|
4788
|
+
);
|
|
4107
4789
|
}
|
|
4108
4790
|
break;
|
|
4109
4791
|
}
|
|
4110
4792
|
case "finalize": {
|
|
4793
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4111
4794
|
const target = nodes.get(patch.at.nodeId ?? patch.at.blockId);
|
|
4112
4795
|
if (!target || !target.block) break;
|
|
4113
4796
|
if (!target.block.isFinalized) {
|
|
@@ -4116,6 +4799,17 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4116
4799
|
target.version++;
|
|
4117
4800
|
touched.add(target.id);
|
|
4118
4801
|
mutatedBlocks = true;
|
|
4802
|
+
if (!patch.at.nodeId && target.id === patch.at.blockId && target.type !== "code" && target.parentId) {
|
|
4803
|
+
const parent = nodes.get(target.parentId);
|
|
4804
|
+
const index = parent ? parent.children.indexOf(target.id) : -1;
|
|
4805
|
+
if (parent && index !== -1) {
|
|
4806
|
+
const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(target.block));
|
|
4807
|
+
replaceSnapshotAt(nodes, parent, index, snapshot, touched, target.blockEpoch);
|
|
4808
|
+
if (isListRelated(target.type) || isListRelated(snapshot.type)) {
|
|
4809
|
+
markListDepthDirty(target.id);
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4119
4813
|
}
|
|
4120
4814
|
if (isListRelated(target.type)) {
|
|
4121
4815
|
markListDepthDirty(target.id);
|
|
@@ -4129,6 +4823,7 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4129
4823
|
break;
|
|
4130
4824
|
}
|
|
4131
4825
|
case "reorder": {
|
|
4826
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4132
4827
|
const parent = resolveParent(nodes, patch.at);
|
|
4133
4828
|
if (!parent) break;
|
|
4134
4829
|
const length = parent.children.length;
|
|
@@ -4143,6 +4838,9 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4143
4838
|
parent.children.splice(to, 0, ...moved);
|
|
4144
4839
|
parent.version++;
|
|
4145
4840
|
touched.add(parent.id);
|
|
4841
|
+
if ((0, import_patch_batching3.getPatchKind)(patch) === "semantic") {
|
|
4842
|
+
advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
|
|
4843
|
+
}
|
|
4146
4844
|
if (isListRelated(parent.type)) {
|
|
4147
4845
|
markListDepthDirty(parent.id);
|
|
4148
4846
|
}
|
|
@@ -4158,15 +4856,31 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4158
4856
|
break;
|
|
4159
4857
|
}
|
|
4160
4858
|
case "appendLines": {
|
|
4859
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4161
4860
|
const parent = resolveParent(nodes, patch.at);
|
|
4162
4861
|
if (!parent) break;
|
|
4163
|
-
|
|
4862
|
+
if (parent.type !== "code") {
|
|
4863
|
+
debugCounters.appendLineGuardRejected += 1;
|
|
4864
|
+
appendDiagnostic(`appendLines target not code:${parent.id}:${parent.type}`);
|
|
4865
|
+
break;
|
|
4866
|
+
}
|
|
4867
|
+
const requestedStartIndex = Math.max(0, patch.startIndex);
|
|
4868
|
+
const startIndex = Math.max(0, Math.min(requestedStartIndex, parent.children.length));
|
|
4164
4869
|
const lineCount = patch.lines?.length ?? 0;
|
|
4165
4870
|
if (lineCount === 0) break;
|
|
4871
|
+
const prefixMatches = parent.children.every((childId, index) => childId === expectedCodeLineId(parent.id, index));
|
|
4872
|
+
const isStrictTailAppend = requestedStartIndex === parent.children.length;
|
|
4873
|
+
if (!isStrictTailAppend || !prefixMatches) {
|
|
4874
|
+
debugCounters.appendLineGuardRejected += 1;
|
|
4875
|
+
appendDiagnostic(
|
|
4876
|
+
`appendLines guard rejected:${parent.id}:requestedStart=${requestedStartIndex}:childCount=${parent.children.length}:prefixMatches=${prefixMatches}`
|
|
4877
|
+
);
|
|
4878
|
+
break;
|
|
4879
|
+
}
|
|
4166
4880
|
const originalChildren = parent.children.slice();
|
|
4167
4881
|
const insertedIds = [];
|
|
4168
4882
|
const insertedSet = /* @__PURE__ */ new Set();
|
|
4169
|
-
const isTrailingAppend =
|
|
4883
|
+
const isTrailingAppend = true;
|
|
4170
4884
|
let parentChildrenChanged = false;
|
|
4171
4885
|
let codeLinesMutated = false;
|
|
4172
4886
|
for (let offset = 0; offset < lineCount; offset++) {
|
|
@@ -4208,7 +4922,8 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4208
4922
|
parentId: parent.id,
|
|
4209
4923
|
children: [],
|
|
4210
4924
|
props: nextLineProps,
|
|
4211
|
-
version: 0
|
|
4925
|
+
version: 0,
|
|
4926
|
+
blockEpoch: parent.blockEpoch
|
|
4212
4927
|
};
|
|
4213
4928
|
nodes.set(lineId, record);
|
|
4214
4929
|
touched.add(lineId);
|
|
@@ -4258,6 +4973,7 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4258
4973
|
break;
|
|
4259
4974
|
}
|
|
4260
4975
|
case "setHTML": {
|
|
4976
|
+
if (rejectStaleEpochPatch(patch, patch.at)) break;
|
|
4261
4977
|
const target = nodes.get(patch.at.nodeId ?? patch.at.blockId);
|
|
4262
4978
|
if (!target) break;
|
|
4263
4979
|
const sanitized = patch.sanitized ? patch.html : (0, import_core4.sanitizeHTML)(patch.html);
|
|
@@ -4300,6 +5016,30 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4300
5016
|
applyPatch(patch);
|
|
4301
5017
|
}
|
|
4302
5018
|
}
|
|
5019
|
+
const finalizedTableRoots = /* @__PURE__ */ new Set();
|
|
5020
|
+
for (const touchedId of touched) {
|
|
5021
|
+
let cursor = nodes.get(touchedId);
|
|
5022
|
+
while (cursor && cursor.id !== import_core4.PATCH_ROOT_ID) {
|
|
5023
|
+
if (cursor.type === "table" && cursor.block?.isFinalized && cursor.parentId) {
|
|
5024
|
+
finalizedTableRoots.add(cursor.id);
|
|
5025
|
+
break;
|
|
5026
|
+
}
|
|
5027
|
+
cursor = cursor.parentId ? nodes.get(cursor.parentId) : void 0;
|
|
5028
|
+
}
|
|
5029
|
+
}
|
|
5030
|
+
if (finalizedTableRoots.size > 0) {
|
|
5031
|
+
for (const tableId of finalizedTableRoots) {
|
|
5032
|
+
const tableNode = nodes.get(tableId);
|
|
5033
|
+
if (!tableNode || !tableNode.block || !tableNode.parentId) continue;
|
|
5034
|
+
const parent = nodes.get(tableNode.parentId);
|
|
5035
|
+
if (!parent) continue;
|
|
5036
|
+
const index = parent.children.indexOf(tableNode.id);
|
|
5037
|
+
if (index === -1) continue;
|
|
5038
|
+
const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(tableNode.block));
|
|
5039
|
+
replaceSnapshotAt(nodes, parent, index, snapshot, touched, tableNode.blockEpoch);
|
|
5040
|
+
mutatedBlocks = true;
|
|
5041
|
+
}
|
|
5042
|
+
}
|
|
4303
5043
|
if (mutatedBlocks) {
|
|
4304
5044
|
blocksDirty = true;
|
|
4305
5045
|
}
|
|
@@ -4320,6 +5060,8 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4320
5060
|
normalizeListDepthsForIds(nodes, touched, listDepthDirtyNodes, import_core4.PATCH_ROOT_ID);
|
|
4321
5061
|
}
|
|
4322
5062
|
}
|
|
5063
|
+
invariantViolations = [...collectStoreInvariantViolations(nodes), ...transientDiagnostics];
|
|
5064
|
+
debugCounters.storeInvariantViolationCount += invariantViolations.length;
|
|
4323
5065
|
if (touched.size > 0 || mutatedBlocks) {
|
|
4324
5066
|
version++;
|
|
4325
5067
|
scheduleNotify();
|
|
@@ -4368,6 +5110,7 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4368
5110
|
if (!record) {
|
|
4369
5111
|
return EMPTY_NODE_SNAPSHOT;
|
|
4370
5112
|
}
|
|
5113
|
+
const nodeSnapshotCache = getNodeSnapshotCacheForMap(nodes);
|
|
4371
5114
|
const cached = nodeSnapshotCache.get(id);
|
|
4372
5115
|
if (cached && cached.version === record.version && cached.node === record) {
|
|
4373
5116
|
return cached;
|
|
@@ -4387,6 +5130,7 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4387
5130
|
if (!record) {
|
|
4388
5131
|
return EMPTY_CHILDREN_SNAPSHOT;
|
|
4389
5132
|
}
|
|
5133
|
+
const childrenSnapshotCache = getChildrenSnapshotCacheForMap(nodes);
|
|
4390
5134
|
const cached = childrenSnapshotCache.get(id);
|
|
4391
5135
|
if (cached && cached.version === record.version) {
|
|
4392
5136
|
return cached;
|
|
@@ -4396,6 +5140,12 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4396
5140
|
pruneCache(childrenSnapshotCache, CHILDREN_SNAPSHOT_CACHE_LIMIT, CHILDREN_SNAPSHOT_CACHE_BUFFER);
|
|
4397
5141
|
return snapshot;
|
|
4398
5142
|
},
|
|
5143
|
+
getInvariantViolations() {
|
|
5144
|
+
return invariantViolations.slice();
|
|
5145
|
+
},
|
|
5146
|
+
getDebugCounters() {
|
|
5147
|
+
return { ...debugCounters };
|
|
5148
|
+
},
|
|
4399
5149
|
getLastCoalescingMetrics() {
|
|
4400
5150
|
return lastCoalescingMetrics;
|
|
4401
5151
|
},
|
|
@@ -4410,43 +5160,43 @@ function createRendererStore(initialBlocks = []) {
|
|
|
4410
5160
|
}
|
|
4411
5161
|
|
|
4412
5162
|
// src/renderer/blocks-renderer.tsx
|
|
4413
|
-
var
|
|
5163
|
+
var import_react13 = __toESM(require("react"), 1);
|
|
4414
5164
|
var import_core6 = require("@stream-mdx/core");
|
|
4415
5165
|
|
|
4416
5166
|
// src/renderer/hooks.ts
|
|
4417
|
-
var
|
|
5167
|
+
var import_react9 = require("react");
|
|
4418
5168
|
function useRendererBlocks(store) {
|
|
4419
|
-
return (0,
|
|
5169
|
+
return (0, import_react9.useSyncExternalStore)(
|
|
4420
5170
|
store.subscribe,
|
|
4421
5171
|
() => store.getBlocks(),
|
|
4422
5172
|
() => store.getBlocks()
|
|
4423
5173
|
);
|
|
4424
5174
|
}
|
|
4425
5175
|
function useRendererNode(store, id) {
|
|
4426
|
-
const selector = (0,
|
|
5176
|
+
const selector = (0, import_react9.useMemo)(() => {
|
|
4427
5177
|
return () => store.getNodeWithVersion(id);
|
|
4428
5178
|
}, [store, id]);
|
|
4429
|
-
const snapshot = (0,
|
|
5179
|
+
const snapshot = (0, import_react9.useSyncExternalStore)(store.subscribe, selector, selector);
|
|
4430
5180
|
return snapshot.node;
|
|
4431
5181
|
}
|
|
4432
5182
|
function useRendererChildren(store, id) {
|
|
4433
|
-
const selector = (0,
|
|
5183
|
+
const selector = (0, import_react9.useMemo)(() => {
|
|
4434
5184
|
return () => store.getChildrenWithVersion(id);
|
|
4435
5185
|
}, [store, id]);
|
|
4436
|
-
const snapshot = (0,
|
|
5186
|
+
const snapshot = (0, import_react9.useSyncExternalStore)(store.subscribe, selector, selector);
|
|
4437
5187
|
return snapshot.children;
|
|
4438
5188
|
}
|
|
4439
5189
|
|
|
4440
5190
|
// src/renderer/node-views.tsx
|
|
4441
5191
|
var import_core5 = require("@stream-mdx/core");
|
|
4442
|
-
var
|
|
5192
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
4443
5193
|
|
|
4444
5194
|
// src/renderer/deferred-render-context.tsx
|
|
4445
|
-
var
|
|
4446
|
-
var DeferredRenderContext =
|
|
5195
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
5196
|
+
var DeferredRenderContext = import_react10.default.createContext(null);
|
|
4447
5197
|
|
|
4448
5198
|
// src/renderer/virtualized-code.tsx
|
|
4449
|
-
var
|
|
5199
|
+
var import_react11 = require("react");
|
|
4450
5200
|
var DEFAULT_VIRTUALIZED_CODE_CONFIG = {
|
|
4451
5201
|
enabled: true,
|
|
4452
5202
|
windowSize: 100,
|
|
@@ -4486,11 +5236,11 @@ function calculateCodeWindow(lines, scrollTop, containerHeight, lineHeight, conf
|
|
|
4486
5236
|
};
|
|
4487
5237
|
}
|
|
4488
5238
|
function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
4489
|
-
const containerRef = (0,
|
|
4490
|
-
const [scrollTop, setScrollTop] = (0,
|
|
4491
|
-
const [containerHeight, setContainerHeight] = (0,
|
|
4492
|
-
const lineHeightRef = (0,
|
|
4493
|
-
(0,
|
|
5239
|
+
const containerRef = (0, import_react11.useRef)(null);
|
|
5240
|
+
const [scrollTop, setScrollTop] = (0, import_react11.useState)(0);
|
|
5241
|
+
const [containerHeight, setContainerHeight] = (0, import_react11.useState)(0);
|
|
5242
|
+
const lineHeightRef = (0, import_react11.useRef)(20);
|
|
5243
|
+
(0, import_react11.useEffect)(() => {
|
|
4494
5244
|
if (!containerRef.current || lines.length === 0) return;
|
|
4495
5245
|
const timeoutId = setTimeout(() => {
|
|
4496
5246
|
if (!containerRef.current) return;
|
|
@@ -4504,12 +5254,12 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
|
4504
5254
|
}, 0);
|
|
4505
5255
|
return () => clearTimeout(timeoutId);
|
|
4506
5256
|
}, [lines.length]);
|
|
4507
|
-
const handleScroll = (0,
|
|
5257
|
+
const handleScroll = (0, import_react11.useCallback)((e) => {
|
|
4508
5258
|
const target = e.currentTarget;
|
|
4509
5259
|
setScrollTop(target.scrollTop);
|
|
4510
5260
|
setContainerHeight(target.clientHeight);
|
|
4511
5261
|
}, []);
|
|
4512
|
-
(0,
|
|
5262
|
+
(0, import_react11.useEffect)(() => {
|
|
4513
5263
|
if (!containerRef.current) return;
|
|
4514
5264
|
const resizeObserver = new ResizeObserver((entries2) => {
|
|
4515
5265
|
for (const entry of entries2) {
|
|
@@ -4519,10 +5269,10 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
|
4519
5269
|
resizeObserver.observe(containerRef.current);
|
|
4520
5270
|
return () => resizeObserver.disconnect();
|
|
4521
5271
|
}, []);
|
|
4522
|
-
const window2 = (0,
|
|
5272
|
+
const window2 = (0, import_react11.useMemo)(() => {
|
|
4523
5273
|
return calculateCodeWindow(lines, scrollTop, containerHeight, lineHeightRef.current, config);
|
|
4524
5274
|
}, [lines, scrollTop, containerHeight, config]);
|
|
4525
|
-
const scrollToLine = (0,
|
|
5275
|
+
const scrollToLine = (0, import_react11.useCallback)((lineIndex) => {
|
|
4526
5276
|
if (!containerRef.current) return;
|
|
4527
5277
|
const targetScrollTop = lineIndex * lineHeightRef.current;
|
|
4528
5278
|
containerRef.current.scrollTop = targetScrollTop;
|
|
@@ -4539,31 +5289,31 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
|
4539
5289
|
}
|
|
4540
5290
|
|
|
4541
5291
|
// src/renderer/node-views.tsx
|
|
4542
|
-
var
|
|
5292
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
4543
5293
|
var BlockNodeRenderer = ({ store, blockId, registry }) => {
|
|
4544
5294
|
const node = useRendererNode(store, blockId);
|
|
4545
5295
|
const block = node?.block;
|
|
4546
5296
|
if (!node || !block) return null;
|
|
4547
5297
|
switch (block.type) {
|
|
4548
5298
|
case "paragraph":
|
|
4549
|
-
return /* @__PURE__ */ (0,
|
|
5299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ParagraphBlockView, { store, blockId: block.id, registry });
|
|
4550
5300
|
case "blockquote":
|
|
4551
|
-
return /* @__PURE__ */ (0,
|
|
5301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BlockquoteBlockView, { store, blockId: block.id, registry });
|
|
4552
5302
|
case "list":
|
|
4553
|
-
return /* @__PURE__ */ (0,
|
|
5303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ListBlockView, { store, blockId: block.id, registry, depth: 0 });
|
|
4554
5304
|
case "table":
|
|
4555
|
-
return /* @__PURE__ */ (0,
|
|
5305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableBlockView, { store, blockId: block.id, registry });
|
|
4556
5306
|
case "code":
|
|
4557
|
-
return /* @__PURE__ */ (0,
|
|
5307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CodeBlockView, { store, blockId: block.id, registry });
|
|
4558
5308
|
case "html":
|
|
4559
|
-
return /* @__PURE__ */ (0,
|
|
5309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HtmlBlockView, { store, blockId: block.id, registry });
|
|
4560
5310
|
case "mdx":
|
|
4561
|
-
return /* @__PURE__ */ (0,
|
|
5311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdxBlockView, { store, blockId: block.id, registry });
|
|
4562
5312
|
default:
|
|
4563
5313
|
return registry.renderBlock(block);
|
|
4564
5314
|
}
|
|
4565
5315
|
};
|
|
4566
|
-
var ParagraphBlockView =
|
|
5316
|
+
var ParagraphBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
|
|
4567
5317
|
const node = useRendererNode(store, blockId);
|
|
4568
5318
|
const block = node?.block;
|
|
4569
5319
|
const childIds = useRendererChildren(store, blockId);
|
|
@@ -4578,12 +5328,12 @@ var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry
|
|
|
4578
5328
|
if (segments2.length > 0) {
|
|
4579
5329
|
const allowMixedStreaming = Boolean(meta.allowMixedStreaming);
|
|
4580
5330
|
if (!allowMixedStreaming) {
|
|
4581
|
-
return /* @__PURE__ */ (0,
|
|
5331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
|
|
4582
5332
|
}
|
|
4583
5333
|
const structured = renderParagraphMixedSegments(segments2, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
4584
5334
|
if (structured.length === 1) {
|
|
4585
5335
|
const [single] = structured;
|
|
4586
|
-
return
|
|
5336
|
+
return import_react12.default.isValidElement(single) ? single : single;
|
|
4587
5337
|
}
|
|
4588
5338
|
return structured;
|
|
4589
5339
|
}
|
|
@@ -4601,26 +5351,26 @@ var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry
|
|
|
4601
5351
|
const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
4602
5352
|
if (structured.length === 1) {
|
|
4603
5353
|
const [single] = structured;
|
|
4604
|
-
return
|
|
5354
|
+
return import_react12.default.isValidElement(single) ? single : single;
|
|
4605
5355
|
}
|
|
4606
5356
|
return structured;
|
|
4607
5357
|
}
|
|
4608
|
-
return /* @__PURE__ */ (0,
|
|
5358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph streaming-partial", children: renderInlineNodes(inlineNodes2, inlineComponents) });
|
|
4609
5359
|
}
|
|
4610
|
-
return /* @__PURE__ */ (0,
|
|
5360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
|
|
4611
5361
|
}
|
|
4612
5362
|
const propsBlock = node.props?.block;
|
|
4613
5363
|
const inlineStatus = propsBlock?.payload?.meta?.inlineStatus ?? block.payload.meta?.inlineStatus ?? node.props?.inlineStatus;
|
|
4614
5364
|
if (inlineStatus && inlineStatus !== "complete") {
|
|
4615
5365
|
const raw = typeof block.payload.raw === "string" ? block.payload.raw : "";
|
|
4616
|
-
return /* @__PURE__ */ (0,
|
|
5366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph", children: raw });
|
|
4617
5367
|
}
|
|
4618
5368
|
const segments = Array.isArray(block.payload.meta?.mixedSegments) ? block.payload.meta.mixedSegments : void 0;
|
|
4619
5369
|
if (segments && segments.length > 0) {
|
|
4620
5370
|
const structured = renderParagraphMixedSegments(segments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
4621
5371
|
if (structured.length === 1) {
|
|
4622
5372
|
const [single] = structured;
|
|
4623
|
-
return
|
|
5373
|
+
return import_react12.default.isValidElement(single) ? single : single;
|
|
4624
5374
|
}
|
|
4625
5375
|
return structured;
|
|
4626
5376
|
}
|
|
@@ -4637,31 +5387,31 @@ var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry
|
|
|
4637
5387
|
const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
4638
5388
|
if (structured.length === 1) {
|
|
4639
5389
|
const [single] = structured;
|
|
4640
|
-
return
|
|
5390
|
+
return import_react12.default.isValidElement(single) ? single : single;
|
|
4641
5391
|
}
|
|
4642
5392
|
return structured;
|
|
4643
5393
|
}
|
|
4644
5394
|
const ParagraphComponent = registry.getBlockComponent("paragraph");
|
|
4645
|
-
const baseElement =
|
|
5395
|
+
const baseElement = import_react12.default.createElement(ParagraphComponent, {
|
|
4646
5396
|
inlines: block.payload.inline ?? [],
|
|
4647
5397
|
raw: block.payload.raw,
|
|
4648
5398
|
meta: block.payload.meta
|
|
4649
5399
|
});
|
|
4650
5400
|
if (childIds.length > 0) {
|
|
4651
|
-
const renderedChildren = childIds.map((childId) => /* @__PURE__ */ (0,
|
|
4652
|
-
if (
|
|
5401
|
+
const renderedChildren = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
5402
|
+
if (import_react12.default.isValidElement(baseElement)) {
|
|
4653
5403
|
const { children: _ignored, className = "markdown-paragraph", inlines: _inlines, raw: _raw, meta: _meta, ...rest } = baseElement.props ?? {};
|
|
4654
|
-
return
|
|
5404
|
+
return import_react12.default.createElement("p", { ...rest, className }, renderedChildren);
|
|
4655
5405
|
}
|
|
4656
|
-
return /* @__PURE__ */ (0,
|
|
5406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph", children: renderedChildren });
|
|
4657
5407
|
}
|
|
4658
|
-
if (
|
|
5408
|
+
if (import_react12.default.isValidElement(baseElement)) {
|
|
4659
5409
|
return baseElement;
|
|
4660
5410
|
}
|
|
4661
|
-
return /* @__PURE__ */ (0,
|
|
5411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph", children: renderInlineNodes(block.payload.inline ?? [], inlineComponents) });
|
|
4662
5412
|
});
|
|
4663
5413
|
ParagraphBlockView.displayName = "ParagraphBlockView";
|
|
4664
|
-
var BlockquoteBlockView =
|
|
5414
|
+
var BlockquoteBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
|
|
4665
5415
|
const node = useRendererNode(store, blockId);
|
|
4666
5416
|
const block = node?.block;
|
|
4667
5417
|
const childIds = useRendererChildren(store, blockId);
|
|
@@ -4679,9 +5429,9 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
|
|
|
4679
5429
|
return lines.map((line, idx) => {
|
|
4680
5430
|
const key = `${keyPrefix}${offset}`;
|
|
4681
5431
|
offset += line.length + 1;
|
|
4682
|
-
return /* @__PURE__ */ (0,
|
|
5432
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "markdown-blockquote-line", children: [
|
|
4683
5433
|
line,
|
|
4684
|
-
idx < lastIndex ? /* @__PURE__ */ (0,
|
|
5434
|
+
idx < lastIndex ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("br", {}) : null
|
|
4685
5435
|
] }, key);
|
|
4686
5436
|
});
|
|
4687
5437
|
};
|
|
@@ -4707,7 +5457,7 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
|
|
|
4707
5457
|
elements.push(htmlNode);
|
|
4708
5458
|
} else {
|
|
4709
5459
|
elements.push(
|
|
4710
|
-
|
|
5460
|
+
import_react12.default.createElement("span", {
|
|
4711
5461
|
key: `blockquote-html-${block.id}-${segmentIndex}`,
|
|
4712
5462
|
className: "markdown-inline-html",
|
|
4713
5463
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: segment content is sanitized by the worker before streaming */
|
|
@@ -4719,16 +5469,16 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
|
|
|
4719
5469
|
}
|
|
4720
5470
|
case "mdx":
|
|
4721
5471
|
elements.push(
|
|
4722
|
-
/* @__PURE__ */ (0,
|
|
5472
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-mdx-status": segment.status ?? "pending", children: segment.value }, `blockquote-mdx-${block.id}-${segmentIndex}`)
|
|
4723
5473
|
);
|
|
4724
5474
|
break;
|
|
4725
5475
|
default: {
|
|
4726
5476
|
const inline = renderInlineContent(segment.inline, `blockquote-text-inline-${block.id}-${segmentIndex}-`);
|
|
4727
5477
|
if (inline) {
|
|
4728
|
-
elements.push(/* @__PURE__ */ (0,
|
|
5478
|
+
elements.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react12.default.Fragment, { children: inline }, `blockquote-inline-${block.id}-${segmentIndex}`));
|
|
4729
5479
|
} else {
|
|
4730
5480
|
elements.push(
|
|
4731
|
-
/* @__PURE__ */ (0,
|
|
5481
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react12.default.Fragment, { children: renderTextWithBreaks(segment.value, `blockquote-text-${block.id}-${segmentIndex}-`) }, `blockquote-text-${block.id}-${segmentIndex}`)
|
|
4732
5482
|
);
|
|
4733
5483
|
}
|
|
4734
5484
|
break;
|
|
@@ -4745,9 +5495,9 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
|
|
|
4745
5495
|
const streamingContent = mixedSegmentElements.length ? mixedSegmentElements : inlineElements ? inlineElements : fallbackElements;
|
|
4746
5496
|
const shouldShowStreaming = !block.isFinalized && (!streamingContent || Array.isArray(streamingContent) && streamingContent.length === 0);
|
|
4747
5497
|
const className = shouldShowStreaming ? "markdown-blockquote streaming-partial" : "markdown-blockquote";
|
|
4748
|
-
return /* @__PURE__ */ (0,
|
|
5498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("blockquote", { className, children: streamingContent });
|
|
4749
5499
|
}
|
|
4750
|
-
const childContent = childIds.map((childId) => /* @__PURE__ */ (0,
|
|
5500
|
+
const childContent = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
4751
5501
|
const renderedContent = (() => {
|
|
4752
5502
|
if (mixedSegmentElements.length > 0) {
|
|
4753
5503
|
return mixedSegmentElements;
|
|
@@ -4767,7 +5517,7 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
|
|
|
4767
5517
|
return null;
|
|
4768
5518
|
})();
|
|
4769
5519
|
const BlockquoteComponent = registry.getBlockComponent("blockquote");
|
|
4770
|
-
const baseElement =
|
|
5520
|
+
const baseElement = import_react12.default.createElement(
|
|
4771
5521
|
BlockquoteComponent,
|
|
4772
5522
|
{
|
|
4773
5523
|
inlines: block.payload.inline ?? [],
|
|
@@ -4775,13 +5525,13 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
|
|
|
4775
5525
|
},
|
|
4776
5526
|
renderedContent
|
|
4777
5527
|
);
|
|
4778
|
-
if (
|
|
5528
|
+
if (import_react12.default.isValidElement(baseElement)) {
|
|
4779
5529
|
return baseElement;
|
|
4780
5530
|
}
|
|
4781
|
-
return /* @__PURE__ */ (0,
|
|
5531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("blockquote", { className: "markdown-blockquote", children: renderedContent });
|
|
4782
5532
|
});
|
|
4783
5533
|
BlockquoteBlockView.displayName = "BlockquoteBlockView";
|
|
4784
|
-
var MixedSegmentView =
|
|
5534
|
+
var MixedSegmentView = import_react12.default.memo(({ store, nodeId, inlineComponents }) => {
|
|
4785
5535
|
const node = useRendererNode(store, nodeId);
|
|
4786
5536
|
if (!node) return null;
|
|
4787
5537
|
switch (node.type) {
|
|
@@ -4809,7 +5559,7 @@ var MixedSegmentView = import_react11.default.memo(({ store, nodeId, inlineCompo
|
|
|
4809
5559
|
return rendered;
|
|
4810
5560
|
}
|
|
4811
5561
|
if (!html) return null;
|
|
4812
|
-
return
|
|
5562
|
+
return import_react12.default.createElement("span", {
|
|
4813
5563
|
className: "markdown-inline-html",
|
|
4814
5564
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: html is sanitized upstream before reaching the renderer */
|
|
4815
5565
|
dangerouslySetInnerHTML: { __html: html }
|
|
@@ -4821,32 +5571,32 @@ var MixedSegmentView = import_react11.default.memo(({ store, nodeId, inlineCompo
|
|
|
4821
5571
|
const status = node.props?.status ?? "pending";
|
|
4822
5572
|
const raw = typeof node.props?.raw === "string" ? node.props?.raw : "";
|
|
4823
5573
|
if (status === "compiled") {
|
|
4824
|
-
return /* @__PURE__ */ (0,
|
|
5574
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
|
|
4825
5575
|
}
|
|
4826
5576
|
if (status === "error") {
|
|
4827
5577
|
const message = raw || "MDX error";
|
|
4828
|
-
return /* @__PURE__ */ (0,
|
|
5578
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error", children: message });
|
|
4829
5579
|
}
|
|
4830
|
-
return /* @__PURE__ */ (0,
|
|
5580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": status, children: status === "compiled" ? "" : raw });
|
|
4831
5581
|
}
|
|
4832
5582
|
default:
|
|
4833
5583
|
return null;
|
|
4834
5584
|
}
|
|
4835
5585
|
});
|
|
4836
5586
|
MixedSegmentView.displayName = "MixedSegmentView";
|
|
4837
|
-
var HtmlBlockView =
|
|
5587
|
+
var HtmlBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
|
|
4838
5588
|
const node = useRendererNode(store, blockId);
|
|
4839
5589
|
if (!node || !node.block) return null;
|
|
4840
5590
|
return registry.renderBlock(node.block);
|
|
4841
5591
|
});
|
|
4842
5592
|
HtmlBlockView.displayName = "HtmlBlockView";
|
|
4843
|
-
var MdxBlockView =
|
|
5593
|
+
var MdxBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
|
|
4844
5594
|
const node = useRendererNode(store, blockId);
|
|
4845
5595
|
if (!node || !node.block) return null;
|
|
4846
5596
|
return registry.renderBlock(node.block);
|
|
4847
5597
|
});
|
|
4848
5598
|
MdxBlockView.displayName = "MdxBlockView";
|
|
4849
|
-
var ListBlockView =
|
|
5599
|
+
var ListBlockView = import_react12.default.memo(
|
|
4850
5600
|
({ store, blockId, registry, depth = 0 }) => {
|
|
4851
5601
|
const node = useRendererNode(store, blockId);
|
|
4852
5602
|
const block = node?.block;
|
|
@@ -4855,7 +5605,7 @@ var ListBlockView = import_react11.default.memo(
|
|
|
4855
5605
|
const ordered = Boolean(node?.props?.ordered ?? block?.payload.meta?.ordered);
|
|
4856
5606
|
const Tag = ordered ? "ol" : "ul";
|
|
4857
5607
|
const listDebugEnabled = isListPatchDebugEnabled();
|
|
4858
|
-
const listItemIds =
|
|
5608
|
+
const listItemIds = import_react12.default.useMemo(() => {
|
|
4859
5609
|
const ids = [];
|
|
4860
5610
|
for (const childId of childIds) {
|
|
4861
5611
|
const childNode = store.getNode(childId);
|
|
@@ -4865,7 +5615,7 @@ var ListBlockView = import_react11.default.memo(
|
|
|
4865
5615
|
}
|
|
4866
5616
|
return ids;
|
|
4867
5617
|
}, [childIds, store]);
|
|
4868
|
-
|
|
5618
|
+
import_react12.default.useEffect(() => {
|
|
4869
5619
|
if (!listDebugEnabled) return;
|
|
4870
5620
|
const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
|
|
4871
5621
|
console.info("[stream-mdx:list-render]", {
|
|
@@ -4880,8 +5630,10 @@ var ListBlockView = import_react11.default.memo(
|
|
|
4880
5630
|
isFinalized: block?.isFinalized ?? false
|
|
4881
5631
|
});
|
|
4882
5632
|
}, [listDebugEnabled, blockId, depth, ordered, childIds, listItemIds, store, block?.isFinalized]);
|
|
4883
|
-
const listStyle =
|
|
4884
|
-
if (!ordered || listItemIds.length === 0)
|
|
5633
|
+
const { listStyle, markerDigits } = import_react12.default.useMemo(() => {
|
|
5634
|
+
if (!ordered || listItemIds.length === 0) {
|
|
5635
|
+
return { listStyle: void 0, markerDigits: 1 };
|
|
5636
|
+
}
|
|
4885
5637
|
let maxDigits = 1;
|
|
4886
5638
|
listItemIds.forEach((childId, index) => {
|
|
4887
5639
|
const childNode = store.getNode(childId);
|
|
@@ -4893,20 +5645,26 @@ var ListBlockView = import_react11.default.memo(
|
|
|
4893
5645
|
const digits = digitMatch ? digitMatch.length : text.length;
|
|
4894
5646
|
if (digits > maxDigits) maxDigits = digits;
|
|
4895
5647
|
});
|
|
4896
|
-
const baseIndent = depth === 0 ? "
|
|
5648
|
+
const baseIndent = depth === 0 ? "2rem" : depth === 1 ? "1.75rem" : "1.5rem";
|
|
5649
|
+
const extraDigits = Math.max(0, maxDigits - 1);
|
|
4897
5650
|
return {
|
|
4898
|
-
|
|
5651
|
+
markerDigits: maxDigits,
|
|
5652
|
+
listStyle: {
|
|
5653
|
+
["--list-indent"]: extraDigits > 0 ? `calc(${baseIndent} + ${extraDigits}ch)` : baseIndent,
|
|
5654
|
+
["--list-marker-digits"]: String(maxDigits)
|
|
5655
|
+
}
|
|
4899
5656
|
};
|
|
4900
5657
|
}, [ordered, listItemIds, store, depth]);
|
|
4901
5658
|
if (listItemIds.length === 0) return null;
|
|
4902
|
-
return /* @__PURE__ */ (0,
|
|
5659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
4903
5660
|
Tag,
|
|
4904
5661
|
{
|
|
4905
5662
|
className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
|
|
4906
5663
|
"data-list-depth": depth,
|
|
5664
|
+
"data-marker-digits": ordered ? markerDigits : void 0,
|
|
4907
5665
|
"data-list-id": listDebugEnabled ? blockId : void 0,
|
|
4908
5666
|
style: listStyle,
|
|
4909
|
-
children: listItemIds.map((childId, index) => /* @__PURE__ */ (0,
|
|
5667
|
+
children: listItemIds.map((childId, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
4910
5668
|
ListItemView,
|
|
4911
5669
|
{
|
|
4912
5670
|
store,
|
|
@@ -4924,7 +5682,7 @@ var ListBlockView = import_react11.default.memo(
|
|
|
4924
5682
|
}
|
|
4925
5683
|
);
|
|
4926
5684
|
ListBlockView.displayName = "ListBlockView";
|
|
4927
|
-
var ListItemView =
|
|
5685
|
+
var ListItemView = import_react12.default.memo(({ store, nodeId, inlineComponents, registry, ordered, index, depth }) => {
|
|
4928
5686
|
const node = useRendererNode(store, nodeId);
|
|
4929
5687
|
const childIds = useRendererChildren(store, nodeId);
|
|
4930
5688
|
const inline = node?.props?.inline ?? [];
|
|
@@ -4939,7 +5697,7 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
|
|
|
4939
5697
|
const counterText = !isTask ? isOrdered ? marker ? marker : `${inferredIndex + 1}.` : "\u2022" : void 0;
|
|
4940
5698
|
const listDebugEnabled = isListPatchDebugEnabled();
|
|
4941
5699
|
const inlineLength = inline.length;
|
|
4942
|
-
const [segmentChildIds, contentChildIds] =
|
|
5700
|
+
const [segmentChildIds, contentChildIds] = import_react12.default.useMemo(() => {
|
|
4943
5701
|
const segments = [];
|
|
4944
5702
|
const structural = [];
|
|
4945
5703
|
for (const childId of childIds) {
|
|
@@ -4953,34 +5711,34 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
|
|
|
4953
5711
|
}
|
|
4954
5712
|
return [segments, structural];
|
|
4955
5713
|
}, [childIds, store]);
|
|
4956
|
-
const segmentElements =
|
|
4957
|
-
return segmentChildIds.map((childId) => /* @__PURE__ */ (0,
|
|
5714
|
+
const segmentElements = import_react12.default.useMemo(() => {
|
|
5715
|
+
return segmentChildIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
4958
5716
|
}, [segmentChildIds, store, inlineComponents]);
|
|
4959
|
-
const primaryContent =
|
|
5717
|
+
const primaryContent = import_react12.default.useMemo(() => {
|
|
4960
5718
|
if (segmentChildIds.length > 0) {
|
|
4961
5719
|
return segmentElements;
|
|
4962
5720
|
}
|
|
4963
5721
|
return renderInlineNodes(inline, inlineComponents);
|
|
4964
5722
|
}, [segmentChildIds, segmentElements, inline, inlineComponents]);
|
|
4965
|
-
const trailingChildren =
|
|
5723
|
+
const trailingChildren = import_react12.default.useMemo(() => {
|
|
4966
5724
|
return contentChildIds.map((childId) => {
|
|
4967
5725
|
const childNode = store.getNode(childId);
|
|
4968
5726
|
if (!childNode) return null;
|
|
4969
5727
|
switch (childNode.type) {
|
|
4970
5728
|
case "paragraph": {
|
|
4971
5729
|
const childInline = childNode.props?.inline ?? [];
|
|
4972
|
-
return /* @__PURE__ */ (0,
|
|
5730
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-list-item-paragraph", children: renderInlineNodes(childInline, inlineComponents) }, childId);
|
|
4973
5731
|
}
|
|
4974
5732
|
case "list":
|
|
4975
|
-
return /* @__PURE__ */ (0,
|
|
5733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ListBlockView, { store, blockId: childId, registry, depth: depth + 1 }, childId);
|
|
4976
5734
|
default:
|
|
4977
|
-
return /* @__PURE__ */ (0,
|
|
5735
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BlockNodeRenderer, { store, blockId: childId, registry }, childId);
|
|
4978
5736
|
}
|
|
4979
5737
|
});
|
|
4980
5738
|
}, [contentChildIds, store, inlineComponents, registry, depth]);
|
|
4981
5739
|
const filteredChildren = trailingChildren.filter((child) => Boolean(child));
|
|
4982
5740
|
const hasChildren = filteredChildren.length > 0;
|
|
4983
|
-
|
|
5741
|
+
import_react12.default.useEffect(() => {
|
|
4984
5742
|
if (!listDebugEnabled) return;
|
|
4985
5743
|
const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
|
|
4986
5744
|
console.info("[stream-mdx:list-item-render]", {
|
|
@@ -5016,7 +5774,7 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
|
|
|
5016
5774
|
store,
|
|
5017
5775
|
block?.isFinalized
|
|
5018
5776
|
]);
|
|
5019
|
-
return /* @__PURE__ */ (0,
|
|
5777
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
5020
5778
|
"li",
|
|
5021
5779
|
{
|
|
5022
5780
|
className: `markdown-list-item${isTask ? " markdown-list-item-task" : ""}`,
|
|
@@ -5024,44 +5782,44 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
|
|
|
5024
5782
|
"data-list-depth": depth,
|
|
5025
5783
|
"data-list-item-id": listDebugEnabled ? nodeId : void 0,
|
|
5026
5784
|
children: [
|
|
5027
|
-
isTask ? /* @__PURE__ */ (0,
|
|
5028
|
-
/* @__PURE__ */ (0,
|
|
5029
|
-
/* @__PURE__ */ (0,
|
|
5785
|
+
isTask ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "markdown-task", children: [
|
|
5786
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", className: "markdown-task-checkbox", checked: isChecked, readOnly: true, disabled: true, tabIndex: -1, "aria-checked": isChecked }),
|
|
5787
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-task-content", children: primaryContent })
|
|
5030
5788
|
] }) : primaryContent,
|
|
5031
|
-
hasChildren ? /* @__PURE__ */ (0,
|
|
5789
|
+
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "markdown-list-item-children", children: filteredChildren }) : null
|
|
5032
5790
|
]
|
|
5033
5791
|
}
|
|
5034
5792
|
);
|
|
5035
5793
|
});
|
|
5036
5794
|
ListItemView.displayName = "ListItemView";
|
|
5037
|
-
var TableBlockView =
|
|
5795
|
+
var TableBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
|
|
5038
5796
|
const tableElements = registry.getTableElements();
|
|
5039
5797
|
const childIds = useRendererChildren(store, blockId);
|
|
5040
|
-
return /* @__PURE__ */ (0,
|
|
5798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Table, { className: "markdown-table w-full caption-bottom text-base", children: childIds.map((sectionId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableSectionView, { store, nodeId: sectionId, registry }, sectionId)) });
|
|
5041
5799
|
});
|
|
5042
5800
|
TableBlockView.displayName = "TableBlockView";
|
|
5043
|
-
var TableSectionView =
|
|
5801
|
+
var TableSectionView = import_react12.default.memo(({ store, nodeId, registry }) => {
|
|
5044
5802
|
const node = useRendererNode(store, nodeId);
|
|
5045
5803
|
if (!node) return null;
|
|
5046
5804
|
const tableElements = registry.getTableElements();
|
|
5047
5805
|
if (node.type === "table-header") {
|
|
5048
5806
|
const childIds = useRendererChildren(store, nodeId);
|
|
5049
|
-
return /* @__PURE__ */ (0,
|
|
5807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Thead, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Tr, { children: childIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) }) });
|
|
5050
5808
|
}
|
|
5051
5809
|
if (node.type === "table-body") {
|
|
5052
5810
|
const rowIds = useRendererChildren(store, nodeId);
|
|
5053
|
-
return /* @__PURE__ */ (0,
|
|
5811
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Tbody, { children: rowIds.map((rowId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableRowView, { store, nodeId: rowId, registry }, rowId)) });
|
|
5054
5812
|
}
|
|
5055
5813
|
return null;
|
|
5056
5814
|
});
|
|
5057
5815
|
TableSectionView.displayName = "TableSectionView";
|
|
5058
|
-
var TableRowView =
|
|
5816
|
+
var TableRowView = import_react12.default.memo(({ store, nodeId, registry }) => {
|
|
5059
5817
|
const tableElements = registry.getTableElements();
|
|
5060
5818
|
const cellIds = useRendererChildren(store, nodeId);
|
|
5061
|
-
return /* @__PURE__ */ (0,
|
|
5819
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Tr, { children: cellIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) });
|
|
5062
5820
|
});
|
|
5063
5821
|
TableRowView.displayName = "TableRowView";
|
|
5064
|
-
var TableCellView =
|
|
5822
|
+
var TableCellView = import_react12.default.memo(({ store, nodeId, registry }) => {
|
|
5065
5823
|
const node = useRendererNode(store, nodeId);
|
|
5066
5824
|
const inlineComponents = registry.getInlineComponents();
|
|
5067
5825
|
const tableElements = registry.getTableElements();
|
|
@@ -5071,22 +5829,23 @@ var TableCellView = import_react11.default.memo(({ store, nodeId, registry }) =>
|
|
|
5071
5829
|
const align = node.props?.align;
|
|
5072
5830
|
const content = renderInlineNodes(inline, inlineComponents);
|
|
5073
5831
|
const alignProps = align ? { align } : void 0;
|
|
5074
|
-
return /* @__PURE__ */ (0,
|
|
5832
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tag, { ...alignProps, children: content });
|
|
5075
5833
|
});
|
|
5076
5834
|
TableCellView.displayName = "TableCellView";
|
|
5077
|
-
var CodeBlockView =
|
|
5835
|
+
var CodeBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
|
|
5078
5836
|
const node = useRendererNode(store, blockId);
|
|
5079
5837
|
const childIds = useRendererChildren(store, blockId);
|
|
5080
5838
|
const CodeComponent = registry.getBlockComponent("code");
|
|
5081
|
-
const deferredConfig =
|
|
5082
|
-
const deferredRef =
|
|
5839
|
+
const deferredConfig = import_react12.default.useContext(DeferredRenderContext);
|
|
5840
|
+
const deferredRef = import_react12.default.useRef(null);
|
|
5083
5841
|
const shouldRenderDeferred = useDeferredRender(
|
|
5084
5842
|
deferredRef,
|
|
5085
5843
|
deferredConfig ? { ...deferredConfig, enabled: true } : { enabled: false }
|
|
5086
5844
|
);
|
|
5087
5845
|
if (!node || !node.block) return null;
|
|
5846
|
+
const blockIsFinalized = node.block.isFinalized;
|
|
5088
5847
|
const nodeVersion = node.version;
|
|
5089
|
-
const lines =
|
|
5848
|
+
const lines = import_react12.default.useMemo(() => {
|
|
5090
5849
|
const seenIds = /* @__PURE__ */ new Set();
|
|
5091
5850
|
const seenIndices = /* @__PURE__ */ new Set();
|
|
5092
5851
|
const deduped = [];
|
|
@@ -5115,17 +5874,29 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
|
|
|
5115
5874
|
const lang = typeof node.props?.lang === "string" ? node.props?.lang : node.block.payload.meta?.lang;
|
|
5116
5875
|
const preAttrs = node.props?.preAttrs ?? void 0;
|
|
5117
5876
|
const codeAttrs = node.props?.codeAttrs ?? void 0;
|
|
5877
|
+
const blockMeta = node.block.payload.meta ?? void 0;
|
|
5878
|
+
const lazyEnabled = Boolean(blockMeta?.lazyTokenization);
|
|
5879
|
+
const lazyTokenizedUntil = typeof blockMeta?.lazyTokenizedUntil === "number" ? blockMeta.lazyTokenizedUntil : 0;
|
|
5880
|
+
const lazyHighlightedLines = Array.isArray(blockMeta?.highlightedLines) ? blockMeta.highlightedLines.length : 0;
|
|
5881
|
+
const lazyTokenLines = Array.isArray(blockMeta?.tokenLines) ? blockMeta.tokenLines.length : 0;
|
|
5882
|
+
const lazySourceTextLineCount = import_react12.default.useMemo(() => {
|
|
5883
|
+
const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
|
|
5884
|
+
const metaCode = typeof blockMeta?.code === "string" ? blockMeta.code : null;
|
|
5885
|
+
const sourceText = resolveCodeSourceText(raw, metaCode);
|
|
5886
|
+
if (sourceText.length === 0) return 0;
|
|
5887
|
+
return sourceText.split("\n").length;
|
|
5888
|
+
}, [blockMeta, node.block?.payload.raw]);
|
|
5889
|
+
const totalLazyLineCount = Math.max(lines.length, lazyHighlightedLines, lazyTokenLines, lazySourceTextLineCount);
|
|
5118
5890
|
const virtualizationConfig = DEFAULT_VIRTUALIZED_CODE_CONFIG;
|
|
5119
5891
|
const virtualizationDisabled = typeof process !== "undefined" && typeof process.env === "object" && process.env.STREAM_MDX_DISABLE_VIRTUALIZED_CODE === "true";
|
|
5120
|
-
const
|
|
5892
|
+
const canVirtualize = node.block.isFinalized && !lazyEnabled;
|
|
5893
|
+
const shouldVirtualize = canVirtualize && !virtualizationDisabled && virtualizationConfig.enabled && lines.length >= virtualizationConfig.virtualizeThreshold;
|
|
5121
5894
|
const virtualization = useVirtualizedCode(lines, shouldVirtualize ? virtualizationConfig : { ...virtualizationConfig, enabled: false });
|
|
5122
5895
|
const highlightRequester = useCodeHighlightRequester();
|
|
5123
|
-
const
|
|
5124
|
-
const
|
|
5125
|
-
const
|
|
5126
|
-
|
|
5127
|
-
const idleRef = import_react11.default.useRef(null);
|
|
5128
|
-
import_react11.default.useEffect(() => {
|
|
5896
|
+
const lastRangeRef = import_react12.default.useRef(null);
|
|
5897
|
+
const rafRef = import_react12.default.useRef(null);
|
|
5898
|
+
const idleRef = import_react12.default.useRef(null);
|
|
5899
|
+
import_react12.default.useEffect(() => {
|
|
5129
5900
|
if (!shouldVirtualize || !lazyEnabled || !highlightRequester) return;
|
|
5130
5901
|
const { visibleStart, visibleEnd, startIndex, endIndex } = virtualization.window;
|
|
5131
5902
|
if (endIndex <= lazyTokenizedUntil) return;
|
|
@@ -5202,30 +5973,112 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
|
|
|
5202
5973
|
virtualization.window.startIndex,
|
|
5203
5974
|
virtualization.window.endIndex
|
|
5204
5975
|
]);
|
|
5205
|
-
|
|
5206
|
-
if (
|
|
5207
|
-
|
|
5976
|
+
import_react12.default.useEffect(() => {
|
|
5977
|
+
if (shouldVirtualize || !blockIsFinalized || !lazyEnabled || !highlightRequester) return;
|
|
5978
|
+
if (totalLazyLineCount <= 0 || lazyTokenizedUntil >= totalLazyLineCount) return;
|
|
5979
|
+
const nextRange = {
|
|
5980
|
+
visibleStart: 0,
|
|
5981
|
+
visibleEnd: totalLazyLineCount,
|
|
5982
|
+
prefetchStart: 0,
|
|
5983
|
+
prefetchEnd: totalLazyLineCount,
|
|
5984
|
+
tokenizedUntil: lazyTokenizedUntil
|
|
5985
|
+
};
|
|
5986
|
+
const last = lastRangeRef.current;
|
|
5987
|
+
if (last && last.visibleStart === nextRange.visibleStart && last.visibleEnd === nextRange.visibleEnd && last.prefetchStart === nextRange.prefetchStart && last.prefetchEnd === nextRange.prefetchEnd && last.tokenizedUntil === nextRange.tokenizedUntil) {
|
|
5988
|
+
return;
|
|
5208
5989
|
}
|
|
5990
|
+
lastRangeRef.current = nextRange;
|
|
5991
|
+
if (rafRef.current !== null && typeof cancelAnimationFrame === "function") {
|
|
5992
|
+
cancelAnimationFrame(rafRef.current);
|
|
5993
|
+
}
|
|
5994
|
+
const requestFullHighlight = () => {
|
|
5995
|
+
highlightRequester({
|
|
5996
|
+
blockId,
|
|
5997
|
+
startLine: 0,
|
|
5998
|
+
endLine: totalLazyLineCount,
|
|
5999
|
+
priority: "visible",
|
|
6000
|
+
reason: "finalize-full"
|
|
6001
|
+
});
|
|
6002
|
+
rafRef.current = null;
|
|
6003
|
+
};
|
|
6004
|
+
if (typeof requestAnimationFrame === "function") {
|
|
6005
|
+
rafRef.current = requestAnimationFrame(requestFullHighlight);
|
|
6006
|
+
} else {
|
|
6007
|
+
requestFullHighlight();
|
|
6008
|
+
}
|
|
6009
|
+
}, [blockId, blockIsFinalized, highlightRequester, lazyEnabled, lazyTokenizedUntil, shouldVirtualize, totalLazyLineCount]);
|
|
6010
|
+
const highlightedHtml = import_react12.default.useMemo(() => {
|
|
6011
|
+
const blockHtml = node.block?.payload.highlightedHtml ?? "";
|
|
6012
|
+
const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
|
|
6013
|
+
const metaCode = typeof node.block?.payload.meta?.code === "string" ? (node.block?.payload.meta).code : null;
|
|
6014
|
+
const sourceText = resolveCodeSourceText(raw, metaCode);
|
|
6015
|
+
const sourceEndsWithNewline = sourceText.endsWith("\n");
|
|
6016
|
+
const sourceLines = sourceText.length > 0 ? sourceText.split("\n") : [];
|
|
6017
|
+
const rawFallbackLines = buildCodeFallbackLines(raw);
|
|
6018
|
+
const deterministicWrapperAttrs = (0, import_core5.getDefaultCodeWrapperAttributes)(lang);
|
|
6019
|
+
const composedPreAttrs = deterministicWrapperAttrs.preAttrs;
|
|
6020
|
+
const composedCodeAttrs = deterministicWrapperAttrs.codeAttrs;
|
|
6021
|
+
const shouldAppendTerminalNewline = (renderedLines) => {
|
|
6022
|
+
if (!sourceEndsWithNewline || renderedLines.length === 0 || lines.length === 0) {
|
|
6023
|
+
return false;
|
|
6024
|
+
}
|
|
6025
|
+
const lastRendered = renderedLines[renderedLines.length - 1];
|
|
6026
|
+
const lastKnown = lines[lines.length - 1];
|
|
6027
|
+
if (!lastRendered || !lastKnown || lastRendered.index !== lastKnown.index || lastRendered.text === "") {
|
|
6028
|
+
return false;
|
|
6029
|
+
}
|
|
6030
|
+
const expectedRenderedLineCount = Math.max(0, sourceLines.length - 1);
|
|
6031
|
+
const expectedLastRenderedLine = sourceLines.length >= 2 ? sourceLines[sourceLines.length - 2] ?? "" : "";
|
|
6032
|
+
return renderedLines.length === expectedRenderedLineCount && lastRendered.text === expectedLastRenderedLine;
|
|
6033
|
+
};
|
|
5209
6034
|
if (lines.length > 0) {
|
|
5210
6035
|
const hasLineHtml = lines.some((line) => typeof line.html === "string" && line.html.length > 0);
|
|
5211
|
-
if (!hasLineHtml &&
|
|
5212
|
-
return
|
|
6036
|
+
if (!hasLineHtml && blockHtml) {
|
|
6037
|
+
return blockHtml;
|
|
5213
6038
|
}
|
|
5214
6039
|
if (shouldVirtualize) {
|
|
5215
|
-
return composeHighlightedHtml(
|
|
6040
|
+
return composeHighlightedHtml(
|
|
6041
|
+
virtualization.window.visibleLines,
|
|
6042
|
+
composedPreAttrs,
|
|
6043
|
+
composedCodeAttrs,
|
|
6044
|
+
shouldAppendTerminalNewline(virtualization.window.visibleLines)
|
|
6045
|
+
);
|
|
5216
6046
|
}
|
|
5217
|
-
return composeHighlightedHtml(lines,
|
|
6047
|
+
return composeHighlightedHtml(lines, composedPreAttrs, composedCodeAttrs, shouldAppendTerminalNewline(lines));
|
|
6048
|
+
}
|
|
6049
|
+
if (!shouldVirtualize && blockHtml) {
|
|
6050
|
+
const hasHighlightedLines = blockHtml.includes('class="line"');
|
|
6051
|
+
if (!hasHighlightedLines && rawFallbackLines.length > 0) {
|
|
6052
|
+
return composeHighlightedHtml(
|
|
6053
|
+
rawFallbackLines,
|
|
6054
|
+
composedPreAttrs,
|
|
6055
|
+
composedCodeAttrs,
|
|
6056
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
6057
|
+
);
|
|
6058
|
+
}
|
|
6059
|
+
return blockHtml;
|
|
5218
6060
|
}
|
|
5219
|
-
const blockHtml = node.block?.payload.highlightedHtml ?? "";
|
|
5220
6061
|
if (blockHtml?.trim().match(/^```[\w-]*\s*$/)) {
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
6062
|
+
if (rawFallbackLines.length > 0) {
|
|
6063
|
+
return composeHighlightedHtml(
|
|
6064
|
+
rawFallbackLines,
|
|
6065
|
+
composedPreAttrs,
|
|
6066
|
+
composedCodeAttrs,
|
|
6067
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
6068
|
+
);
|
|
5224
6069
|
}
|
|
5225
6070
|
}
|
|
6071
|
+
if (!blockHtml && rawFallbackLines.length > 0) {
|
|
6072
|
+
return composeHighlightedHtml(
|
|
6073
|
+
rawFallbackLines,
|
|
6074
|
+
composedPreAttrs,
|
|
6075
|
+
composedCodeAttrs,
|
|
6076
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
6077
|
+
);
|
|
6078
|
+
}
|
|
5226
6079
|
return blockHtml;
|
|
5227
|
-
}, [shouldVirtualize, node.block?.payload.highlightedHtml,
|
|
5228
|
-
const rendered = /* @__PURE__ */ (0,
|
|
6080
|
+
}, [blockIsFinalized, shouldVirtualize, node.block?.payload.highlightedHtml, node.block?.payload.meta, lines, lang, virtualization.window.visibleLines, node.block?.payload.raw]);
|
|
6081
|
+
const rendered = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
5229
6082
|
CodeComponent,
|
|
5230
6083
|
{
|
|
5231
6084
|
html: highlightedHtml,
|
|
@@ -5236,20 +6089,26 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
|
|
|
5236
6089
|
codeAttrs
|
|
5237
6090
|
}
|
|
5238
6091
|
);
|
|
6092
|
+
const effectiveLineCount = import_react12.default.useMemo(() => {
|
|
6093
|
+
if (lines.length > 0) {
|
|
6094
|
+
return lines.length;
|
|
6095
|
+
}
|
|
6096
|
+
return 1;
|
|
6097
|
+
}, [lines.length]);
|
|
5239
6098
|
const codeFrameClass = "not-prose flex flex-col rounded-lg border border-input pt-1 font-mono text-sm";
|
|
5240
6099
|
const codeMetricsAttrs = {
|
|
5241
6100
|
"data-code-block": "true",
|
|
5242
6101
|
"data-block-id": blockId,
|
|
5243
6102
|
"data-code-virtualized": shouldVirtualize ? "true" : "false",
|
|
5244
|
-
"data-code-total-lines": String(
|
|
5245
|
-
"data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines :
|
|
6103
|
+
"data-code-total-lines": String(effectiveLineCount),
|
|
6104
|
+
"data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines : effectiveLineCount),
|
|
5246
6105
|
"data-code-window-size": String(virtualization.config.windowSize)
|
|
5247
6106
|
};
|
|
5248
6107
|
const codeView = shouldVirtualize ? (() => {
|
|
5249
6108
|
const { containerRef, window: window2, handleScroll, lineHeight } = virtualization;
|
|
5250
6109
|
const spacerTop = window2.startIndex * lineHeight;
|
|
5251
6110
|
const spacerBottom = (window2.totalLines - window2.endIndex) * lineHeight;
|
|
5252
|
-
return /* @__PURE__ */ (0,
|
|
6111
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
5253
6112
|
"div",
|
|
5254
6113
|
{
|
|
5255
6114
|
ref: containerRef,
|
|
@@ -5257,13 +6116,13 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
|
|
|
5257
6116
|
style: { overflowY: "auto", overflowX: "hidden", maxHeight: "600px" },
|
|
5258
6117
|
onScroll: handleScroll,
|
|
5259
6118
|
children: [
|
|
5260
|
-
/* @__PURE__ */ (0,
|
|
6119
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { height: spacerTop }, "aria-hidden": "true" }),
|
|
5261
6120
|
rendered,
|
|
5262
|
-
/* @__PURE__ */ (0,
|
|
6121
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { height: spacerBottom }, "aria-hidden": "true" })
|
|
5263
6122
|
]
|
|
5264
6123
|
}
|
|
5265
6124
|
) });
|
|
5266
|
-
})() : /* @__PURE__ */ (0,
|
|
6125
|
+
})() : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: rendered });
|
|
5267
6126
|
const blockComponentMap = registry.getBlockComponentMap();
|
|
5268
6127
|
const MermaidComponent = Object.prototype.hasOwnProperty.call(blockComponentMap, "mermaid") ? blockComponentMap.mermaid : null;
|
|
5269
6128
|
if ((lang ?? "").toLowerCase() === "mermaid" && MermaidComponent) {
|
|
@@ -5271,14 +6130,14 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
|
|
|
5271
6130
|
const fenced = (0, import_core5.stripCodeFence)(raw);
|
|
5272
6131
|
const code = fenced.hadFence ? fenced.code : raw;
|
|
5273
6132
|
if (deferredConfig) {
|
|
5274
|
-
return /* @__PURE__ */ (0,
|
|
6133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: deferredRef, children: shouldRenderDeferred ? import_react12.default.createElement(MermaidComponent, {
|
|
5275
6134
|
code,
|
|
5276
6135
|
renderCode: codeView,
|
|
5277
6136
|
meta: node.block.payload.meta,
|
|
5278
6137
|
isFinalized: node.block.isFinalized
|
|
5279
6138
|
}) : codeView });
|
|
5280
6139
|
}
|
|
5281
|
-
return
|
|
6140
|
+
return import_react12.default.createElement(MermaidComponent, {
|
|
5282
6141
|
code,
|
|
5283
6142
|
renderCode: codeView,
|
|
5284
6143
|
meta: node.block.payload.meta,
|
|
@@ -5288,21 +6147,152 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
|
|
|
5288
6147
|
return codeView;
|
|
5289
6148
|
});
|
|
5290
6149
|
CodeBlockView.displayName = "CodeBlockView";
|
|
5291
|
-
function composeHighlightedHtml(lines, preAttrs, codeAttrs) {
|
|
6150
|
+
function composeHighlightedHtml(lines, preAttrs, codeAttrs, appendTerminalNewline = false) {
|
|
5292
6151
|
const lineMarkup = lines.map((line) => {
|
|
5293
|
-
const content = line.html ?? escapeHtml3(line.text);
|
|
6152
|
+
const content = line.html ?? renderTokenLineHtml(line.tokens) ?? escapeHtml3(line.text);
|
|
5294
6153
|
const dataLine = Number.isFinite(line.index) ? ` data-line="${line.index + 1}"` : "";
|
|
5295
6154
|
return `<span class="line"${dataLine}>${content}</span>`;
|
|
5296
6155
|
}).join("\n");
|
|
5297
6156
|
const preAttr = attrsToString(preAttrs);
|
|
5298
6157
|
const codeAttr = attrsToString(codeAttrs);
|
|
5299
|
-
return `<pre${preAttr}><code${codeAttr}>${lineMarkup}
|
|
5300
|
-
|
|
6158
|
+
return `<pre${preAttr}><code${codeAttr}>${lineMarkup}${appendTerminalNewline ? "\n" : ""}</code></pre>`;
|
|
6159
|
+
}
|
|
6160
|
+
var TOKEN_FONT_STYLE_ITALIC = 1;
|
|
6161
|
+
var TOKEN_FONT_STYLE_BOLD = 2;
|
|
6162
|
+
var TOKEN_FONT_STYLE_UNDERLINE = 4;
|
|
6163
|
+
var TOKEN_FONT_STYLE_STRIKETHROUGH = 8;
|
|
6164
|
+
function renderTokenLineHtml(tokens) {
|
|
6165
|
+
if (!tokens || !Array.isArray(tokens.spans)) {
|
|
6166
|
+
return null;
|
|
6167
|
+
}
|
|
6168
|
+
return mergeRenderableTokenSpans(tokens.spans).map((span) => renderTokenSpanHtml(span)).join("");
|
|
6169
|
+
}
|
|
6170
|
+
function renderTokenSpanHtml(span) {
|
|
6171
|
+
const dark = span.v?.dark;
|
|
6172
|
+
const light = span.v?.light;
|
|
6173
|
+
const single = span.s;
|
|
6174
|
+
const styles = [];
|
|
6175
|
+
if (dark?.fg) {
|
|
6176
|
+
styles.push(`--shiki-dark:${dark.fg}`);
|
|
6177
|
+
}
|
|
6178
|
+
if (light?.fg) {
|
|
6179
|
+
styles.push(`--shiki-light:${light.fg}`);
|
|
6180
|
+
}
|
|
6181
|
+
if (!light?.fg && !dark?.fg && single?.fg) {
|
|
6182
|
+
styles.push(`color:${single.fg}`);
|
|
6183
|
+
}
|
|
6184
|
+
const fontStyle = light?.fs ?? dark?.fs ?? single?.fs;
|
|
6185
|
+
if (typeof fontStyle === "number" && fontStyle > 0) {
|
|
6186
|
+
if (fontStyle & TOKEN_FONT_STYLE_ITALIC) {
|
|
6187
|
+
styles.push("font-style: italic");
|
|
6188
|
+
}
|
|
6189
|
+
if (fontStyle & TOKEN_FONT_STYLE_BOLD) {
|
|
6190
|
+
styles.push("font-weight: bold");
|
|
6191
|
+
}
|
|
6192
|
+
const decorations = [];
|
|
6193
|
+
if (fontStyle & TOKEN_FONT_STYLE_UNDERLINE) {
|
|
6194
|
+
decorations.push("underline");
|
|
6195
|
+
}
|
|
6196
|
+
if (fontStyle & TOKEN_FONT_STYLE_STRIKETHROUGH) {
|
|
6197
|
+
decorations.push("line-through");
|
|
6198
|
+
}
|
|
6199
|
+
if (decorations.length > 0) {
|
|
6200
|
+
styles.push(`text-decoration: ${decorations.join(" ")}`);
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6203
|
+
const content = escapeHtml3(span.t ?? "");
|
|
6204
|
+
if (styles.length === 0) {
|
|
6205
|
+
return content;
|
|
6206
|
+
}
|
|
6207
|
+
return `<span style="${styles.join(";")}">${content}</span>`;
|
|
6208
|
+
}
|
|
6209
|
+
function mergeRenderableTokenSpans(spans) {
|
|
6210
|
+
if (spans.length <= 1) {
|
|
6211
|
+
return spans.slice();
|
|
6212
|
+
}
|
|
6213
|
+
const merged = [];
|
|
6214
|
+
let pendingWhitespace = "";
|
|
6215
|
+
for (const span of spans) {
|
|
6216
|
+
const text = typeof span.t === "string" ? span.t : "";
|
|
6217
|
+
if (/^[\t ]+$/.test(text)) {
|
|
6218
|
+
pendingWhitespace += text;
|
|
6219
|
+
continue;
|
|
6220
|
+
}
|
|
6221
|
+
const nextSpan = pendingWhitespace ? { ...span, t: `${pendingWhitespace}${text}` } : span;
|
|
6222
|
+
pendingWhitespace = "";
|
|
6223
|
+
const previous = merged[merged.length - 1];
|
|
6224
|
+
if (previous && sameTokenSpanStyle(previous, nextSpan)) {
|
|
6225
|
+
previous.t += nextSpan.t;
|
|
6226
|
+
} else {
|
|
6227
|
+
merged.push({ ...nextSpan });
|
|
6228
|
+
}
|
|
6229
|
+
}
|
|
6230
|
+
if (pendingWhitespace) {
|
|
6231
|
+
const previous = merged[merged.length - 1];
|
|
6232
|
+
if (previous) {
|
|
6233
|
+
previous.t += pendingWhitespace;
|
|
6234
|
+
} else {
|
|
6235
|
+
merged.push({ t: pendingWhitespace });
|
|
6236
|
+
}
|
|
6237
|
+
}
|
|
6238
|
+
return merged;
|
|
6239
|
+
}
|
|
6240
|
+
function sameTokenSpanStyle(a, b) {
|
|
6241
|
+
const variantKeys = /* @__PURE__ */ new Set([
|
|
6242
|
+
...Object.keys(a.v ?? {}),
|
|
6243
|
+
...Object.keys(b.v ?? {})
|
|
6244
|
+
]);
|
|
6245
|
+
for (const key of variantKeys) {
|
|
6246
|
+
const aStyle = a.v?.[key];
|
|
6247
|
+
const bStyle = b.v?.[key];
|
|
6248
|
+
if ((aStyle?.fg ?? null) !== (bStyle?.fg ?? null)) return false;
|
|
6249
|
+
if ((aStyle?.bg ?? null) !== (bStyle?.bg ?? null)) return false;
|
|
6250
|
+
if ((aStyle?.fs ?? null) !== (bStyle?.fs ?? null)) return false;
|
|
6251
|
+
}
|
|
6252
|
+
if ((a.s?.fg ?? null) !== (b.s?.fg ?? null)) return false;
|
|
6253
|
+
if ((a.s?.bg ?? null) !== (b.s?.bg ?? null)) return false;
|
|
6254
|
+
if ((a.s?.fs ?? null) !== (b.s?.fs ?? null)) return false;
|
|
6255
|
+
return true;
|
|
6256
|
+
}
|
|
6257
|
+
function resolveCodeSourceText(raw, metaCode) {
|
|
6258
|
+
if (metaCode !== null) {
|
|
6259
|
+
return metaCode.replace(/\r\n?/g, "\n");
|
|
6260
|
+
}
|
|
6261
|
+
if (!raw) return "";
|
|
6262
|
+
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
6263
|
+
const fenced = (0, import_core5.stripCodeFence)(normalized);
|
|
6264
|
+
return fenced.hadFence ? fenced.code : normalized;
|
|
5301
6265
|
}
|
|
5302
6266
|
function attrsToString(attrs) {
|
|
5303
6267
|
if (!attrs) return "";
|
|
5304
6268
|
return Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttribute(value)}"`).join("");
|
|
5305
6269
|
}
|
|
6270
|
+
function buildCodeFallbackLines(raw) {
|
|
6271
|
+
const normalized = normalizeCodeFallbackRaw(raw);
|
|
6272
|
+
if (normalized.length === 0) {
|
|
6273
|
+
if (/^\s*```[^\n]*\n?\s*$/.test(raw)) {
|
|
6274
|
+
return [{ id: "temp-0", index: 0, text: "", html: null }];
|
|
6275
|
+
}
|
|
6276
|
+
return [];
|
|
6277
|
+
}
|
|
6278
|
+
return normalized.split("\n").map((line, index) => ({
|
|
6279
|
+
id: `temp-${index}`,
|
|
6280
|
+
index,
|
|
6281
|
+
text: line,
|
|
6282
|
+
html: null
|
|
6283
|
+
}));
|
|
6284
|
+
}
|
|
6285
|
+
function normalizeCodeFallbackRaw(raw) {
|
|
6286
|
+
if (!raw) return "";
|
|
6287
|
+
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
6288
|
+
const fenced = (0, import_core5.stripCodeFence)(normalized);
|
|
6289
|
+
if (!fenced.hadFence) {
|
|
6290
|
+
return normalized.replace(/\n+$/, "");
|
|
6291
|
+
}
|
|
6292
|
+
let code = fenced.code;
|
|
6293
|
+
code = code.replace(/\n+$/, "");
|
|
6294
|
+
return code;
|
|
6295
|
+
}
|
|
5306
6296
|
function escapeHtml3(value) {
|
|
5307
6297
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5308
6298
|
}
|
|
@@ -5311,22 +6301,22 @@ function escapeAttribute(value) {
|
|
|
5311
6301
|
}
|
|
5312
6302
|
|
|
5313
6303
|
// src/renderer/blocks-renderer.tsx
|
|
5314
|
-
var MarkdownBlocksRenderer =
|
|
6304
|
+
var MarkdownBlocksRenderer = import_react13.default.memo(({ blocks, componentRegistry, className = "markdown-renderer", style, store }) => {
|
|
5315
6305
|
if (store) {
|
|
5316
|
-
return
|
|
6306
|
+
return import_react13.default.createElement(
|
|
5317
6307
|
"div",
|
|
5318
6308
|
{
|
|
5319
6309
|
className,
|
|
5320
6310
|
style: { contain: "content", ...style ?? {} }
|
|
5321
6311
|
// CSS containment for performance
|
|
5322
6312
|
},
|
|
5323
|
-
|
|
6313
|
+
import_react13.default.createElement(StoreBackedBlocks, { store, componentRegistry })
|
|
5324
6314
|
);
|
|
5325
6315
|
}
|
|
5326
|
-
const renderedBlocks = (0,
|
|
6316
|
+
const renderedBlocks = (0, import_react13.useMemo)(() => {
|
|
5327
6317
|
return blocks.map((block) => {
|
|
5328
6318
|
const key = (0, import_core6.getBlockKey)(block);
|
|
5329
|
-
return
|
|
6319
|
+
return import_react13.default.createElement(BlockRenderer, {
|
|
5330
6320
|
key,
|
|
5331
6321
|
block,
|
|
5332
6322
|
componentRegistry,
|
|
@@ -5334,7 +6324,7 @@ var MarkdownBlocksRenderer = import_react12.default.memo(({ blocks, componentReg
|
|
|
5334
6324
|
});
|
|
5335
6325
|
});
|
|
5336
6326
|
}, [blocks, componentRegistry]);
|
|
5337
|
-
return
|
|
6327
|
+
return import_react13.default.createElement(
|
|
5338
6328
|
"div",
|
|
5339
6329
|
{
|
|
5340
6330
|
className,
|
|
@@ -5344,23 +6334,23 @@ var MarkdownBlocksRenderer = import_react12.default.memo(({ blocks, componentReg
|
|
|
5344
6334
|
renderedBlocks
|
|
5345
6335
|
);
|
|
5346
6336
|
});
|
|
5347
|
-
var StoreBackedBlocks =
|
|
6337
|
+
var StoreBackedBlocks = import_react13.default.memo(
|
|
5348
6338
|
({ store, componentRegistry }) => {
|
|
5349
6339
|
const blockIds = useRendererChildren(store, import_core6.PATCH_ROOT_ID);
|
|
5350
|
-
return
|
|
5351
|
-
|
|
6340
|
+
return import_react13.default.createElement(
|
|
6341
|
+
import_react13.default.Fragment,
|
|
5352
6342
|
null,
|
|
5353
|
-
blockIds.map((blockId) =>
|
|
6343
|
+
blockIds.map((blockId) => import_react13.default.createElement(BlockNodeRenderer, { key: blockId, store, blockId, registry: componentRegistry }))
|
|
5354
6344
|
);
|
|
5355
6345
|
}
|
|
5356
6346
|
);
|
|
5357
6347
|
StoreBackedBlocks.displayName = "StoreBackedBlocks";
|
|
5358
|
-
var BlockRenderer =
|
|
5359
|
-
const element = (0,
|
|
6348
|
+
var BlockRenderer = import_react13.default.memo(({ block, componentRegistry, isFinalized }) => {
|
|
6349
|
+
const element = (0, import_react13.useMemo)(() => {
|
|
5360
6350
|
return componentRegistry.renderBlock(block);
|
|
5361
6351
|
}, [block, componentRegistry]);
|
|
5362
6352
|
const className = `markdown-block markdown-block-${block.type} ${isFinalized ? "finalized" : "dirty"}`;
|
|
5363
|
-
return
|
|
6353
|
+
return import_react13.default.cloneElement(element, {
|
|
5364
6354
|
className: `${element.props.className || ""} ${className}`.trim(),
|
|
5365
6355
|
"data-block-id": block.id,
|
|
5366
6356
|
"data-finalized": isFinalized
|
|
@@ -5426,7 +6416,9 @@ var MarkdownRenderer = class {
|
|
|
5426
6416
|
lowPriorityFrameBudgetMs: this.config.performance?.lowPriorityFrameBudgetMs,
|
|
5427
6417
|
urgentQueueThreshold: this.config.performance?.urgentQueueThreshold,
|
|
5428
6418
|
batch: this.config.performance?.batch,
|
|
5429
|
-
historyLimit: this.config.performance?.historyLimit
|
|
6419
|
+
historyLimit: this.config.performance?.historyLimit,
|
|
6420
|
+
startupMicrotaskFlushes: this.config.performance?.startupMicrotaskFlushes,
|
|
6421
|
+
adaptiveBudgeting: this.config.performance?.adaptiveBudgeting
|
|
5430
6422
|
}
|
|
5431
6423
|
});
|
|
5432
6424
|
}
|
|
@@ -5620,18 +6612,8 @@ var MarkdownRenderer = class {
|
|
|
5620
6612
|
const receivedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
5621
6613
|
const batches = (0, import_patch_batching.splitPatchBatch)(message.patches);
|
|
5622
6614
|
batches.forEach((batch, index) => {
|
|
5623
|
-
const
|
|
5624
|
-
|
|
5625
|
-
case "insertChild":
|
|
5626
|
-
case "replaceChild":
|
|
5627
|
-
case "deleteChild":
|
|
5628
|
-
case "reorder":
|
|
5629
|
-
return true;
|
|
5630
|
-
default:
|
|
5631
|
-
return false;
|
|
5632
|
-
}
|
|
5633
|
-
});
|
|
5634
|
-
const priority = hasStructural ? "high" : batch.some(import_patch_batching.isHeavyPatch) ? "low" : "high";
|
|
6615
|
+
const hasSemantic = batch.some((patch) => (0, import_patch_batching.getPatchKind)(patch) === "semantic");
|
|
6616
|
+
const priority = hasSemantic ? "high" : batch.some(import_patch_batching.isHeavyPatch) ? "low" : "high";
|
|
5635
6617
|
this.patchScheduler.enqueue({
|
|
5636
6618
|
patches: batch,
|
|
5637
6619
|
meta: {
|
|
@@ -5768,10 +6750,10 @@ var MarkdownRenderer = class {
|
|
|
5768
6750
|
}
|
|
5769
6751
|
};
|
|
5770
6752
|
function useMarkdownRenderer(config = {}) {
|
|
5771
|
-
const [renderer] = (0,
|
|
5772
|
-
const [blocks, setBlocks] = (0,
|
|
5773
|
-
const workerRef = (0,
|
|
5774
|
-
(0,
|
|
6753
|
+
const [renderer] = (0, import_react14.useState)(() => new MarkdownRenderer(config));
|
|
6754
|
+
const [blocks, setBlocks] = (0, import_react14.useState)([]);
|
|
6755
|
+
const workerRef = (0, import_react14.useRef)(null);
|
|
6756
|
+
(0, import_react14.useEffect)(() => {
|
|
5775
6757
|
if (!workerRef.current) {
|
|
5776
6758
|
const fallbackFactory = () => new Worker("/workers/markdown-worker.js", { type: "module", name: "markdown-v2" });
|
|
5777
6759
|
const worker = (0, import_worker.createDefaultWorker)() ?? fallbackFactory();
|
|
@@ -5786,41 +6768,41 @@ function useMarkdownRenderer(config = {}) {
|
|
|
5786
6768
|
}
|
|
5787
6769
|
};
|
|
5788
6770
|
}, [renderer]);
|
|
5789
|
-
(0,
|
|
6771
|
+
(0, import_react14.useEffect)(() => {
|
|
5790
6772
|
const unsubscribe = renderer.onUpdate(setBlocks);
|
|
5791
6773
|
return unsubscribe;
|
|
5792
6774
|
}, [renderer]);
|
|
5793
6775
|
const mdxComponents = config.mdx?.components;
|
|
5794
|
-
(0,
|
|
6776
|
+
(0, import_react14.useEffect)(() => {
|
|
5795
6777
|
if (mdxComponents && Object.keys(mdxComponents).length > 0) {
|
|
5796
6778
|
renderer.setMdxComponents(mdxComponents);
|
|
5797
6779
|
}
|
|
5798
6780
|
}, [renderer, mdxComponents]);
|
|
5799
|
-
const append = (0,
|
|
6781
|
+
const append = (0, import_react14.useCallback)(
|
|
5800
6782
|
(text) => {
|
|
5801
6783
|
renderer.append(text);
|
|
5802
6784
|
},
|
|
5803
6785
|
[renderer]
|
|
5804
6786
|
);
|
|
5805
|
-
const renderStatic = (0,
|
|
6787
|
+
const renderStatic = (0, import_react14.useCallback)(
|
|
5806
6788
|
(text) => {
|
|
5807
6789
|
return renderer.renderStatic(text);
|
|
5808
6790
|
},
|
|
5809
6791
|
[renderer]
|
|
5810
6792
|
);
|
|
5811
|
-
const setBlockComponents = (0,
|
|
6793
|
+
const setBlockComponents = (0, import_react14.useCallback)(
|
|
5812
6794
|
(components) => {
|
|
5813
6795
|
renderer.setBlockComponents(components);
|
|
5814
6796
|
},
|
|
5815
6797
|
[renderer]
|
|
5816
6798
|
);
|
|
5817
|
-
const setInlineComponents = (0,
|
|
6799
|
+
const setInlineComponents = (0, import_react14.useCallback)(
|
|
5818
6800
|
(components) => {
|
|
5819
6801
|
renderer.setInlineComponents(components);
|
|
5820
6802
|
},
|
|
5821
6803
|
[renderer]
|
|
5822
6804
|
);
|
|
5823
|
-
const setMdxComponents = (0,
|
|
6805
|
+
const setMdxComponents = (0, import_react14.useCallback)(
|
|
5824
6806
|
(components) => {
|
|
5825
6807
|
renderer.setMdxComponents(components);
|
|
5826
6808
|
},
|
|
@@ -5839,24 +6821,24 @@ function useMarkdownRenderer(config = {}) {
|
|
|
5839
6821
|
}
|
|
5840
6822
|
var MarkdownRenderer2 = ({ config, className, onBlocksChange, children }) => {
|
|
5841
6823
|
const api = useMarkdownRenderer(config);
|
|
5842
|
-
const highlightRequester = (0,
|
|
6824
|
+
const highlightRequester = (0, import_react14.useCallback)(
|
|
5843
6825
|
(request) => {
|
|
5844
6826
|
api.renderer.requestCodeHighlightRange(request);
|
|
5845
6827
|
},
|
|
5846
6828
|
[api.renderer]
|
|
5847
6829
|
);
|
|
5848
|
-
(0,
|
|
6830
|
+
(0, import_react14.useEffect)(() => {
|
|
5849
6831
|
if (onBlocksChange) {
|
|
5850
6832
|
onBlocksChange(api.blocks);
|
|
5851
6833
|
}
|
|
5852
6834
|
}, [api.blocks, onBlocksChange]);
|
|
5853
6835
|
if (children) {
|
|
5854
|
-
return
|
|
6836
|
+
return import_react14.default.createElement(import_react14.default.Fragment, {}, children(api));
|
|
5855
6837
|
}
|
|
5856
|
-
return
|
|
6838
|
+
return import_react14.default.createElement(
|
|
5857
6839
|
CodeHighlightRequestContext.Provider,
|
|
5858
6840
|
{ value: highlightRequester },
|
|
5859
|
-
|
|
6841
|
+
import_react14.default.createElement(MarkdownBlocksRenderer, {
|
|
5860
6842
|
blocks: api.blocks,
|
|
5861
6843
|
componentRegistry: api.renderer.getComponentRegistry(),
|
|
5862
6844
|
className,
|
|
@@ -5869,9 +6851,9 @@ function createMarkdownRenderer(config = {}) {
|
|
|
5869
6851
|
}
|
|
5870
6852
|
|
|
5871
6853
|
// src/streaming-markdown.tsx
|
|
5872
|
-
var
|
|
6854
|
+
var import_react15 = __toESM(require("react"), 1);
|
|
5873
6855
|
var import_worker2 = require("@stream-mdx/worker");
|
|
5874
|
-
var
|
|
6856
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
5875
6857
|
var EMPTY_BLOCKS = [];
|
|
5876
6858
|
function createConfigSignature(input) {
|
|
5877
6859
|
return JSON.stringify(input);
|
|
@@ -5883,13 +6865,13 @@ var MdxCoordinatorBridge = ({ store, mode }) => {
|
|
|
5883
6865
|
};
|
|
5884
6866
|
var MdxPrefetchBridge = ({ store }) => {
|
|
5885
6867
|
const blocks = useRendererBlocks(store);
|
|
5886
|
-
const prefetchedRuntimeRef = (0,
|
|
5887
|
-
const trackedIdsRef = (0,
|
|
5888
|
-
const queueRef = (0,
|
|
6868
|
+
const prefetchedRuntimeRef = (0, import_react15.useRef)(false);
|
|
6869
|
+
const trackedIdsRef = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
|
|
6870
|
+
const queueRef = (0, import_react15.useRef)(null);
|
|
5889
6871
|
if (!queueRef.current) {
|
|
5890
6872
|
queueRef.current = new MdxPrefetchQueue();
|
|
5891
6873
|
}
|
|
5892
|
-
(0,
|
|
6874
|
+
(0, import_react15.useEffect)(() => {
|
|
5893
6875
|
const queue = queueRef.current;
|
|
5894
6876
|
if (!queue) return;
|
|
5895
6877
|
const nextIds = /* @__PURE__ */ new Map();
|
|
@@ -5927,7 +6909,7 @@ var MdxPrefetchBridge = ({ store }) => {
|
|
|
5927
6909
|
}
|
|
5928
6910
|
trackedIdsRef.current = new Set(nextIds.keys());
|
|
5929
6911
|
}, [blocks]);
|
|
5930
|
-
(0,
|
|
6912
|
+
(0, import_react15.useEffect)(() => {
|
|
5931
6913
|
return () => {
|
|
5932
6914
|
queueRef.current?.cancelAll();
|
|
5933
6915
|
};
|
|
@@ -6001,7 +6983,7 @@ function StreamingMarkdownComponent({
|
|
|
6001
6983
|
const effectiveScheduling = scheduling ?? DEFAULT_SCHEDULING;
|
|
6002
6984
|
const adaptiveSwitchEnabled = effectiveScheduling.batch === "microtask" && (scheduling?.adaptiveSwitch ?? true);
|
|
6003
6985
|
const adaptiveQueueThreshold = scheduling?.adaptiveQueueThreshold ?? (typeof effectiveScheduling.maxBatchesPerFlush === "number" ? effectiveScheduling.maxBatchesPerFlush : DEFAULT_ADAPTIVE_QUEUE_THRESHOLD);
|
|
6004
|
-
const configSignature = (0,
|
|
6986
|
+
const configSignature = (0, import_react15.useMemo)(
|
|
6005
6987
|
() => createConfigSignature({
|
|
6006
6988
|
features,
|
|
6007
6989
|
prewarm: prewarmLangs,
|
|
@@ -6012,16 +6994,16 @@ function StreamingMarkdownComponent({
|
|
|
6012
6994
|
}),
|
|
6013
6995
|
[features, prewarmLangs, effectiveScheduling, mdxCompileMode, mdxComponents, mdxHydration]
|
|
6014
6996
|
);
|
|
6015
|
-
const mdxHydrationController = (0,
|
|
6016
|
-
const mdxHydrationContextValue = (0,
|
|
6997
|
+
const mdxHydrationController = (0, import_react15.useMemo)(() => createMdxHydrationController(mdxHydration), [mdxHydration]);
|
|
6998
|
+
const mdxHydrationContextValue = (0, import_react15.useMemo)(
|
|
6017
6999
|
() => ({
|
|
6018
7000
|
controller: mdxHydrationController,
|
|
6019
7001
|
options: mdxHydration
|
|
6020
7002
|
}),
|
|
6021
7003
|
[mdxHydrationController, mdxHydration]
|
|
6022
7004
|
);
|
|
6023
|
-
const rendererRef = (0,
|
|
6024
|
-
const [session, setSession] = (0,
|
|
7005
|
+
const rendererRef = (0, import_react15.useRef)();
|
|
7006
|
+
const [session, setSession] = (0, import_react15.useState)(0);
|
|
6025
7007
|
const rendererKey = `${configSignature}:${session}`;
|
|
6026
7008
|
const historyLimit = effectiveScheduling.historyLimit ?? DEFAULT_HISTORY_LIMIT;
|
|
6027
7009
|
if (!rendererRef.current || rendererRef.current.signature !== rendererKey) {
|
|
@@ -6040,7 +7022,9 @@ function StreamingMarkdownComponent({
|
|
|
6040
7022
|
lowPriorityFrameBudgetMs: effectiveScheduling.lowPriorityFrameBudgetMs,
|
|
6041
7023
|
urgentQueueThreshold: effectiveScheduling.urgentQueueThreshold,
|
|
6042
7024
|
batch: effectiveScheduling.batch,
|
|
6043
|
-
historyLimit
|
|
7025
|
+
historyLimit,
|
|
7026
|
+
startupMicrotaskFlushes: effectiveScheduling.startupMicrotaskFlushes,
|
|
7027
|
+
adaptiveBudgeting: effectiveScheduling.adaptiveBudgeting
|
|
6044
7028
|
},
|
|
6045
7029
|
mdx: mdxConfig
|
|
6046
7030
|
};
|
|
@@ -6050,7 +7034,7 @@ function StreamingMarkdownComponent({
|
|
|
6050
7034
|
};
|
|
6051
7035
|
}
|
|
6052
7036
|
const renderer = rendererRef.current.renderer;
|
|
6053
|
-
const highlightRequester = (0,
|
|
7037
|
+
const highlightRequester = (0, import_react15.useCallback)(
|
|
6054
7038
|
(request) => {
|
|
6055
7039
|
renderer.requestCodeHighlightRange(request);
|
|
6056
7040
|
},
|
|
@@ -6058,15 +7042,15 @@ function StreamingMarkdownComponent({
|
|
|
6058
7042
|
);
|
|
6059
7043
|
const store = renderer.getStore();
|
|
6060
7044
|
const blocks = useRendererBlocks(store);
|
|
6061
|
-
const adaptiveSwitchedRef = (0,
|
|
6062
|
-
const adaptiveFirstFlushRef = (0,
|
|
7045
|
+
const adaptiveSwitchedRef = (0, import_react15.useRef)(false);
|
|
7046
|
+
const adaptiveFirstFlushRef = (0, import_react15.useRef)(false);
|
|
6063
7047
|
const mdxMode = mdxCompileMode ?? "server";
|
|
6064
|
-
const [workerReady, setWorkerReady] = (0,
|
|
6065
|
-
const workerReadyRef = (0,
|
|
6066
|
-
const [streamStatus, setStreamStatus] = (0,
|
|
6067
|
-
const lastMetricsRef = (0,
|
|
6068
|
-
const patchHistoryRef = (0,
|
|
6069
|
-
(0,
|
|
7048
|
+
const [workerReady, setWorkerReady] = (0, import_react15.useState)(false);
|
|
7049
|
+
const workerReadyRef = (0, import_react15.useRef)(false);
|
|
7050
|
+
const [streamStatus, setStreamStatus] = (0, import_react15.useState)("idle");
|
|
7051
|
+
const lastMetricsRef = (0, import_react15.useRef)(null);
|
|
7052
|
+
const patchHistoryRef = (0, import_react15.useRef)([]);
|
|
7053
|
+
(0, import_react15.useEffect)(() => {
|
|
6070
7054
|
if (typeof window === "undefined" || typeof PerformanceObserver === "undefined") {
|
|
6071
7055
|
return void 0;
|
|
6072
7056
|
}
|
|
@@ -6090,27 +7074,27 @@ function StreamingMarkdownComponent({
|
|
|
6090
7074
|
observer?.disconnect();
|
|
6091
7075
|
};
|
|
6092
7076
|
}, []);
|
|
6093
|
-
const previousTextRef = (0,
|
|
6094
|
-
(0,
|
|
7077
|
+
const previousTextRef = (0, import_react15.useRef)();
|
|
7078
|
+
(0, import_react15.useEffect)(() => {
|
|
6095
7079
|
if (text !== void 0 && text !== previousTextRef.current) {
|
|
6096
7080
|
previousTextRef.current = text;
|
|
6097
7081
|
setSession((prev) => prev + 1);
|
|
6098
7082
|
}
|
|
6099
7083
|
}, [text]);
|
|
6100
|
-
const previousStreamRef = (0,
|
|
6101
|
-
(0,
|
|
7084
|
+
const previousStreamRef = (0, import_react15.useRef)();
|
|
7085
|
+
(0, import_react15.useEffect)(() => {
|
|
6102
7086
|
if (stream && stream !== previousStreamRef.current) {
|
|
6103
7087
|
previousStreamRef.current = stream;
|
|
6104
7088
|
setSession((prev) => prev + 1);
|
|
6105
7089
|
}
|
|
6106
7090
|
}, [stream]);
|
|
6107
7091
|
const linkSafetyEnabled = Boolean(linkSafety?.enabled);
|
|
6108
|
-
const [linkModalState, setLinkModalState] = (0,
|
|
7092
|
+
const [linkModalState, setLinkModalState] = (0, import_react15.useState)({
|
|
6109
7093
|
url: "",
|
|
6110
7094
|
isOpen: false,
|
|
6111
7095
|
isChecking: false
|
|
6112
7096
|
});
|
|
6113
|
-
const openLink = (0,
|
|
7097
|
+
const openLink = (0, import_react15.useMemo)(() => {
|
|
6114
7098
|
return (url) => {
|
|
6115
7099
|
if (typeof window === "undefined") return;
|
|
6116
7100
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
@@ -6120,7 +7104,7 @@ function StreamingMarkdownComponent({
|
|
|
6120
7104
|
}
|
|
6121
7105
|
};
|
|
6122
7106
|
}, []);
|
|
6123
|
-
const handleLinkClick = (0,
|
|
7107
|
+
const handleLinkClick = (0, import_react15.useMemo)(() => {
|
|
6124
7108
|
return async (url) => {
|
|
6125
7109
|
if (!linkSafetyEnabled) {
|
|
6126
7110
|
openLink(url);
|
|
@@ -6142,10 +7126,10 @@ function StreamingMarkdownComponent({
|
|
|
6142
7126
|
setLinkModalState({ url, isOpen: true, isChecking: false });
|
|
6143
7127
|
};
|
|
6144
7128
|
}, [linkSafety, linkSafetyEnabled, openLink]);
|
|
6145
|
-
const handleLinkClose = (0,
|
|
7129
|
+
const handleLinkClose = (0, import_react15.useMemo)(() => {
|
|
6146
7130
|
return () => setLinkModalState((prev) => ({ ...prev, isOpen: false }));
|
|
6147
7131
|
}, []);
|
|
6148
|
-
const handleLinkConfirm = (0,
|
|
7132
|
+
const handleLinkConfirm = (0, import_react15.useMemo)(() => {
|
|
6149
7133
|
return () => {
|
|
6150
7134
|
const url = linkModalState.url;
|
|
6151
7135
|
setLinkModalState((prev) => ({ ...prev, isOpen: false }));
|
|
@@ -6154,7 +7138,7 @@ function StreamingMarkdownComponent({
|
|
|
6154
7138
|
}
|
|
6155
7139
|
};
|
|
6156
7140
|
}, [linkModalState.url, openLink]);
|
|
6157
|
-
const handleLinkCopy = (0,
|
|
7141
|
+
const handleLinkCopy = (0, import_react15.useMemo)(() => {
|
|
6158
7142
|
return () => {
|
|
6159
7143
|
const url = linkModalState.url;
|
|
6160
7144
|
if (!url || typeof navigator === "undefined") return;
|
|
@@ -6175,7 +7159,7 @@ function StreamingMarkdownComponent({
|
|
|
6175
7159
|
}
|
|
6176
7160
|
};
|
|
6177
7161
|
}, [linkModalState.url]);
|
|
6178
|
-
const resolvedInlineComponents = (0,
|
|
7162
|
+
const resolvedInlineComponents = (0, import_react15.useMemo)(() => {
|
|
6179
7163
|
if (!linkSafetyEnabled) {
|
|
6180
7164
|
return inlineComponents;
|
|
6181
7165
|
}
|
|
@@ -6183,9 +7167,9 @@ function StreamingMarkdownComponent({
|
|
|
6183
7167
|
const url = typeof href === "string" ? href : "";
|
|
6184
7168
|
const isIncomplete = url.startsWith("streamdown:incomplete-link") || url.startsWith("stream-mdx:incomplete-link");
|
|
6185
7169
|
if (!url || isIncomplete) {
|
|
6186
|
-
return
|
|
7170
|
+
return import_react15.default.createElement("span", { className: "markdown-link", title }, children);
|
|
6187
7171
|
}
|
|
6188
|
-
return
|
|
7172
|
+
return import_react15.default.createElement(
|
|
6189
7173
|
"button",
|
|
6190
7174
|
{
|
|
6191
7175
|
type: "button",
|
|
@@ -6202,14 +7186,14 @@ function StreamingMarkdownComponent({
|
|
|
6202
7186
|
};
|
|
6203
7187
|
return { ...inlineComponents ?? {}, link: LinkComponent };
|
|
6204
7188
|
}, [handleLinkClick, inlineComponents, linkSafetyEnabled]);
|
|
6205
|
-
(0,
|
|
7189
|
+
(0, import_react15.useEffect)(() => {
|
|
6206
7190
|
setStreamStatus("idle");
|
|
6207
7191
|
}, [session]);
|
|
6208
|
-
(0,
|
|
7192
|
+
(0, import_react15.useEffect)(() => {
|
|
6209
7193
|
adaptiveSwitchedRef.current = false;
|
|
6210
7194
|
adaptiveFirstFlushRef.current = false;
|
|
6211
7195
|
}, [renderer]);
|
|
6212
|
-
(0,
|
|
7196
|
+
(0, import_react15.useEffect)(() => {
|
|
6213
7197
|
if (!adaptiveSwitchEnabled) return void 0;
|
|
6214
7198
|
const unsubscribe = renderer.addFlushListener((result) => {
|
|
6215
7199
|
if (adaptiveSwitchedRef.current) return;
|
|
@@ -6231,12 +7215,12 @@ function StreamingMarkdownComponent({
|
|
|
6231
7215
|
});
|
|
6232
7216
|
return unsubscribe;
|
|
6233
7217
|
}, [renderer, adaptiveSwitchEnabled, adaptiveQueueThreshold]);
|
|
6234
|
-
(0,
|
|
7218
|
+
(0, import_react15.useEffect)(() => {
|
|
6235
7219
|
lastMetricsRef.current = null;
|
|
6236
7220
|
patchHistoryRef.current = [];
|
|
6237
7221
|
void renderer;
|
|
6238
7222
|
}, [renderer]);
|
|
6239
|
-
(0,
|
|
7223
|
+
(0, import_react15.useEffect)(() => {
|
|
6240
7224
|
if (components) {
|
|
6241
7225
|
renderer.setBlockComponents(components);
|
|
6242
7226
|
}
|
|
@@ -6255,7 +7239,7 @@ function StreamingMarkdownComponent({
|
|
|
6255
7239
|
renderer.getComponentRegistry().setHtmlElements(htmlElements);
|
|
6256
7240
|
}
|
|
6257
7241
|
}, [renderer, components, mdxComponents, inlineComponents, resolvedInlineComponents, tableElements, htmlElements]);
|
|
6258
|
-
(0,
|
|
7242
|
+
(0, import_react15.useEffect)(() => {
|
|
6259
7243
|
const removeListener = renderer.addFlushListener((result) => {
|
|
6260
7244
|
const metrics = summarizeFlush(result);
|
|
6261
7245
|
lastMetricsRef.current = metrics;
|
|
@@ -6273,12 +7257,12 @@ function StreamingMarkdownComponent({
|
|
|
6273
7257
|
});
|
|
6274
7258
|
return removeListener;
|
|
6275
7259
|
}, [renderer, historyLimit, onMetrics]);
|
|
6276
|
-
(0,
|
|
7260
|
+
(0, import_react15.useEffect)(() => {
|
|
6277
7261
|
if (patchHistoryRef.current.length > historyLimit) {
|
|
6278
7262
|
patchHistoryRef.current.splice(0, patchHistoryRef.current.length - historyLimit);
|
|
6279
7263
|
}
|
|
6280
7264
|
}, [historyLimit]);
|
|
6281
|
-
(0,
|
|
7265
|
+
(0, import_react15.useEffect)(() => {
|
|
6282
7266
|
const restartToken = session;
|
|
6283
7267
|
void restartToken;
|
|
6284
7268
|
if (process.env.NODE_ENV !== "production" && DEBUG_WORKER) {
|
|
@@ -6334,7 +7318,7 @@ function StreamingMarkdownComponent({
|
|
|
6334
7318
|
}
|
|
6335
7319
|
};
|
|
6336
7320
|
}, [renderer, workerSource, session, onError, managedWorker]);
|
|
6337
|
-
(0,
|
|
7321
|
+
(0, import_react15.useEffect)(() => {
|
|
6338
7322
|
const restartToken = session;
|
|
6339
7323
|
void restartToken;
|
|
6340
7324
|
let cancelled = false;
|
|
@@ -6397,7 +7381,7 @@ function StreamingMarkdownComponent({
|
|
|
6397
7381
|
cancelled = true;
|
|
6398
7382
|
};
|
|
6399
7383
|
}, [renderer, text, stream, workerReady, session, onError, managedWorker]);
|
|
6400
|
-
(0,
|
|
7384
|
+
(0, import_react15.useImperativeHandle)(
|
|
6401
7385
|
ref,
|
|
6402
7386
|
() => ({
|
|
6403
7387
|
pause() {
|
|
@@ -6451,8 +7435,8 @@ function StreamingMarkdownComponent({
|
|
|
6451
7435
|
}),
|
|
6452
7436
|
[renderer, store]
|
|
6453
7437
|
);
|
|
6454
|
-
const hasActiveBlocks = (0,
|
|
6455
|
-
const caretValue = (0,
|
|
7438
|
+
const hasActiveBlocks = (0, import_react15.useMemo)(() => blocks.some((block) => !block.isFinalized), [blocks]);
|
|
7439
|
+
const caretValue = (0, import_react15.useMemo)(() => {
|
|
6456
7440
|
if (!caret) {
|
|
6457
7441
|
return null;
|
|
6458
7442
|
}
|
|
@@ -6473,7 +7457,7 @@ function StreamingMarkdownComponent({
|
|
|
6473
7457
|
...style ?? {},
|
|
6474
7458
|
["--stream-mdx-caret"]: JSON.stringify(caretValue)
|
|
6475
7459
|
} : style;
|
|
6476
|
-
const deferredConfig = (0,
|
|
7460
|
+
const deferredConfig = (0, import_react15.useMemo)(() => {
|
|
6477
7461
|
if (!deferHeavyBlocks) {
|
|
6478
7462
|
return null;
|
|
6479
7463
|
}
|
|
@@ -6490,10 +7474,10 @@ function StreamingMarkdownComponent({
|
|
|
6490
7474
|
onConfirm: handleLinkConfirm,
|
|
6491
7475
|
onCopy: handleLinkCopy
|
|
6492
7476
|
}) : null;
|
|
6493
|
-
return /* @__PURE__ */ (0,
|
|
6494
|
-
/* @__PURE__ */ (0,
|
|
6495
|
-
mdxMode === "server" ? /* @__PURE__ */ (0,
|
|
6496
|
-
/* @__PURE__ */ (0,
|
|
7477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MdxHydrationContext.Provider, { value: mdxHydrationContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(DeferredRenderContext.Provider, { value: deferredConfig, children: [
|
|
7478
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MdxPrefetchBridge, { store }),
|
|
7479
|
+
mdxMode === "server" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MdxCoordinatorBridge, { store, mode: mdxMode }) : null,
|
|
7480
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CodeHighlightRequestContext.Provider, { value: highlightRequester, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6497
7481
|
MarkdownBlocksRenderer,
|
|
6498
7482
|
{
|
|
6499
7483
|
blocks: EMPTY_BLOCKS,
|
|
@@ -6506,7 +7490,7 @@ function StreamingMarkdownComponent({
|
|
|
6506
7490
|
linkModal
|
|
6507
7491
|
] }) });
|
|
6508
7492
|
}
|
|
6509
|
-
var StreamingMarkdownWithRef = (0,
|
|
7493
|
+
var StreamingMarkdownWithRef = (0, import_react15.forwardRef)(StreamingMarkdownComponent);
|
|
6510
7494
|
StreamingMarkdownWithRef.displayName = "StreamingMarkdown";
|
|
6511
7495
|
var StreamingMarkdown = StreamingMarkdownWithRef;
|
|
6512
7496
|
function instantiateWorker(source) {
|
|
@@ -6613,6 +7597,7 @@ function percentile2(values, ratio) {
|
|
|
6613
7597
|
}
|
|
6614
7598
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6615
7599
|
0 && (module.exports = {
|
|
7600
|
+
BottomStickScrollArea,
|
|
6616
7601
|
ComponentRegistry,
|
|
6617
7602
|
DEFAULT_COALESCE_CONFIG,
|
|
6618
7603
|
DEFAULT_VIRTUALIZED_CODE_CONFIG,
|
|
@@ -6638,6 +7623,7 @@ function percentile2(values, ratio) {
|
|
|
6638
7623
|
defaultInlineComponents,
|
|
6639
7624
|
getMDXClient,
|
|
6640
7625
|
getMDXComponentFactory,
|
|
7626
|
+
getPatchKind,
|
|
6641
7627
|
isHeavyPatch,
|
|
6642
7628
|
isListPatchDebugEnabled,
|
|
6643
7629
|
mapHtmlToReact,
|