@stream-mdx/react 0.3.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 -14
- 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 +511 -176
- package/dist/components/index.d.cts +3 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.mjs +358 -26
- package/dist/{index-D7px9jug.d.cts → index-BVhp_pcF.d.ts} +4 -1
- package/dist/{index-D7px9jug.d.ts → index-EaeouYp2.d.cts} +4 -1
- package/dist/index.cjs +2146 -1145
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +3835 -2836
- 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 +273 -24
- package/dist/renderer/node-views.d.cts +3 -1
- package/dist/renderer/node-views.d.ts +3 -1
- package/dist/renderer/node-views.mjs +274 -25
- 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 +3386 -2727
- package/dist/renderer.d.cts +15 -12
- package/dist/renderer.d.ts +15 -12
- package/dist/renderer.mjs +3410 -2751
- package/dist/server.cjs +4842 -0
- package/dist/server.d.cts +254 -0
- package/dist/server.d.ts +254 -0
- package/dist/server.mjs +4824 -0
- package/dist/{streaming-markdown-Dp1IDgMT.d.ts → streaming-markdown-CEI9eDZm.d.ts} +3 -1
- package/dist/{streaming-markdown-DSC4L0xR.d.cts → streaming-markdown-DRisClXb.d.cts} +3 -1
- package/dist/streaming-markdown.cjs +3476 -2794
- package/dist/streaming-markdown.d.cts +4 -2
- package/dist/streaming-markdown.d.ts +4 -2
- package/dist/streaming-markdown.mjs +3436 -2754
- package/dist/utils/inline-html.d.cts +3 -1
- package/dist/utils/inline-html.d.ts +3 -1
- package/package.json +19 -3
- package/shadcn/README.md +28 -0
- package/shadcn/bottom-stick-scroll-area.tsx +358 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/renderer/node-views.tsx
|
|
4
|
-
import { stripCodeFence } from "@stream-mdx/core";
|
|
4
|
+
import { getDefaultCodeWrapperAttributes as getDefaultCodeWrapperAttributes2, stripCodeFence } from "@stream-mdx/core";
|
|
5
5
|
import React5 from "react";
|
|
6
6
|
|
|
7
7
|
// src/components/index.ts
|
|
@@ -488,7 +488,11 @@ var defaultInlineComponents = {
|
|
|
488
488
|
const n = number ?? "?";
|
|
489
489
|
const href = number ? `#fn:${n}` : void 0;
|
|
490
490
|
const id = number ? `fnref:${n}` : void 0;
|
|
491
|
-
return React2.createElement(
|
|
491
|
+
return React2.createElement(
|
|
492
|
+
"sup",
|
|
493
|
+
{ className: "footnote-ref" },
|
|
494
|
+
React2.createElement("a", { href, id, "data-label": label, style: { color: "var(--foreground)", textDecoration: "underline" } }, String(n))
|
|
495
|
+
);
|
|
492
496
|
}
|
|
493
497
|
};
|
|
494
498
|
function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRenderers) {
|
|
@@ -704,6 +708,7 @@ import {
|
|
|
704
708
|
sanitizeHTML as sanitizeHTML2,
|
|
705
709
|
PATCH_ROOT_ID
|
|
706
710
|
} from "@stream-mdx/core";
|
|
711
|
+
import { getPatchKind } from "@stream-mdx/core/perf/patch-batching";
|
|
707
712
|
var NODE_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
708
713
|
var CHILDREN_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
709
714
|
var NODE_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(NODE_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
@@ -1182,8 +1187,10 @@ var ListBlockView = React5.memo(
|
|
|
1182
1187
|
isFinalized: block?.isFinalized ?? false
|
|
1183
1188
|
});
|
|
1184
1189
|
}, [listDebugEnabled, blockId, depth, ordered, childIds, listItemIds, store, block?.isFinalized]);
|
|
1185
|
-
const listStyle = React5.useMemo(() => {
|
|
1186
|
-
if (!ordered || listItemIds.length === 0)
|
|
1190
|
+
const { listStyle, markerDigits } = React5.useMemo(() => {
|
|
1191
|
+
if (!ordered || listItemIds.length === 0) {
|
|
1192
|
+
return { listStyle: void 0, markerDigits: 1 };
|
|
1193
|
+
}
|
|
1187
1194
|
let maxDigits = 1;
|
|
1188
1195
|
listItemIds.forEach((childId, index) => {
|
|
1189
1196
|
const childNode = store.getNode(childId);
|
|
@@ -1195,9 +1202,14 @@ var ListBlockView = React5.memo(
|
|
|
1195
1202
|
const digits = digitMatch ? digitMatch.length : text.length;
|
|
1196
1203
|
if (digits > maxDigits) maxDigits = digits;
|
|
1197
1204
|
});
|
|
1198
|
-
const baseIndent = depth === 0 ? "
|
|
1205
|
+
const baseIndent = depth === 0 ? "2rem" : depth === 1 ? "1.75rem" : "1.5rem";
|
|
1206
|
+
const extraDigits = Math.max(0, maxDigits - 1);
|
|
1199
1207
|
return {
|
|
1200
|
-
|
|
1208
|
+
markerDigits: maxDigits,
|
|
1209
|
+
listStyle: {
|
|
1210
|
+
["--list-indent"]: extraDigits > 0 ? `calc(${baseIndent} + ${extraDigits}ch)` : baseIndent,
|
|
1211
|
+
["--list-marker-digits"]: String(maxDigits)
|
|
1212
|
+
}
|
|
1201
1213
|
};
|
|
1202
1214
|
}, [ordered, listItemIds, store, depth]);
|
|
1203
1215
|
if (listItemIds.length === 0) return null;
|
|
@@ -1206,6 +1218,7 @@ var ListBlockView = React5.memo(
|
|
|
1206
1218
|
{
|
|
1207
1219
|
className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
|
|
1208
1220
|
"data-list-depth": depth,
|
|
1221
|
+
"data-marker-digits": ordered ? markerDigits : void 0,
|
|
1209
1222
|
"data-list-id": listDebugEnabled ? blockId : void 0,
|
|
1210
1223
|
style: listStyle,
|
|
1211
1224
|
children: listItemIds.map((childId, index) => /* @__PURE__ */ jsx(
|
|
@@ -1387,6 +1400,7 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1387
1400
|
deferredConfig ? { ...deferredConfig, enabled: true } : { enabled: false }
|
|
1388
1401
|
);
|
|
1389
1402
|
if (!node || !node.block) return null;
|
|
1403
|
+
const blockIsFinalized = node.block.isFinalized;
|
|
1390
1404
|
const nodeVersion = node.version;
|
|
1391
1405
|
const lines = React5.useMemo(() => {
|
|
1392
1406
|
const seenIds = /* @__PURE__ */ new Set();
|
|
@@ -1417,13 +1431,25 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1417
1431
|
const lang = typeof node.props?.lang === "string" ? node.props?.lang : node.block.payload.meta?.lang;
|
|
1418
1432
|
const preAttrs = node.props?.preAttrs ?? void 0;
|
|
1419
1433
|
const codeAttrs = node.props?.codeAttrs ?? void 0;
|
|
1434
|
+
const blockMeta = node.block.payload.meta ?? void 0;
|
|
1435
|
+
const lazyEnabled = Boolean(blockMeta?.lazyTokenization);
|
|
1436
|
+
const lazyTokenizedUntil = typeof blockMeta?.lazyTokenizedUntil === "number" ? blockMeta.lazyTokenizedUntil : 0;
|
|
1437
|
+
const lazyHighlightedLines = Array.isArray(blockMeta?.highlightedLines) ? blockMeta.highlightedLines.length : 0;
|
|
1438
|
+
const lazyTokenLines = Array.isArray(blockMeta?.tokenLines) ? blockMeta.tokenLines.length : 0;
|
|
1439
|
+
const lazySourceTextLineCount = React5.useMemo(() => {
|
|
1440
|
+
const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
|
|
1441
|
+
const metaCode = typeof blockMeta?.code === "string" ? blockMeta.code : null;
|
|
1442
|
+
const sourceText = resolveCodeSourceText(raw, metaCode);
|
|
1443
|
+
if (sourceText.length === 0) return 0;
|
|
1444
|
+
return sourceText.split("\n").length;
|
|
1445
|
+
}, [blockMeta, node.block?.payload.raw]);
|
|
1446
|
+
const totalLazyLineCount = Math.max(lines.length, lazyHighlightedLines, lazyTokenLines, lazySourceTextLineCount);
|
|
1420
1447
|
const virtualizationConfig = DEFAULT_VIRTUALIZED_CODE_CONFIG;
|
|
1421
1448
|
const virtualizationDisabled = typeof process !== "undefined" && typeof process.env === "object" && process.env.STREAM_MDX_DISABLE_VIRTUALIZED_CODE === "true";
|
|
1422
|
-
const
|
|
1449
|
+
const canVirtualize = node.block.isFinalized && !lazyEnabled;
|
|
1450
|
+
const shouldVirtualize = canVirtualize && !virtualizationDisabled && virtualizationConfig.enabled && lines.length >= virtualizationConfig.virtualizeThreshold;
|
|
1423
1451
|
const virtualization = useVirtualizedCode(lines, shouldVirtualize ? virtualizationConfig : { ...virtualizationConfig, enabled: false });
|
|
1424
1452
|
const highlightRequester = useCodeHighlightRequester();
|
|
1425
|
-
const lazyEnabled = Boolean(node.block.payload.meta?.lazyTokenization);
|
|
1426
|
-
const lazyTokenizedUntil = typeof node.block.payload.meta?.lazyTokenizedUntil === "number" ? node.block.payload.meta.lazyTokenizedUntil : 0;
|
|
1427
1453
|
const lastRangeRef = React5.useRef(null);
|
|
1428
1454
|
const rafRef = React5.useRef(null);
|
|
1429
1455
|
const idleRef = React5.useRef(null);
|
|
@@ -1504,25 +1530,111 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1504
1530
|
virtualization.window.startIndex,
|
|
1505
1531
|
virtualization.window.endIndex
|
|
1506
1532
|
]);
|
|
1507
|
-
|
|
1508
|
-
if (
|
|
1509
|
-
|
|
1533
|
+
React5.useEffect(() => {
|
|
1534
|
+
if (shouldVirtualize || !blockIsFinalized || !lazyEnabled || !highlightRequester) return;
|
|
1535
|
+
if (totalLazyLineCount <= 0 || lazyTokenizedUntil >= totalLazyLineCount) return;
|
|
1536
|
+
const nextRange = {
|
|
1537
|
+
visibleStart: 0,
|
|
1538
|
+
visibleEnd: totalLazyLineCount,
|
|
1539
|
+
prefetchStart: 0,
|
|
1540
|
+
prefetchEnd: totalLazyLineCount,
|
|
1541
|
+
tokenizedUntil: lazyTokenizedUntil
|
|
1542
|
+
};
|
|
1543
|
+
const last = lastRangeRef.current;
|
|
1544
|
+
if (last && last.visibleStart === nextRange.visibleStart && last.visibleEnd === nextRange.visibleEnd && last.prefetchStart === nextRange.prefetchStart && last.prefetchEnd === nextRange.prefetchEnd && last.tokenizedUntil === nextRange.tokenizedUntil) {
|
|
1545
|
+
return;
|
|
1510
1546
|
}
|
|
1547
|
+
lastRangeRef.current = nextRange;
|
|
1548
|
+
if (rafRef.current !== null && typeof cancelAnimationFrame === "function") {
|
|
1549
|
+
cancelAnimationFrame(rafRef.current);
|
|
1550
|
+
}
|
|
1551
|
+
const requestFullHighlight = () => {
|
|
1552
|
+
highlightRequester({
|
|
1553
|
+
blockId,
|
|
1554
|
+
startLine: 0,
|
|
1555
|
+
endLine: totalLazyLineCount,
|
|
1556
|
+
priority: "visible",
|
|
1557
|
+
reason: "finalize-full"
|
|
1558
|
+
});
|
|
1559
|
+
rafRef.current = null;
|
|
1560
|
+
};
|
|
1561
|
+
if (typeof requestAnimationFrame === "function") {
|
|
1562
|
+
rafRef.current = requestAnimationFrame(requestFullHighlight);
|
|
1563
|
+
} else {
|
|
1564
|
+
requestFullHighlight();
|
|
1565
|
+
}
|
|
1566
|
+
}, [blockId, blockIsFinalized, highlightRequester, lazyEnabled, lazyTokenizedUntil, shouldVirtualize, totalLazyLineCount]);
|
|
1567
|
+
const highlightedHtml = React5.useMemo(() => {
|
|
1568
|
+
const blockHtml = node.block?.payload.highlightedHtml ?? "";
|
|
1569
|
+
const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
|
|
1570
|
+
const metaCode = typeof node.block?.payload.meta?.code === "string" ? (node.block?.payload.meta).code : null;
|
|
1571
|
+
const sourceText = resolveCodeSourceText(raw, metaCode);
|
|
1572
|
+
const sourceEndsWithNewline = sourceText.endsWith("\n");
|
|
1573
|
+
const sourceLines = sourceText.length > 0 ? sourceText.split("\n") : [];
|
|
1574
|
+
const rawFallbackLines = buildCodeFallbackLines(raw);
|
|
1575
|
+
const deterministicWrapperAttrs = getDefaultCodeWrapperAttributes2(lang);
|
|
1576
|
+
const composedPreAttrs = deterministicWrapperAttrs.preAttrs;
|
|
1577
|
+
const composedCodeAttrs = deterministicWrapperAttrs.codeAttrs;
|
|
1578
|
+
const shouldAppendTerminalNewline = (renderedLines) => {
|
|
1579
|
+
if (!sourceEndsWithNewline || renderedLines.length === 0 || lines.length === 0) {
|
|
1580
|
+
return false;
|
|
1581
|
+
}
|
|
1582
|
+
const lastRendered = renderedLines[renderedLines.length - 1];
|
|
1583
|
+
const lastKnown = lines[lines.length - 1];
|
|
1584
|
+
if (!lastRendered || !lastKnown || lastRendered.index !== lastKnown.index || lastRendered.text === "") {
|
|
1585
|
+
return false;
|
|
1586
|
+
}
|
|
1587
|
+
const expectedRenderedLineCount = Math.max(0, sourceLines.length - 1);
|
|
1588
|
+
const expectedLastRenderedLine = sourceLines.length >= 2 ? sourceLines[sourceLines.length - 2] ?? "" : "";
|
|
1589
|
+
return renderedLines.length === expectedRenderedLineCount && lastRendered.text === expectedLastRenderedLine;
|
|
1590
|
+
};
|
|
1511
1591
|
if (lines.length > 0) {
|
|
1592
|
+
const hasLineHtml = lines.some((line) => typeof line.html === "string" && line.html.length > 0);
|
|
1593
|
+
if (!hasLineHtml && blockHtml) {
|
|
1594
|
+
return blockHtml;
|
|
1595
|
+
}
|
|
1512
1596
|
if (shouldVirtualize) {
|
|
1513
|
-
return composeHighlightedHtml(
|
|
1597
|
+
return composeHighlightedHtml(
|
|
1598
|
+
virtualization.window.visibleLines,
|
|
1599
|
+
composedPreAttrs,
|
|
1600
|
+
composedCodeAttrs,
|
|
1601
|
+
shouldAppendTerminalNewline(virtualization.window.visibleLines)
|
|
1602
|
+
);
|
|
1514
1603
|
}
|
|
1515
|
-
return composeHighlightedHtml(lines,
|
|
1604
|
+
return composeHighlightedHtml(lines, composedPreAttrs, composedCodeAttrs, shouldAppendTerminalNewline(lines));
|
|
1605
|
+
}
|
|
1606
|
+
if (!shouldVirtualize && blockHtml) {
|
|
1607
|
+
const hasHighlightedLines = blockHtml.includes('class="line"');
|
|
1608
|
+
if (!hasHighlightedLines && rawFallbackLines.length > 0) {
|
|
1609
|
+
return composeHighlightedHtml(
|
|
1610
|
+
rawFallbackLines,
|
|
1611
|
+
composedPreAttrs,
|
|
1612
|
+
composedCodeAttrs,
|
|
1613
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1616
|
+
return blockHtml;
|
|
1516
1617
|
}
|
|
1517
|
-
const blockHtml = node.block?.payload.highlightedHtml ?? "";
|
|
1518
1618
|
if (blockHtml?.trim().match(/^```[\w-]*\s*$/)) {
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1619
|
+
if (rawFallbackLines.length > 0) {
|
|
1620
|
+
return composeHighlightedHtml(
|
|
1621
|
+
rawFallbackLines,
|
|
1622
|
+
composedPreAttrs,
|
|
1623
|
+
composedCodeAttrs,
|
|
1624
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1625
|
+
);
|
|
1522
1626
|
}
|
|
1523
1627
|
}
|
|
1628
|
+
if (!blockHtml && rawFallbackLines.length > 0) {
|
|
1629
|
+
return composeHighlightedHtml(
|
|
1630
|
+
rawFallbackLines,
|
|
1631
|
+
composedPreAttrs,
|
|
1632
|
+
composedCodeAttrs,
|
|
1633
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1524
1636
|
return blockHtml;
|
|
1525
|
-
}, [shouldVirtualize, node.block?.payload.highlightedHtml,
|
|
1637
|
+
}, [blockIsFinalized, shouldVirtualize, node.block?.payload.highlightedHtml, node.block?.payload.meta, lines, lang, virtualization.window.visibleLines, node.block?.payload.raw]);
|
|
1526
1638
|
const rendered = /* @__PURE__ */ jsx(
|
|
1527
1639
|
CodeComponent,
|
|
1528
1640
|
{
|
|
@@ -1534,13 +1646,19 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1534
1646
|
codeAttrs
|
|
1535
1647
|
}
|
|
1536
1648
|
);
|
|
1649
|
+
const effectiveLineCount = React5.useMemo(() => {
|
|
1650
|
+
if (lines.length > 0) {
|
|
1651
|
+
return lines.length;
|
|
1652
|
+
}
|
|
1653
|
+
return 1;
|
|
1654
|
+
}, [lines.length]);
|
|
1537
1655
|
const codeFrameClass = "not-prose flex flex-col rounded-lg border border-input pt-1 font-mono text-sm";
|
|
1538
1656
|
const codeMetricsAttrs = {
|
|
1539
1657
|
"data-code-block": "true",
|
|
1540
1658
|
"data-block-id": blockId,
|
|
1541
1659
|
"data-code-virtualized": shouldVirtualize ? "true" : "false",
|
|
1542
|
-
"data-code-total-lines": String(
|
|
1543
|
-
"data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines :
|
|
1660
|
+
"data-code-total-lines": String(effectiveLineCount),
|
|
1661
|
+
"data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines : effectiveLineCount),
|
|
1544
1662
|
"data-code-window-size": String(virtualization.config.windowSize)
|
|
1545
1663
|
};
|
|
1546
1664
|
const codeView = shouldVirtualize ? (() => {
|
|
@@ -1586,21 +1704,152 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1586
1704
|
return codeView;
|
|
1587
1705
|
});
|
|
1588
1706
|
CodeBlockView.displayName = "CodeBlockView";
|
|
1589
|
-
function composeHighlightedHtml(lines, preAttrs, codeAttrs) {
|
|
1707
|
+
function composeHighlightedHtml(lines, preAttrs, codeAttrs, appendTerminalNewline = false) {
|
|
1590
1708
|
const lineMarkup = lines.map((line) => {
|
|
1591
|
-
const content = line.html ?? escapeHtml(line.text);
|
|
1709
|
+
const content = line.html ?? renderTokenLineHtml(line.tokens) ?? escapeHtml(line.text);
|
|
1592
1710
|
const dataLine = Number.isFinite(line.index) ? ` data-line="${line.index + 1}"` : "";
|
|
1593
1711
|
return `<span class="line"${dataLine}>${content}</span>`;
|
|
1594
1712
|
}).join("\n");
|
|
1595
1713
|
const preAttr = attrsToString(preAttrs);
|
|
1596
1714
|
const codeAttr = attrsToString(codeAttrs);
|
|
1597
|
-
return `<pre${preAttr}><code${codeAttr}>${lineMarkup}
|
|
1598
|
-
|
|
1715
|
+
return `<pre${preAttr}><code${codeAttr}>${lineMarkup}${appendTerminalNewline ? "\n" : ""}</code></pre>`;
|
|
1716
|
+
}
|
|
1717
|
+
var TOKEN_FONT_STYLE_ITALIC = 1;
|
|
1718
|
+
var TOKEN_FONT_STYLE_BOLD = 2;
|
|
1719
|
+
var TOKEN_FONT_STYLE_UNDERLINE = 4;
|
|
1720
|
+
var TOKEN_FONT_STYLE_STRIKETHROUGH = 8;
|
|
1721
|
+
function renderTokenLineHtml(tokens) {
|
|
1722
|
+
if (!tokens || !Array.isArray(tokens.spans)) {
|
|
1723
|
+
return null;
|
|
1724
|
+
}
|
|
1725
|
+
return mergeRenderableTokenSpans(tokens.spans).map((span) => renderTokenSpanHtml(span)).join("");
|
|
1726
|
+
}
|
|
1727
|
+
function renderTokenSpanHtml(span) {
|
|
1728
|
+
const dark = span.v?.dark;
|
|
1729
|
+
const light = span.v?.light;
|
|
1730
|
+
const single = span.s;
|
|
1731
|
+
const styles = [];
|
|
1732
|
+
if (dark?.fg) {
|
|
1733
|
+
styles.push(`--shiki-dark:${dark.fg}`);
|
|
1734
|
+
}
|
|
1735
|
+
if (light?.fg) {
|
|
1736
|
+
styles.push(`--shiki-light:${light.fg}`);
|
|
1737
|
+
}
|
|
1738
|
+
if (!light?.fg && !dark?.fg && single?.fg) {
|
|
1739
|
+
styles.push(`color:${single.fg}`);
|
|
1740
|
+
}
|
|
1741
|
+
const fontStyle = light?.fs ?? dark?.fs ?? single?.fs;
|
|
1742
|
+
if (typeof fontStyle === "number" && fontStyle > 0) {
|
|
1743
|
+
if (fontStyle & TOKEN_FONT_STYLE_ITALIC) {
|
|
1744
|
+
styles.push("font-style: italic");
|
|
1745
|
+
}
|
|
1746
|
+
if (fontStyle & TOKEN_FONT_STYLE_BOLD) {
|
|
1747
|
+
styles.push("font-weight: bold");
|
|
1748
|
+
}
|
|
1749
|
+
const decorations = [];
|
|
1750
|
+
if (fontStyle & TOKEN_FONT_STYLE_UNDERLINE) {
|
|
1751
|
+
decorations.push("underline");
|
|
1752
|
+
}
|
|
1753
|
+
if (fontStyle & TOKEN_FONT_STYLE_STRIKETHROUGH) {
|
|
1754
|
+
decorations.push("line-through");
|
|
1755
|
+
}
|
|
1756
|
+
if (decorations.length > 0) {
|
|
1757
|
+
styles.push(`text-decoration: ${decorations.join(" ")}`);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
const content = escapeHtml(span.t ?? "");
|
|
1761
|
+
if (styles.length === 0) {
|
|
1762
|
+
return content;
|
|
1763
|
+
}
|
|
1764
|
+
return `<span style="${styles.join(";")}">${content}</span>`;
|
|
1765
|
+
}
|
|
1766
|
+
function mergeRenderableTokenSpans(spans) {
|
|
1767
|
+
if (spans.length <= 1) {
|
|
1768
|
+
return spans.slice();
|
|
1769
|
+
}
|
|
1770
|
+
const merged = [];
|
|
1771
|
+
let pendingWhitespace = "";
|
|
1772
|
+
for (const span of spans) {
|
|
1773
|
+
const text = typeof span.t === "string" ? span.t : "";
|
|
1774
|
+
if (/^[\t ]+$/.test(text)) {
|
|
1775
|
+
pendingWhitespace += text;
|
|
1776
|
+
continue;
|
|
1777
|
+
}
|
|
1778
|
+
const nextSpan = pendingWhitespace ? { ...span, t: `${pendingWhitespace}${text}` } : span;
|
|
1779
|
+
pendingWhitespace = "";
|
|
1780
|
+
const previous = merged[merged.length - 1];
|
|
1781
|
+
if (previous && sameTokenSpanStyle(previous, nextSpan)) {
|
|
1782
|
+
previous.t += nextSpan.t;
|
|
1783
|
+
} else {
|
|
1784
|
+
merged.push({ ...nextSpan });
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
if (pendingWhitespace) {
|
|
1788
|
+
const previous = merged[merged.length - 1];
|
|
1789
|
+
if (previous) {
|
|
1790
|
+
previous.t += pendingWhitespace;
|
|
1791
|
+
} else {
|
|
1792
|
+
merged.push({ t: pendingWhitespace });
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
return merged;
|
|
1796
|
+
}
|
|
1797
|
+
function sameTokenSpanStyle(a, b) {
|
|
1798
|
+
const variantKeys = /* @__PURE__ */ new Set([
|
|
1799
|
+
...Object.keys(a.v ?? {}),
|
|
1800
|
+
...Object.keys(b.v ?? {})
|
|
1801
|
+
]);
|
|
1802
|
+
for (const key of variantKeys) {
|
|
1803
|
+
const aStyle = a.v?.[key];
|
|
1804
|
+
const bStyle = b.v?.[key];
|
|
1805
|
+
if ((aStyle?.fg ?? null) !== (bStyle?.fg ?? null)) return false;
|
|
1806
|
+
if ((aStyle?.bg ?? null) !== (bStyle?.bg ?? null)) return false;
|
|
1807
|
+
if ((aStyle?.fs ?? null) !== (bStyle?.fs ?? null)) return false;
|
|
1808
|
+
}
|
|
1809
|
+
if ((a.s?.fg ?? null) !== (b.s?.fg ?? null)) return false;
|
|
1810
|
+
if ((a.s?.bg ?? null) !== (b.s?.bg ?? null)) return false;
|
|
1811
|
+
if ((a.s?.fs ?? null) !== (b.s?.fs ?? null)) return false;
|
|
1812
|
+
return true;
|
|
1813
|
+
}
|
|
1814
|
+
function resolveCodeSourceText(raw, metaCode) {
|
|
1815
|
+
if (metaCode !== null) {
|
|
1816
|
+
return metaCode.replace(/\r\n?/g, "\n");
|
|
1817
|
+
}
|
|
1818
|
+
if (!raw) return "";
|
|
1819
|
+
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
1820
|
+
const fenced = stripCodeFence(normalized);
|
|
1821
|
+
return fenced.hadFence ? fenced.code : normalized;
|
|
1599
1822
|
}
|
|
1600
1823
|
function attrsToString(attrs) {
|
|
1601
1824
|
if (!attrs) return "";
|
|
1602
1825
|
return Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttribute(value)}"`).join("");
|
|
1603
1826
|
}
|
|
1827
|
+
function buildCodeFallbackLines(raw) {
|
|
1828
|
+
const normalized = normalizeCodeFallbackRaw(raw);
|
|
1829
|
+
if (normalized.length === 0) {
|
|
1830
|
+
if (/^\s*```[^\n]*\n?\s*$/.test(raw)) {
|
|
1831
|
+
return [{ id: "temp-0", index: 0, text: "", html: null }];
|
|
1832
|
+
}
|
|
1833
|
+
return [];
|
|
1834
|
+
}
|
|
1835
|
+
return normalized.split("\n").map((line, index) => ({
|
|
1836
|
+
id: `temp-${index}`,
|
|
1837
|
+
index,
|
|
1838
|
+
text: line,
|
|
1839
|
+
html: null
|
|
1840
|
+
}));
|
|
1841
|
+
}
|
|
1842
|
+
function normalizeCodeFallbackRaw(raw) {
|
|
1843
|
+
if (!raw) return "";
|
|
1844
|
+
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
1845
|
+
const fenced = stripCodeFence(normalized);
|
|
1846
|
+
if (!fenced.hadFence) {
|
|
1847
|
+
return normalized.replace(/\n+$/, "");
|
|
1848
|
+
}
|
|
1849
|
+
let code = fenced.code;
|
|
1850
|
+
code = code.replace(/\n+$/, "");
|
|
1851
|
+
return code;
|
|
1852
|
+
}
|
|
1604
1853
|
function escapeHtml(value) {
|
|
1605
1854
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1606
1855
|
}
|
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/renderer/patch-batching.ts
|
|
22
22
|
var patch_batching_exports = {};
|
|
23
23
|
__export(patch_batching_exports, {
|
|
24
|
+
getPatchKind: () => import_patch_batching.getPatchKind,
|
|
24
25
|
isHeavyPatch: () => import_patch_batching.isHeavyPatch,
|
|
25
26
|
splitPatchBatch: () => import_patch_batching.splitPatchBatch
|
|
26
27
|
});
|
|
@@ -28,6 +29,7 @@ module.exports = __toCommonJS(patch_batching_exports);
|
|
|
28
29
|
var import_patch_batching = require("@stream-mdx/core/perf/patch-batching");
|
|
29
30
|
// Annotate the CommonJS export names for ESM import in node:
|
|
30
31
|
0 && (module.exports = {
|
|
32
|
+
getPatchKind,
|
|
31
33
|
isHeavyPatch,
|
|
32
34
|
splitPatchBatch
|
|
33
35
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { isHeavyPatch, splitPatchBatch } from '@stream-mdx/core/perf/patch-batching';
|
|
1
|
+
export { getPatchKind, isHeavyPatch, splitPatchBatch } from '@stream-mdx/core/perf/patch-batching';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { isHeavyPatch, splitPatchBatch } from '@stream-mdx/core/perf/patch-batching';
|
|
1
|
+
export { getPatchKind, isHeavyPatch, splitPatchBatch } from '@stream-mdx/core/perf/patch-batching';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/renderer/patch-batching.ts
|
|
4
|
-
import { isHeavyPatch, splitPatchBatch } from "@stream-mdx/core/perf/patch-batching";
|
|
4
|
+
import { getPatchKind, isHeavyPatch, splitPatchBatch } from "@stream-mdx/core/perf/patch-batching";
|
|
5
5
|
export {
|
|
6
|
+
getPatchKind,
|
|
6
7
|
isHeavyPatch,
|
|
7
8
|
splitPatchBatch
|
|
8
9
|
};
|