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.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(messageId: string, input: string): ComponentData[];
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, useEffect, useMemo, useRef, useCallback } from 'react';
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 (messageId, input) {
319
+ MDXStreamingParser.prototype.parse = function (_messageId, input) {
320
320
  var e_1, _a, e_2, _b, e_3, _c;
321
- // 获取或创建该消息的解析状态
322
- var state = this.messages.get(messageId);
323
- if (!state) {
324
- state = {
325
- position: 0,
326
- stack: [],
327
- buffer: '',
328
- pendingClosingTag: undefined,
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 = state.position;
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: isComplete // 自闭合一定完整,非自闭合取决于是否有 props
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
- state.position = i;
705
- // 保存状态
706
- this.messages.set(messageId, state);
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 themes = {
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
- darkMode = _a.darkMode;
39570
- var _c = __read(useState(false), 2),
39571
- showCopy = _c[0],
39572
- setShowCopy = _c[1];
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: darkMode ? "#555" : "#333",
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: themes.dark,
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 CodeComponent = function (props) {
39794
- var children = props.children,
39795
- className = props.className;
39796
- props.node;
39797
- var rest = __rest(props, ["children", "className", "node"]);
39798
- var match = /language-(\w+)/.exec(className || "");
39799
- String(children).replace(/\n$/, '');
39800
- var extractText = function (children) {
39801
- return React__default.Children.toArray(children).reduce(function (acc, child) {
39802
- if (typeof child === 'string') {
39803
- return acc + child;
39804
- } else if (/*#__PURE__*/React__default.isValidElement(child) && child.props && child.props.children) {
39805
- return acc + extractText(child.props.children);
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
- return acc;
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
- var content = extractText(children);
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
- var BuiltInComponents = {
39858
- _THINK: Think,
39859
- // _TOOL_CALL: ToolCall,
39860
- pre: PreComponent,
39861
- code: CodeComponent,
39862
- p: PComponent,
39863
- a: AComponent,
39864
- video: VideoComponent,
39865
- audio: AudioComponent
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
- var _e = __read(useState(null), 2),
59467
- component = _e[0],
59468
- setComponent = _e[1];
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
- var allComponents = __assign(__assign({}, BuiltInComponents), normalizedComponents);
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
- var parser = new MDXStreamingParser(allComponentHandlers);
59616
+ if (!parserRef.current) {
59617
+ parserRef.current = new MDXStreamingParser(allComponentHandlers);
59618
+ }
59619
+ var parser = parserRef.current;
59489
59620
  var mdxContent = content || '';
59490
- // FallbackView 错误状态变化时的回调
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 ThinkComponent, ResultComponent, protectedContent, _a, thinkContent, resultContent, parsedData, parsedComponents, currentComponentCount, cacheKeys, cacheKeys_1, cacheKeys_1_1, key, indexMatch, index, finalComponent, fallbackComponent, _loop_2, i, MDXComponent, parsedDataLength, lastItem;
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
- _loop_2 = function (i) {
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*/, 11];
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*/, 9];
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*/, 8];
59757
+ return [3 /*break*/, 9];
59610
59758
  case 6:
59611
- return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59612
- case 7:
59613
- // 组件未完成,正常渲染
59614
- _result = _d.sent();
59759
+ if (!placeholderForFallback) return [3 /*break*/, 7];
59615
59760
  finalComponent.push(placeholderForFallback);
59616
- _d.label = 8;
59761
+ return [3 /*break*/, 9];
59762
+ case 7:
59763
+ return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59617
59764
  case 8:
59618
- return [3 /*break*/, 11];
59765
+ _result = _d.sent();
59766
+ finalComponent.push(_result);
59767
+ _d.label = 9;
59619
59768
  case 9:
59620
- return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
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 = 11;
59626
- case 11:
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**/, _loop_2(i)];
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
- }, [content]);
59833
+ return function () {
59834
+ cancelled = true;
59835
+ };
59836
+ }, [content, theme, codeTheme]);
59685
59837
  if (!isBrowser) {
59686
59838
  return null;
59687
59839
  }