@stream-mdx/react 0.5.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +371 -0
- package/README.md +79 -4
- package/dist/blocks-renderer-DAOBFBfi.d.ts +29 -0
- package/dist/blocks-renderer-DQEL1kJW.d.cts +29 -0
- package/dist/components/bottom-stick-scroll-area.cjs +117 -193
- package/dist/components/bottom-stick-scroll-area.mjs +112 -183
- package/dist/components/diff-renderer.cjs +86 -0
- package/dist/components/diff-renderer.d.cts +11 -0
- package/dist/components/diff-renderer.d.ts +11 -0
- package/dist/components/diff-renderer.mjs +66 -0
- package/dist/components/index.cjs +2761 -1508
- package/dist/components/index.d.cts +7 -2
- package/dist/components/index.d.ts +7 -2
- package/dist/components/index.mjs +2730 -1493
- package/dist/components/katex-math.cjs +220 -0
- package/dist/components/katex-math.d.cts +10 -0
- package/dist/components/katex-math.d.ts +10 -0
- package/dist/components/katex-math.mjs +188 -0
- package/dist/contexts/math-tracker.cjs +240 -521
- package/dist/contexts/math-tracker.mjs +235 -513
- package/dist/index-Cmne1yUK.d.cts +723 -0
- package/dist/index-D7dyyu3q.d.ts +723 -0
- package/dist/index.cjs +13029 -6475
- package/dist/index.d.cts +69 -39
- package/dist/index.d.ts +69 -39
- package/dist/index.mjs +13007 -6442
- package/dist/math/display-wrapper.cjs +7 -15
- package/dist/math/display-wrapper.d.cts +2 -2
- package/dist/math/display-wrapper.d.ts +2 -2
- package/dist/math/display-wrapper.mjs +2 -6
- package/dist/node-views-Bpc6Gkgl.d.cts +13 -0
- package/dist/node-views-DpnYdaAS.d.ts +13 -0
- package/dist/renderer/hooks.cjs +35 -20
- package/dist/renderer/hooks.d.cts +22 -1
- package/dist/renderer/hooks.d.ts +22 -1
- package/dist/renderer/hooks.mjs +27 -12
- package/dist/renderer/patch-batching.cjs +5 -8
- package/dist/renderer/patch-coalescing.cjs +5 -8
- package/dist/renderer/patch-commit-scheduler.cjs +138 -356
- package/dist/renderer/patch-commit-scheduler.d.cts +13 -1
- package/dist/renderer/patch-commit-scheduler.d.ts +13 -1
- package/dist/renderer/patch-commit-scheduler.mjs +133 -348
- package/dist/renderer/store.cjs +3775 -1373
- package/dist/renderer/store.d.cts +108 -3
- package/dist/renderer/store.d.ts +108 -3
- package/dist/renderer/store.mjs +3778 -1362
- package/dist/renderer/virtualized-code.cjs +415 -71
- package/dist/renderer/virtualized-code.d.cts +24 -23
- package/dist/renderer/virtualized-code.d.ts +24 -23
- package/dist/renderer/virtualized-code.mjs +409 -62
- package/dist/renderer.cjs +10655 -4334
- package/dist/renderer.d.cts +98 -29
- package/dist/renderer.d.ts +98 -29
- package/dist/renderer.mjs +10582 -4212
- package/dist/server-regions-CPLHGli0.d.cts +32 -0
- package/dist/server-regions-mUhyoKi7.d.ts +32 -0
- package/dist/server.cjs +10195 -3872
- package/dist/server.d.cts +17 -252
- package/dist/server.d.ts +17 -252
- package/dist/server.mjs +9997 -3649
- package/dist/{streaming-markdown-CEI9eDZm.d.ts → streaming-markdown-yELbJxyH.d.ts} +49 -55
- package/dist/{streaming-markdown-DRisClXb.d.cts → streaming-markdown-zVwFuaJG.d.cts} +49 -55
- package/dist/streaming-markdown.cjs +11660 -5378
- package/dist/streaming-markdown.d.cts +7 -2
- package/dist/streaming-markdown.d.ts +7 -2
- package/dist/streaming-markdown.mjs +11679 -5347
- package/dist/trusted-mdx/index.cjs +833 -0
- package/dist/trusted-mdx/index.d.cts +11 -0
- package/dist/trusted-mdx/index.d.ts +11 -0
- package/dist/trusted-mdx/index.mjs +807 -0
- package/dist/trusted-mdx/native-children-slot.cjs +45 -0
- package/dist/trusted-mdx/native-children-slot.d.cts +11 -0
- package/dist/trusted-mdx/native-children-slot.d.ts +11 -0
- package/dist/trusted-mdx/native-children-slot.mjs +24 -0
- package/dist/trusted-mdx/server.cjs +752 -0
- package/dist/trusted-mdx/server.d.cts +24 -0
- package/dist/trusted-mdx/server.d.ts +24 -0
- package/dist/trusted-mdx/server.mjs +724 -0
- package/dist/trusted-mdx-contract-ElKpkDI5.d.cts +113 -0
- package/dist/trusted-mdx-contract-ElKpkDI5.d.ts +113 -0
- package/dist/utils/inline-html.cjs +246 -147
- package/dist/utils/inline-html.d.cts +37 -6
- package/dist/utils/inline-html.d.ts +37 -6
- package/dist/utils/inline-html.mjs +237 -134
- package/package.json +41 -18
- package/dist/index-BVhp_pcF.d.ts +0 -251
- package/dist/index-EaeouYp2.d.cts +0 -251
- package/dist/mdx-client.cjs +0 -408
- package/dist/mdx-client.d.cts +0 -113
- package/dist/mdx-client.d.ts +0 -113
- package/dist/mdx-client.mjs +0 -369
- package/dist/mdx-coordinator.cjs +0 -584
- package/dist/mdx-coordinator.d.cts +0 -21
- package/dist/mdx-coordinator.d.ts +0 -21
- package/dist/mdx-coordinator.mjs +0 -550
- package/dist/renderer/node-views.cjs +0 -1887
- package/dist/renderer/node-views.d.cts +0 -14
- package/dist/renderer/node-views.d.ts +0 -14
- package/dist/renderer/node-views.mjs +0 -1861
|
@@ -1,1887 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all)
|
|
11
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
-
};
|
|
13
|
-
var __copyProps = (to, from, except, desc) => {
|
|
14
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
-
for (let key of __getOwnPropNames(from))
|
|
16
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
-
}
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
-
mod
|
|
28
|
-
));
|
|
29
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
-
|
|
31
|
-
// src/renderer/node-views.tsx
|
|
32
|
-
var node_views_exports = {};
|
|
33
|
-
__export(node_views_exports, {
|
|
34
|
-
BlockNodeRenderer: () => BlockNodeRenderer
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(node_views_exports);
|
|
37
|
-
var import_core4 = require("@stream-mdx/core");
|
|
38
|
-
var import_react8 = __toESM(require("react"), 1);
|
|
39
|
-
|
|
40
|
-
// src/components/index.ts
|
|
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
|
|
100
|
-
var import_core2 = require("@stream-mdx/core");
|
|
101
|
-
var import_react3 = __toESM(require("react"), 1);
|
|
102
|
-
|
|
103
|
-
// src/utils/inline-html.ts
|
|
104
|
-
var import_react2 = __toESM(require("react"), 1);
|
|
105
|
-
var BACKTICK_CONTENT = /^`([\s\S]+)`$/;
|
|
106
|
-
var DEFAULT_INLINE_HTML_RENDERERS = {
|
|
107
|
-
kbd: (descriptor, ctx) => {
|
|
108
|
-
const trimmed = descriptor.rawInner.trim();
|
|
109
|
-
const match = BACKTICK_CONTENT.exec(trimmed);
|
|
110
|
-
if (match) {
|
|
111
|
-
const codeText = decodeHtmlEntities(match[1]);
|
|
112
|
-
const props = mapAttributesToProps(descriptor.attributes);
|
|
113
|
-
if (ctx.key !== void 0 && ctx.key !== null) {
|
|
114
|
-
props.key = ctx.key;
|
|
115
|
-
}
|
|
116
|
-
return import_react2.default.createElement("kbd", props, import_react2.default.createElement("code", { className: "inline-code" }, codeText));
|
|
117
|
-
}
|
|
118
|
-
return ctx.defaultRender();
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
function renderInlineHtmlSegment(raw, sanitized, options = {}) {
|
|
122
|
-
const descriptor = parseInlineHtmlDescriptor(raw, sanitized);
|
|
123
|
-
if (!descriptor) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
const className = options.className ?? "markdown-inline-html";
|
|
127
|
-
const isInlineTag = INLINE_ELEMENTS.has(descriptor.tagName);
|
|
128
|
-
const defaultRender = () => {
|
|
129
|
-
if (!descriptor.sanitized || descriptor.sanitized.length === 0) {
|
|
130
|
-
if (!descriptor.text) {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
if (options.key !== void 0 && options.key !== null) {
|
|
134
|
-
return import_react2.default.createElement(import_react2.default.Fragment, { key: options.key }, descriptor.text);
|
|
135
|
-
}
|
|
136
|
-
return import_react2.default.createElement(import_react2.default.Fragment, {}, descriptor.text);
|
|
137
|
-
}
|
|
138
|
-
if (isInlineTag) {
|
|
139
|
-
const parsedElement = renderSanitizedHtmlTree(descriptor.sanitized, options.key);
|
|
140
|
-
if (parsedElement) {
|
|
141
|
-
return parsedElement;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
const props = {
|
|
145
|
-
className,
|
|
146
|
-
dangerouslySetInnerHTML: { __html: descriptor.sanitized }
|
|
147
|
-
};
|
|
148
|
-
if (options.key !== void 0 && options.key !== null) {
|
|
149
|
-
props.key = options.key;
|
|
150
|
-
}
|
|
151
|
-
return import_react2.default.createElement("span", props);
|
|
152
|
-
};
|
|
153
|
-
const allRenderers = options.renderers ? { ...DEFAULT_INLINE_HTML_RENDERERS, ...options.renderers } : DEFAULT_INLINE_HTML_RENDERERS;
|
|
154
|
-
const renderer = allRenderers[descriptor.tagName];
|
|
155
|
-
if (renderer) {
|
|
156
|
-
const rendered = renderer(descriptor, { key: options.key, defaultRender });
|
|
157
|
-
if (rendered) {
|
|
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 });
|
|
160
|
-
}
|
|
161
|
-
return rendered;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return defaultRender();
|
|
165
|
-
}
|
|
166
|
-
function parseInlineHtmlDescriptor(raw, sanitized) {
|
|
167
|
-
const normalizedRaw = typeof raw === "string" ? raw.trim() : "";
|
|
168
|
-
const normalizedSanitized = typeof sanitized === "string" && sanitized.length > 0 ? sanitized.trim() : normalizedRaw;
|
|
169
|
-
if (!normalizedSanitized) {
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
const match = normalizedSanitized.match(/^<([A-Za-z][\w:-]*)(\s[^>]*)?>([\s\S]*)<\/\1>$/);
|
|
173
|
-
if (!match) {
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
const [, tagNameRaw, attrString = "", sanitizedInner = ""] = match;
|
|
177
|
-
const tagName = tagNameRaw.toLowerCase();
|
|
178
|
-
const attributes = parseAttributes(attrString);
|
|
179
|
-
let rawInner = "";
|
|
180
|
-
if (normalizedRaw) {
|
|
181
|
-
const rawMatch = normalizedRaw.match(/^<([A-Za-z][\w:-]*)(\s[^>]*)?>([\s\S]*)<\/\1>$/);
|
|
182
|
-
rawInner = rawMatch ? rawMatch[3] ?? "" : normalizedRaw;
|
|
183
|
-
}
|
|
184
|
-
const text = extractPlainText(rawInner || sanitizedInner);
|
|
185
|
-
return {
|
|
186
|
-
tagName,
|
|
187
|
-
attributes,
|
|
188
|
-
raw: normalizedRaw || normalizedSanitized,
|
|
189
|
-
sanitized: normalizedSanitized,
|
|
190
|
-
rawInner,
|
|
191
|
-
sanitizedInner,
|
|
192
|
-
text
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
function parseAttributes(input) {
|
|
196
|
-
const attrs = {};
|
|
197
|
-
if (!input) return attrs;
|
|
198
|
-
const attrPattern = /([A-Za-z_:][\w:.\-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
|
|
199
|
-
let match = attrPattern.exec(input);
|
|
200
|
-
while (match !== null) {
|
|
201
|
-
const name = match[1];
|
|
202
|
-
if (!name) continue;
|
|
203
|
-
const value = match[2] ?? match[3] ?? match[4] ?? "";
|
|
204
|
-
attrs[name] = value;
|
|
205
|
-
match = attrPattern.exec(input);
|
|
206
|
-
}
|
|
207
|
-
return attrs;
|
|
208
|
-
}
|
|
209
|
-
function mapAttributesToProps(attrs) {
|
|
210
|
-
const props = {};
|
|
211
|
-
for (const [key, value] of Object.entries(attrs)) {
|
|
212
|
-
if (key === "class") {
|
|
213
|
-
props.className = value;
|
|
214
|
-
} else if (key === "style") {
|
|
215
|
-
props.style = parseStyleAttribute(value);
|
|
216
|
-
} else if (key === "tabindex" || key === "tabIndex") {
|
|
217
|
-
const normalized = normalizeTabIndex(value);
|
|
218
|
-
if (normalized !== void 0) {
|
|
219
|
-
props.tabIndex = normalized;
|
|
220
|
-
}
|
|
221
|
-
} else {
|
|
222
|
-
props[key] = value;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return props;
|
|
226
|
-
}
|
|
227
|
-
function parseStyleAttribute(value) {
|
|
228
|
-
const style = {};
|
|
229
|
-
if (!value) return style;
|
|
230
|
-
const pairs = value.split(";");
|
|
231
|
-
for (const pair of pairs) {
|
|
232
|
-
if (!pair.trim()) continue;
|
|
233
|
-
const [property, rawVal] = pair.split(":");
|
|
234
|
-
if (!property || rawVal === void 0) continue;
|
|
235
|
-
const camelProp = property.trim().replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
236
|
-
style[camelProp] = rawVal.trim();
|
|
237
|
-
}
|
|
238
|
-
return style;
|
|
239
|
-
}
|
|
240
|
-
function normalizeTabIndex(value) {
|
|
241
|
-
const numeric = Number(value);
|
|
242
|
-
return Number.isNaN(numeric) ? void 0 : numeric;
|
|
243
|
-
}
|
|
244
|
-
function decodeHtmlEntities(value) {
|
|
245
|
-
return value.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'");
|
|
246
|
-
}
|
|
247
|
-
function extractPlainText(value) {
|
|
248
|
-
if (!value) return "";
|
|
249
|
-
const withoutTags = value.replace(/<\/?[^>]+>/g, "");
|
|
250
|
-
return decodeHtmlEntities(withoutTags);
|
|
251
|
-
}
|
|
252
|
-
function renderSanitizedHtmlTree(html, key) {
|
|
253
|
-
if (typeof DOMParser === "undefined") {
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
try {
|
|
257
|
-
const parser = new DOMParser();
|
|
258
|
-
const doc = parser.parseFromString(html, "text/html");
|
|
259
|
-
const body = doc.body;
|
|
260
|
-
const nodes = Array.from(body.childNodes);
|
|
261
|
-
if (nodes.length === 0) {
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
const baseKey = typeof key === "string" || typeof key === "number" ? String(key) : "inline-html";
|
|
265
|
-
const children = nodes.map((node, index) => convertDomNode(node, `${baseKey}-${index}`)).filter((child) => child !== null && child !== void 0);
|
|
266
|
-
if (children.length === 0) {
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
269
|
-
if (children.length === 1) {
|
|
270
|
-
const [child] = children;
|
|
271
|
-
if (import_react2.default.isValidElement(child)) {
|
|
272
|
-
if (key !== void 0 && key !== null) {
|
|
273
|
-
return import_react2.default.cloneElement(child, { key });
|
|
274
|
-
}
|
|
275
|
-
return child;
|
|
276
|
-
}
|
|
277
|
-
if (typeof child === "string" || typeof child === "number") {
|
|
278
|
-
if (key !== void 0 && key !== null) {
|
|
279
|
-
return import_react2.default.createElement(import_react2.default.Fragment, { key }, child);
|
|
280
|
-
}
|
|
281
|
-
return import_react2.default.createElement(import_react2.default.Fragment, {}, child);
|
|
282
|
-
}
|
|
283
|
-
return import_react2.default.createElement(import_react2.default.Fragment, { key }, child);
|
|
284
|
-
}
|
|
285
|
-
return import_react2.default.createElement(import_react2.default.Fragment, { key }, ...children);
|
|
286
|
-
} catch {
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
function convertDomNode(node, key) {
|
|
291
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
292
|
-
return node.textContent ?? "";
|
|
293
|
-
}
|
|
294
|
-
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
297
|
-
const element = node;
|
|
298
|
-
const tagName = element.tagName.toLowerCase();
|
|
299
|
-
const attrs = getElementAttributes(element);
|
|
300
|
-
const props = mapAttributesToProps(attrs);
|
|
301
|
-
props.key = key;
|
|
302
|
-
const children = [];
|
|
303
|
-
element.childNodes.forEach((child, index) => {
|
|
304
|
-
const converted = convertDomNode(child, `${key}-${index}`);
|
|
305
|
-
if (converted !== null && converted !== void 0) {
|
|
306
|
-
children.push(converted);
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
if (children.length === 0) {
|
|
310
|
-
return import_react2.default.createElement(tagName, props);
|
|
311
|
-
}
|
|
312
|
-
return import_react2.default.createElement(tagName, props, ...children);
|
|
313
|
-
}
|
|
314
|
-
function getElementAttributes(element) {
|
|
315
|
-
const attrs = {};
|
|
316
|
-
for (const attr of Array.from(element.attributes)) {
|
|
317
|
-
attrs[attr.name] = attr.value;
|
|
318
|
-
}
|
|
319
|
-
return attrs;
|
|
320
|
-
}
|
|
321
|
-
var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
322
|
-
"a",
|
|
323
|
-
"abbr",
|
|
324
|
-
"b",
|
|
325
|
-
"bdi",
|
|
326
|
-
"bdo",
|
|
327
|
-
"br",
|
|
328
|
-
"cite",
|
|
329
|
-
"code",
|
|
330
|
-
"data",
|
|
331
|
-
"dfn",
|
|
332
|
-
"em",
|
|
333
|
-
"i",
|
|
334
|
-
"kbd",
|
|
335
|
-
"mark",
|
|
336
|
-
"q",
|
|
337
|
-
"rp",
|
|
338
|
-
"rt",
|
|
339
|
-
"ruby",
|
|
340
|
-
"s",
|
|
341
|
-
"samp",
|
|
342
|
-
"small",
|
|
343
|
-
"span",
|
|
344
|
-
"strong",
|
|
345
|
-
"sub",
|
|
346
|
-
"sup",
|
|
347
|
-
"time",
|
|
348
|
-
"u",
|
|
349
|
-
"var",
|
|
350
|
-
// MathML inline elements commonly emitted by KaTeX
|
|
351
|
-
"annotation",
|
|
352
|
-
"semantics",
|
|
353
|
-
"mtext",
|
|
354
|
-
"mn",
|
|
355
|
-
"mo",
|
|
356
|
-
"mi",
|
|
357
|
-
"mspace",
|
|
358
|
-
"mrow",
|
|
359
|
-
"msup",
|
|
360
|
-
"msub",
|
|
361
|
-
"msubsup",
|
|
362
|
-
"munder",
|
|
363
|
-
"mover",
|
|
364
|
-
"munderover",
|
|
365
|
-
"msqrt",
|
|
366
|
-
"mroot",
|
|
367
|
-
"mtable",
|
|
368
|
-
"mtr",
|
|
369
|
-
"mtd"
|
|
370
|
-
]);
|
|
371
|
-
|
|
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
|
-
};
|
|
396
|
-
function renderInlineNodes(nodes, components) {
|
|
397
|
-
return nodes.map((node, index) => {
|
|
398
|
-
const key = `${node.kind}-${index}`;
|
|
399
|
-
switch (node.kind) {
|
|
400
|
-
case "text": {
|
|
401
|
-
const textComponent = components.text;
|
|
402
|
-
if (textComponent && textComponent !== defaultInlineComponents.text) {
|
|
403
|
-
return import_react3.default.createElement(textComponent, { key, text: node.text });
|
|
404
|
-
}
|
|
405
|
-
return import_react3.default.createElement(import_react3.default.Fragment, { key, children: node.text });
|
|
406
|
-
}
|
|
407
|
-
case "strong":
|
|
408
|
-
return import_react3.default.createElement(components.strong, {
|
|
409
|
-
key,
|
|
410
|
-
children: renderInlineNodes(node.children, components)
|
|
411
|
-
});
|
|
412
|
-
case "em":
|
|
413
|
-
return import_react3.default.createElement(components.em, {
|
|
414
|
-
key,
|
|
415
|
-
children: renderInlineNodes(node.children, components)
|
|
416
|
-
});
|
|
417
|
-
case "strike": {
|
|
418
|
-
const StrikeComponent = components.strike ?? ((props) => import_react3.default.createElement("del", {}, props.children));
|
|
419
|
-
return import_react3.default.createElement(StrikeComponent, {
|
|
420
|
-
key,
|
|
421
|
-
children: renderInlineNodes(node.children, components)
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
case "code":
|
|
425
|
-
return import_react3.default.createElement(components.code, { key, text: node.text });
|
|
426
|
-
case "link":
|
|
427
|
-
return import_react3.default.createElement(
|
|
428
|
-
components.link,
|
|
429
|
-
{
|
|
430
|
-
key,
|
|
431
|
-
href: node.href,
|
|
432
|
-
title: node.title,
|
|
433
|
-
children: renderInlineNodes(node.children, components)
|
|
434
|
-
}
|
|
435
|
-
);
|
|
436
|
-
case "image":
|
|
437
|
-
return import_react3.default.createElement(components.image, {
|
|
438
|
-
key,
|
|
439
|
-
src: node.src,
|
|
440
|
-
alt: node.alt,
|
|
441
|
-
title: node.title
|
|
442
|
-
});
|
|
443
|
-
case "br":
|
|
444
|
-
return import_react3.default.createElement(import_react3.default.Fragment, { key }, import_react3.default.createElement(components.br, {}));
|
|
445
|
-
default: {
|
|
446
|
-
const component = components[node.kind];
|
|
447
|
-
if (component) {
|
|
448
|
-
return import_react3.default.createElement(component, { key, ...node });
|
|
449
|
-
}
|
|
450
|
-
return null;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
var defaultInlineComponents = {
|
|
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(
|
|
461
|
-
"code",
|
|
462
|
-
{
|
|
463
|
-
className: "inline-code"
|
|
464
|
-
},
|
|
465
|
-
text
|
|
466
|
-
),
|
|
467
|
-
link: ({ href, title, children }) => import_react3.default.createElement(
|
|
468
|
-
"a",
|
|
469
|
-
{
|
|
470
|
-
href,
|
|
471
|
-
title,
|
|
472
|
-
className: "markdown-link",
|
|
473
|
-
target: href?.startsWith("http") ? "_blank" : void 0,
|
|
474
|
-
rel: href?.startsWith("http") ? "noopener noreferrer" : void 0
|
|
475
|
-
},
|
|
476
|
-
children
|
|
477
|
-
),
|
|
478
|
-
image: ({ src, alt, title }) => import_react3.default.createElement("img", {
|
|
479
|
-
src,
|
|
480
|
-
alt,
|
|
481
|
-
title,
|
|
482
|
-
className: "markdown-image"
|
|
483
|
-
}),
|
|
484
|
-
br: () => import_react3.default.createElement("br"),
|
|
485
|
-
// Custom extensible components
|
|
486
|
-
mention: ({ handle }) => import_react3.default.createElement(
|
|
487
|
-
"span",
|
|
488
|
-
{
|
|
489
|
-
className: "mention",
|
|
490
|
-
"data-handle": handle
|
|
491
|
-
},
|
|
492
|
-
`@${handle}`
|
|
493
|
-
),
|
|
494
|
-
citation: ({ id }) => import_react3.default.createElement(
|
|
495
|
-
"span",
|
|
496
|
-
{
|
|
497
|
-
className: "citation",
|
|
498
|
-
"data-citation-id": id
|
|
499
|
-
},
|
|
500
|
-
`[${id}]`
|
|
501
|
-
),
|
|
502
|
-
"math-inline": ({ tex }) => import_react3.default.createElement(
|
|
503
|
-
"span",
|
|
504
|
-
{
|
|
505
|
-
className: "math-inline",
|
|
506
|
-
"data-tex": tex
|
|
507
|
-
},
|
|
508
|
-
`$${tex}$`
|
|
509
|
-
),
|
|
510
|
-
"math-display": ({ tex }) => import_react3.default.createElement(
|
|
511
|
-
"div",
|
|
512
|
-
{
|
|
513
|
-
className: "math-display markdown-math-display",
|
|
514
|
-
"data-tex": tex,
|
|
515
|
-
style: { overflowX: "auto" }
|
|
516
|
-
},
|
|
517
|
-
import_react3.default.createElement("span", { className: "math-display-content" }, `$$${tex}$$`)
|
|
518
|
-
),
|
|
519
|
-
// Footnote inline reference (superscript anchor)
|
|
520
|
-
"footnote-ref": ({ label, number }) => {
|
|
521
|
-
const n = number ?? "?";
|
|
522
|
-
const href = number ? `#fn:${n}` : void 0;
|
|
523
|
-
const id = number ? `fnref:${n}` : void 0;
|
|
524
|
-
return import_react3.default.createElement(
|
|
525
|
-
"sup",
|
|
526
|
-
{ className: "footnote-ref" },
|
|
527
|
-
import_react3.default.createElement("a", { href, id, "data-label": label, style: { color: "var(--foreground)", textDecoration: "underline" } }, String(n))
|
|
528
|
-
);
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRenderers) {
|
|
532
|
-
const result = [];
|
|
533
|
-
let inlineBuffer = [];
|
|
534
|
-
let inlineGroupIndex = 0;
|
|
535
|
-
const pushRenderedNodes = (nodes, target, baseKey) => {
|
|
536
|
-
nodes.forEach((node, idx) => {
|
|
537
|
-
if (node === null || node === void 0) return;
|
|
538
|
-
const key = `${baseKey}-${idx}`;
|
|
539
|
-
if (import_react3.default.isValidElement(node)) {
|
|
540
|
-
target.push(node.key === key ? node : import_react3.default.cloneElement(node, { key }));
|
|
541
|
-
} else if (typeof node === "string" || typeof node === "number") {
|
|
542
|
-
target.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, node));
|
|
543
|
-
} else {
|
|
544
|
-
target.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, node));
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
};
|
|
548
|
-
const ensureArray = (value) => {
|
|
549
|
-
if (value === null || value === void 0) {
|
|
550
|
-
return [];
|
|
551
|
-
}
|
|
552
|
-
return Array.isArray(value) ? value : [value];
|
|
553
|
-
};
|
|
554
|
-
const flushInline = () => {
|
|
555
|
-
if (inlineBuffer.length === 0) {
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
const key = `paragraph-inline-group-${inlineGroupIndex++}`;
|
|
559
|
-
result.push(
|
|
560
|
-
import_react3.default.createElement(
|
|
561
|
-
"p",
|
|
562
|
-
{
|
|
563
|
-
key,
|
|
564
|
-
className: "markdown-paragraph"
|
|
565
|
-
},
|
|
566
|
-
inlineBuffer
|
|
567
|
-
)
|
|
568
|
-
);
|
|
569
|
-
inlineBuffer = [];
|
|
570
|
-
};
|
|
571
|
-
segments.forEach((segment, index) => {
|
|
572
|
-
const key = `paragraph-segment-${index}`;
|
|
573
|
-
switch (segment.kind) {
|
|
574
|
-
case "text": {
|
|
575
|
-
const inlineNodes = Array.isArray(segment.inline) ? segment.inline : [];
|
|
576
|
-
if (inlineNodes.length === 0) {
|
|
577
|
-
if (segment.value) {
|
|
578
|
-
inlineBuffer.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, segment.value));
|
|
579
|
-
}
|
|
580
|
-
break;
|
|
581
|
-
}
|
|
582
|
-
let chunk = [];
|
|
583
|
-
const pushChunk = (chunkNodes, chunkKey) => {
|
|
584
|
-
if (chunkNodes.length === 0) return;
|
|
585
|
-
const rendered = renderInlineNodes(chunkNodes, inlineComponents);
|
|
586
|
-
pushRenderedNodes(ensureArray(rendered), inlineBuffer, chunkKey);
|
|
587
|
-
};
|
|
588
|
-
inlineNodes.forEach((inlineNode, inlineIdx) => {
|
|
589
|
-
if (inlineNode.kind === "math-display") {
|
|
590
|
-
pushChunk(chunk, `${key}-chunk-${inlineIdx}`);
|
|
591
|
-
chunk = [];
|
|
592
|
-
flushInline();
|
|
593
|
-
const rendered = renderInlineNodes([inlineNode], inlineComponents);
|
|
594
|
-
pushRenderedNodes(ensureArray(rendered), result, `${key}-math-${inlineIdx}`);
|
|
595
|
-
} else {
|
|
596
|
-
chunk.push(inlineNode);
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
pushChunk(chunk, `${key}-chunk-tail`);
|
|
600
|
-
break;
|
|
601
|
-
}
|
|
602
|
-
case "mdx": {
|
|
603
|
-
const status = segment.status ?? "pending";
|
|
604
|
-
let element;
|
|
605
|
-
if (status === "compiled") {
|
|
606
|
-
element = import_react3.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
|
|
607
|
-
} else if (status === "error") {
|
|
608
|
-
const message = segment.value || "MDX error";
|
|
609
|
-
element = import_react3.default.createElement("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error" }, message);
|
|
610
|
-
} else {
|
|
611
|
-
element = import_react3.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": status }, segment.value);
|
|
612
|
-
}
|
|
613
|
-
inlineBuffer.push(import_react3.default.createElement(import_react3.default.Fragment, { key }, element));
|
|
614
|
-
break;
|
|
615
|
-
}
|
|
616
|
-
case "html": {
|
|
617
|
-
const html = segment.sanitized ?? segment.value;
|
|
618
|
-
const isBlockLevel = isBlockLevelHtml(html);
|
|
619
|
-
const element = renderInlineHtmlSegment(segment.value, segment.sanitized, {
|
|
620
|
-
key,
|
|
621
|
-
renderers: inlineHtmlRenderers
|
|
622
|
-
});
|
|
623
|
-
if (isBlockLevel) {
|
|
624
|
-
flushInline();
|
|
625
|
-
if (element) {
|
|
626
|
-
result.push(element);
|
|
627
|
-
} else if (html) {
|
|
628
|
-
result.push(
|
|
629
|
-
import_react3.default.createElement("div", {
|
|
630
|
-
key,
|
|
631
|
-
className: "markdown-inline-html-block",
|
|
632
|
-
dangerouslySetInnerHTML: { __html: html }
|
|
633
|
-
})
|
|
634
|
-
);
|
|
635
|
-
}
|
|
636
|
-
} else if (element) {
|
|
637
|
-
inlineBuffer.push(element);
|
|
638
|
-
}
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
641
|
-
default:
|
|
642
|
-
break;
|
|
643
|
-
}
|
|
644
|
-
});
|
|
645
|
-
flushInline();
|
|
646
|
-
if (result.length === 0) {
|
|
647
|
-
return [
|
|
648
|
-
import_react3.default.createElement(
|
|
649
|
-
"p",
|
|
650
|
-
{
|
|
651
|
-
key: "paragraph-inline-group-0",
|
|
652
|
-
className: "markdown-paragraph"
|
|
653
|
-
},
|
|
654
|
-
inlineBuffer
|
|
655
|
-
)
|
|
656
|
-
];
|
|
657
|
-
}
|
|
658
|
-
return result;
|
|
659
|
-
}
|
|
660
|
-
function isBlockLevelHtml(html) {
|
|
661
|
-
if (!html) return false;
|
|
662
|
-
const trimmed = html.trim();
|
|
663
|
-
if (!trimmed.startsWith("<")) {
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
const match = trimmed.match(/^<([A-Za-z][\w:-]*)\b/);
|
|
667
|
-
if (!match) {
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
const tag = match[1].toLowerCase();
|
|
671
|
-
return BLOCK_LEVEL_TAGS.has(tag);
|
|
672
|
-
}
|
|
673
|
-
var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
674
|
-
"address",
|
|
675
|
-
"article",
|
|
676
|
-
"aside",
|
|
677
|
-
"blockquote",
|
|
678
|
-
"canvas",
|
|
679
|
-
"div",
|
|
680
|
-
"dl",
|
|
681
|
-
"fieldset",
|
|
682
|
-
"figcaption",
|
|
683
|
-
"figure",
|
|
684
|
-
"footer",
|
|
685
|
-
"form",
|
|
686
|
-
"h1",
|
|
687
|
-
"h2",
|
|
688
|
-
"h3",
|
|
689
|
-
"h4",
|
|
690
|
-
"h5",
|
|
691
|
-
"h6",
|
|
692
|
-
"header",
|
|
693
|
-
"hr",
|
|
694
|
-
"li",
|
|
695
|
-
"main",
|
|
696
|
-
"nav",
|
|
697
|
-
"ol",
|
|
698
|
-
"p",
|
|
699
|
-
"pre",
|
|
700
|
-
"section",
|
|
701
|
-
"table",
|
|
702
|
-
"ul",
|
|
703
|
-
"math"
|
|
704
|
-
]);
|
|
705
|
-
|
|
706
|
-
// src/renderer/hooks.ts
|
|
707
|
-
var import_react4 = require("react");
|
|
708
|
-
function useRendererNode(store, id) {
|
|
709
|
-
const selector = (0, import_react4.useMemo)(() => {
|
|
710
|
-
return () => store.getNodeWithVersion(id);
|
|
711
|
-
}, [store, id]);
|
|
712
|
-
const snapshot = (0, import_react4.useSyncExternalStore)(store.subscribe, selector, selector);
|
|
713
|
-
return snapshot.node;
|
|
714
|
-
}
|
|
715
|
-
function useRendererChildren(store, id) {
|
|
716
|
-
const selector = (0, import_react4.useMemo)(() => {
|
|
717
|
-
return () => store.getChildrenWithVersion(id);
|
|
718
|
-
}, [store, id]);
|
|
719
|
-
const snapshot = (0, import_react4.useSyncExternalStore)(store.subscribe, selector, selector);
|
|
720
|
-
return snapshot.children;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// src/renderer/code-highlight-context.tsx
|
|
724
|
-
var import_react5 = __toESM(require("react"), 1);
|
|
725
|
-
var CodeHighlightRequestContext = import_react5.default.createContext(null);
|
|
726
|
-
function useCodeHighlightRequester() {
|
|
727
|
-
return import_react5.default.useContext(CodeHighlightRequestContext);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// src/renderer/deferred-render-context.tsx
|
|
731
|
-
var import_react6 = __toESM(require("react"), 1);
|
|
732
|
-
var DeferredRenderContext = import_react6.default.createContext(null);
|
|
733
|
-
|
|
734
|
-
// src/renderer/store.ts
|
|
735
|
-
var import_core3 = require("@stream-mdx/core");
|
|
736
|
-
var import_patch_batching = require("@stream-mdx/core/perf/patch-batching");
|
|
737
|
-
var NODE_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
738
|
-
var CHILDREN_SNAPSHOT_CACHE_LIMIT = 5e4;
|
|
739
|
-
var NODE_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(NODE_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
740
|
-
var CHILDREN_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(CHILDREN_SNAPSHOT_CACHE_LIMIT * 0.1));
|
|
741
|
-
var EMPTY_CHILDREN = Object.freeze([]);
|
|
742
|
-
var EMPTY_NODE_SNAPSHOT = Object.freeze({ version: -1, node: void 0 });
|
|
743
|
-
var EMPTY_CHILDREN_SNAPSHOT = Object.freeze({
|
|
744
|
-
version: -1,
|
|
745
|
-
children: EMPTY_CHILDREN
|
|
746
|
-
});
|
|
747
|
-
function isListPatchDebugEnabled() {
|
|
748
|
-
if (typeof globalThis !== "undefined") {
|
|
749
|
-
const flag = globalThis.__STREAMING_LIST_DEBUG__;
|
|
750
|
-
if (flag === true) return true;
|
|
751
|
-
}
|
|
752
|
-
if (typeof process !== "undefined" && process.env.NEXT_PUBLIC_STREAMING_LIST_DEBUG === "true") {
|
|
753
|
-
return true;
|
|
754
|
-
}
|
|
755
|
-
return false;
|
|
756
|
-
}
|
|
757
|
-
var CODE_BLOCK_DEBUG_ENABLED = (() => {
|
|
758
|
-
try {
|
|
759
|
-
if (typeof process !== "undefined" && process.env && process.env.NEXT_PUBLIC_STREAMING_DEBUG_CODELINES === "1") {
|
|
760
|
-
return true;
|
|
761
|
-
}
|
|
762
|
-
if (typeof globalThis !== "undefined") {
|
|
763
|
-
const debug = globalThis?.__STREAMING_DEBUG__;
|
|
764
|
-
if (debug?.codeLines) {
|
|
765
|
-
return true;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
} catch {
|
|
769
|
-
}
|
|
770
|
-
return false;
|
|
771
|
-
})() || false;
|
|
772
|
-
var CODE_BLOCK_VALIDATION_ENABLED = typeof process !== "undefined" && process.env ? process.env.NODE_ENV !== "production" : true;
|
|
773
|
-
var getPerfNow = (() => {
|
|
774
|
-
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
775
|
-
return () => performance.now();
|
|
776
|
-
}
|
|
777
|
-
return () => Date.now();
|
|
778
|
-
})();
|
|
779
|
-
|
|
780
|
-
// src/renderer/virtualized-code.tsx
|
|
781
|
-
var import_react7 = require("react");
|
|
782
|
-
var DEFAULT_VIRTUALIZED_CODE_CONFIG = {
|
|
783
|
-
enabled: true,
|
|
784
|
-
windowSize: 100,
|
|
785
|
-
// Render 100 lines at a time
|
|
786
|
-
bufferSize: 50,
|
|
787
|
-
// +50 lines buffer above/below
|
|
788
|
-
virtualizeThreshold: 200
|
|
789
|
-
// Only virtualize if 200+ lines
|
|
790
|
-
};
|
|
791
|
-
function calculateCodeWindow(lines, scrollTop, containerHeight, lineHeight, config) {
|
|
792
|
-
const totalLines = lines.length;
|
|
793
|
-
if (!config.enabled || totalLines < config.virtualizeThreshold) {
|
|
794
|
-
return {
|
|
795
|
-
startIndex: 0,
|
|
796
|
-
endIndex: totalLines,
|
|
797
|
-
visibleStart: 0,
|
|
798
|
-
visibleEnd: totalLines,
|
|
799
|
-
visibleLines: lines,
|
|
800
|
-
totalLines,
|
|
801
|
-
mountedLines: totalLines
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
const firstVisibleLine = Math.floor(scrollTop / lineHeight);
|
|
805
|
-
const lastVisibleLine = Math.ceil((scrollTop + containerHeight) / lineHeight);
|
|
806
|
-
const visibleStart = Math.max(0, firstVisibleLine);
|
|
807
|
-
const visibleEnd = Math.min(totalLines, Math.max(visibleStart, lastVisibleLine));
|
|
808
|
-
const startIndex = Math.max(0, visibleStart - config.bufferSize);
|
|
809
|
-
const endIndex = Math.min(totalLines, visibleEnd + config.bufferSize);
|
|
810
|
-
return {
|
|
811
|
-
startIndex,
|
|
812
|
-
endIndex,
|
|
813
|
-
visibleStart,
|
|
814
|
-
visibleEnd,
|
|
815
|
-
visibleLines: lines.slice(startIndex, endIndex),
|
|
816
|
-
totalLines,
|
|
817
|
-
mountedLines: endIndex - startIndex
|
|
818
|
-
};
|
|
819
|
-
}
|
|
820
|
-
function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
|
|
821
|
-
const containerRef = (0, import_react7.useRef)(null);
|
|
822
|
-
const [scrollTop, setScrollTop] = (0, import_react7.useState)(0);
|
|
823
|
-
const [containerHeight, setContainerHeight] = (0, import_react7.useState)(0);
|
|
824
|
-
const lineHeightRef = (0, import_react7.useRef)(20);
|
|
825
|
-
(0, import_react7.useEffect)(() => {
|
|
826
|
-
if (!containerRef.current || lines.length === 0) return;
|
|
827
|
-
const timeoutId = setTimeout(() => {
|
|
828
|
-
if (!containerRef.current) return;
|
|
829
|
-
const firstLine = containerRef.current.querySelector(".line");
|
|
830
|
-
if (firstLine) {
|
|
831
|
-
const measuredHeight = firstLine.offsetHeight || 20;
|
|
832
|
-
if (measuredHeight !== lineHeightRef.current) {
|
|
833
|
-
lineHeightRef.current = measuredHeight;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}, 0);
|
|
837
|
-
return () => clearTimeout(timeoutId);
|
|
838
|
-
}, [lines.length]);
|
|
839
|
-
const handleScroll = (0, import_react7.useCallback)((e) => {
|
|
840
|
-
const target = e.currentTarget;
|
|
841
|
-
setScrollTop(target.scrollTop);
|
|
842
|
-
setContainerHeight(target.clientHeight);
|
|
843
|
-
}, []);
|
|
844
|
-
(0, import_react7.useEffect)(() => {
|
|
845
|
-
if (!containerRef.current) return;
|
|
846
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
847
|
-
for (const entry of entries) {
|
|
848
|
-
setContainerHeight(entry.contentRect.height);
|
|
849
|
-
}
|
|
850
|
-
});
|
|
851
|
-
resizeObserver.observe(containerRef.current);
|
|
852
|
-
return () => resizeObserver.disconnect();
|
|
853
|
-
}, []);
|
|
854
|
-
const window2 = (0, import_react7.useMemo)(() => {
|
|
855
|
-
return calculateCodeWindow(lines, scrollTop, containerHeight, lineHeightRef.current, config);
|
|
856
|
-
}, [lines, scrollTop, containerHeight, config]);
|
|
857
|
-
const scrollToLine = (0, import_react7.useCallback)((lineIndex) => {
|
|
858
|
-
if (!containerRef.current) return;
|
|
859
|
-
const targetScrollTop = lineIndex * lineHeightRef.current;
|
|
860
|
-
containerRef.current.scrollTop = targetScrollTop;
|
|
861
|
-
setScrollTop(targetScrollTop);
|
|
862
|
-
}, []);
|
|
863
|
-
return {
|
|
864
|
-
containerRef,
|
|
865
|
-
window: window2,
|
|
866
|
-
handleScroll,
|
|
867
|
-
scrollToLine,
|
|
868
|
-
lineHeight: lineHeightRef.current,
|
|
869
|
-
config
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
// src/renderer/node-views.tsx
|
|
874
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
875
|
-
var BlockNodeRenderer = ({ store, blockId, registry }) => {
|
|
876
|
-
const node = useRendererNode(store, blockId);
|
|
877
|
-
const block = node?.block;
|
|
878
|
-
if (!node || !block) return null;
|
|
879
|
-
switch (block.type) {
|
|
880
|
-
case "paragraph":
|
|
881
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ParagraphBlockView, { store, blockId: block.id, registry });
|
|
882
|
-
case "blockquote":
|
|
883
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockquoteBlockView, { store, blockId: block.id, registry });
|
|
884
|
-
case "list":
|
|
885
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListBlockView, { store, blockId: block.id, registry, depth: 0 });
|
|
886
|
-
case "table":
|
|
887
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableBlockView, { store, blockId: block.id, registry });
|
|
888
|
-
case "code":
|
|
889
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CodeBlockView, { store, blockId: block.id, registry });
|
|
890
|
-
case "html":
|
|
891
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HtmlBlockView, { store, blockId: block.id, registry });
|
|
892
|
-
case "mdx":
|
|
893
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MdxBlockView, { store, blockId: block.id, registry });
|
|
894
|
-
default:
|
|
895
|
-
return registry.renderBlock(block);
|
|
896
|
-
}
|
|
897
|
-
};
|
|
898
|
-
var ParagraphBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
899
|
-
const node = useRendererNode(store, blockId);
|
|
900
|
-
const block = node?.block;
|
|
901
|
-
const childIds = useRendererChildren(store, blockId);
|
|
902
|
-
if (!node || !block) {
|
|
903
|
-
return null;
|
|
904
|
-
}
|
|
905
|
-
const inlineComponents = registry.getInlineComponents();
|
|
906
|
-
if (!block.isFinalized) {
|
|
907
|
-
const raw = typeof block.payload.raw === "string" ? block.payload.raw : "";
|
|
908
|
-
const meta = block.payload.meta ?? {};
|
|
909
|
-
const segments2 = Array.isArray(meta.mixedSegments) ? meta.mixedSegments : [];
|
|
910
|
-
if (segments2.length > 0) {
|
|
911
|
-
const allowMixedStreaming = Boolean(meta.allowMixedStreaming);
|
|
912
|
-
if (!allowMixedStreaming) {
|
|
913
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
|
|
914
|
-
}
|
|
915
|
-
const structured = renderParagraphMixedSegments(segments2, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
916
|
-
if (structured.length === 1) {
|
|
917
|
-
const [single] = structured;
|
|
918
|
-
return import_react8.default.isValidElement(single) ? single : single;
|
|
919
|
-
}
|
|
920
|
-
return structured;
|
|
921
|
-
}
|
|
922
|
-
if (meta.inlineStatus === "complete" || meta.inlineStatus === "anticipated") {
|
|
923
|
-
const inlineNodes2 = block.payload.inline ?? [];
|
|
924
|
-
const containsDisplayMath2 = inlineNodes2.some((node2) => node2.kind === "math-display");
|
|
925
|
-
if (containsDisplayMath2) {
|
|
926
|
-
const derivedSegments = [
|
|
927
|
-
{
|
|
928
|
-
kind: "text",
|
|
929
|
-
value: raw,
|
|
930
|
-
inline: inlineNodes2
|
|
931
|
-
}
|
|
932
|
-
];
|
|
933
|
-
const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
934
|
-
if (structured.length === 1) {
|
|
935
|
-
const [single] = structured;
|
|
936
|
-
return import_react8.default.isValidElement(single) ? single : single;
|
|
937
|
-
}
|
|
938
|
-
return structured;
|
|
939
|
-
}
|
|
940
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph streaming-partial", children: renderInlineNodes(inlineNodes2, inlineComponents) });
|
|
941
|
-
}
|
|
942
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
|
|
943
|
-
}
|
|
944
|
-
const propsBlock = node.props?.block;
|
|
945
|
-
const inlineStatus = propsBlock?.payload?.meta?.inlineStatus ?? block.payload.meta?.inlineStatus ?? node.props?.inlineStatus;
|
|
946
|
-
if (inlineStatus && inlineStatus !== "complete") {
|
|
947
|
-
const raw = typeof block.payload.raw === "string" ? block.payload.raw : "";
|
|
948
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph", children: raw });
|
|
949
|
-
}
|
|
950
|
-
const segments = Array.isArray(block.payload.meta?.mixedSegments) ? block.payload.meta.mixedSegments : void 0;
|
|
951
|
-
if (segments && segments.length > 0) {
|
|
952
|
-
const structured = renderParagraphMixedSegments(segments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
953
|
-
if (structured.length === 1) {
|
|
954
|
-
const [single] = structured;
|
|
955
|
-
return import_react8.default.isValidElement(single) ? single : single;
|
|
956
|
-
}
|
|
957
|
-
return structured;
|
|
958
|
-
}
|
|
959
|
-
const inlineNodes = block.payload.inline ?? [];
|
|
960
|
-
const containsDisplayMath = inlineNodes.some((node2) => node2.kind === "math-display");
|
|
961
|
-
if (containsDisplayMath) {
|
|
962
|
-
const derivedSegments = [
|
|
963
|
-
{
|
|
964
|
-
kind: "text",
|
|
965
|
-
value: typeof block.payload.raw === "string" ? block.payload.raw : "",
|
|
966
|
-
inline: inlineNodes
|
|
967
|
-
}
|
|
968
|
-
];
|
|
969
|
-
const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
|
|
970
|
-
if (structured.length === 1) {
|
|
971
|
-
const [single] = structured;
|
|
972
|
-
return import_react8.default.isValidElement(single) ? single : single;
|
|
973
|
-
}
|
|
974
|
-
return structured;
|
|
975
|
-
}
|
|
976
|
-
const ParagraphComponent = registry.getBlockComponent("paragraph");
|
|
977
|
-
const baseElement = import_react8.default.createElement(ParagraphComponent, {
|
|
978
|
-
inlines: block.payload.inline ?? [],
|
|
979
|
-
raw: block.payload.raw,
|
|
980
|
-
meta: block.payload.meta
|
|
981
|
-
});
|
|
982
|
-
if (childIds.length > 0) {
|
|
983
|
-
const renderedChildren = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
984
|
-
if (import_react8.default.isValidElement(baseElement)) {
|
|
985
|
-
const { children: _ignored, className = "markdown-paragraph", inlines: _inlines, raw: _raw, meta: _meta, ...rest } = baseElement.props ?? {};
|
|
986
|
-
return import_react8.default.createElement("p", { ...rest, className }, renderedChildren);
|
|
987
|
-
}
|
|
988
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph", children: renderedChildren });
|
|
989
|
-
}
|
|
990
|
-
if (import_react8.default.isValidElement(baseElement)) {
|
|
991
|
-
return baseElement;
|
|
992
|
-
}
|
|
993
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-paragraph", children: renderInlineNodes(block.payload.inline ?? [], inlineComponents) });
|
|
994
|
-
});
|
|
995
|
-
ParagraphBlockView.displayName = "ParagraphBlockView";
|
|
996
|
-
var BlockquoteBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
997
|
-
const node = useRendererNode(store, blockId);
|
|
998
|
-
const block = node?.block;
|
|
999
|
-
const childIds = useRendererChildren(store, blockId);
|
|
1000
|
-
if (!node || !block) {
|
|
1001
|
-
return null;
|
|
1002
|
-
}
|
|
1003
|
-
const meta = block.payload.meta ?? {};
|
|
1004
|
-
const mixedSegments = Array.isArray(meta.mixedSegments) ? meta.mixedSegments : [];
|
|
1005
|
-
const normalizedText = typeof meta.normalizedText === "string" && meta.normalizedText.length > 0 ? meta.normalizedText : typeof block.payload.raw === "string" ? block.payload.raw : "";
|
|
1006
|
-
const inlineComponents = registry.getInlineComponents();
|
|
1007
|
-
const renderTextWithBreaks = (text, keyPrefix) => {
|
|
1008
|
-
const lines = text.split("\n");
|
|
1009
|
-
const lastIndex = lines.length - 1;
|
|
1010
|
-
let offset = 0;
|
|
1011
|
-
return lines.map((line, idx) => {
|
|
1012
|
-
const key = `${keyPrefix}${offset}`;
|
|
1013
|
-
offset += line.length + 1;
|
|
1014
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "markdown-blockquote-line", children: [
|
|
1015
|
-
line,
|
|
1016
|
-
idx < lastIndex ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}) : null
|
|
1017
|
-
] }, key);
|
|
1018
|
-
});
|
|
1019
|
-
};
|
|
1020
|
-
const renderInlineContent = (inline, keyPrefix) => {
|
|
1021
|
-
if (inline && inline.length > 0) {
|
|
1022
|
-
return renderInlineNodes(inline, inlineComponents);
|
|
1023
|
-
}
|
|
1024
|
-
return null;
|
|
1025
|
-
};
|
|
1026
|
-
const renderMixedSegments = () => {
|
|
1027
|
-
if (!mixedSegments.length) {
|
|
1028
|
-
return [];
|
|
1029
|
-
}
|
|
1030
|
-
const elements = [];
|
|
1031
|
-
mixedSegments.forEach((segment, segmentIndex) => {
|
|
1032
|
-
switch (segment.kind) {
|
|
1033
|
-
case "html": {
|
|
1034
|
-
const htmlNode = renderInlineHtmlSegment(segment.value, segment.sanitized ?? segment.value, {
|
|
1035
|
-
key: `blockquote-html-${block.id}-${segmentIndex}`,
|
|
1036
|
-
renderers: DEFAULT_INLINE_HTML_RENDERERS
|
|
1037
|
-
});
|
|
1038
|
-
if (htmlNode) {
|
|
1039
|
-
elements.push(htmlNode);
|
|
1040
|
-
} else {
|
|
1041
|
-
elements.push(
|
|
1042
|
-
import_react8.default.createElement("span", {
|
|
1043
|
-
key: `blockquote-html-${block.id}-${segmentIndex}`,
|
|
1044
|
-
className: "markdown-inline-html",
|
|
1045
|
-
/* biome-ignore lint/security/noDangerouslySetInnerHtml: segment content is sanitized by the worker before streaming */
|
|
1046
|
-
dangerouslySetInnerHTML: { __html: segment.sanitized ?? segment.value }
|
|
1047
|
-
})
|
|
1048
|
-
);
|
|
1049
|
-
}
|
|
1050
|
-
break;
|
|
1051
|
-
}
|
|
1052
|
-
case "mdx":
|
|
1053
|
-
elements.push(
|
|
1054
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "data-mdx-status": segment.status ?? "pending", children: segment.value }, `blockquote-mdx-${block.id}-${segmentIndex}`)
|
|
1055
|
-
);
|
|
1056
|
-
break;
|
|
1057
|
-
default: {
|
|
1058
|
-
const inline = renderInlineContent(segment.inline, `blockquote-text-inline-${block.id}-${segmentIndex}-`);
|
|
1059
|
-
if (inline) {
|
|
1060
|
-
elements.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react8.default.Fragment, { children: inline }, `blockquote-inline-${block.id}-${segmentIndex}`));
|
|
1061
|
-
} else {
|
|
1062
|
-
elements.push(
|
|
1063
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react8.default.Fragment, { children: renderTextWithBreaks(segment.value, `blockquote-text-${block.id}-${segmentIndex}-`) }, `blockquote-text-${block.id}-${segmentIndex}`)
|
|
1064
|
-
);
|
|
1065
|
-
}
|
|
1066
|
-
break;
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
});
|
|
1070
|
-
return elements;
|
|
1071
|
-
};
|
|
1072
|
-
const mixedSegmentElements = renderMixedSegments();
|
|
1073
|
-
const fallbackElements = normalizedText ? renderTextWithBreaks(normalizedText, `blockquote-fallback-${block.id}-`) : null;
|
|
1074
|
-
const inlineNodes = block.payload.inline ?? [];
|
|
1075
|
-
const inlineElements = inlineNodes.length > 0 ? renderInlineNodes(inlineNodes, inlineComponents) : null;
|
|
1076
|
-
if (!block.isFinalized) {
|
|
1077
|
-
const streamingContent = mixedSegmentElements.length ? mixedSegmentElements : inlineElements ? inlineElements : fallbackElements;
|
|
1078
|
-
const shouldShowStreaming = !block.isFinalized && (!streamingContent || Array.isArray(streamingContent) && streamingContent.length === 0);
|
|
1079
|
-
const className = shouldShowStreaming ? "markdown-blockquote streaming-partial" : "markdown-blockquote";
|
|
1080
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("blockquote", { className, children: streamingContent });
|
|
1081
|
-
}
|
|
1082
|
-
const childContent = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
1083
|
-
const renderedContent = (() => {
|
|
1084
|
-
if (mixedSegmentElements.length > 0) {
|
|
1085
|
-
return mixedSegmentElements;
|
|
1086
|
-
}
|
|
1087
|
-
if (childIds.length > 0) {
|
|
1088
|
-
const resolved = childContent.filter((child) => child !== null);
|
|
1089
|
-
if (resolved.length > 0) {
|
|
1090
|
-
return resolved;
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
if (inlineElements) {
|
|
1094
|
-
return inlineElements;
|
|
1095
|
-
}
|
|
1096
|
-
if (fallbackElements && fallbackElements.length > 0) {
|
|
1097
|
-
return fallbackElements;
|
|
1098
|
-
}
|
|
1099
|
-
return null;
|
|
1100
|
-
})();
|
|
1101
|
-
const BlockquoteComponent = registry.getBlockComponent("blockquote");
|
|
1102
|
-
const baseElement = import_react8.default.createElement(
|
|
1103
|
-
BlockquoteComponent,
|
|
1104
|
-
{
|
|
1105
|
-
inlines: block.payload.inline ?? [],
|
|
1106
|
-
renderedContent
|
|
1107
|
-
},
|
|
1108
|
-
renderedContent
|
|
1109
|
-
);
|
|
1110
|
-
if (import_react8.default.isValidElement(baseElement)) {
|
|
1111
|
-
return baseElement;
|
|
1112
|
-
}
|
|
1113
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("blockquote", { className: "markdown-blockquote", children: renderedContent });
|
|
1114
|
-
});
|
|
1115
|
-
BlockquoteBlockView.displayName = "BlockquoteBlockView";
|
|
1116
|
-
var MixedSegmentView = import_react8.default.memo(({ store, nodeId, inlineComponents }) => {
|
|
1117
|
-
const node = useRendererNode(store, nodeId);
|
|
1118
|
-
if (!node) return null;
|
|
1119
|
-
switch (node.type) {
|
|
1120
|
-
case "paragraph-text":
|
|
1121
|
-
case "blockquote-text":
|
|
1122
|
-
case "list-item-text": {
|
|
1123
|
-
const inline = node.props?.inline ?? [];
|
|
1124
|
-
if (inline.length > 0) {
|
|
1125
|
-
return renderInlineNodes(inline, inlineComponents);
|
|
1126
|
-
}
|
|
1127
|
-
const text = typeof node.props?.text === "string" ? node.props?.text : "";
|
|
1128
|
-
if (!text) return null;
|
|
1129
|
-
return text;
|
|
1130
|
-
}
|
|
1131
|
-
case "paragraph-html":
|
|
1132
|
-
case "blockquote-html":
|
|
1133
|
-
case "list-item-html": {
|
|
1134
|
-
const raw = typeof node.props?.raw === "string" ? node.props.raw : void 0;
|
|
1135
|
-
const html = typeof node.props?.html === "string" ? node.props?.html : "";
|
|
1136
|
-
const rendered = renderInlineHtmlSegment(raw, html, {
|
|
1137
|
-
key: node.id,
|
|
1138
|
-
renderers: DEFAULT_INLINE_HTML_RENDERERS
|
|
1139
|
-
});
|
|
1140
|
-
if (rendered) {
|
|
1141
|
-
return rendered;
|
|
1142
|
-
}
|
|
1143
|
-
if (!html) return null;
|
|
1144
|
-
return import_react8.default.createElement("span", {
|
|
1145
|
-
className: "markdown-inline-html",
|
|
1146
|
-
/* biome-ignore lint/security/noDangerouslySetInnerHtml: html is sanitized upstream before reaching the renderer */
|
|
1147
|
-
dangerouslySetInnerHTML: { __html: html }
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
case "paragraph-mdx":
|
|
1151
|
-
case "blockquote-mdx":
|
|
1152
|
-
case "list-item-mdx": {
|
|
1153
|
-
const status = node.props?.status ?? "pending";
|
|
1154
|
-
const raw = typeof node.props?.raw === "string" ? node.props?.raw : "";
|
|
1155
|
-
if (status === "compiled") {
|
|
1156
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
|
|
1157
|
-
}
|
|
1158
|
-
if (status === "error") {
|
|
1159
|
-
const message = raw || "MDX error";
|
|
1160
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error", children: message });
|
|
1161
|
-
}
|
|
1162
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": status, children: status === "compiled" ? "" : raw });
|
|
1163
|
-
}
|
|
1164
|
-
default:
|
|
1165
|
-
return null;
|
|
1166
|
-
}
|
|
1167
|
-
});
|
|
1168
|
-
MixedSegmentView.displayName = "MixedSegmentView";
|
|
1169
|
-
var HtmlBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1170
|
-
const node = useRendererNode(store, blockId);
|
|
1171
|
-
if (!node || !node.block) return null;
|
|
1172
|
-
return registry.renderBlock(node.block);
|
|
1173
|
-
});
|
|
1174
|
-
HtmlBlockView.displayName = "HtmlBlockView";
|
|
1175
|
-
var MdxBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1176
|
-
const node = useRendererNode(store, blockId);
|
|
1177
|
-
if (!node || !node.block) return null;
|
|
1178
|
-
return registry.renderBlock(node.block);
|
|
1179
|
-
});
|
|
1180
|
-
MdxBlockView.displayName = "MdxBlockView";
|
|
1181
|
-
var ListBlockView = import_react8.default.memo(
|
|
1182
|
-
({ store, blockId, registry, depth = 0 }) => {
|
|
1183
|
-
const node = useRendererNode(store, blockId);
|
|
1184
|
-
const block = node?.block;
|
|
1185
|
-
const childIds = useRendererChildren(store, blockId);
|
|
1186
|
-
const inlineComponents = registry.getInlineComponents();
|
|
1187
|
-
const ordered = Boolean(node?.props?.ordered ?? block?.payload.meta?.ordered);
|
|
1188
|
-
const Tag = ordered ? "ol" : "ul";
|
|
1189
|
-
const listDebugEnabled = isListPatchDebugEnabled();
|
|
1190
|
-
const listItemIds = import_react8.default.useMemo(() => {
|
|
1191
|
-
const ids = [];
|
|
1192
|
-
for (const childId of childIds) {
|
|
1193
|
-
const childNode = store.getNode(childId);
|
|
1194
|
-
if (childNode?.type === "list-item") {
|
|
1195
|
-
ids.push(childId);
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
return ids;
|
|
1199
|
-
}, [childIds, store]);
|
|
1200
|
-
import_react8.default.useEffect(() => {
|
|
1201
|
-
if (!listDebugEnabled) return;
|
|
1202
|
-
const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
|
|
1203
|
-
console.info("[stream-mdx:list-render]", {
|
|
1204
|
-
listId: blockId,
|
|
1205
|
-
depth,
|
|
1206
|
-
ordered,
|
|
1207
|
-
childIds,
|
|
1208
|
-
childTypes,
|
|
1209
|
-
listItemIds,
|
|
1210
|
-
listItems: listItemIds.length,
|
|
1211
|
-
totalChildren: childIds.length,
|
|
1212
|
-
isFinalized: block?.isFinalized ?? false
|
|
1213
|
-
});
|
|
1214
|
-
}, [listDebugEnabled, blockId, depth, ordered, childIds, listItemIds, store, block?.isFinalized]);
|
|
1215
|
-
const { listStyle, markerDigits } = import_react8.default.useMemo(() => {
|
|
1216
|
-
if (!ordered || listItemIds.length === 0) {
|
|
1217
|
-
return { listStyle: void 0, markerDigits: 1 };
|
|
1218
|
-
}
|
|
1219
|
-
let maxDigits = 1;
|
|
1220
|
-
listItemIds.forEach((childId, index) => {
|
|
1221
|
-
const childNode = store.getNode(childId);
|
|
1222
|
-
const raw = typeof childNode?.block?.payload?.raw === "string" ? childNode.block.payload.raw : void 0;
|
|
1223
|
-
const markerMatch = raw ? raw.match(/^([^\s]+)\s+/) : null;
|
|
1224
|
-
const marker = markerMatch?.[1]?.trim();
|
|
1225
|
-
const text = marker ?? `${index + 1}.`;
|
|
1226
|
-
const digitMatch = text.match(/\d/g);
|
|
1227
|
-
const digits = digitMatch ? digitMatch.length : text.length;
|
|
1228
|
-
if (digits > maxDigits) maxDigits = digits;
|
|
1229
|
-
});
|
|
1230
|
-
const baseIndent = depth === 0 ? "2rem" : depth === 1 ? "1.75rem" : "1.5rem";
|
|
1231
|
-
const extraDigits = Math.max(0, maxDigits - 1);
|
|
1232
|
-
return {
|
|
1233
|
-
markerDigits: maxDigits,
|
|
1234
|
-
listStyle: {
|
|
1235
|
-
["--list-indent"]: extraDigits > 0 ? `calc(${baseIndent} + ${extraDigits}ch)` : baseIndent,
|
|
1236
|
-
["--list-marker-digits"]: String(maxDigits)
|
|
1237
|
-
}
|
|
1238
|
-
};
|
|
1239
|
-
}, [ordered, listItemIds, store, depth]);
|
|
1240
|
-
if (listItemIds.length === 0) return null;
|
|
1241
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1242
|
-
Tag,
|
|
1243
|
-
{
|
|
1244
|
-
className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
|
|
1245
|
-
"data-list-depth": depth,
|
|
1246
|
-
"data-marker-digits": ordered ? markerDigits : void 0,
|
|
1247
|
-
"data-list-id": listDebugEnabled ? blockId : void 0,
|
|
1248
|
-
style: listStyle,
|
|
1249
|
-
children: listItemIds.map((childId, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1250
|
-
ListItemView,
|
|
1251
|
-
{
|
|
1252
|
-
store,
|
|
1253
|
-
nodeId: childId,
|
|
1254
|
-
inlineComponents,
|
|
1255
|
-
registry,
|
|
1256
|
-
ordered,
|
|
1257
|
-
index,
|
|
1258
|
-
depth
|
|
1259
|
-
},
|
|
1260
|
-
childId
|
|
1261
|
-
))
|
|
1262
|
-
}
|
|
1263
|
-
);
|
|
1264
|
-
}
|
|
1265
|
-
);
|
|
1266
|
-
ListBlockView.displayName = "ListBlockView";
|
|
1267
|
-
var ListItemView = import_react8.default.memo(({ store, nodeId, inlineComponents, registry, ordered, index, depth }) => {
|
|
1268
|
-
const node = useRendererNode(store, nodeId);
|
|
1269
|
-
const childIds = useRendererChildren(store, nodeId);
|
|
1270
|
-
const inline = node?.props?.inline ?? [];
|
|
1271
|
-
const isTask = Boolean(node?.props?.task);
|
|
1272
|
-
const isChecked = Boolean(node?.props?.checked);
|
|
1273
|
-
const block = node?.block;
|
|
1274
|
-
const raw = typeof block?.payload?.raw === "string" ? block.payload.raw : void 0;
|
|
1275
|
-
const markerMatch = raw ? raw.match(/^([^\s]+)\s+/) : null;
|
|
1276
|
-
const marker = markerMatch?.[1]?.trim();
|
|
1277
|
-
const inferredIndex = typeof node?.props?.index === "number" ? Number(node?.props?.index) : index;
|
|
1278
|
-
const isOrdered = Boolean(node?.props?.ordered ?? ordered);
|
|
1279
|
-
const counterText = !isTask ? isOrdered ? marker ? marker : `${inferredIndex + 1}.` : "\u2022" : void 0;
|
|
1280
|
-
const listDebugEnabled = isListPatchDebugEnabled();
|
|
1281
|
-
const inlineLength = inline.length;
|
|
1282
|
-
const [segmentChildIds, contentChildIds] = import_react8.default.useMemo(() => {
|
|
1283
|
-
const segments = [];
|
|
1284
|
-
const structural = [];
|
|
1285
|
-
for (const childId of childIds) {
|
|
1286
|
-
const childNode = store.getNode(childId);
|
|
1287
|
-
if (!childNode) continue;
|
|
1288
|
-
if (childNode.type?.startsWith("list-item-")) {
|
|
1289
|
-
segments.push(childId);
|
|
1290
|
-
} else {
|
|
1291
|
-
structural.push(childId);
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
return [segments, structural];
|
|
1295
|
-
}, [childIds, store]);
|
|
1296
|
-
const segmentElements = import_react8.default.useMemo(() => {
|
|
1297
|
-
return segmentChildIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
|
|
1298
|
-
}, [segmentChildIds, store, inlineComponents]);
|
|
1299
|
-
const primaryContent = import_react8.default.useMemo(() => {
|
|
1300
|
-
if (segmentChildIds.length > 0) {
|
|
1301
|
-
return segmentElements;
|
|
1302
|
-
}
|
|
1303
|
-
return renderInlineNodes(inline, inlineComponents);
|
|
1304
|
-
}, [segmentChildIds, segmentElements, inline, inlineComponents]);
|
|
1305
|
-
const trailingChildren = import_react8.default.useMemo(() => {
|
|
1306
|
-
return contentChildIds.map((childId) => {
|
|
1307
|
-
const childNode = store.getNode(childId);
|
|
1308
|
-
if (!childNode) return null;
|
|
1309
|
-
switch (childNode.type) {
|
|
1310
|
-
case "paragraph": {
|
|
1311
|
-
const childInline = childNode.props?.inline ?? [];
|
|
1312
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "markdown-list-item-paragraph", children: renderInlineNodes(childInline, inlineComponents) }, childId);
|
|
1313
|
-
}
|
|
1314
|
-
case "list":
|
|
1315
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListBlockView, { store, blockId: childId, registry, depth: depth + 1 }, childId);
|
|
1316
|
-
default:
|
|
1317
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockNodeRenderer, { store, blockId: childId, registry }, childId);
|
|
1318
|
-
}
|
|
1319
|
-
});
|
|
1320
|
-
}, [contentChildIds, store, inlineComponents, registry, depth]);
|
|
1321
|
-
const filteredChildren = trailingChildren.filter((child) => Boolean(child));
|
|
1322
|
-
const hasChildren = filteredChildren.length > 0;
|
|
1323
|
-
import_react8.default.useEffect(() => {
|
|
1324
|
-
if (!listDebugEnabled) return;
|
|
1325
|
-
const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
|
|
1326
|
-
console.info("[stream-mdx:list-item-render]", {
|
|
1327
|
-
itemId: nodeId,
|
|
1328
|
-
depth,
|
|
1329
|
-
ordered: isOrdered,
|
|
1330
|
-
inferredIndex,
|
|
1331
|
-
marker,
|
|
1332
|
-
isTask,
|
|
1333
|
-
isChecked,
|
|
1334
|
-
childIds,
|
|
1335
|
-
childTypes,
|
|
1336
|
-
segmentChildIds,
|
|
1337
|
-
contentChildIds,
|
|
1338
|
-
inlineLength,
|
|
1339
|
-
hasChildren,
|
|
1340
|
-
isFinalized: block?.isFinalized ?? false
|
|
1341
|
-
});
|
|
1342
|
-
}, [
|
|
1343
|
-
listDebugEnabled,
|
|
1344
|
-
nodeId,
|
|
1345
|
-
depth,
|
|
1346
|
-
isOrdered,
|
|
1347
|
-
inferredIndex,
|
|
1348
|
-
marker,
|
|
1349
|
-
isTask,
|
|
1350
|
-
isChecked,
|
|
1351
|
-
childIds,
|
|
1352
|
-
segmentChildIds,
|
|
1353
|
-
contentChildIds,
|
|
1354
|
-
inlineLength,
|
|
1355
|
-
hasChildren,
|
|
1356
|
-
store,
|
|
1357
|
-
block?.isFinalized
|
|
1358
|
-
]);
|
|
1359
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1360
|
-
"li",
|
|
1361
|
-
{
|
|
1362
|
-
className: `markdown-list-item${isTask ? " markdown-list-item-task" : ""}`,
|
|
1363
|
-
"data-counter-text": counterText,
|
|
1364
|
-
"data-list-depth": depth,
|
|
1365
|
-
"data-list-item-id": listDebugEnabled ? nodeId : void 0,
|
|
1366
|
-
children: [
|
|
1367
|
-
isTask ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "markdown-task", children: [
|
|
1368
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", className: "markdown-task-checkbox", checked: isChecked, readOnly: true, disabled: true, tabIndex: -1, "aria-checked": isChecked }),
|
|
1369
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "markdown-task-content", children: primaryContent })
|
|
1370
|
-
] }) : primaryContent,
|
|
1371
|
-
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "markdown-list-item-children", children: filteredChildren }) : null
|
|
1372
|
-
]
|
|
1373
|
-
}
|
|
1374
|
-
);
|
|
1375
|
-
});
|
|
1376
|
-
ListItemView.displayName = "ListItemView";
|
|
1377
|
-
var TableBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1378
|
-
const tableElements = registry.getTableElements();
|
|
1379
|
-
const childIds = useRendererChildren(store, blockId);
|
|
1380
|
-
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)) });
|
|
1381
|
-
});
|
|
1382
|
-
TableBlockView.displayName = "TableBlockView";
|
|
1383
|
-
var TableSectionView = import_react8.default.memo(({ store, nodeId, registry }) => {
|
|
1384
|
-
const node = useRendererNode(store, nodeId);
|
|
1385
|
-
if (!node) return null;
|
|
1386
|
-
const tableElements = registry.getTableElements();
|
|
1387
|
-
if (node.type === "table-header") {
|
|
1388
|
-
const childIds = useRendererChildren(store, nodeId);
|
|
1389
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(tableElements.Thead, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(tableElements.Tr, { children: childIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) }) });
|
|
1390
|
-
}
|
|
1391
|
-
if (node.type === "table-body") {
|
|
1392
|
-
const rowIds = useRendererChildren(store, nodeId);
|
|
1393
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(tableElements.Tbody, { children: rowIds.map((rowId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRowView, { store, nodeId: rowId, registry }, rowId)) });
|
|
1394
|
-
}
|
|
1395
|
-
return null;
|
|
1396
|
-
});
|
|
1397
|
-
TableSectionView.displayName = "TableSectionView";
|
|
1398
|
-
var TableRowView = import_react8.default.memo(({ store, nodeId, registry }) => {
|
|
1399
|
-
const tableElements = registry.getTableElements();
|
|
1400
|
-
const cellIds = useRendererChildren(store, nodeId);
|
|
1401
|
-
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)) });
|
|
1402
|
-
});
|
|
1403
|
-
TableRowView.displayName = "TableRowView";
|
|
1404
|
-
var TableCellView = import_react8.default.memo(({ store, nodeId, registry }) => {
|
|
1405
|
-
const node = useRendererNode(store, nodeId);
|
|
1406
|
-
const inlineComponents = registry.getInlineComponents();
|
|
1407
|
-
const tableElements = registry.getTableElements();
|
|
1408
|
-
if (!node) return null;
|
|
1409
|
-
const Tag = node.type === "table-header-cell" ? tableElements.Th : tableElements.Td;
|
|
1410
|
-
const inline = node.props?.inline ?? [];
|
|
1411
|
-
const align = node.props?.align;
|
|
1412
|
-
const content = renderInlineNodes(inline, inlineComponents);
|
|
1413
|
-
const alignProps = align ? { align } : void 0;
|
|
1414
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { ...alignProps, children: content });
|
|
1415
|
-
});
|
|
1416
|
-
TableCellView.displayName = "TableCellView";
|
|
1417
|
-
var CodeBlockView = import_react8.default.memo(({ store, blockId, registry }) => {
|
|
1418
|
-
const node = useRendererNode(store, blockId);
|
|
1419
|
-
const childIds = useRendererChildren(store, blockId);
|
|
1420
|
-
const CodeComponent = registry.getBlockComponent("code");
|
|
1421
|
-
const deferredConfig = import_react8.default.useContext(DeferredRenderContext);
|
|
1422
|
-
const deferredRef = import_react8.default.useRef(null);
|
|
1423
|
-
const shouldRenderDeferred = useDeferredRender(
|
|
1424
|
-
deferredRef,
|
|
1425
|
-
deferredConfig ? { ...deferredConfig, enabled: true } : { enabled: false }
|
|
1426
|
-
);
|
|
1427
|
-
if (!node || !node.block) return null;
|
|
1428
|
-
const blockIsFinalized = node.block.isFinalized;
|
|
1429
|
-
const nodeVersion = node.version;
|
|
1430
|
-
const lines = import_react8.default.useMemo(() => {
|
|
1431
|
-
const seenIds = /* @__PURE__ */ new Set();
|
|
1432
|
-
const seenIndices = /* @__PURE__ */ new Set();
|
|
1433
|
-
const deduped = [];
|
|
1434
|
-
for (const childId of childIds) {
|
|
1435
|
-
const child = store.getNode(childId);
|
|
1436
|
-
if (!child) continue;
|
|
1437
|
-
const index = typeof child.props?.index === "number" ? child.props?.index : deduped.length;
|
|
1438
|
-
const text = typeof child.props?.text === "string" ? child.props?.text : "";
|
|
1439
|
-
const html = typeof child.props?.html === "string" ? child.props?.html : null;
|
|
1440
|
-
const tokens = Object.prototype.hasOwnProperty.call(child.props ?? {}, "tokens") ? child.props?.tokens : void 0;
|
|
1441
|
-
if (seenIds.has(child.id) || seenIndices.has(index)) {
|
|
1442
|
-
console.warn("[renderer-view] duplicate code line detected", {
|
|
1443
|
-
blockId,
|
|
1444
|
-
childId: child.id,
|
|
1445
|
-
index
|
|
1446
|
-
});
|
|
1447
|
-
continue;
|
|
1448
|
-
}
|
|
1449
|
-
seenIds.add(child.id);
|
|
1450
|
-
seenIndices.add(index);
|
|
1451
|
-
deduped.push({ id: child.id, index, text, html, tokens });
|
|
1452
|
-
}
|
|
1453
|
-
deduped.sort((a, b) => a.index - b.index);
|
|
1454
|
-
return deduped;
|
|
1455
|
-
}, [childIds, store, blockId, nodeVersion]);
|
|
1456
|
-
const lang = typeof node.props?.lang === "string" ? node.props?.lang : node.block.payload.meta?.lang;
|
|
1457
|
-
const preAttrs = node.props?.preAttrs ?? void 0;
|
|
1458
|
-
const codeAttrs = node.props?.codeAttrs ?? void 0;
|
|
1459
|
-
const blockMeta = node.block.payload.meta ?? void 0;
|
|
1460
|
-
const lazyEnabled = Boolean(blockMeta?.lazyTokenization);
|
|
1461
|
-
const lazyTokenizedUntil = typeof blockMeta?.lazyTokenizedUntil === "number" ? blockMeta.lazyTokenizedUntil : 0;
|
|
1462
|
-
const lazyHighlightedLines = Array.isArray(blockMeta?.highlightedLines) ? blockMeta.highlightedLines.length : 0;
|
|
1463
|
-
const lazyTokenLines = Array.isArray(blockMeta?.tokenLines) ? blockMeta.tokenLines.length : 0;
|
|
1464
|
-
const lazySourceTextLineCount = import_react8.default.useMemo(() => {
|
|
1465
|
-
const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
|
|
1466
|
-
const metaCode = typeof blockMeta?.code === "string" ? blockMeta.code : null;
|
|
1467
|
-
const sourceText = resolveCodeSourceText(raw, metaCode);
|
|
1468
|
-
if (sourceText.length === 0) return 0;
|
|
1469
|
-
return sourceText.split("\n").length;
|
|
1470
|
-
}, [blockMeta, node.block?.payload.raw]);
|
|
1471
|
-
const totalLazyLineCount = Math.max(lines.length, lazyHighlightedLines, lazyTokenLines, lazySourceTextLineCount);
|
|
1472
|
-
const virtualizationConfig = DEFAULT_VIRTUALIZED_CODE_CONFIG;
|
|
1473
|
-
const virtualizationDisabled = typeof process !== "undefined" && typeof process.env === "object" && process.env.STREAM_MDX_DISABLE_VIRTUALIZED_CODE === "true";
|
|
1474
|
-
const canVirtualize = node.block.isFinalized && !lazyEnabled;
|
|
1475
|
-
const shouldVirtualize = canVirtualize && !virtualizationDisabled && virtualizationConfig.enabled && lines.length >= virtualizationConfig.virtualizeThreshold;
|
|
1476
|
-
const virtualization = useVirtualizedCode(lines, shouldVirtualize ? virtualizationConfig : { ...virtualizationConfig, enabled: false });
|
|
1477
|
-
const highlightRequester = useCodeHighlightRequester();
|
|
1478
|
-
const lastRangeRef = import_react8.default.useRef(null);
|
|
1479
|
-
const rafRef = import_react8.default.useRef(null);
|
|
1480
|
-
const idleRef = import_react8.default.useRef(null);
|
|
1481
|
-
import_react8.default.useEffect(() => {
|
|
1482
|
-
if (!shouldVirtualize || !lazyEnabled || !highlightRequester) return;
|
|
1483
|
-
const { visibleStart, visibleEnd, startIndex, endIndex } = virtualization.window;
|
|
1484
|
-
if (endIndex <= lazyTokenizedUntil) return;
|
|
1485
|
-
const nextRange = {
|
|
1486
|
-
visibleStart,
|
|
1487
|
-
visibleEnd,
|
|
1488
|
-
prefetchStart: startIndex,
|
|
1489
|
-
prefetchEnd: endIndex,
|
|
1490
|
-
tokenizedUntil: lazyTokenizedUntil
|
|
1491
|
-
};
|
|
1492
|
-
const last = lastRangeRef.current;
|
|
1493
|
-
if (last && last.visibleStart === nextRange.visibleStart && last.visibleEnd === nextRange.visibleEnd && last.prefetchStart === nextRange.prefetchStart && last.prefetchEnd === nextRange.prefetchEnd && last.tokenizedUntil === nextRange.tokenizedUntil) {
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
|
-
lastRangeRef.current = nextRange;
|
|
1497
|
-
if (rafRef.current !== null && typeof cancelAnimationFrame === "function") {
|
|
1498
|
-
cancelAnimationFrame(rafRef.current);
|
|
1499
|
-
}
|
|
1500
|
-
if (typeof requestAnimationFrame === "function") {
|
|
1501
|
-
rafRef.current = requestAnimationFrame(() => {
|
|
1502
|
-
highlightRequester({
|
|
1503
|
-
blockId,
|
|
1504
|
-
startLine: visibleStart,
|
|
1505
|
-
endLine: visibleEnd,
|
|
1506
|
-
priority: "visible",
|
|
1507
|
-
reason: "scroll"
|
|
1508
|
-
});
|
|
1509
|
-
rafRef.current = null;
|
|
1510
|
-
});
|
|
1511
|
-
} else {
|
|
1512
|
-
highlightRequester({
|
|
1513
|
-
blockId,
|
|
1514
|
-
startLine: visibleStart,
|
|
1515
|
-
endLine: visibleEnd,
|
|
1516
|
-
priority: "visible",
|
|
1517
|
-
reason: "scroll"
|
|
1518
|
-
});
|
|
1519
|
-
}
|
|
1520
|
-
const prefetchNeeded = startIndex < visibleStart || endIndex > visibleEnd;
|
|
1521
|
-
if (prefetchNeeded) {
|
|
1522
|
-
const idleCallback = globalThis.requestIdleCallback;
|
|
1523
|
-
const cancelIdle = globalThis.cancelIdleCallback;
|
|
1524
|
-
if (idleRef.current !== null) {
|
|
1525
|
-
if (typeof cancelIdle === "function") {
|
|
1526
|
-
cancelIdle(idleRef.current);
|
|
1527
|
-
} else if (typeof clearTimeout === "function") {
|
|
1528
|
-
clearTimeout(idleRef.current);
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
const schedule = () => {
|
|
1532
|
-
highlightRequester({
|
|
1533
|
-
blockId,
|
|
1534
|
-
startLine: startIndex,
|
|
1535
|
-
endLine: endIndex,
|
|
1536
|
-
priority: "prefetch",
|
|
1537
|
-
reason: "buffer"
|
|
1538
|
-
});
|
|
1539
|
-
idleRef.current = null;
|
|
1540
|
-
};
|
|
1541
|
-
if (typeof idleCallback === "function") {
|
|
1542
|
-
idleRef.current = idleCallback(() => schedule());
|
|
1543
|
-
} else if (typeof setTimeout === "function") {
|
|
1544
|
-
idleRef.current = setTimeout(schedule, 80);
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
}, [
|
|
1548
|
-
blockId,
|
|
1549
|
-
highlightRequester,
|
|
1550
|
-
lazyEnabled,
|
|
1551
|
-
lazyTokenizedUntil,
|
|
1552
|
-
shouldVirtualize,
|
|
1553
|
-
virtualization.window.visibleStart,
|
|
1554
|
-
virtualization.window.visibleEnd,
|
|
1555
|
-
virtualization.window.startIndex,
|
|
1556
|
-
virtualization.window.endIndex
|
|
1557
|
-
]);
|
|
1558
|
-
import_react8.default.useEffect(() => {
|
|
1559
|
-
if (shouldVirtualize || !blockIsFinalized || !lazyEnabled || !highlightRequester) return;
|
|
1560
|
-
if (totalLazyLineCount <= 0 || lazyTokenizedUntil >= totalLazyLineCount) return;
|
|
1561
|
-
const nextRange = {
|
|
1562
|
-
visibleStart: 0,
|
|
1563
|
-
visibleEnd: totalLazyLineCount,
|
|
1564
|
-
prefetchStart: 0,
|
|
1565
|
-
prefetchEnd: totalLazyLineCount,
|
|
1566
|
-
tokenizedUntil: lazyTokenizedUntil
|
|
1567
|
-
};
|
|
1568
|
-
const last = lastRangeRef.current;
|
|
1569
|
-
if (last && last.visibleStart === nextRange.visibleStart && last.visibleEnd === nextRange.visibleEnd && last.prefetchStart === nextRange.prefetchStart && last.prefetchEnd === nextRange.prefetchEnd && last.tokenizedUntil === nextRange.tokenizedUntil) {
|
|
1570
|
-
return;
|
|
1571
|
-
}
|
|
1572
|
-
lastRangeRef.current = nextRange;
|
|
1573
|
-
if (rafRef.current !== null && typeof cancelAnimationFrame === "function") {
|
|
1574
|
-
cancelAnimationFrame(rafRef.current);
|
|
1575
|
-
}
|
|
1576
|
-
const requestFullHighlight = () => {
|
|
1577
|
-
highlightRequester({
|
|
1578
|
-
blockId,
|
|
1579
|
-
startLine: 0,
|
|
1580
|
-
endLine: totalLazyLineCount,
|
|
1581
|
-
priority: "visible",
|
|
1582
|
-
reason: "finalize-full"
|
|
1583
|
-
});
|
|
1584
|
-
rafRef.current = null;
|
|
1585
|
-
};
|
|
1586
|
-
if (typeof requestAnimationFrame === "function") {
|
|
1587
|
-
rafRef.current = requestAnimationFrame(requestFullHighlight);
|
|
1588
|
-
} else {
|
|
1589
|
-
requestFullHighlight();
|
|
1590
|
-
}
|
|
1591
|
-
}, [blockId, blockIsFinalized, highlightRequester, lazyEnabled, lazyTokenizedUntil, shouldVirtualize, totalLazyLineCount]);
|
|
1592
|
-
const highlightedHtml = import_react8.default.useMemo(() => {
|
|
1593
|
-
const blockHtml = node.block?.payload.highlightedHtml ?? "";
|
|
1594
|
-
const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
|
|
1595
|
-
const metaCode = typeof node.block?.payload.meta?.code === "string" ? (node.block?.payload.meta).code : null;
|
|
1596
|
-
const sourceText = resolveCodeSourceText(raw, metaCode);
|
|
1597
|
-
const sourceEndsWithNewline = sourceText.endsWith("\n");
|
|
1598
|
-
const sourceLines = sourceText.length > 0 ? sourceText.split("\n") : [];
|
|
1599
|
-
const rawFallbackLines = buildCodeFallbackLines(raw);
|
|
1600
|
-
const deterministicWrapperAttrs = (0, import_core4.getDefaultCodeWrapperAttributes)(lang);
|
|
1601
|
-
const composedPreAttrs = deterministicWrapperAttrs.preAttrs;
|
|
1602
|
-
const composedCodeAttrs = deterministicWrapperAttrs.codeAttrs;
|
|
1603
|
-
const shouldAppendTerminalNewline = (renderedLines) => {
|
|
1604
|
-
if (!sourceEndsWithNewline || renderedLines.length === 0 || lines.length === 0) {
|
|
1605
|
-
return false;
|
|
1606
|
-
}
|
|
1607
|
-
const lastRendered = renderedLines[renderedLines.length - 1];
|
|
1608
|
-
const lastKnown = lines[lines.length - 1];
|
|
1609
|
-
if (!lastRendered || !lastKnown || lastRendered.index !== lastKnown.index || lastRendered.text === "") {
|
|
1610
|
-
return false;
|
|
1611
|
-
}
|
|
1612
|
-
const expectedRenderedLineCount = Math.max(0, sourceLines.length - 1);
|
|
1613
|
-
const expectedLastRenderedLine = sourceLines.length >= 2 ? sourceLines[sourceLines.length - 2] ?? "" : "";
|
|
1614
|
-
return renderedLines.length === expectedRenderedLineCount && lastRendered.text === expectedLastRenderedLine;
|
|
1615
|
-
};
|
|
1616
|
-
if (lines.length > 0) {
|
|
1617
|
-
const hasLineHtml = lines.some((line) => typeof line.html === "string" && line.html.length > 0);
|
|
1618
|
-
if (!hasLineHtml && blockHtml) {
|
|
1619
|
-
return blockHtml;
|
|
1620
|
-
}
|
|
1621
|
-
if (shouldVirtualize) {
|
|
1622
|
-
return composeHighlightedHtml(
|
|
1623
|
-
virtualization.window.visibleLines,
|
|
1624
|
-
composedPreAttrs,
|
|
1625
|
-
composedCodeAttrs,
|
|
1626
|
-
shouldAppendTerminalNewline(virtualization.window.visibleLines)
|
|
1627
|
-
);
|
|
1628
|
-
}
|
|
1629
|
-
return composeHighlightedHtml(lines, composedPreAttrs, composedCodeAttrs, shouldAppendTerminalNewline(lines));
|
|
1630
|
-
}
|
|
1631
|
-
if (!shouldVirtualize && blockHtml) {
|
|
1632
|
-
const hasHighlightedLines = blockHtml.includes('class="line"');
|
|
1633
|
-
if (!hasHighlightedLines && rawFallbackLines.length > 0) {
|
|
1634
|
-
return composeHighlightedHtml(
|
|
1635
|
-
rawFallbackLines,
|
|
1636
|
-
composedPreAttrs,
|
|
1637
|
-
composedCodeAttrs,
|
|
1638
|
-
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1639
|
-
);
|
|
1640
|
-
}
|
|
1641
|
-
return blockHtml;
|
|
1642
|
-
}
|
|
1643
|
-
if (blockHtml?.trim().match(/^```[\w-]*\s*$/)) {
|
|
1644
|
-
if (rawFallbackLines.length > 0) {
|
|
1645
|
-
return composeHighlightedHtml(
|
|
1646
|
-
rawFallbackLines,
|
|
1647
|
-
composedPreAttrs,
|
|
1648
|
-
composedCodeAttrs,
|
|
1649
|
-
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1650
|
-
);
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
if (!blockHtml && rawFallbackLines.length > 0) {
|
|
1654
|
-
return composeHighlightedHtml(
|
|
1655
|
-
rawFallbackLines,
|
|
1656
|
-
composedPreAttrs,
|
|
1657
|
-
composedCodeAttrs,
|
|
1658
|
-
sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
|
|
1659
|
-
);
|
|
1660
|
-
}
|
|
1661
|
-
return blockHtml;
|
|
1662
|
-
}, [blockIsFinalized, shouldVirtualize, node.block?.payload.highlightedHtml, node.block?.payload.meta, lines, lang, virtualization.window.visibleLines, node.block?.payload.raw]);
|
|
1663
|
-
const rendered = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1664
|
-
CodeComponent,
|
|
1665
|
-
{
|
|
1666
|
-
html: highlightedHtml,
|
|
1667
|
-
meta: node.block.payload.meta,
|
|
1668
|
-
lines: shouldVirtualize ? virtualization.window.visibleLines : lines,
|
|
1669
|
-
lang,
|
|
1670
|
-
preAttrs,
|
|
1671
|
-
codeAttrs
|
|
1672
|
-
}
|
|
1673
|
-
);
|
|
1674
|
-
const effectiveLineCount = import_react8.default.useMemo(() => {
|
|
1675
|
-
if (lines.length > 0) {
|
|
1676
|
-
return lines.length;
|
|
1677
|
-
}
|
|
1678
|
-
return 1;
|
|
1679
|
-
}, [lines.length]);
|
|
1680
|
-
const codeFrameClass = "not-prose flex flex-col rounded-lg border border-input pt-1 font-mono text-sm";
|
|
1681
|
-
const codeMetricsAttrs = {
|
|
1682
|
-
"data-code-block": "true",
|
|
1683
|
-
"data-block-id": blockId,
|
|
1684
|
-
"data-code-virtualized": shouldVirtualize ? "true" : "false",
|
|
1685
|
-
"data-code-total-lines": String(effectiveLineCount),
|
|
1686
|
-
"data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines : effectiveLineCount),
|
|
1687
|
-
"data-code-window-size": String(virtualization.config.windowSize)
|
|
1688
|
-
};
|
|
1689
|
-
const codeView = shouldVirtualize ? (() => {
|
|
1690
|
-
const { containerRef, window: window2, handleScroll, lineHeight } = virtualization;
|
|
1691
|
-
const spacerTop = window2.startIndex * lineHeight;
|
|
1692
|
-
const spacerBottom = (window2.totalLines - window2.endIndex) * lineHeight;
|
|
1693
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1694
|
-
"div",
|
|
1695
|
-
{
|
|
1696
|
-
ref: containerRef,
|
|
1697
|
-
className: "markdown-code-block-container relative",
|
|
1698
|
-
style: { overflowY: "auto", overflowX: "hidden", maxHeight: "600px" },
|
|
1699
|
-
onScroll: handleScroll,
|
|
1700
|
-
children: [
|
|
1701
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: spacerTop }, "aria-hidden": "true" }),
|
|
1702
|
-
rendered,
|
|
1703
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: spacerBottom }, "aria-hidden": "true" })
|
|
1704
|
-
]
|
|
1705
|
-
}
|
|
1706
|
-
) });
|
|
1707
|
-
})() : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: rendered });
|
|
1708
|
-
const blockComponentMap = registry.getBlockComponentMap();
|
|
1709
|
-
const MermaidComponent = Object.prototype.hasOwnProperty.call(blockComponentMap, "mermaid") ? blockComponentMap.mermaid : null;
|
|
1710
|
-
if ((lang ?? "").toLowerCase() === "mermaid" && MermaidComponent) {
|
|
1711
|
-
const raw = typeof node.block.payload.raw === "string" ? node.block.payload.raw : "";
|
|
1712
|
-
const fenced = (0, import_core4.stripCodeFence)(raw);
|
|
1713
|
-
const code = fenced.hadFence ? fenced.code : raw;
|
|
1714
|
-
if (deferredConfig) {
|
|
1715
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: deferredRef, children: shouldRenderDeferred ? import_react8.default.createElement(MermaidComponent, {
|
|
1716
|
-
code,
|
|
1717
|
-
renderCode: codeView,
|
|
1718
|
-
meta: node.block.payload.meta,
|
|
1719
|
-
isFinalized: node.block.isFinalized
|
|
1720
|
-
}) : codeView });
|
|
1721
|
-
}
|
|
1722
|
-
return import_react8.default.createElement(MermaidComponent, {
|
|
1723
|
-
code,
|
|
1724
|
-
renderCode: codeView,
|
|
1725
|
-
meta: node.block.payload.meta,
|
|
1726
|
-
isFinalized: node.block.isFinalized
|
|
1727
|
-
});
|
|
1728
|
-
}
|
|
1729
|
-
return codeView;
|
|
1730
|
-
});
|
|
1731
|
-
CodeBlockView.displayName = "CodeBlockView";
|
|
1732
|
-
function composeHighlightedHtml(lines, preAttrs, codeAttrs, appendTerminalNewline = false) {
|
|
1733
|
-
const lineMarkup = lines.map((line) => {
|
|
1734
|
-
const content = line.html ?? renderTokenLineHtml(line.tokens) ?? escapeHtml(line.text);
|
|
1735
|
-
const dataLine = Number.isFinite(line.index) ? ` data-line="${line.index + 1}"` : "";
|
|
1736
|
-
return `<span class="line"${dataLine}>${content}</span>`;
|
|
1737
|
-
}).join("\n");
|
|
1738
|
-
const preAttr = attrsToString(preAttrs);
|
|
1739
|
-
const codeAttr = attrsToString(codeAttrs);
|
|
1740
|
-
return `<pre${preAttr}><code${codeAttr}>${lineMarkup}${appendTerminalNewline ? "\n" : ""}</code></pre>`;
|
|
1741
|
-
}
|
|
1742
|
-
var TOKEN_FONT_STYLE_ITALIC = 1;
|
|
1743
|
-
var TOKEN_FONT_STYLE_BOLD = 2;
|
|
1744
|
-
var TOKEN_FONT_STYLE_UNDERLINE = 4;
|
|
1745
|
-
var TOKEN_FONT_STYLE_STRIKETHROUGH = 8;
|
|
1746
|
-
function renderTokenLineHtml(tokens) {
|
|
1747
|
-
if (!tokens || !Array.isArray(tokens.spans)) {
|
|
1748
|
-
return null;
|
|
1749
|
-
}
|
|
1750
|
-
return mergeRenderableTokenSpans(tokens.spans).map((span) => renderTokenSpanHtml(span)).join("");
|
|
1751
|
-
}
|
|
1752
|
-
function renderTokenSpanHtml(span) {
|
|
1753
|
-
const dark = span.v?.dark;
|
|
1754
|
-
const light = span.v?.light;
|
|
1755
|
-
const single = span.s;
|
|
1756
|
-
const styles = [];
|
|
1757
|
-
if (dark?.fg) {
|
|
1758
|
-
styles.push(`--shiki-dark:${dark.fg}`);
|
|
1759
|
-
}
|
|
1760
|
-
if (light?.fg) {
|
|
1761
|
-
styles.push(`--shiki-light:${light.fg}`);
|
|
1762
|
-
}
|
|
1763
|
-
if (!light?.fg && !dark?.fg && single?.fg) {
|
|
1764
|
-
styles.push(`color:${single.fg}`);
|
|
1765
|
-
}
|
|
1766
|
-
const fontStyle = light?.fs ?? dark?.fs ?? single?.fs;
|
|
1767
|
-
if (typeof fontStyle === "number" && fontStyle > 0) {
|
|
1768
|
-
if (fontStyle & TOKEN_FONT_STYLE_ITALIC) {
|
|
1769
|
-
styles.push("font-style: italic");
|
|
1770
|
-
}
|
|
1771
|
-
if (fontStyle & TOKEN_FONT_STYLE_BOLD) {
|
|
1772
|
-
styles.push("font-weight: bold");
|
|
1773
|
-
}
|
|
1774
|
-
const decorations = [];
|
|
1775
|
-
if (fontStyle & TOKEN_FONT_STYLE_UNDERLINE) {
|
|
1776
|
-
decorations.push("underline");
|
|
1777
|
-
}
|
|
1778
|
-
if (fontStyle & TOKEN_FONT_STYLE_STRIKETHROUGH) {
|
|
1779
|
-
decorations.push("line-through");
|
|
1780
|
-
}
|
|
1781
|
-
if (decorations.length > 0) {
|
|
1782
|
-
styles.push(`text-decoration: ${decorations.join(" ")}`);
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
const content = escapeHtml(span.t ?? "");
|
|
1786
|
-
if (styles.length === 0) {
|
|
1787
|
-
return content;
|
|
1788
|
-
}
|
|
1789
|
-
return `<span style="${styles.join(";")}">${content}</span>`;
|
|
1790
|
-
}
|
|
1791
|
-
function mergeRenderableTokenSpans(spans) {
|
|
1792
|
-
if (spans.length <= 1) {
|
|
1793
|
-
return spans.slice();
|
|
1794
|
-
}
|
|
1795
|
-
const merged = [];
|
|
1796
|
-
let pendingWhitespace = "";
|
|
1797
|
-
for (const span of spans) {
|
|
1798
|
-
const text = typeof span.t === "string" ? span.t : "";
|
|
1799
|
-
if (/^[\t ]+$/.test(text)) {
|
|
1800
|
-
pendingWhitespace += text;
|
|
1801
|
-
continue;
|
|
1802
|
-
}
|
|
1803
|
-
const nextSpan = pendingWhitespace ? { ...span, t: `${pendingWhitespace}${text}` } : span;
|
|
1804
|
-
pendingWhitespace = "";
|
|
1805
|
-
const previous = merged[merged.length - 1];
|
|
1806
|
-
if (previous && sameTokenSpanStyle(previous, nextSpan)) {
|
|
1807
|
-
previous.t += nextSpan.t;
|
|
1808
|
-
} else {
|
|
1809
|
-
merged.push({ ...nextSpan });
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
if (pendingWhitespace) {
|
|
1813
|
-
const previous = merged[merged.length - 1];
|
|
1814
|
-
if (previous) {
|
|
1815
|
-
previous.t += pendingWhitespace;
|
|
1816
|
-
} else {
|
|
1817
|
-
merged.push({ t: pendingWhitespace });
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
return merged;
|
|
1821
|
-
}
|
|
1822
|
-
function sameTokenSpanStyle(a, b) {
|
|
1823
|
-
const variantKeys = /* @__PURE__ */ new Set([
|
|
1824
|
-
...Object.keys(a.v ?? {}),
|
|
1825
|
-
...Object.keys(b.v ?? {})
|
|
1826
|
-
]);
|
|
1827
|
-
for (const key of variantKeys) {
|
|
1828
|
-
const aStyle = a.v?.[key];
|
|
1829
|
-
const bStyle = b.v?.[key];
|
|
1830
|
-
if ((aStyle?.fg ?? null) !== (bStyle?.fg ?? null)) return false;
|
|
1831
|
-
if ((aStyle?.bg ?? null) !== (bStyle?.bg ?? null)) return false;
|
|
1832
|
-
if ((aStyle?.fs ?? null) !== (bStyle?.fs ?? null)) return false;
|
|
1833
|
-
}
|
|
1834
|
-
if ((a.s?.fg ?? null) !== (b.s?.fg ?? null)) return false;
|
|
1835
|
-
if ((a.s?.bg ?? null) !== (b.s?.bg ?? null)) return false;
|
|
1836
|
-
if ((a.s?.fs ?? null) !== (b.s?.fs ?? null)) return false;
|
|
1837
|
-
return true;
|
|
1838
|
-
}
|
|
1839
|
-
function resolveCodeSourceText(raw, metaCode) {
|
|
1840
|
-
if (metaCode !== null) {
|
|
1841
|
-
return metaCode.replace(/\r\n?/g, "\n");
|
|
1842
|
-
}
|
|
1843
|
-
if (!raw) return "";
|
|
1844
|
-
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
1845
|
-
const fenced = (0, import_core4.stripCodeFence)(normalized);
|
|
1846
|
-
return fenced.hadFence ? fenced.code : normalized;
|
|
1847
|
-
}
|
|
1848
|
-
function attrsToString(attrs) {
|
|
1849
|
-
if (!attrs) return "";
|
|
1850
|
-
return Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttribute(value)}"`).join("");
|
|
1851
|
-
}
|
|
1852
|
-
function buildCodeFallbackLines(raw) {
|
|
1853
|
-
const normalized = normalizeCodeFallbackRaw(raw);
|
|
1854
|
-
if (normalized.length === 0) {
|
|
1855
|
-
if (/^\s*```[^\n]*\n?\s*$/.test(raw)) {
|
|
1856
|
-
return [{ id: "temp-0", index: 0, text: "", html: null }];
|
|
1857
|
-
}
|
|
1858
|
-
return [];
|
|
1859
|
-
}
|
|
1860
|
-
return normalized.split("\n").map((line, index) => ({
|
|
1861
|
-
id: `temp-${index}`,
|
|
1862
|
-
index,
|
|
1863
|
-
text: line,
|
|
1864
|
-
html: null
|
|
1865
|
-
}));
|
|
1866
|
-
}
|
|
1867
|
-
function normalizeCodeFallbackRaw(raw) {
|
|
1868
|
-
if (!raw) return "";
|
|
1869
|
-
const normalized = raw.replace(/\r\n?/g, "\n");
|
|
1870
|
-
const fenced = (0, import_core4.stripCodeFence)(normalized);
|
|
1871
|
-
if (!fenced.hadFence) {
|
|
1872
|
-
return normalized.replace(/\n+$/, "");
|
|
1873
|
-
}
|
|
1874
|
-
let code = fenced.code;
|
|
1875
|
-
code = code.replace(/\n+$/, "");
|
|
1876
|
-
return code;
|
|
1877
|
-
}
|
|
1878
|
-
function escapeHtml(value) {
|
|
1879
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1880
|
-
}
|
|
1881
|
-
function escapeAttribute(value) {
|
|
1882
|
-
return value.replace(/"/g, """);
|
|
1883
|
-
}
|
|
1884
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1885
|
-
0 && (module.exports = {
|
|
1886
|
-
BlockNodeRenderer
|
|
1887
|
-
});
|