@stream-mdx/react 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.cjs +497 -163
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.mjs +496 -163
- package/dist/{index-Bt1opGCs.d.cts → index-D7px9jug.d.cts} +27 -2
- package/dist/{index-Bt1opGCs.d.ts → index-D7px9jug.d.ts} +27 -2
- package/dist/index.cjs +3767 -2043
- package/dist/index.d.cts +43 -5
- package/dist/index.d.ts +43 -5
- package/dist/index.mjs +3991 -2265
- package/dist/mdx-client.cjs +60 -18
- package/dist/mdx-client.d.cts +11 -0
- package/dist/mdx-client.d.ts +11 -0
- package/dist/mdx-client.mjs +60 -18
- package/dist/mdx-coordinator.cjs +60 -18
- package/dist/mdx-coordinator.mjs +60 -18
- package/dist/renderer/node-views.cjs +466 -133
- package/dist/renderer/node-views.d.cts +1 -1
- package/dist/renderer/node-views.d.ts +1 -1
- package/dist/renderer/node-views.mjs +409 -68
- package/dist/renderer/patch-commit-scheduler.cjs +68 -7
- package/dist/renderer/patch-commit-scheduler.d.cts +6 -5
- package/dist/renderer/patch-commit-scheduler.d.ts +6 -5
- package/dist/renderer/patch-commit-scheduler.mjs +68 -7
- package/dist/renderer/store.cjs +481 -56
- package/dist/renderer/store.d.cts +2 -1
- package/dist/renderer/store.d.ts +2 -1
- package/dist/renderer/store.mjs +479 -47
- package/dist/renderer/virtualized-code.cjs +8 -2
- package/dist/renderer/virtualized-code.d.cts +4 -0
- package/dist/renderer/virtualized-code.d.ts +4 -0
- package/dist/renderer/virtualized-code.mjs +8 -2
- package/dist/renderer.cjs +3199 -2208
- package/dist/renderer.d.cts +4 -2
- package/dist/renderer.d.ts +4 -2
- package/dist/renderer.mjs +2956 -1957
- package/dist/streaming-markdown-DSC4L0xR.d.cts +157 -0
- package/dist/streaming-markdown-Dp1IDgMT.d.ts +157 -0
- package/dist/streaming-markdown.cjs +3950 -2248
- package/dist/streaming-markdown.d.cts +6 -95
- package/dist/streaming-markdown.d.ts +6 -95
- package/dist/streaming-markdown.mjs +3962 -2252
- package/dist/utils/inline-html.d.cts +1 -1
- package/dist/utils/inline-html.d.ts +1 -1
- package/package.json +3 -3
|
@@ -34,16 +34,74 @@ __export(node_views_exports, {
|
|
|
34
34
|
BlockNodeRenderer: () => BlockNodeRenderer
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(node_views_exports);
|
|
37
|
-
var
|
|
38
|
-
var
|
|
37
|
+
var import_core4 = require("@stream-mdx/core");
|
|
38
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
39
39
|
|
|
40
40
|
// src/components/index.ts
|
|
41
41
|
var import_core = require("@stream-mdx/core");
|
|
42
|
+
|
|
43
|
+
// src/renderer/use-deferred-render.ts
|
|
44
|
+
var import_react = require("react");
|
|
45
|
+
function useDeferredRender(ref, options) {
|
|
46
|
+
const enabled = options?.enabled ?? true;
|
|
47
|
+
const [shouldRender, setShouldRender] = (0, import_react.useState)(!enabled);
|
|
48
|
+
(0, import_react.useEffect)(() => {
|
|
49
|
+
if (!enabled) {
|
|
50
|
+
setShouldRender(true);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const target = ref.current;
|
|
54
|
+
if (!target) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
let cancelled = false;
|
|
58
|
+
let idleId = null;
|
|
59
|
+
let timerId = null;
|
|
60
|
+
const scheduleRender = () => {
|
|
61
|
+
if (cancelled) return;
|
|
62
|
+
setShouldRender(true);
|
|
63
|
+
};
|
|
64
|
+
const runWithIdle = () => {
|
|
65
|
+
if (typeof globalThis.requestIdleCallback === "function") {
|
|
66
|
+
idleId = globalThis.requestIdleCallback(scheduleRender, { timeout: options?.idleTimeoutMs ?? 200 });
|
|
67
|
+
} else {
|
|
68
|
+
timerId = window.setTimeout(scheduleRender, options?.idleTimeoutMs ?? 200);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const observer = new IntersectionObserver(
|
|
72
|
+
(entries) => {
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
if (entry.isIntersecting || entry.intersectionRatio > 0) {
|
|
75
|
+
observer.disconnect();
|
|
76
|
+
const debounceMs = options?.debounceMs ?? 80;
|
|
77
|
+
timerId = window.setTimeout(runWithIdle, debounceMs);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{ rootMargin: options?.rootMargin ?? "200px 0px" }
|
|
83
|
+
);
|
|
84
|
+
observer.observe(target);
|
|
85
|
+
return () => {
|
|
86
|
+
cancelled = true;
|
|
87
|
+
observer.disconnect();
|
|
88
|
+
if (idleId !== null && typeof globalThis.cancelIdleCallback === "function") {
|
|
89
|
+
globalThis.cancelIdleCallback(idleId);
|
|
90
|
+
}
|
|
91
|
+
if (timerId !== null) {
|
|
92
|
+
window.clearTimeout(timerId);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}, [enabled, options?.debounceMs, options?.idleTimeoutMs, options?.rootMargin, ref]);
|
|
96
|
+
return shouldRender;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/components/index.ts
|
|
42
100
|
var import_core2 = require("@stream-mdx/core");
|
|
43
|
-
var
|
|
101
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
44
102
|
|
|
45
103
|
// src/utils/inline-html.ts
|
|
46
|
-
var
|
|
104
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
47
105
|
var BACKTICK_CONTENT = /^`([\s\S]+)`$/;
|
|
48
106
|
var DEFAULT_INLINE_HTML_RENDERERS = {
|
|
49
107
|
kbd: (descriptor, ctx) => {
|
|
@@ -55,7 +113,7 @@ var DEFAULT_INLINE_HTML_RENDERERS = {
|
|
|
55
113
|
if (ctx.key !== void 0 && ctx.key !== null) {
|
|
56
114
|
props.key = ctx.key;
|
|
57
115
|
}
|
|
58
|
-
return
|
|
116
|
+
return import_react2.default.createElement("kbd", props, import_react2.default.createElement("code", { className: "inline-code" }, codeText));
|
|
59
117
|
}
|
|
60
118
|
return ctx.defaultRender();
|
|
61
119
|
}
|
|
@@ -73,9 +131,9 @@ function renderInlineHtmlSegment(raw, sanitized, options = {}) {
|
|
|
73
131
|
return null;
|
|
74
132
|
}
|
|
75
133
|
if (options.key !== void 0 && options.key !== null) {
|
|
76
|
-
return
|
|
134
|
+
return import_react2.default.createElement(import_react2.default.Fragment, { key: options.key }, descriptor.text);
|
|
77
135
|
}
|
|
78
|
-
return
|
|
136
|
+
return import_react2.default.createElement(import_react2.default.Fragment, {}, descriptor.text);
|
|
79
137
|
}
|
|
80
138
|
if (isInlineTag) {
|
|
81
139
|
const parsedElement = renderSanitizedHtmlTree(descriptor.sanitized, options.key);
|
|
@@ -90,15 +148,15 @@ function renderInlineHtmlSegment(raw, sanitized, options = {}) {
|
|
|
90
148
|
if (options.key !== void 0 && options.key !== null) {
|
|
91
149
|
props.key = options.key;
|
|
92
150
|
}
|
|
93
|
-
return
|
|
151
|
+
return import_react2.default.createElement("span", props);
|
|
94
152
|
};
|
|
95
153
|
const allRenderers = options.renderers ? { ...DEFAULT_INLINE_HTML_RENDERERS, ...options.renderers } : DEFAULT_INLINE_HTML_RENDERERS;
|
|
96
154
|
const renderer = allRenderers[descriptor.tagName];
|
|
97
155
|
if (renderer) {
|
|
98
156
|
const rendered = renderer(descriptor, { key: options.key, defaultRender });
|
|
99
157
|
if (rendered) {
|
|
100
|
-
if (options.key !== void 0 && options.key !== null &&
|
|
101
|
-
return
|
|
158
|
+
if (options.key !== void 0 && options.key !== null && import_react2.default.isValidElement(rendered) && rendered.key === null) {
|
|
159
|
+
return import_react2.default.cloneElement(rendered, { key: options.key });
|
|
102
160
|
}
|
|
103
161
|
return rendered;
|
|
104
162
|
}
|
|
@@ -210,21 +268,21 @@ function renderSanitizedHtmlTree(html, key) {
|
|
|
210
268
|
}
|
|
211
269
|
if (children.length === 1) {
|
|
212
270
|
const [child] = children;
|
|
213
|
-
if (
|
|
271
|
+
if (import_react2.default.isValidElement(child)) {
|
|
214
272
|
if (key !== void 0 && key !== null) {
|
|
215
|
-
return
|
|
273
|
+
return import_react2.default.cloneElement(child, { key });
|
|
216
274
|
}
|
|
217
275
|
return child;
|
|
218
276
|
}
|
|
219
277
|
if (typeof child === "string" || typeof child === "number") {
|
|
220
278
|
if (key !== void 0 && key !== null) {
|
|
221
|
-
return
|
|
279
|
+
return import_react2.default.createElement(import_react2.default.Fragment, { key }, child);
|
|
222
280
|
}
|
|
223
|
-
return
|
|
281
|
+
return import_react2.default.createElement(import_react2.default.Fragment, {}, child);
|
|
224
282
|
}
|
|
225
|
-
return
|
|
283
|
+
return import_react2.default.createElement(import_react2.default.Fragment, { key }, child);
|
|
226
284
|
}
|
|
227
|
-
return
|
|
285
|
+
return import_react2.default.createElement(import_react2.default.Fragment, { key }, ...children);
|
|
228
286
|
} catch {
|
|
229
287
|
return null;
|
|
230
288
|
}
|
|
@@ -249,9 +307,9 @@ function convertDomNode(node, key) {
|
|
|
249
307
|
}
|
|
250
308
|
});
|
|
251
309
|
if (children.length === 0) {
|
|
252
|
-
return
|
|
310
|
+
return import_react2.default.createElement(tagName, props);
|
|
253
311
|
}
|
|
254
|
-
return
|
|
312
|
+
return import_react2.default.createElement(tagName, props, ...children);
|
|
255
313
|
}
|
|
256
314
|
function getElementAttributes(element) {
|
|
257
315
|
const attrs = {};
|
|
@@ -312,6 +370,29 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
312
370
|
]);
|
|
313
371
|
|
|
314
372
|
// src/components/index.ts
|
|
373
|
+
var MdxRuntimeBoundary = class extends import_react3.default.Component {
|
|
374
|
+
constructor() {
|
|
375
|
+
super(...arguments);
|
|
376
|
+
this.state = { hasError: false };
|
|
377
|
+
}
|
|
378
|
+
static getDerivedStateFromError() {
|
|
379
|
+
return { hasError: true };
|
|
380
|
+
}
|
|
381
|
+
componentDidCatch(error) {
|
|
382
|
+
this.props.onError(error);
|
|
383
|
+
}
|
|
384
|
+
componentDidUpdate(prevProps) {
|
|
385
|
+
if (prevProps.resetKey !== this.props.resetKey && this.state.hasError) {
|
|
386
|
+
this.setState({ hasError: false });
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
render() {
|
|
390
|
+
if (this.state.hasError) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
return this.props.children;
|
|
394
|
+
}
|
|
395
|
+
};
|
|
315
396
|
function renderInlineNodes(nodes, components) {
|
|
316
397
|
return nodes.map((node, index) => {
|
|
317
398
|
const key = `${node.kind}-${index}`;
|
|
@@ -319,31 +400,31 @@ function renderInlineNodes(nodes, components) {
|
|
|
319
400
|
case "text": {
|
|
320
401
|
const textComponent = components.text;
|
|
321
402
|
if (textComponent && textComponent !== defaultInlineComponents.text) {
|
|
322
|
-
return
|
|
403
|
+
return import_react3.default.createElement(textComponent, { key, text: node.text });
|
|
323
404
|
}
|
|
324
|
-
return
|
|
405
|
+
return import_react3.default.createElement(import_react3.default.Fragment, { key, children: node.text });
|
|
325
406
|
}
|
|
326
407
|
case "strong":
|
|
327
|
-
return
|
|
408
|
+
return import_react3.default.createElement(components.strong, {
|
|
328
409
|
key,
|
|
329
410
|
children: renderInlineNodes(node.children, components)
|
|
330
411
|
});
|
|
331
412
|
case "em":
|
|
332
|
-
return
|
|
413
|
+
return import_react3.default.createElement(components.em, {
|
|
333
414
|
key,
|
|
334
415
|
children: renderInlineNodes(node.children, components)
|
|
335
416
|
});
|
|
336
417
|
case "strike": {
|
|
337
|
-
const StrikeComponent = components.strike ?? ((props) =>
|
|
338
|
-
return
|
|
418
|
+
const StrikeComponent = components.strike ?? ((props) => import_react3.default.createElement("del", {}, props.children));
|
|
419
|
+
return import_react3.default.createElement(StrikeComponent, {
|
|
339
420
|
key,
|
|
340
421
|
children: renderInlineNodes(node.children, components)
|
|
341
422
|
});
|
|
342
423
|
}
|
|
343
424
|
case "code":
|
|
344
|
-
return
|
|
425
|
+
return import_react3.default.createElement(components.code, { key, text: node.text });
|
|
345
426
|
case "link":
|
|
346
|
-
return
|
|
427
|
+
return import_react3.default.createElement(
|
|
347
428
|
components.link,
|
|
348
429
|
{
|
|
349
430
|
key,
|
|
@@ -353,18 +434,18 @@ function renderInlineNodes(nodes, components) {
|
|
|
353
434
|
}
|
|
354
435
|
);
|
|
355
436
|
case "image":
|
|
356
|
-
return
|
|
437
|
+
return import_react3.default.createElement(components.image, {
|
|
357
438
|
key,
|
|
358
439
|
src: node.src,
|
|
359
440
|
alt: node.alt,
|
|
360
441
|
title: node.title
|
|
361
442
|
});
|
|
362
443
|
case "br":
|
|
363
|
-
return
|
|
444
|
+
return import_react3.default.createElement(import_react3.default.Fragment, { key }, import_react3.default.createElement(components.br, {}));
|
|
364
445
|
default: {
|
|
365
446
|
const component = components[node.kind];
|
|
366
447
|
if (component) {
|
|
367
|
-
return
|
|
448
|
+
return import_react3.default.createElement(component, { key, ...node });
|
|
368
449
|
}
|
|
369
450
|
return null;
|
|
370
451
|
}
|
|
@@ -372,18 +453,18 @@ function renderInlineNodes(nodes, components) {
|
|
|
372
453
|
});
|
|
373
454
|
}
|
|
374
455
|
var defaultInlineComponents = {
|
|
375
|
-
text: ({ text }) =>
|
|
376
|
-
strong: ({ children }) =>
|
|
377
|
-
em: ({ children }) =>
|
|
378
|
-
strike: ({ children }) =>
|
|
379
|
-
code: ({ text }) =>
|
|
456
|
+
text: ({ text }) => import_react3.default.createElement(import_react3.default.Fragment, {}, text),
|
|
457
|
+
strong: ({ children }) => import_react3.default.createElement("strong", {}, children),
|
|
458
|
+
em: ({ children }) => import_react3.default.createElement("em", {}, children),
|
|
459
|
+
strike: ({ children }) => import_react3.default.createElement("del", {}, children),
|
|
460
|
+
code: ({ text }) => import_react3.default.createElement(
|
|
380
461
|
"code",
|
|
381
462
|
{
|
|
382
463
|
className: "inline-code"
|
|
383
464
|
},
|
|
384
465
|
text
|
|
385
466
|
),
|
|
386
|
-
link: ({ href, title, children }) =>
|
|
467
|
+
link: ({ href, title, children }) => import_react3.default.createElement(
|
|
387
468
|
"a",
|
|
388
469
|
{
|
|
389
470
|
href,
|
|
@@ -394,15 +475,15 @@ var defaultInlineComponents = {
|
|
|
394
475
|
},
|
|
395
476
|
children
|
|
396
477
|
),
|
|
397
|
-
image: ({ src, alt, title }) =>
|
|
478
|
+
image: ({ src, alt, title }) => import_react3.default.createElement("img", {
|
|
398
479
|
src,
|
|
399
480
|
alt,
|
|
400
481
|
title,
|
|
401
482
|
className: "markdown-image"
|
|
402
483
|
}),
|
|
403
|
-
br: () =>
|
|
484
|
+
br: () => import_react3.default.createElement("br"),
|
|
404
485
|
// Custom extensible components
|
|
405
|
-
mention: ({ handle }) =>
|
|
486
|
+
mention: ({ handle }) => import_react3.default.createElement(
|
|
406
487
|
"span",
|
|
407
488
|
{
|
|
408
489
|
className: "mention",
|
|
@@ -410,7 +491,7 @@ var defaultInlineComponents = {
|
|
|
410
491
|
},
|
|
411
492
|
`@${handle}`
|
|
412
493
|
),
|
|
413
|
-
citation: ({ id }) =>
|
|
494
|
+
citation: ({ id }) => import_react3.default.createElement(
|
|
414
495
|
"span",
|
|
415
496
|
{
|
|
416
497
|
className: "citation",
|
|
@@ -418,7 +499,7 @@ var defaultInlineComponents = {
|
|
|
418
499
|
},
|
|
419
500
|
`[${id}]`
|
|
420
501
|
),
|
|
421
|
-
"math-inline": ({ tex }) =>
|
|
502
|
+
"math-inline": ({ tex }) => import_react3.default.createElement(
|
|
422
503
|
"span",
|
|
423
504
|
{
|
|
424
505
|
className: "math-inline",
|
|
@@ -426,21 +507,21 @@ var defaultInlineComponents = {
|
|
|
426
507
|
},
|
|
427
508
|
`$${tex}$`
|
|
428
509
|
),
|
|
429
|
-
"math-display": ({ tex }) =>
|
|
510
|
+
"math-display": ({ tex }) => import_react3.default.createElement(
|
|
430
511
|
"div",
|
|
431
512
|
{
|
|
432
513
|
className: "math-display markdown-math-display",
|
|
433
514
|
"data-tex": tex,
|
|
434
515
|
style: { overflowX: "auto" }
|
|
435
516
|
},
|
|
436
|
-
|
|
517
|
+
import_react3.default.createElement("span", { className: "math-display-content" }, `$$${tex}$$`)
|
|
437
518
|
),
|
|
438
519
|
// Footnote inline reference (superscript anchor)
|
|
439
520
|
"footnote-ref": ({ label, number }) => {
|
|
440
521
|
const n = number ?? "?";
|
|
441
522
|
const href = number ? `#fn:${n}` : void 0;
|
|
442
523
|
const id = number ? `fnref:${n}` : void 0;
|
|
443
|
-
return
|
|
524
|
+
return import_react3.default.createElement("sup", { className: "footnote-ref" }, import_react3.default.createElement("a", { href, id, "data-label": label }, String(n)));
|
|
444
525
|
}
|
|
445
526
|
};
|
|
446
527
|
function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRenderers) {
|
|
@@ -451,12 +532,12 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
451
532
|
nodes.forEach((node, idx) => {
|
|
452
533
|
if (node === null || node === void 0) return;
|
|
453
534
|
const key = `${baseKey}-${idx}`;
|
|
454
|
-
if (
|
|
455
|
-
target.push(node.key === key ? node :
|
|
535
|
+
if (import_react3.default.isValidElement(node)) {
|
|
536
|
+
target.push(node.key === key ? node : import_react3.default.cloneElement(node, { key }));
|
|
456
537
|
} else if (typeof node === "string" || typeof node === "number") {
|
|
457
|
-
target.push(
|
|
538
|
+
target.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, node));
|
|
458
539
|
} else {
|
|
459
|
-
target.push(
|
|
540
|
+
target.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, node));
|
|
460
541
|
}
|
|
461
542
|
});
|
|
462
543
|
};
|
|
@@ -472,7 +553,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
472
553
|
}
|
|
473
554
|
const key = `paragraph-inline-group-${inlineGroupIndex++}`;
|
|
474
555
|
result.push(
|
|
475
|
-
|
|
556
|
+
import_react3.default.createElement(
|
|
476
557
|
"p",
|
|
477
558
|
{
|
|
478
559
|
key,
|
|
@@ -490,7 +571,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
490
571
|
const inlineNodes = Array.isArray(segment.inline) ? segment.inline : [];
|
|
491
572
|
if (inlineNodes.length === 0) {
|
|
492
573
|
if (segment.value) {
|
|
493
|
-
inlineBuffer.push(
|
|
574
|
+
inlineBuffer.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, segment.value));
|
|
494
575
|
}
|
|
495
576
|
break;
|
|
496
577
|
}
|
|
@@ -518,14 +599,14 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
518
599
|
const status = segment.status ?? "pending";
|
|
519
600
|
let element;
|
|
520
601
|
if (status === "compiled") {
|
|
521
|
-
element =
|
|
602
|
+
element = import_react3.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
|
|
522
603
|
} else if (status === "error") {
|
|
523
604
|
const message = segment.value || "MDX error";
|
|
524
|
-
element =
|
|
605
|
+
element = import_react3.default.createElement("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error" }, message);
|
|
525
606
|
} else {
|
|
526
|
-
element =
|
|
607
|
+
element = import_react3.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": status }, segment.value);
|
|
527
608
|
}
|
|
528
|
-
inlineBuffer.push(
|
|
609
|
+
inlineBuffer.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, element));
|
|
529
610
|
break;
|
|
530
611
|
}
|
|
531
612
|
case "html": {
|
|
@@ -541,7 +622,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
541
622
|
result.push(element);
|
|
542
623
|
} else if (html) {
|
|
543
624
|
result.push(
|
|
544
|
-
|
|
625
|
+
import_react3.default.createElement("div", {
|
|
545
626
|
key,
|
|
546
627
|
className: "markdown-inline-html-block",
|
|
547
628
|
dangerouslySetInnerHTML: { __html: html }
|
|
@@ -560,7 +641,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
|
|
|
560
641
|
flushInline();
|
|
561
642
|
if (result.length === 0) {
|
|
562
643
|
return [
|
|
563
|
-
|
|
644
|
+
import_react3.default.createElement(
|
|
564
645
|
"p",
|
|
565
646
|
{
|
|
566
647
|
key: "paragraph-inline-group-0",
|
|
@@ -619,24 +700,80 @@ var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
|
619
700
|
]);
|
|
620
701
|
|
|
621
702
|
// src/renderer/hooks.ts
|
|
622
|
-
var
|
|
703
|
+
var import_react4 = require("react");
|
|
623
704
|
function useRendererNode(store, id) {
|
|
624
|
-
const selector = (0,
|
|
705
|
+
const selector = (0, import_react4.useMemo)(() => {
|
|
625
706
|
return () => store.getNodeWithVersion(id);
|
|
626
707
|
}, [store, id]);
|
|
627
|
-
const snapshot = (0,
|
|
708
|
+
const snapshot = (0, import_react4.useSyncExternalStore)(store.subscribe, selector, selector);
|
|
628
709
|
return snapshot.node;
|
|
629
710
|
}
|
|
630
711
|
function useRendererChildren(store, id) {
|
|
631
|
-
const selector = (0,
|
|
712
|
+
const selector = (0, import_react4.useMemo)(() => {
|
|
632
713
|
return () => store.getChildrenWithVersion(id);
|
|
633
714
|
}, [store, id]);
|
|
634
|
-
const snapshot = (0,
|
|
715
|
+
const snapshot = (0, import_react4.useSyncExternalStore)(store.subscribe, selector, selector);
|
|
635
716
|
return snapshot.children;
|
|
636
717
|
}
|
|
637
718
|
|
|
719
|
+
// src/renderer/code-highlight-context.tsx
|
|
720
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
721
|
+
var CodeHighlightRequestContext = import_react5.default.createContext(null);
|
|
722
|
+
function useCodeHighlightRequester() {
|
|
723
|
+
return import_react5.default.useContext(CodeHighlightRequestContext);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// src/renderer/deferred-render-context.tsx
|
|
727
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
728
|
+
var DeferredRenderContext = import_react6.default.createContext(null);
|
|
729
|
+
|
|
730
|
+
// src/renderer/store.ts
|
|
731
|
+
var import_core3 = require("@stream-mdx/core");
|
|
732
|
+
var NODE_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
733
|
+
var CHILDREN_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
734
|
+
var NODE_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(NODE_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
735
|
+
var CHILDREN_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(CHILDREN_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
736
|
+
var EMPTY_CHILDREN = Object.freeze([]);
|
|
737
|
+
var EMPTY_NODE_SNAPSHOT = Object.freeze({ version: -1, node: void 0 });
|
|
738
|
+
var EMPTY_CHILDREN_SNAPSHOT = Object.freeze({
|
|
739
|
+
version: -1,
|
|
740
|
+
children: EMPTY_CHILDREN
|
|
741
|
+
});
|
|
742
|
+
function isListPatchDebugEnabled() {
|
|
743
|
+
if (typeof globalThis !== "undefined") {
|
|
744
|
+
const flag = globalThis.__STREAMING_LIST_DEBUG__;
|
|
745
|
+
if (flag === true) return true;
|
|
746
|
+
}
|
|
747
|
+
if (typeof process !== "undefined" && process.env.NEXT_PUBLIC_STREAMING_LIST_DEBUG === "true") {
|
|
748
|
+
return true;
|
|
749
|
+
}
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
var CODE_BLOCK_DEBUG_ENABLED = (() => {
|
|
753
|
+
try {
|
|
754
|
+
if (typeof process !== "undefined" && process.env && process.env.NEXT_PUBLIC_STREAMING_DEBUG_CODELINES === "1") {
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
757
|
+
if (typeof globalThis !== "undefined") {
|
|
758
|
+
const debug = globalThis?.__STREAMING_DEBUG__;
|
|
759
|
+
if (debug?.codeLines) {
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
} catch {
|
|
764
|
+
}
|
|
765
|
+
return false;
|
|
766
|
+
})() || false;
|
|
767
|
+
var CODE_BLOCK_VALIDATION_ENABLED = typeof process !== "undefined" && process.env ? process.env.NODE_ENV !== "production" : true;
|
|
768
|
+
var getPerfNow = (() => {
|
|
769
|
+
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
770
|
+
return () => performance.now();
|
|
771
|
+
}
|
|
772
|
+
return () => Date.now();
|
|
773
|
+
})();
|
|
774
|
+
|
|
638
775
|
// src/renderer/virtualized-code.tsx
|
|
639
|
-
var
|
|
776
|
+
var import_react7 = require("react");
|
|
640
777
|
var DEFAULT_VIRTUALIZED_CODE_CONFIG = {
|
|
641
778
|
enabled: true,
|
|
642
779
|
windowSize: 100,
|
|
@@ -652,6 +789,8 @@ function calculateCodeWindow(lines, scrollTop, containerHeight, lineHeight, conf
|
|
|
652
789
|
return {
|
|
653
790
|
startIndex: 0,
|
|
654
791
|
endIndex: totalLines,
|
|
792
|
+
visibleStart: 0,
|
|
793
|
+
visibleEnd: totalLines,
|
|
655
794
|
visibleLines: lines,
|
|
656
795
|
totalLines,
|
|
657
796
|
mountedLines: totalLines
|
|
@@ -659,22 +798,26 @@ function calculateCodeWindow(lines, scrollTop, containerHeight, lineHeight, conf
|
|
|
659
798
|
}
|
|
660
799
|
const firstVisibleLine = Math.floor(scrollTop / lineHeight);
|
|
661
800
|
const lastVisibleLine = Math.ceil((scrollTop + containerHeight) / lineHeight);
|
|
662
|
-
const
|
|
663
|
-
const
|
|
801
|
+
const visibleStart = Math.max(0, firstVisibleLine);
|
|
802
|
+
const visibleEnd = Math.min(totalLines, Math.max(visibleStart, lastVisibleLine));
|
|
803
|
+
const startIndex = Math.max(0, visibleStart - config.bufferSize);
|
|
804
|
+
const endIndex = Math.min(totalLines, visibleEnd + config.bufferSize);
|
|
664
805
|
return {
|
|
665
806
|
startIndex,
|
|
666
807
|
endIndex,
|
|
808
|
+
visibleStart,
|
|
809
|
+
visibleEnd,
|
|
667
810
|
visibleLines: lines.slice(startIndex, endIndex),
|
|
668
811
|
totalLines,
|
|
669
812
|
mountedLines: endIndex - startIndex
|
|
670
813
|
};
|
|
671
814
|
}
|
|
672
815
|
function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
673
|
-
const containerRef = (0,
|
|
674
|
-
const [scrollTop, setScrollTop] = (0,
|
|
675
|
-
const [containerHeight, setContainerHeight] = (0,
|
|
676
|
-
const lineHeightRef = (0,
|
|
677
|
-
(0,
|
|
816
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
817
|
+
const [scrollTop, setScrollTop] = (0, import_react7.useState)(0);
|
|
818
|
+
const [containerHeight, setContainerHeight] = (0, import_react7.useState)(0);
|
|
819
|
+
const lineHeightRef = (0, import_react7.useRef)(20);
|
|
820
|
+
(0, import_react7.useEffect)(() => {
|
|
678
821
|
if (!containerRef.current || lines.length === 0) return;
|
|
679
822
|
const timeoutId = setTimeout(() => {
|
|
680
823
|
if (!containerRef.current) return;
|
|
@@ -688,12 +831,12 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
|
688
831
|
}, 0);
|
|
689
832
|
return () => clearTimeout(timeoutId);
|
|
690
833
|
}, [lines.length]);
|
|
691
|
-
const handleScroll = (0,
|
|
834
|
+
const handleScroll = (0, import_react7.useCallback)((e) => {
|
|
692
835
|
const target = e.currentTarget;
|
|
693
836
|
setScrollTop(target.scrollTop);
|
|
694
837
|
setContainerHeight(target.clientHeight);
|
|
695
838
|
}, []);
|
|
696
|
-
(0,
|
|
839
|
+
(0, import_react7.useEffect)(() => {
|
|
697
840
|
if (!containerRef.current) return;
|
|
698
841
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
699
842
|
for (const entry of entries) {
|
|
@@ -703,10 +846,10 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
|
703
846
|
resizeObserver.observe(containerRef.current);
|
|
704
847
|
return () => resizeObserver.disconnect();
|
|
705
848
|
}, []);
|
|
706
|
-
const window2 = (0,
|
|
849
|
+
const window2 = (0, import_react7.useMemo)(() => {
|
|
707
850
|
return calculateCodeWindow(lines, scrollTop, containerHeight, lineHeightRef.current, config);
|
|
708
851
|
}, [lines, scrollTop, containerHeight, config]);
|
|
709
|
-
const scrollToLine = (0,
|
|
852
|
+
const scrollToLine = (0, import_react7.useCallback)((lineIndex) => {
|
|
710
853
|
if (!containerRef.current) return;
|
|
711
854
|
const targetScrollTop = lineIndex * lineHeightRef.current;
|
|
712
855
|
containerRef.current.scrollTop = targetScrollTop;
|
|
@@ -747,7 +890,7 @@ var BlockNodeRenderer = ({ store, blockId, registry }) => {
|
|
|
747
890
|
return registry.renderBlock(block);
|
|
748
891
|
}
|
|
749
892
|
};
|
|
750
|
-
var ParagraphBlockView =
|
|
893
|
+
var ParagraphBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
751
894
|
const node = useRendererNode(store, blockId);
|
|
752
895
|
const block = node?.block;
|
|
753
896
|
const childIds = useRendererChildren(store, blockId);
|
|
@@ -767,7 +910,7 @@ var ParagraphBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
767
910
|
const structured = renderParagraphMixedSegments(segments2, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
768
911
|
if (structured.length === 1) {
|
|
769
912
|
const [single] = structured;
|
|
770
|
-
return
|
|
913
|
+
return import_react8.default.isValidElement(single) ? single : single;
|
|
771
914
|
}
|
|
772
915
|
return structured;
|
|
773
916
|
}
|
|
@@ -785,7 +928,7 @@ var ParagraphBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
785
928
|
const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
786
929
|
if (structured.length === 1) {
|
|
787
930
|
const [single] = structured;
|
|
788
|
-
return
|
|
931
|
+
return import_react8.default.isValidElement(single) ? single : single;
|
|
789
932
|
}
|
|
790
933
|
return structured;
|
|
791
934
|
}
|
|
@@ -804,7 +947,7 @@ var ParagraphBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
804
947
|
const structured = renderParagraphMixedSegments(segments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
805
948
|
if (structured.length === 1) {
|
|
806
949
|
const [single] = structured;
|
|
807
|
-
return
|
|
950
|
+
return import_react8.default.isValidElement(single) ? single : single;
|
|
808
951
|
}
|
|
809
952
|
return structured;
|
|
810
953
|
}
|
|
@@ -821,31 +964,31 @@ var ParagraphBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
821
964
|
const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
822
965
|
if (structured.length === 1) {
|
|
823
966
|
const [single] = structured;
|
|
824
|
-
return
|
|
967
|
+
return import_react8.default.isValidElement(single) ? single : single;
|
|
825
968
|
}
|
|
826
969
|
return structured;
|
|
827
970
|
}
|
|
828
971
|
const ParagraphComponent = registry.getBlockComponent("paragraph");
|
|
829
|
-
const baseElement =
|
|
972
|
+
const baseElement = import_react8.default.createElement(ParagraphComponent, {
|
|
830
973
|
inlines: block.payload.inline ?? [],
|
|
831
974
|
raw: block.payload.raw,
|
|
832
975
|
meta: block.payload.meta
|
|
833
976
|
});
|
|
834
977
|
if (childIds.length > 0) {
|
|
835
978
|
const renderedChildren = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
836
|
-
if (
|
|
979
|
+
if (import_react8.default.isValidElement(baseElement)) {
|
|
837
980
|
const { children: _ignored, className = "markdown-paragraph", inlines: _inlines, raw: _raw, meta: _meta, ...rest } = baseElement.props ?? {};
|
|
838
|
-
return
|
|
981
|
+
return import_react8.default.createElement("p", { ...rest, className }, renderedChildren);
|
|
839
982
|
}
|
|
840
983
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph", children: renderedChildren });
|
|
841
984
|
}
|
|
842
|
-
if (
|
|
985
|
+
if (import_react8.default.isValidElement(baseElement)) {
|
|
843
986
|
return baseElement;
|
|
844
987
|
}
|
|
845
988
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph", children: renderInlineNodes(block.payload.inline ?? [], inlineComponents) });
|
|
846
989
|
});
|
|
847
990
|
ParagraphBlockView.displayName = "ParagraphBlockView";
|
|
848
|
-
var BlockquoteBlockView =
|
|
991
|
+
var BlockquoteBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
849
992
|
const node = useRendererNode(store, blockId);
|
|
850
993
|
const block = node?.block;
|
|
851
994
|
const childIds = useRendererChildren(store, blockId);
|
|
@@ -891,7 +1034,7 @@ var BlockquoteBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
891
1034
|
elements.push(htmlNode);
|
|
892
1035
|
} else {
|
|
893
1036
|
elements.push(
|
|
894
|
-
|
|
1037
|
+
import_react8.default.createElement("span", {
|
|
895
1038
|
key: `blockquote-html-${block.id}-${segmentIndex}`,
|
|
896
1039
|
className: "markdown-inline-html",
|
|
897
1040
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: segment content is sanitized by the worker before streaming */
|
|
@@ -909,10 +1052,10 @@ var BlockquoteBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
909
1052
|
default: {
|
|
910
1053
|
const inline = renderInlineContent(segment.inline, `blockquote-text-inline-${block.id}-${segmentIndex}-`);
|
|
911
1054
|
if (inline) {
|
|
912
|
-
elements.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1055
|
+
elements.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react8.default.Fragment, { children: inline }, `blockquote-inline-${block.id}-${segmentIndex}`));
|
|
913
1056
|
} else {
|
|
914
1057
|
elements.push(
|
|
915
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react8.default.Fragment, { children: renderTextWithBreaks(segment.value, `blockquote-text-${block.id}-${segmentIndex}-`) }, `blockquote-text-${block.id}-${segmentIndex}`)
|
|
916
1059
|
);
|
|
917
1060
|
}
|
|
918
1061
|
break;
|
|
@@ -951,7 +1094,7 @@ var BlockquoteBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
951
1094
|
return null;
|
|
952
1095
|
})();
|
|
953
1096
|
const BlockquoteComponent = registry.getBlockComponent("blockquote");
|
|
954
|
-
const baseElement =
|
|
1097
|
+
const baseElement = import_react8.default.createElement(
|
|
955
1098
|
BlockquoteComponent,
|
|
956
1099
|
{
|
|
957
1100
|
inlines: block.payload.inline ?? [],
|
|
@@ -959,13 +1102,13 @@ var BlockquoteBlockView = import_react5.default.memo(({ store, blockId, registry
|
|
|
959
1102
|
},
|
|
960
1103
|
renderedContent
|
|
961
1104
|
);
|
|
962
|
-
if (
|
|
1105
|
+
if (import_react8.default.isValidElement(baseElement)) {
|
|
963
1106
|
return baseElement;
|
|
964
1107
|
}
|
|
965
1108
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("blockquote", { className: "markdown-blockquote", children: renderedContent });
|
|
966
1109
|
});
|
|
967
1110
|
BlockquoteBlockView.displayName = "BlockquoteBlockView";
|
|
968
|
-
var MixedSegmentView =
|
|
1111
|
+
var MixedSegmentView = import_react8.default.memo(({ store, nodeId, inlineComponents }) => {
|
|
969
1112
|
const node = useRendererNode(store, nodeId);
|
|
970
1113
|
if (!node) return null;
|
|
971
1114
|
switch (node.type) {
|
|
@@ -993,7 +1136,7 @@ var MixedSegmentView = import_react5.default.memo(({ store, nodeId, inlineCompon
|
|
|
993
1136
|
return rendered;
|
|
994
1137
|
}
|
|
995
1138
|
if (!html) return null;
|
|
996
|
-
return
|
|
1139
|
+
return import_react8.default.createElement("span", {
|
|
997
1140
|
className: "markdown-inline-html",
|
|
998
1141
|
/* biome-ignore lint/security/noDangerouslySetInnerHtml: html is sanitized upstream before reaching the renderer */
|
|
999
1142
|
dangerouslySetInnerHTML: { __html: html }
|
|
@@ -1018,19 +1161,19 @@ var MixedSegmentView = import_react5.default.memo(({ store, nodeId, inlineCompon
|
|
|
1018
1161
|
}
|
|
1019
1162
|
});
|
|
1020
1163
|
MixedSegmentView.displayName = "MixedSegmentView";
|
|
1021
|
-
var HtmlBlockView =
|
|
1164
|
+
var HtmlBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1022
1165
|
const node = useRendererNode(store, blockId);
|
|
1023
1166
|
if (!node || !node.block) return null;
|
|
1024
1167
|
return registry.renderBlock(node.block);
|
|
1025
1168
|
});
|
|
1026
1169
|
HtmlBlockView.displayName = "HtmlBlockView";
|
|
1027
|
-
var MdxBlockView =
|
|
1170
|
+
var MdxBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1028
1171
|
const node = useRendererNode(store, blockId);
|
|
1029
1172
|
if (!node || !node.block) return null;
|
|
1030
1173
|
return registry.renderBlock(node.block);
|
|
1031
1174
|
});
|
|
1032
1175
|
MdxBlockView.displayName = "MdxBlockView";
|
|
1033
|
-
var ListBlockView =
|
|
1176
|
+
var ListBlockView = import_react8.default.memo(
|
|
1034
1177
|
({ store, blockId, registry, depth = 0 }) => {
|
|
1035
1178
|
const node = useRendererNode(store, blockId);
|
|
1036
1179
|
const block = node?.block;
|
|
@@ -1038,10 +1181,36 @@ var ListBlockView = import_react5.default.memo(
|
|
|
1038
1181
|
const inlineComponents = registry.getInlineComponents();
|
|
1039
1182
|
const ordered = Boolean(node?.props?.ordered ?? block?.payload.meta?.ordered);
|
|
1040
1183
|
const Tag = ordered ? "ol" : "ul";
|
|
1041
|
-
const
|
|
1042
|
-
|
|
1184
|
+
const listDebugEnabled = isListPatchDebugEnabled();
|
|
1185
|
+
const listItemIds = import_react8.default.useMemo(() => {
|
|
1186
|
+
const ids = [];
|
|
1187
|
+
for (const childId of childIds) {
|
|
1188
|
+
const childNode = store.getNode(childId);
|
|
1189
|
+
if (childNode?.type === "list-item") {
|
|
1190
|
+
ids.push(childId);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
return ids;
|
|
1194
|
+
}, [childIds, store]);
|
|
1195
|
+
import_react8.default.useEffect(() => {
|
|
1196
|
+
if (!listDebugEnabled) return;
|
|
1197
|
+
const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
|
|
1198
|
+
console.info("[stream-mdx:list-render]", {
|
|
1199
|
+
listId: blockId,
|
|
1200
|
+
depth,
|
|
1201
|
+
ordered,
|
|
1202
|
+
childIds,
|
|
1203
|
+
childTypes,
|
|
1204
|
+
listItemIds,
|
|
1205
|
+
listItems: listItemIds.length,
|
|
1206
|
+
totalChildren: childIds.length,
|
|
1207
|
+
isFinalized: block?.isFinalized ?? false
|
|
1208
|
+
});
|
|
1209
|
+
}, [listDebugEnabled, blockId, depth, ordered, childIds, listItemIds, store, block?.isFinalized]);
|
|
1210
|
+
const listStyle = import_react8.default.useMemo(() => {
|
|
1211
|
+
if (!ordered || listItemIds.length === 0) return void 0;
|
|
1043
1212
|
let maxDigits = 1;
|
|
1044
|
-
|
|
1213
|
+
listItemIds.forEach((childId, index) => {
|
|
1045
1214
|
const childNode = store.getNode(childId);
|
|
1046
1215
|
const raw = typeof childNode?.block?.payload?.raw === "string" ? childNode.block.payload.raw : void 0;
|
|
1047
1216
|
const markerMatch = raw ? raw.match(/^([^\s]+)\s+/) : null;
|
|
@@ -1055,24 +1224,34 @@ var ListBlockView = import_react5.default.memo(
|
|
|
1055
1224
|
return {
|
|
1056
1225
|
["--list-indent"]: `calc(${baseIndent} + ${maxDigits}ch)`
|
|
1057
1226
|
};
|
|
1058
|
-
}, [ordered,
|
|
1059
|
-
|
|
1060
|
-
|
|
1227
|
+
}, [ordered, listItemIds, store, depth]);
|
|
1228
|
+
if (listItemIds.length === 0) return null;
|
|
1229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1230
|
+
Tag,
|
|
1061
1231
|
{
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1232
|
+
className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
|
|
1233
|
+
"data-list-depth": depth,
|
|
1234
|
+
"data-list-id": listDebugEnabled ? blockId : void 0,
|
|
1235
|
+
style: listStyle,
|
|
1236
|
+
children: listItemIds.map((childId, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1237
|
+
ListItemView,
|
|
1238
|
+
{
|
|
1239
|
+
store,
|
|
1240
|
+
nodeId: childId,
|
|
1241
|
+
inlineComponents,
|
|
1242
|
+
registry,
|
|
1243
|
+
ordered,
|
|
1244
|
+
index,
|
|
1245
|
+
depth
|
|
1246
|
+
},
|
|
1247
|
+
childId
|
|
1248
|
+
))
|
|
1249
|
+
}
|
|
1250
|
+
);
|
|
1072
1251
|
}
|
|
1073
1252
|
);
|
|
1074
1253
|
ListBlockView.displayName = "ListBlockView";
|
|
1075
|
-
var ListItemView =
|
|
1254
|
+
var ListItemView = import_react8.default.memo(({ store, nodeId, inlineComponents, registry, ordered, index, depth }) => {
|
|
1076
1255
|
const node = useRendererNode(store, nodeId);
|
|
1077
1256
|
const childIds = useRendererChildren(store, nodeId);
|
|
1078
1257
|
const inline = node?.props?.inline ?? [];
|
|
@@ -1085,7 +1264,9 @@ var ListItemView = import_react5.default.memo(({ store, nodeId, inlineComponents
|
|
|
1085
1264
|
const inferredIndex = typeof node?.props?.index === "number" ? Number(node?.props?.index) : index;
|
|
1086
1265
|
const isOrdered = Boolean(node?.props?.ordered ?? ordered);
|
|
1087
1266
|
const counterText = !isTask ? isOrdered ? marker ? marker : `${inferredIndex + 1}.` : "\u2022" : void 0;
|
|
1088
|
-
const
|
|
1267
|
+
const listDebugEnabled = isListPatchDebugEnabled();
|
|
1268
|
+
const inlineLength = inline.length;
|
|
1269
|
+
const [segmentChildIds, contentChildIds] = import_react8.default.useMemo(() => {
|
|
1089
1270
|
const segments = [];
|
|
1090
1271
|
const structural = [];
|
|
1091
1272
|
for (const childId of childIds) {
|
|
@@ -1099,16 +1280,16 @@ var ListItemView = import_react5.default.memo(({ store, nodeId, inlineComponents
|
|
|
1099
1280
|
}
|
|
1100
1281
|
return [segments, structural];
|
|
1101
1282
|
}, [childIds, store]);
|
|
1102
|
-
const segmentElements =
|
|
1283
|
+
const segmentElements = import_react8.default.useMemo(() => {
|
|
1103
1284
|
return segmentChildIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
1104
1285
|
}, [segmentChildIds, store, inlineComponents]);
|
|
1105
|
-
const primaryContent =
|
|
1286
|
+
const primaryContent = import_react8.default.useMemo(() => {
|
|
1106
1287
|
if (segmentChildIds.length > 0) {
|
|
1107
1288
|
return segmentElements;
|
|
1108
1289
|
}
|
|
1109
1290
|
return renderInlineNodes(inline, inlineComponents);
|
|
1110
1291
|
}, [segmentChildIds, segmentElements, inline, inlineComponents]);
|
|
1111
|
-
const trailingChildren =
|
|
1292
|
+
const trailingChildren = import_react8.default.useMemo(() => {
|
|
1112
1293
|
return contentChildIds.map((childId) => {
|
|
1113
1294
|
const childNode = store.getNode(childId);
|
|
1114
1295
|
if (!childNode) return null;
|
|
@@ -1126,22 +1307,67 @@ var ListItemView = import_react5.default.memo(({ store, nodeId, inlineComponents
|
|
|
1126
1307
|
}, [contentChildIds, store, inlineComponents, registry, depth]);
|
|
1127
1308
|
const filteredChildren = trailingChildren.filter((child) => Boolean(child));
|
|
1128
1309
|
const hasChildren = filteredChildren.length > 0;
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1310
|
+
import_react8.default.useEffect(() => {
|
|
1311
|
+
if (!listDebugEnabled) return;
|
|
1312
|
+
const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
|
|
1313
|
+
console.info("[stream-mdx:list-item-render]", {
|
|
1314
|
+
itemId: nodeId,
|
|
1315
|
+
depth,
|
|
1316
|
+
ordered: isOrdered,
|
|
1317
|
+
inferredIndex,
|
|
1318
|
+
marker,
|
|
1319
|
+
isTask,
|
|
1320
|
+
isChecked,
|
|
1321
|
+
childIds,
|
|
1322
|
+
childTypes,
|
|
1323
|
+
segmentChildIds,
|
|
1324
|
+
contentChildIds,
|
|
1325
|
+
inlineLength,
|
|
1326
|
+
hasChildren,
|
|
1327
|
+
isFinalized: block?.isFinalized ?? false
|
|
1328
|
+
});
|
|
1329
|
+
}, [
|
|
1330
|
+
listDebugEnabled,
|
|
1331
|
+
nodeId,
|
|
1332
|
+
depth,
|
|
1333
|
+
isOrdered,
|
|
1334
|
+
inferredIndex,
|
|
1335
|
+
marker,
|
|
1336
|
+
isTask,
|
|
1337
|
+
isChecked,
|
|
1338
|
+
childIds,
|
|
1339
|
+
segmentChildIds,
|
|
1340
|
+
contentChildIds,
|
|
1341
|
+
inlineLength,
|
|
1342
|
+
hasChildren,
|
|
1343
|
+
store,
|
|
1344
|
+
block?.isFinalized
|
|
1345
|
+
]);
|
|
1346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1347
|
+
"li",
|
|
1348
|
+
{
|
|
1349
|
+
className: `markdown-list-item${isTask ? " markdown-list-item-task" : ""}`,
|
|
1350
|
+
"data-counter-text": counterText,
|
|
1351
|
+
"data-list-depth": depth,
|
|
1352
|
+
"data-list-item-id": listDebugEnabled ? nodeId : void 0,
|
|
1353
|
+
children: [
|
|
1354
|
+
isTask ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "markdown-task", children: [
|
|
1355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", className: "markdown-task-checkbox", checked: isChecked, readOnly: true, disabled: true, tabIndex: -1, "aria-checked": isChecked }),
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "markdown-task-content", children: primaryContent })
|
|
1357
|
+
] }) : primaryContent,
|
|
1358
|
+
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "markdown-list-item-children", children: filteredChildren }) : null
|
|
1359
|
+
]
|
|
1360
|
+
}
|
|
1361
|
+
);
|
|
1136
1362
|
});
|
|
1137
1363
|
ListItemView.displayName = "ListItemView";
|
|
1138
|
-
var TableBlockView =
|
|
1364
|
+
var TableBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1139
1365
|
const tableElements = registry.getTableElements();
|
|
1140
1366
|
const childIds = useRendererChildren(store, blockId);
|
|
1141
1367
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(tableElements.Table, { className: "markdown-table w-full caption-bottom text-base", children: childIds.map((sectionId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableSectionView, { store, nodeId: sectionId, registry }, sectionId)) });
|
|
1142
1368
|
});
|
|
1143
1369
|
TableBlockView.displayName = "TableBlockView";
|
|
1144
|
-
var TableSectionView =
|
|
1370
|
+
var TableSectionView = import_react8.default.memo(({ store, nodeId, registry }) => {
|
|
1145
1371
|
const node = useRendererNode(store, nodeId);
|
|
1146
1372
|
if (!node) return null;
|
|
1147
1373
|
const tableElements = registry.getTableElements();
|
|
@@ -1156,13 +1382,13 @@ var TableSectionView = import_react5.default.memo(({ store, nodeId, registry })
|
|
|
1156
1382
|
return null;
|
|
1157
1383
|
});
|
|
1158
1384
|
TableSectionView.displayName = "TableSectionView";
|
|
1159
|
-
var TableRowView =
|
|
1385
|
+
var TableRowView = import_react8.default.memo(({ store, nodeId, registry }) => {
|
|
1160
1386
|
const tableElements = registry.getTableElements();
|
|
1161
1387
|
const cellIds = useRendererChildren(store, nodeId);
|
|
1162
1388
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(tableElements.Tr, { children: cellIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) });
|
|
1163
1389
|
});
|
|
1164
1390
|
TableRowView.displayName = "TableRowView";
|
|
1165
|
-
var TableCellView =
|
|
1391
|
+
var TableCellView = import_react8.default.memo(({ store, nodeId, registry }) => {
|
|
1166
1392
|
const node = useRendererNode(store, nodeId);
|
|
1167
1393
|
const inlineComponents = registry.getInlineComponents();
|
|
1168
1394
|
const tableElements = registry.getTableElements();
|
|
@@ -1175,13 +1401,19 @@ var TableCellView = import_react5.default.memo(({ store, nodeId, registry }) =>
|
|
|
1175
1401
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { ...alignProps, children: content });
|
|
1176
1402
|
});
|
|
1177
1403
|
TableCellView.displayName = "TableCellView";
|
|
1178
|
-
var CodeBlockView =
|
|
1404
|
+
var CodeBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1179
1405
|
const node = useRendererNode(store, blockId);
|
|
1180
1406
|
const childIds = useRendererChildren(store, blockId);
|
|
1181
1407
|
const CodeComponent = registry.getBlockComponent("code");
|
|
1408
|
+
const deferredConfig = import_react8.default.useContext(DeferredRenderContext);
|
|
1409
|
+
const deferredRef = import_react8.default.useRef(null);
|
|
1410
|
+
const shouldRenderDeferred = useDeferredRender(
|
|
1411
|
+
deferredRef,
|
|
1412
|
+
deferredConfig ? { ...deferredConfig, enabled: true } : { enabled: false }
|
|
1413
|
+
);
|
|
1182
1414
|
if (!node || !node.block) return null;
|
|
1183
1415
|
const nodeVersion = node.version;
|
|
1184
|
-
const lines =
|
|
1416
|
+
const lines = import_react8.default.useMemo(() => {
|
|
1185
1417
|
const seenIds = /* @__PURE__ */ new Set();
|
|
1186
1418
|
const seenIndices = /* @__PURE__ */ new Set();
|
|
1187
1419
|
const deduped = [];
|
|
@@ -1191,6 +1423,7 @@ var CodeBlockView = import_react5.default.memo(({ store, blockId, registry }) =>
|
|
|
1191
1423
|
const index = typeof child.props?.index === "number" ? child.props?.index : deduped.length;
|
|
1192
1424
|
const text = typeof child.props?.text === "string" ? child.props?.text : "";
|
|
1193
1425
|
const html = typeof child.props?.html === "string" ? child.props?.html : null;
|
|
1426
|
+
const tokens = Object.prototype.hasOwnProperty.call(child.props ?? {}, "tokens") ? child.props?.tokens : void 0;
|
|
1194
1427
|
if (seenIds.has(child.id) || seenIndices.has(index)) {
|
|
1195
1428
|
console.warn("[renderer-view] duplicate code line detected", {
|
|
1196
1429
|
blockId,
|
|
@@ -1201,7 +1434,7 @@ var CodeBlockView = import_react5.default.memo(({ store, blockId, registry }) =>
|
|
|
1201
1434
|
}
|
|
1202
1435
|
seenIds.add(child.id);
|
|
1203
1436
|
seenIndices.add(index);
|
|
1204
|
-
deduped.push({ id: child.id, index, text, html });
|
|
1437
|
+
deduped.push({ id: child.id, index, text, html, tokens });
|
|
1205
1438
|
}
|
|
1206
1439
|
deduped.sort((a, b) => a.index - b.index);
|
|
1207
1440
|
return deduped;
|
|
@@ -1210,9 +1443,93 @@ var CodeBlockView = import_react5.default.memo(({ store, blockId, registry }) =>
|
|
|
1210
1443
|
const preAttrs = node.props?.preAttrs ?? void 0;
|
|
1211
1444
|
const codeAttrs = node.props?.codeAttrs ?? void 0;
|
|
1212
1445
|
const virtualizationConfig = DEFAULT_VIRTUALIZED_CODE_CONFIG;
|
|
1213
|
-
const
|
|
1446
|
+
const virtualizationDisabled = typeof process !== "undefined" && typeof process.env === "object" && process.env.STREAM_MDX_DISABLE_VIRTUALIZED_CODE === "true";
|
|
1447
|
+
const shouldVirtualize = !virtualizationDisabled && virtualizationConfig.enabled && lines.length >= virtualizationConfig.virtualizeThreshold;
|
|
1214
1448
|
const virtualization = useVirtualizedCode(lines, shouldVirtualize ? virtualizationConfig : { ...virtualizationConfig, enabled: false });
|
|
1215
|
-
const
|
|
1449
|
+
const highlightRequester = useCodeHighlightRequester();
|
|
1450
|
+
const lazyEnabled = Boolean(node.block.payload.meta?.lazyTokenization);
|
|
1451
|
+
const lazyTokenizedUntil = typeof node.block.payload.meta?.lazyTokenizedUntil === "number" ? node.block.payload.meta.lazyTokenizedUntil : 0;
|
|
1452
|
+
const lastRangeRef = import_react8.default.useRef(null);
|
|
1453
|
+
const rafRef = import_react8.default.useRef(null);
|
|
1454
|
+
const idleRef = import_react8.default.useRef(null);
|
|
1455
|
+
import_react8.default.useEffect(() => {
|
|
1456
|
+
if (!shouldVirtualize || !lazyEnabled || !highlightRequester) return;
|
|
1457
|
+
const { visibleStart, visibleEnd, startIndex, endIndex } = virtualization.window;
|
|
1458
|
+
if (endIndex <= lazyTokenizedUntil) return;
|
|
1459
|
+
const nextRange = {
|
|
1460
|
+
visibleStart,
|
|
1461
|
+
visibleEnd,
|
|
1462
|
+
prefetchStart: startIndex,
|
|
1463
|
+
prefetchEnd: endIndex,
|
|
1464
|
+
tokenizedUntil: lazyTokenizedUntil
|
|
1465
|
+
};
|
|
1466
|
+
const last = lastRangeRef.current;
|
|
1467
|
+
if (last && last.visibleStart === nextRange.visibleStart && last.visibleEnd === nextRange.visibleEnd && last.prefetchStart === nextRange.prefetchStart && last.prefetchEnd === nextRange.prefetchEnd && last.tokenizedUntil === nextRange.tokenizedUntil) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
lastRangeRef.current = nextRange;
|
|
1471
|
+
if (rafRef.current !== null && typeof cancelAnimationFrame === "function") {
|
|
1472
|
+
cancelAnimationFrame(rafRef.current);
|
|
1473
|
+
}
|
|
1474
|
+
if (typeof requestAnimationFrame === "function") {
|
|
1475
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
1476
|
+
highlightRequester({
|
|
1477
|
+
blockId,
|
|
1478
|
+
startLine: visibleStart,
|
|
1479
|
+
endLine: visibleEnd,
|
|
1480
|
+
priority: "visible",
|
|
1481
|
+
reason: "scroll"
|
|
1482
|
+
});
|
|
1483
|
+
rafRef.current = null;
|
|
1484
|
+
});
|
|
1485
|
+
} else {
|
|
1486
|
+
highlightRequester({
|
|
1487
|
+
blockId,
|
|
1488
|
+
startLine: visibleStart,
|
|
1489
|
+
endLine: visibleEnd,
|
|
1490
|
+
priority: "visible",
|
|
1491
|
+
reason: "scroll"
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
const prefetchNeeded = startIndex < visibleStart || endIndex > visibleEnd;
|
|
1495
|
+
if (prefetchNeeded) {
|
|
1496
|
+
const idleCallback = globalThis.requestIdleCallback;
|
|
1497
|
+
const cancelIdle = globalThis.cancelIdleCallback;
|
|
1498
|
+
if (idleRef.current !== null) {
|
|
1499
|
+
if (typeof cancelIdle === "function") {
|
|
1500
|
+
cancelIdle(idleRef.current);
|
|
1501
|
+
} else if (typeof clearTimeout === "function") {
|
|
1502
|
+
clearTimeout(idleRef.current);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
const schedule = () => {
|
|
1506
|
+
highlightRequester({
|
|
1507
|
+
blockId,
|
|
1508
|
+
startLine: startIndex,
|
|
1509
|
+
endLine: endIndex,
|
|
1510
|
+
priority: "prefetch",
|
|
1511
|
+
reason: "buffer"
|
|
1512
|
+
});
|
|
1513
|
+
idleRef.current = null;
|
|
1514
|
+
};
|
|
1515
|
+
if (typeof idleCallback === "function") {
|
|
1516
|
+
idleRef.current = idleCallback(() => schedule());
|
|
1517
|
+
} else if (typeof setTimeout === "function") {
|
|
1518
|
+
idleRef.current = setTimeout(schedule, 80);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
}, [
|
|
1522
|
+
blockId,
|
|
1523
|
+
highlightRequester,
|
|
1524
|
+
lazyEnabled,
|
|
1525
|
+
lazyTokenizedUntil,
|
|
1526
|
+
shouldVirtualize,
|
|
1527
|
+
virtualization.window.visibleStart,
|
|
1528
|
+
virtualization.window.visibleEnd,
|
|
1529
|
+
virtualization.window.startIndex,
|
|
1530
|
+
virtualization.window.endIndex
|
|
1531
|
+
]);
|
|
1532
|
+
const highlightedHtml = import_react8.default.useMemo(() => {
|
|
1216
1533
|
if (!shouldVirtualize && node.block?.payload.highlightedHtml) {
|
|
1217
1534
|
return node.block.payload.highlightedHtml;
|
|
1218
1535
|
}
|
|
@@ -1243,11 +1560,19 @@ var CodeBlockView = import_react5.default.memo(({ store, blockId, registry }) =>
|
|
|
1243
1560
|
}
|
|
1244
1561
|
);
|
|
1245
1562
|
const codeFrameClass = "not-prose flex flex-col rounded-lg border border-input pt-1 font-mono text-sm";
|
|
1563
|
+
const codeMetricsAttrs = {
|
|
1564
|
+
"data-code-block": "true",
|
|
1565
|
+
"data-block-id": blockId,
|
|
1566
|
+
"data-code-virtualized": shouldVirtualize ? "true" : "false",
|
|
1567
|
+
"data-code-total-lines": String(lines.length),
|
|
1568
|
+
"data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines : lines.length),
|
|
1569
|
+
"data-code-window-size": String(virtualization.config.windowSize)
|
|
1570
|
+
};
|
|
1246
1571
|
const codeView = shouldVirtualize ? (() => {
|
|
1247
1572
|
const { containerRef, window: window2, handleScroll, lineHeight } = virtualization;
|
|
1248
1573
|
const spacerTop = window2.startIndex * lineHeight;
|
|
1249
1574
|
const spacerBottom = (window2.totalLines - window2.endIndex) * lineHeight;
|
|
1250
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: codeFrameClass, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1251
1576
|
"div",
|
|
1252
1577
|
{
|
|
1253
1578
|
ref: containerRef,
|
|
@@ -1261,14 +1586,22 @@ var CodeBlockView = import_react5.default.memo(({ store, blockId, registry }) =>
|
|
|
1261
1586
|
]
|
|
1262
1587
|
}
|
|
1263
1588
|
) });
|
|
1264
|
-
})() : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: codeFrameClass, children: rendered });
|
|
1589
|
+
})() : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: rendered });
|
|
1265
1590
|
const blockComponentMap = registry.getBlockComponentMap();
|
|
1266
1591
|
const MermaidComponent = Object.prototype.hasOwnProperty.call(blockComponentMap, "mermaid") ? blockComponentMap.mermaid : null;
|
|
1267
1592
|
if ((lang ?? "").toLowerCase() === "mermaid" && MermaidComponent) {
|
|
1268
1593
|
const raw = typeof node.block.payload.raw === "string" ? node.block.payload.raw : "";
|
|
1269
|
-
const fenced = (0,
|
|
1594
|
+
const fenced = (0, import_core4.stripCodeFence)(raw);
|
|
1270
1595
|
const code = fenced.hadFence ? fenced.code : raw;
|
|
1271
|
-
|
|
1596
|
+
if (deferredConfig) {
|
|
1597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: deferredRef, children: shouldRenderDeferred ? import_react8.default.createElement(MermaidComponent, {
|
|
1598
|
+
code,
|
|
1599
|
+
renderCode: codeView,
|
|
1600
|
+
meta: node.block.payload.meta,
|
|
1601
|
+
isFinalized: node.block.isFinalized
|
|
1602
|
+
}) : codeView });
|
|
1603
|
+
}
|
|
1604
|
+
return import_react8.default.createElement(MermaidComponent, {
|
|
1272
1605
|
code,
|
|
1273
1606
|
renderCode: codeView,
|
|
1274
1607
|
meta: node.block.payload.meta,
|