react-ai-renderer 0.1.21 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +274 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +275 -123
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -110,6 +110,12 @@ interface ReactAIRendererProps {
|
|
|
110
110
|
mdxLayoutClassName?: string;
|
|
111
111
|
/** MdxLayout 的自定义样式 */
|
|
112
112
|
mdxLayoutStyle?: React.CSSProperties;
|
|
113
|
+
/** 为 true 时未完成组件优先走 loader,避免 remount 后跳过骨架 */
|
|
114
|
+
streaming?: boolean;
|
|
115
|
+
/** 整体主题:dark(默认)/ light / 自定义字符串 */
|
|
116
|
+
theme?: "dark" | "light" | string;
|
|
117
|
+
/** 代码语法主题:github / atom / 或 react-syntax-highlighter prism 样式名(如 dracula、one-dark 等) */
|
|
118
|
+
codeTheme?: "github" | "atom" | string;
|
|
113
119
|
/** 其他传递给组件的属性 */
|
|
114
120
|
[key: string]: any;
|
|
115
121
|
}
|
|
@@ -159,7 +165,7 @@ declare class MDXStreamingParser {
|
|
|
159
165
|
private messages;
|
|
160
166
|
constructor(components: any[]);
|
|
161
167
|
isComponentRegistered(name: string): boolean;
|
|
162
|
-
parse(
|
|
168
|
+
parse(_messageId: string, input: string): ComponentData[];
|
|
163
169
|
private findComponentClose;
|
|
164
170
|
private parseComponentTag;
|
|
165
171
|
private parsePropsCommon;
|
|
@@ -167,6 +173,6 @@ declare class MDXStreamingParser {
|
|
|
167
173
|
reset(): void;
|
|
168
174
|
}
|
|
169
175
|
|
|
170
|
-
declare function ReactAIRenderer({ content, scope, components, children, componentHandlers, useGithubStyles, mdxLayoutClassName, mdxLayoutStyle }: ReactAIRendererProps): React.JSX.Element | null;
|
|
176
|
+
declare function ReactAIRenderer({ content, scope, components, children, componentHandlers, useGithubStyles, mdxLayoutClassName, mdxLayoutStyle, theme, codeTheme, }: ReactAIRendererProps): React.JSX.Element | null;
|
|
171
177
|
|
|
172
178
|
export { ComponentData$1 as ComponentData, ComponentHandler, ComponentValue, EnhancedComponentConfig, MDXStreamingParser, MdxLayout, MdxLayoutProps, ParseResult, ParserState, ReactAIRendererProps, ReactMarkdownProps, Think, ThinkProps, ToolCall, ToolCallProps, ReactAIRenderer as default };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import React__default, { useState,
|
|
2
|
+
import React__default, { useState, useMemo, useEffect, useRef, useCallback } from 'react';
|
|
3
3
|
import * as runtime from 'react/jsx-runtime';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import RemarkMath from 'remark-math';
|
|
@@ -316,22 +316,18 @@ var MDXStreamingParser = /** @class */function () {
|
|
|
316
316
|
MDXStreamingParser.prototype.isComponentRegistered = function (name) {
|
|
317
317
|
return this.registeredComponents.has(name);
|
|
318
318
|
};
|
|
319
|
-
MDXStreamingParser.prototype.parse = function (
|
|
319
|
+
MDXStreamingParser.prototype.parse = function (_messageId, input) {
|
|
320
320
|
var e_1, _a, e_2, _b, e_3, _c;
|
|
321
|
-
//
|
|
322
|
-
var state =
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
pendingOpeningTag: undefined
|
|
330
|
-
};
|
|
331
|
-
this.messages.set(messageId, state);
|
|
332
|
-
}
|
|
321
|
+
// 每次对完整 content 从零解析,保证流式增量与组件 remount 后全量重解析结果一致
|
|
322
|
+
var state = {
|
|
323
|
+
position: 0,
|
|
324
|
+
stack: [],
|
|
325
|
+
buffer: '',
|
|
326
|
+
pendingClosingTag: undefined,
|
|
327
|
+
pendingOpeningTag: undefined
|
|
328
|
+
};
|
|
333
329
|
var result = [];
|
|
334
|
-
var i =
|
|
330
|
+
var i = 0;
|
|
335
331
|
// 如果有暂存的不完整闭合标签,先尝试与当前输入合并处理
|
|
336
332
|
if (state.pendingClosingTag) {
|
|
337
333
|
var combinedInput = state.pendingClosingTag + input;
|
|
@@ -479,13 +475,11 @@ var MDXStreamingParser = /** @class */function () {
|
|
|
479
475
|
// 如果部分标签是栈顶组件名的前缀,说明可能是不完整的闭合标签
|
|
480
476
|
if (topComponentName.startsWith(partialTag) || partialTag.length === 0) {
|
|
481
477
|
state.pendingClosingTag = input.slice(i);
|
|
482
|
-
this.messages.set(messageId, state);
|
|
483
478
|
break;
|
|
484
479
|
}
|
|
485
480
|
}
|
|
486
481
|
// 否则,可能是其他不完整的标签,暂存起来
|
|
487
482
|
state.pendingClosingTag = input.slice(i);
|
|
488
|
-
this.messages.set(messageId, state);
|
|
489
483
|
break;
|
|
490
484
|
}
|
|
491
485
|
var tagName = input.slice(i + 2, closeTagEnd);
|
|
@@ -531,7 +525,6 @@ var MDXStreamingParser = /** @class */function () {
|
|
|
531
525
|
// 暂存起来,不添加到文本内容
|
|
532
526
|
if (topComponentName.startsWith(tagName) && tagName.length < topComponentName.length) {
|
|
533
527
|
state.pendingClosingTag = input.slice(i, closeTagEnd + 1);
|
|
534
|
-
this.messages.set(messageId, state);
|
|
535
528
|
break;
|
|
536
529
|
}
|
|
537
530
|
}
|
|
@@ -579,12 +572,10 @@ var MDXStreamingParser = /** @class */function () {
|
|
|
579
572
|
// 找到了部分标签,暂存起来
|
|
580
573
|
var partialTagEnd = i + tagEndMatch[0].length - 1;
|
|
581
574
|
state.pendingOpeningTag = input.slice(i, partialTagEnd);
|
|
582
|
-
this.messages.set(messageId, state);
|
|
583
575
|
break;
|
|
584
576
|
} else {
|
|
585
577
|
// 标签完全不完整,暂存整个片段
|
|
586
578
|
state.pendingOpeningTag = input.slice(i);
|
|
587
|
-
this.messages.set(messageId, state);
|
|
588
579
|
break;
|
|
589
580
|
}
|
|
590
581
|
} else {
|
|
@@ -622,18 +613,12 @@ var MDXStreamingParser = /** @class */function () {
|
|
|
622
613
|
props = _k.props,
|
|
623
614
|
endIndex = _k.endIndex,
|
|
624
615
|
selfClosing = _k.selfClosing;
|
|
625
|
-
// 检测组件是否完整:
|
|
626
|
-
// 1. 自闭合组件一定是完整的
|
|
627
|
-
// 2. 非自闭合组件:如果有 props 且不在 stack 中(已闭合),则是完整的
|
|
628
|
-
// 对于流式渲染,如果 props 为空且不是自闭合,说明组件可能还在解析中
|
|
629
|
-
var hasProps = props && Object.keys(props).length > 0;
|
|
630
|
-
var isComplete = selfClosing || hasProps;
|
|
631
616
|
var component = {
|
|
632
617
|
type: "component",
|
|
633
618
|
value: componentName,
|
|
634
619
|
props: props || {},
|
|
635
620
|
selfClosing: selfClosing,
|
|
636
|
-
isComplete:
|
|
621
|
+
isComplete: selfClosing
|
|
637
622
|
};
|
|
638
623
|
if (!selfClosing) {
|
|
639
624
|
state.stack.push(component);
|
|
@@ -701,9 +686,35 @@ var MDXStreamingParser = /** @class */function () {
|
|
|
701
686
|
state.stack.forEach(function (component) {
|
|
702
687
|
component.isComplete = false;
|
|
703
688
|
});
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
689
|
+
// 流式未闭合的根组件可能只在 stack 中,补进 result 供 loader 渲染
|
|
690
|
+
if (state.stack.length > 0) {
|
|
691
|
+
var root_1 = state.stack[0];
|
|
692
|
+
var already = result.some(function (item) {
|
|
693
|
+
return item.type === 'component' && item.value === root_1.value;
|
|
694
|
+
});
|
|
695
|
+
if (!already) {
|
|
696
|
+
result.push(root_1);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
// 流式未闭合的开始标签(尚未入 stack)也产出占位组件,供 loader 渲染
|
|
700
|
+
if (state.pendingOpeningTag) {
|
|
701
|
+
var tagMatch = state.pendingOpeningTag.match(/^<([A-Z][A-Za-z0-9]*)/);
|
|
702
|
+
if (tagMatch && this.isComponentRegistered(tagMatch[1])) {
|
|
703
|
+
var name_1 = tagMatch[1];
|
|
704
|
+
var already = result.some(function (item) {
|
|
705
|
+
return item.type === 'component' && item.value === name_1;
|
|
706
|
+
});
|
|
707
|
+
if (!already) {
|
|
708
|
+
result.push({
|
|
709
|
+
type: 'component',
|
|
710
|
+
value: name_1,
|
|
711
|
+
props: {},
|
|
712
|
+
selfClosing: false,
|
|
713
|
+
isComplete: false
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
707
718
|
return result;
|
|
708
719
|
};
|
|
709
720
|
MDXStreamingParser.prototype.findComponentClose = function (input, startIndex) {
|
|
@@ -39558,18 +39569,64 @@ function requireZTouch () {
|
|
|
39558
39569
|
var _zTouch = _interopRequireDefault(requireZTouch());
|
|
39559
39570
|
} (prism$1));
|
|
39560
39571
|
|
|
39561
|
-
var
|
|
39572
|
+
var CODE_THEME_MAP = {
|
|
39573
|
+
github: "ghcolors",
|
|
39574
|
+
atom: "atom-dark",
|
|
39575
|
+
"atom-dark": "atom-dark",
|
|
39576
|
+
"atom-light": "atom-light",
|
|
39577
|
+
dracula: "dracula",
|
|
39578
|
+
"one-dark": "one-dark",
|
|
39579
|
+
"one-light": "one-light",
|
|
39580
|
+
nord: "nord",
|
|
39581
|
+
"material-dark": "material-dark",
|
|
39582
|
+
"material-light": "material-light",
|
|
39583
|
+
"solarized-light": "solarizedlight",
|
|
39584
|
+
"solarized-dark": "solarized-dark-atom",
|
|
39585
|
+
okaidia: "okaidia",
|
|
39586
|
+
tomorrow: "tomorrow",
|
|
39587
|
+
coy: "coy",
|
|
39588
|
+
"vsc-dark-plus": "vsc-dark-plus",
|
|
39589
|
+
vs: "vs",
|
|
39590
|
+
ghcolors: "ghcolors",
|
|
39591
|
+
prism: "prism",
|
|
39592
|
+
twilight: "twilight",
|
|
39593
|
+
"duotone-dark": "duotone-dark",
|
|
39594
|
+
"duotone-light": "duotone-light",
|
|
39595
|
+
"night-owl": "night-owl",
|
|
39596
|
+
darcula: "darcula",
|
|
39597
|
+
"gruvbox-dark": "gruvbox-dark",
|
|
39598
|
+
"gruvbox-light": "gruvbox-light"
|
|
39599
|
+
};
|
|
39600
|
+
// 预置的默认主题
|
|
39601
|
+
var DEFAULT_THEMES = {
|
|
39562
39602
|
dark: prism$1.vscDarkPlus,
|
|
39563
39603
|
light: prism$1.vs
|
|
39564
39604
|
};
|
|
39605
|
+
/**
|
|
39606
|
+
* 根据 codeTheme 名称加载对应的 prism 样式
|
|
39607
|
+
*/
|
|
39608
|
+
function loadCodeStyle(codeTheme) {
|
|
39609
|
+
// 先查映射表
|
|
39610
|
+
var moduleName = CODE_THEME_MAP[codeTheme] || codeTheme;
|
|
39611
|
+
try {
|
|
39612
|
+
// 使用 require 动态加载 prism 样式模块
|
|
39613
|
+
var styles = require("react-syntax-highlighter/dist/cjs/styles/prism/".concat(moduleName));
|
|
39614
|
+
return styles.default || styles;
|
|
39615
|
+
} catch (_a) {
|
|
39616
|
+
// 加载失败时回退到默认暗色主题
|
|
39617
|
+
return prism$1.vscDarkPlus;
|
|
39618
|
+
}
|
|
39619
|
+
}
|
|
39565
39620
|
var CodeHighlight = function (_a) {
|
|
39566
39621
|
var textContent = _a.textContent,
|
|
39567
39622
|
_b = _a.language,
|
|
39568
39623
|
language = _b === void 0 ? "txt" : _b,
|
|
39569
|
-
|
|
39570
|
-
|
|
39571
|
-
|
|
39572
|
-
|
|
39624
|
+
_c = _a.theme,
|
|
39625
|
+
theme = _c === void 0 ? "dark" : _c,
|
|
39626
|
+
codeTheme = _a.codeTheme;
|
|
39627
|
+
var _d = __read(useState(false), 2),
|
|
39628
|
+
showCopy = _d[0],
|
|
39629
|
+
setShowCopy = _d[1];
|
|
39573
39630
|
var copyToClipboard = function (text) {
|
|
39574
39631
|
return __awaiter(void 0, void 0, void 0, function () {
|
|
39575
39632
|
var textarea;
|
|
@@ -39633,6 +39690,11 @@ var CodeHighlight = function (_a) {
|
|
|
39633
39690
|
}, Date.now())
|
|
39634
39691
|
});
|
|
39635
39692
|
}
|
|
39693
|
+
// 根据 codeTheme / theme 计算最终的代码高亮样式
|
|
39694
|
+
var syntaxStyle = useMemo(function () {
|
|
39695
|
+
if (codeTheme) return loadCodeStyle(codeTheme);
|
|
39696
|
+
return DEFAULT_THEMES[theme] || DEFAULT_THEMES.dark;
|
|
39697
|
+
}, [codeTheme, theme]);
|
|
39636
39698
|
return /*#__PURE__*/jsxs("div", {
|
|
39637
39699
|
style: {
|
|
39638
39700
|
position: "relative"
|
|
@@ -39643,7 +39705,7 @@ var CodeHighlight = function (_a) {
|
|
|
39643
39705
|
right: "10px",
|
|
39644
39706
|
top: "5px",
|
|
39645
39707
|
zIndex: 1,
|
|
39646
|
-
background:
|
|
39708
|
+
background: theme === "light" ? "#e8e8e8" : "#555",
|
|
39647
39709
|
color: "#fff",
|
|
39648
39710
|
border: "none",
|
|
39649
39711
|
padding: "4px 8px",
|
|
@@ -39663,7 +39725,7 @@ var CodeHighlight = function (_a) {
|
|
|
39663
39725
|
},
|
|
39664
39726
|
children: showCopy ? "点击复制" : "复制"
|
|
39665
39727
|
}), /*#__PURE__*/jsx(SyntaxHighlighter, {
|
|
39666
|
-
style:
|
|
39728
|
+
style: syntaxStyle,
|
|
39667
39729
|
language: language,
|
|
39668
39730
|
PreTag: "div",
|
|
39669
39731
|
children: String(textContent).replace(/\n$/, "")
|
|
@@ -39789,44 +39851,48 @@ var AudioComponent = function (_a) {
|
|
|
39789
39851
|
}), "\u4F60\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 audio \u6807\u7B7E"]
|
|
39790
39852
|
});
|
|
39791
39853
|
};
|
|
39792
|
-
//
|
|
39793
|
-
var
|
|
39794
|
-
var
|
|
39795
|
-
|
|
39796
|
-
|
|
39797
|
-
|
|
39798
|
-
|
|
39799
|
-
|
|
39800
|
-
|
|
39801
|
-
|
|
39802
|
-
|
|
39803
|
-
|
|
39804
|
-
|
|
39805
|
-
|
|
39854
|
+
// 代码组件(支持 theme 和 codeTheme 透传)
|
|
39855
|
+
var createCodeComponent = function (theme, codeTheme) {
|
|
39856
|
+
var CodeComponent = function (props) {
|
|
39857
|
+
var children = props.children,
|
|
39858
|
+
className = props.className;
|
|
39859
|
+
props.node;
|
|
39860
|
+
var rest = __rest(props, ["children", "className", "node"]);
|
|
39861
|
+
var match = /language-(\w+)/.exec(className || "");
|
|
39862
|
+
var extractText = function (children) {
|
|
39863
|
+
return React__default.Children.toArray(children).reduce(function (acc, child) {
|
|
39864
|
+
if (typeof child === 'string') {
|
|
39865
|
+
return acc + child;
|
|
39866
|
+
} else if (/*#__PURE__*/React__default.isValidElement(child) && child.props && child.props.children) {
|
|
39867
|
+
return acc + extractText(child.props.children);
|
|
39868
|
+
}
|
|
39869
|
+
return acc;
|
|
39870
|
+
}, '');
|
|
39871
|
+
};
|
|
39872
|
+
var content = extractText(children);
|
|
39873
|
+
// 增强语言检测逻辑,检查内容中是否包含mermaid特征
|
|
39874
|
+
var language = match ? match[1] : "txt";
|
|
39875
|
+
// 如果内容包含mermaid特征且语言未正确识别,则强制设置为mermaid
|
|
39876
|
+
if (!match || match[1] !== "mermaid") {
|
|
39877
|
+
var trimmedContent = content.trim();
|
|
39878
|
+
if (trimmedContent.startsWith('graph') || trimmedContent.startsWith('flowchart') || trimmedContent.startsWith('sequenceDiagram') || trimmedContent.startsWith('gantt') || trimmedContent.startsWith('classDiagram') || trimmedContent.startsWith('stateDiagram') || trimmedContent.startsWith('pie') || trimmedContent.startsWith('erDiagram') || trimmedContent.startsWith('journey') || trimmedContent.startsWith('requirementDiagram') || trimmedContent.startsWith('gitGraph')) {
|
|
39879
|
+
language = "mermaid";
|
|
39806
39880
|
}
|
|
39807
|
-
|
|
39808
|
-
|
|
39881
|
+
}
|
|
39882
|
+
return language !== "txt" ? /*#__PURE__*/jsx(CodeHighlight, {
|
|
39883
|
+
...rest,
|
|
39884
|
+
language: language,
|
|
39885
|
+
textContent: content,
|
|
39886
|
+
theme: theme,
|
|
39887
|
+
codeTheme: codeTheme,
|
|
39888
|
+
children: content
|
|
39889
|
+
}) : /*#__PURE__*/jsx("code", {
|
|
39890
|
+
className: className,
|
|
39891
|
+
...props,
|
|
39892
|
+
children: content
|
|
39893
|
+
});
|
|
39809
39894
|
};
|
|
39810
|
-
|
|
39811
|
-
// 增强语言检测逻辑,检查内容中是否包含mermaid特征
|
|
39812
|
-
var language = match ? match[1] : "txt";
|
|
39813
|
-
// 如果内容包含mermaid特征且语言未正确识别,则强制设置为mermaid
|
|
39814
|
-
if (!match || match[1] !== "mermaid") {
|
|
39815
|
-
var trimmedContent = content.trim();
|
|
39816
|
-
if (trimmedContent.startsWith('graph') || trimmedContent.startsWith('flowchart') || trimmedContent.startsWith('sequenceDiagram') || trimmedContent.startsWith('gantt') || trimmedContent.startsWith('classDiagram') || trimmedContent.startsWith('stateDiagram') || trimmedContent.startsWith('pie') || trimmedContent.startsWith('erDiagram') || trimmedContent.startsWith('journey') || trimmedContent.startsWith('requirementDiagram') || trimmedContent.startsWith('gitGraph')) {
|
|
39817
|
-
language = "mermaid";
|
|
39818
|
-
}
|
|
39819
|
-
}
|
|
39820
|
-
return language !== "txt" ? /*#__PURE__*/jsx(CodeHighlight, {
|
|
39821
|
-
...rest,
|
|
39822
|
-
language: language,
|
|
39823
|
-
textContent: content,
|
|
39824
|
-
children: content
|
|
39825
|
-
}) : /*#__PURE__*/jsx("code", {
|
|
39826
|
-
className: className,
|
|
39827
|
-
...props,
|
|
39828
|
-
children: content
|
|
39829
|
-
});
|
|
39895
|
+
return CodeComponent;
|
|
39830
39896
|
};
|
|
39831
39897
|
// 段落组件
|
|
39832
39898
|
var PComponent = function (pProps) {
|
|
@@ -39854,16 +39920,23 @@ var PreComponent = function (props) {
|
|
|
39854
39920
|
...props
|
|
39855
39921
|
});
|
|
39856
39922
|
};
|
|
39857
|
-
|
|
39858
|
-
|
|
39859
|
-
|
|
39860
|
-
|
|
39861
|
-
|
|
39862
|
-
|
|
39863
|
-
|
|
39864
|
-
|
|
39865
|
-
|
|
39866
|
-
|
|
39923
|
+
/**
|
|
39924
|
+
* 创建带主题配置的内置组件集合
|
|
39925
|
+
* @param theme 整体主题 (dark / light / 自定义)
|
|
39926
|
+
* @param codeTheme 代码语法主题 (github / atom / 自定义)
|
|
39927
|
+
*/
|
|
39928
|
+
function createBuiltInComponents(theme, codeTheme) {
|
|
39929
|
+
var themedCode = createCodeComponent(theme, codeTheme);
|
|
39930
|
+
return {
|
|
39931
|
+
_THINK: Think,
|
|
39932
|
+
pre: PreComponent,
|
|
39933
|
+
code: themedCode,
|
|
39934
|
+
p: PComponent,
|
|
39935
|
+
a: AComponent,
|
|
39936
|
+
video: VideoComponent,
|
|
39937
|
+
audio: AudioComponent
|
|
39938
|
+
};
|
|
39939
|
+
}
|
|
39867
39940
|
|
|
39868
39941
|
var ErrorBoundary = /** @class */function (_super) {
|
|
39869
39942
|
__extends(ErrorBoundary, _super);
|
|
@@ -59390,15 +59463,9 @@ var FallbackView = /** @class */function (_super) {
|
|
|
59390
59463
|
function isEnhancedComponentConfig(value) {
|
|
59391
59464
|
return typeof value === 'object' && value !== null && 'value' in value && typeof value.value !== 'undefined';
|
|
59392
59465
|
}
|
|
59393
|
-
/**
|
|
59394
|
-
* 从组件值中提取实际的组件
|
|
59395
|
-
*/
|
|
59396
59466
|
function extractComponent(value) {
|
|
59397
59467
|
return isEnhancedComponentConfig(value) ? value.value : value;
|
|
59398
59468
|
}
|
|
59399
|
-
/**
|
|
59400
|
-
* 将 components 转换为 ComponentHandler 数组
|
|
59401
|
-
*/
|
|
59402
59469
|
function convertComponentsToHandlers(components, componentHandlers) {
|
|
59403
59470
|
var e_1, _a;
|
|
59404
59471
|
var handlers = [];
|
|
@@ -59450,6 +59517,58 @@ function convertComponentsToHandlers(components, componentHandlers) {
|
|
|
59450
59517
|
}
|
|
59451
59518
|
return handlers;
|
|
59452
59519
|
}
|
|
59520
|
+
function buildLoaderShellFromParsed(parsedData, allComponentHandlers, layoutProps) {
|
|
59521
|
+
if (!parsedData.length) return null;
|
|
59522
|
+
var nodes = [];
|
|
59523
|
+
var _loop_2 = function (i) {
|
|
59524
|
+
var item = parsedData[i];
|
|
59525
|
+
if (item.type === 'text') {
|
|
59526
|
+
var t = String(item.value || '').trim();
|
|
59527
|
+
if (t) {
|
|
59528
|
+
nodes.push(/*#__PURE__*/React__default.createElement('div', {
|
|
59529
|
+
key: "sync-txt-".concat(i),
|
|
59530
|
+
style: {
|
|
59531
|
+
whiteSpace: 'pre-wrap'
|
|
59532
|
+
}
|
|
59533
|
+
}, t));
|
|
59534
|
+
}
|
|
59535
|
+
return "continue";
|
|
59536
|
+
}
|
|
59537
|
+
if (item.type !== 'component' || item.isComplete === true) return "continue";
|
|
59538
|
+
var handler = allComponentHandlers.find(function (c) {
|
|
59539
|
+
return c.name === item.value;
|
|
59540
|
+
});
|
|
59541
|
+
if (!(handler === null || handler === void 0 ? void 0 : handler.loader)) return "continue";
|
|
59542
|
+
var displayName = handler.label || item.value;
|
|
59543
|
+
nodes.push(/*#__PURE__*/React__default.createElement(ComponentPlaceholder, {
|
|
59544
|
+
key: "sync-loader-".concat(item.value, "-").concat(i),
|
|
59545
|
+
componentName: displayName,
|
|
59546
|
+
loader: handler.loader
|
|
59547
|
+
}));
|
|
59548
|
+
};
|
|
59549
|
+
for (var i = 0; i < parsedData.length; i++) {
|
|
59550
|
+
_loop_2(i);
|
|
59551
|
+
}
|
|
59552
|
+
if (!nodes.length) return null;
|
|
59553
|
+
return /*#__PURE__*/React__default.createElement(MdxLayout, __assign(__assign({}, layoutProps), {
|
|
59554
|
+
children: React__default.createElement.apply(React__default, __spreadArray([React__default.Fragment, null], __read(nodes), false))
|
|
59555
|
+
}));
|
|
59556
|
+
}
|
|
59557
|
+
function parsedStructureSignature(parsedData) {
|
|
59558
|
+
return parsedData.map(function (p) {
|
|
59559
|
+
if (p.type === 'text') return "t:".concat(String(p.value || '').length);
|
|
59560
|
+
return "c:".concat(p.value, ":").concat(p.isComplete === true ? '1' : '0');
|
|
59561
|
+
}).join('|');
|
|
59562
|
+
}
|
|
59563
|
+
function hasPendingLoaderComponents(parsedData, handlers) {
|
|
59564
|
+
return parsedData.some(function (item) {
|
|
59565
|
+
var _a;
|
|
59566
|
+
if (item.type !== 'component' || item.isComplete === true) return false;
|
|
59567
|
+
return Boolean((_a = handlers.find(function (h) {
|
|
59568
|
+
return h.name === item.value;
|
|
59569
|
+
})) === null || _a === void 0 ? void 0 : _a.loader);
|
|
59570
|
+
});
|
|
59571
|
+
}
|
|
59453
59572
|
function ReactAIRenderer(_a) {
|
|
59454
59573
|
var _this = this;
|
|
59455
59574
|
var content = _a.content,
|
|
@@ -59462,14 +59581,19 @@ function ReactAIRenderer(_a) {
|
|
|
59462
59581
|
componentHandlers = _d === void 0 ? [] : _d,
|
|
59463
59582
|
useGithubStyles = _a.useGithubStyles,
|
|
59464
59583
|
mdxLayoutClassName = _a.mdxLayoutClassName,
|
|
59465
|
-
mdxLayoutStyle = _a.mdxLayoutStyle
|
|
59466
|
-
|
|
59467
|
-
|
|
59468
|
-
|
|
59584
|
+
mdxLayoutStyle = _a.mdxLayoutStyle,
|
|
59585
|
+
_e = _a.theme,
|
|
59586
|
+
theme = _e === void 0 ? "dark" : _e,
|
|
59587
|
+
codeTheme = _a.codeTheme;
|
|
59588
|
+
var _f = __read(useState(null), 2),
|
|
59589
|
+
component = _f[0],
|
|
59590
|
+
setComponent = _f[1];
|
|
59469
59591
|
var fallbackErrorRef = useRef({
|
|
59470
59592
|
hasError: false
|
|
59471
59593
|
});
|
|
59472
59594
|
var completedComponentsCacheRef = useRef(new Map());
|
|
59595
|
+
var parserRef = useRef(null);
|
|
59596
|
+
var lastLoaderSigRef = useRef('');
|
|
59473
59597
|
var isBrowser = typeof window !== 'undefined';
|
|
59474
59598
|
content = content || children || '';
|
|
59475
59599
|
var normalizedComponents = components ? Object.fromEntries(Object.entries(components).filter(function (_a) {
|
|
@@ -59483,11 +59607,26 @@ function ReactAIRenderer(_a) {
|
|
|
59483
59607
|
value = _b[1];
|
|
59484
59608
|
return [name, extractComponent(value)];
|
|
59485
59609
|
})) : {};
|
|
59486
|
-
|
|
59610
|
+
// 根据 theme / codeTheme 创建带主题配置的内置组件
|
|
59611
|
+
var themedBuiltInComponents = useMemo(function () {
|
|
59612
|
+
return createBuiltInComponents(theme, codeTheme);
|
|
59613
|
+
}, [theme, codeTheme]);
|
|
59614
|
+
var allComponents = __assign(__assign({}, themedBuiltInComponents), normalizedComponents);
|
|
59487
59615
|
var allComponentHandlers = __spreadArray(__spreadArray([], __read(components ? convertComponentsToHandlers(components, componentHandlers) : []), false), __read(componentHandlers), false);
|
|
59488
|
-
|
|
59616
|
+
if (!parserRef.current) {
|
|
59617
|
+
parserRef.current = new MDXStreamingParser(allComponentHandlers);
|
|
59618
|
+
}
|
|
59619
|
+
var parser = parserRef.current;
|
|
59489
59620
|
var mdxContent = content || '';
|
|
59490
|
-
|
|
59621
|
+
var handlersRef = useRef(allComponentHandlers);
|
|
59622
|
+
handlersRef.current = allComponentHandlers;
|
|
59623
|
+
var layoutProps = useMemo(function () {
|
|
59624
|
+
return {
|
|
59625
|
+
useGithubStyles: useGithubStyles,
|
|
59626
|
+
className: mdxLayoutClassName,
|
|
59627
|
+
style: mdxLayoutStyle
|
|
59628
|
+
};
|
|
59629
|
+
}, [useGithubStyles, mdxLayoutClassName, mdxLayoutStyle]);
|
|
59491
59630
|
var handleFallbackErrorChange = function (hasError, error) {
|
|
59492
59631
|
fallbackErrorRef.current = {
|
|
59493
59632
|
hasError: hasError,
|
|
@@ -59496,17 +59635,32 @@ function ReactAIRenderer(_a) {
|
|
|
59496
59635
|
};
|
|
59497
59636
|
useEffect(function () {
|
|
59498
59637
|
if (!isBrowser) return;
|
|
59638
|
+
var cancelled = false;
|
|
59499
59639
|
var parseMDX = function () {
|
|
59500
59640
|
return __awaiter(_this, void 0, void 0, function () {
|
|
59501
|
-
var
|
|
59641
|
+
var protectedContent, _a, thinkContent, resultContent, parsedData_1, loaderSig, shell, ThinkComponent, ResultComponent, parsedData, parsedComponents, currentComponentCount, cacheKeys, cacheKeys_1, cacheKeys_1_1, key, indexMatch, index, finalComponent, fallbackComponent, _loop_3, i, MDXComponent, parsedDataLength, lastItem;
|
|
59502
59642
|
var e_2, _b;
|
|
59503
59643
|
return __generator(this, function (_c) {
|
|
59504
59644
|
switch (_c.label) {
|
|
59505
59645
|
case 0:
|
|
59506
|
-
ThinkComponent = null;
|
|
59507
|
-
ResultComponent = null;
|
|
59508
59646
|
protectedContent = protectSpecialSyntax(mdxContent);
|
|
59509
59647
|
_a = remarkThinkUpdate(protectedContent), thinkContent = _a.thinkContent, resultContent = _a.resultContent;
|
|
59648
|
+
if (resultContent) {
|
|
59649
|
+
resultContent = fixMDXContent(resultContent);
|
|
59650
|
+
parsedData_1 = parser.parse('magic', resultContent);
|
|
59651
|
+
loaderSig = parsedStructureSignature(parsedData_1);
|
|
59652
|
+
if (hasPendingLoaderComponents(parsedData_1, handlersRef.current)) {
|
|
59653
|
+
if (loaderSig !== lastLoaderSigRef.current) {
|
|
59654
|
+
lastLoaderSigRef.current = loaderSig;
|
|
59655
|
+
shell = buildLoaderShellFromParsed(parsedData_1, handlersRef.current, layoutProps);
|
|
59656
|
+
if (shell && !cancelled) setComponent(shell);
|
|
59657
|
+
}
|
|
59658
|
+
return [2 /*return*/];
|
|
59659
|
+
}
|
|
59660
|
+
lastLoaderSigRef.current = '';
|
|
59661
|
+
}
|
|
59662
|
+
ThinkComponent = null;
|
|
59663
|
+
ResultComponent = null;
|
|
59510
59664
|
if (!thinkContent) return [3 /*break*/, 2];
|
|
59511
59665
|
return [4 /*yield*/, renderMdx(thinkContent, scope, allComponents)];
|
|
59512
59666
|
case 1:
|
|
@@ -59515,7 +59669,6 @@ function ReactAIRenderer(_a) {
|
|
|
59515
59669
|
case 2:
|
|
59516
59670
|
parsedData = [];
|
|
59517
59671
|
if (!resultContent) return [3 /*break*/, 8];
|
|
59518
|
-
resultContent = fixMDXContent(resultContent);
|
|
59519
59672
|
parsedData = parser.parse('magic', resultContent);
|
|
59520
59673
|
return [4 /*yield*/, Promise.all(parsedData.map(function (item) {
|
|
59521
59674
|
return parseComponentRecursively(allComponentHandlers, item, scope);
|
|
@@ -59531,7 +59684,6 @@ function ReactAIRenderer(_a) {
|
|
|
59531
59684
|
if (indexMatch) {
|
|
59532
59685
|
index = parseInt(indexMatch[1], 10);
|
|
59533
59686
|
if (index >= currentComponentCount) {
|
|
59534
|
-
// 如果索引超出当前组件数量,删除缓存
|
|
59535
59687
|
completedComponentsCacheRef.current.delete(key);
|
|
59536
59688
|
}
|
|
59537
59689
|
}
|
|
@@ -59549,7 +59701,7 @@ function ReactAIRenderer(_a) {
|
|
|
59549
59701
|
}
|
|
59550
59702
|
finalComponent = [];
|
|
59551
59703
|
fallbackComponent = [];
|
|
59552
|
-
|
|
59704
|
+
_loop_3 = function (i) {
|
|
59553
59705
|
var item, currentParsedItem, _result, placeholderForFallback, componentNameMatch, componentName_1, componentHandler, displayName, cacheKey;
|
|
59554
59706
|
return __generator(this, function (_d) {
|
|
59555
59707
|
switch (_d.label) {
|
|
@@ -59563,10 +59715,10 @@ function ReactAIRenderer(_a) {
|
|
|
59563
59715
|
case 1:
|
|
59564
59716
|
_result = _d.sent();
|
|
59565
59717
|
finalComponent.push(_result);
|
|
59566
|
-
return [3 /*break*/,
|
|
59718
|
+
return [3 /*break*/, 12];
|
|
59567
59719
|
case 2:
|
|
59568
59720
|
componentNameMatch = item.value.match(/<([A-Z][A-Za-z0-9]*)/);
|
|
59569
|
-
if (!componentNameMatch) return [3 /*break*/,
|
|
59721
|
+
if (!componentNameMatch) return [3 /*break*/, 10];
|
|
59570
59722
|
componentName_1 = componentNameMatch[1];
|
|
59571
59723
|
componentHandler = allComponentHandlers.find(function (c) {
|
|
59572
59724
|
return c.name === componentName_1;
|
|
@@ -59583,15 +59735,12 @@ function ReactAIRenderer(_a) {
|
|
|
59583
59735
|
if (!(currentParsedItem.isComplete === true || !(componentHandler === null || componentHandler === void 0 ? void 0 : componentHandler.loader))) return [3 /*break*/, 6];
|
|
59584
59736
|
cacheKey = "mdx-component-".concat(componentName_1, "-").concat(i);
|
|
59585
59737
|
if (!completedComponentsCacheRef.current.has(cacheKey)) return [3 /*break*/, 3];
|
|
59586
|
-
// 使用缓存的组件
|
|
59587
59738
|
_result = completedComponentsCacheRef.current.get(cacheKey);
|
|
59588
59739
|
return [3 /*break*/, 5];
|
|
59589
59740
|
case 3:
|
|
59590
59741
|
return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
|
|
59591
59742
|
case 4:
|
|
59592
|
-
// 缓存不存在,调用 renderMdx 并存入缓存
|
|
59593
59743
|
_result = _d.sent();
|
|
59594
|
-
// 为组件设置 key,确保 React 能正确识别
|
|
59595
59744
|
if (/*#__PURE__*/React__default.isValidElement(_result)) {
|
|
59596
59745
|
_result = /*#__PURE__*/React__default.cloneElement(_result, {
|
|
59597
59746
|
key: cacheKey
|
|
@@ -59601,30 +59750,30 @@ function ReactAIRenderer(_a) {
|
|
|
59601
59750
|
key: cacheKey
|
|
59602
59751
|
}, _result);
|
|
59603
59752
|
}
|
|
59604
|
-
// 存入缓存
|
|
59605
59753
|
completedComponentsCacheRef.current.set(cacheKey, _result);
|
|
59606
59754
|
_d.label = 5;
|
|
59607
59755
|
case 5:
|
|
59608
59756
|
finalComponent.push(_result);
|
|
59609
|
-
return [3 /*break*/,
|
|
59757
|
+
return [3 /*break*/, 9];
|
|
59610
59758
|
case 6:
|
|
59611
|
-
return [
|
|
59612
|
-
case 7:
|
|
59613
|
-
// 组件未完成,正常渲染
|
|
59614
|
-
_result = _d.sent();
|
|
59759
|
+
if (!placeholderForFallback) return [3 /*break*/, 7];
|
|
59615
59760
|
finalComponent.push(placeholderForFallback);
|
|
59616
|
-
|
|
59761
|
+
return [3 /*break*/, 9];
|
|
59762
|
+
case 7:
|
|
59763
|
+
return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
|
|
59617
59764
|
case 8:
|
|
59618
|
-
|
|
59765
|
+
_result = _d.sent();
|
|
59766
|
+
finalComponent.push(_result);
|
|
59767
|
+
_d.label = 9;
|
|
59619
59768
|
case 9:
|
|
59620
|
-
return [
|
|
59769
|
+
return [3 /*break*/, 12];
|
|
59621
59770
|
case 10:
|
|
59622
|
-
|
|
59771
|
+
return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
|
|
59772
|
+
case 11:
|
|
59623
59773
|
_result = _d.sent();
|
|
59624
59774
|
finalComponent.push(_result);
|
|
59625
|
-
_d.label =
|
|
59626
|
-
case
|
|
59627
|
-
// fallbackComponent 应该是 finalComponent 的前 i 个元素 + 当前 item 的 loader
|
|
59775
|
+
_d.label = 12;
|
|
59776
|
+
case 12:
|
|
59628
59777
|
fallbackComponent.length = 0;
|
|
59629
59778
|
fallbackComponent.push.apply(fallbackComponent, __spreadArray([], __read(finalComponent.slice(0, i)), false));
|
|
59630
59779
|
if (placeholderForFallback) {
|
|
@@ -59638,7 +59787,7 @@ function ReactAIRenderer(_a) {
|
|
|
59638
59787
|
_c.label = 4;
|
|
59639
59788
|
case 4:
|
|
59640
59789
|
if (!(i < parsedComponents.length)) return [3 /*break*/, 7];
|
|
59641
|
-
return [5 /*yield**/,
|
|
59790
|
+
return [5 /*yield**/, _loop_3(i)];
|
|
59642
59791
|
case 5:
|
|
59643
59792
|
_c.sent();
|
|
59644
59793
|
_c.label = 6;
|
|
@@ -59661,13 +59810,13 @@ function ReactAIRenderer(_a) {
|
|
|
59661
59810
|
MDXComponent = /*#__PURE__*/jsxs(React__default.Fragment, {
|
|
59662
59811
|
children: [ThinkComponent, ResultComponent]
|
|
59663
59812
|
});
|
|
59813
|
+
if (cancelled) return [2 /*return*/];
|
|
59664
59814
|
if (!fallbackErrorRef.current.hasError) {
|
|
59665
59815
|
setComponent(MDXComponent);
|
|
59666
59816
|
} else {
|
|
59667
59817
|
parsedDataLength = parsedData.length;
|
|
59668
59818
|
if (parsedDataLength > 0) {
|
|
59669
59819
|
lastItem = parsedData[parsedDataLength - 1];
|
|
59670
|
-
// 如果最后一个组件是完整的,强制更新
|
|
59671
59820
|
if (lastItem.isComplete === true) {
|
|
59672
59821
|
setComponent(MDXComponent);
|
|
59673
59822
|
} else if (lastItem.type === 'text') {
|
|
@@ -59681,7 +59830,10 @@ function ReactAIRenderer(_a) {
|
|
|
59681
59830
|
});
|
|
59682
59831
|
};
|
|
59683
59832
|
parseMDX();
|
|
59684
|
-
|
|
59833
|
+
return function () {
|
|
59834
|
+
cancelled = true;
|
|
59835
|
+
};
|
|
59836
|
+
}, [content, theme, codeTheme]);
|
|
59685
59837
|
if (!isBrowser) {
|
|
59686
59838
|
return null;
|
|
59687
59839
|
}
|