@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
|
@@ -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,29 +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;
|
|
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();
|
|
1510
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) {
|
|
1512
1592
|
const hasLineHtml = lines.some((line) => typeof line.html === "string" && line.html.length > 0);
|
|
1513
|
-
if (!hasLineHtml &&
|
|
1514
|
-
return
|
|
1593
|
+
if (!hasLineHtml && blockHtml) {
|
|
1594
|
+
return blockHtml;
|
|
1515
1595
|
}
|
|
1516
1596
|
if (shouldVirtualize) {
|
|
1517
|
-
return composeHighlightedHtml(
|
|
1597
|
+
return composeHighlightedHtml(
|
|
1598
|
+
virtualization.window.visibleLines,
|
|
1599
|
+
composedPreAttrs,
|
|
1600
|
+
composedCodeAttrs,
|
|
1601
|
+
shouldAppendTerminalNewline(virtualization.window.visibleLines)
|
|
1602
|
+
);
|
|
1518
1603
|
}
|
|
1519
|
-
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;
|
|
1520
1617
|
}
|
|
1521
|
-
const blockHtml = node.block?.payload.highlightedHtml ?? "";
|
|
1522
1618
|
if (blockHtml?.trim().match(/^```[\w-]*\s*$/)) {
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1619
|
+
if (rawFallbackLines.length > 0) {
|
|
1620
|
+
return composeHighlightedHtml(
|
|
1621
|
+
rawFallbackLines,
|
|
1622
|
+
composedPreAttrs,
|
|
1623
|
+
composedCodeAttrs,
|
|
1624
|
+
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1625
|
+
);
|
|
1526
1626
|
}
|
|
1527
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
|
+
}
|
|
1528
1636
|
return blockHtml;
|
|
1529
|
-
}, [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]);
|
|
1530
1638
|
const rendered = /* @__PURE__ */ jsx(
|
|
1531
1639
|
CodeComponent,
|
|
1532
1640
|
{
|
|
@@ -1538,13 +1646,19 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1538
1646
|
codeAttrs
|
|
1539
1647
|
}
|
|
1540
1648
|
);
|
|
1649
|
+
const effectiveLineCount = React5.useMemo(() => {
|
|
1650
|
+
if (lines.length > 0) {
|
|
1651
|
+
return lines.length;
|
|
1652
|
+
}
|
|
1653
|
+
return 1;
|
|
1654
|
+
}, [lines.length]);
|
|
1541
1655
|
const codeFrameClass = "not-prose flex flex-col rounded-lg border border-input pt-1 font-mono text-sm";
|
|
1542
1656
|
const codeMetricsAttrs = {
|
|
1543
1657
|
"data-code-block": "true",
|
|
1544
1658
|
"data-block-id": blockId,
|
|
1545
1659
|
"data-code-virtualized": shouldVirtualize ? "true" : "false",
|
|
1546
|
-
"data-code-total-lines": String(
|
|
1547
|
-
"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),
|
|
1548
1662
|
"data-code-window-size": String(virtualization.config.windowSize)
|
|
1549
1663
|
};
|
|
1550
1664
|
const codeView = shouldVirtualize ? (() => {
|
|
@@ -1590,21 +1704,152 @@ var CodeBlockView = React5.memo(({ store, blockId, registry }) => {
|
|
|
1590
1704
|
return codeView;
|
|
1591
1705
|
});
|
|
1592
1706
|
CodeBlockView.displayName = "CodeBlockView";
|
|
1593
|
-
function composeHighlightedHtml(lines, preAttrs, codeAttrs) {
|
|
1707
|
+
function composeHighlightedHtml(lines, preAttrs, codeAttrs, appendTerminalNewline = false) {
|
|
1594
1708
|
const lineMarkup = lines.map((line) => {
|
|
1595
|
-
const content = line.html ?? escapeHtml(line.text);
|
|
1709
|
+
const content = line.html ?? renderTokenLineHtml(line.tokens) ?? escapeHtml(line.text);
|
|
1596
1710
|
const dataLine = Number.isFinite(line.index) ? ` data-line="${line.index + 1}"` : "";
|
|
1597
1711
|
return `<span class="line"${dataLine}>${content}</span>`;
|
|
1598
1712
|
}).join("\n");
|
|
1599
1713
|
const preAttr = attrsToString(preAttrs);
|
|
1600
1714
|
const codeAttr = attrsToString(codeAttrs);
|
|
1601
|
-
return `<pre${preAttr}><code${codeAttr}>${lineMarkup}
|
|
1602
|
-
|
|
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;
|
|
1603
1822
|
}
|
|
1604
1823
|
function attrsToString(attrs) {
|
|
1605
1824
|
if (!attrs) return "";
|
|
1606
1825
|
return Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttribute(value)}"`).join("");
|
|
1607
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
|
+
}
|
|
1608
1853
|
function escapeHtml(value) {
|
|
1609
1854
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1610
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
|
};
|