react-ai-renderer 0.1.21 → 0.1.25

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 CHANGED
@@ -338,22 +338,18 @@ var MDXStreamingParser = /** @class */function () {
338
338
  MDXStreamingParser.prototype.isComponentRegistered = function (name) {
339
339
  return this.registeredComponents.has(name);
340
340
  };
341
- MDXStreamingParser.prototype.parse = function (messageId, input) {
341
+ MDXStreamingParser.prototype.parse = function (_messageId, input) {
342
342
  var e_1, _a, e_2, _b, e_3, _c;
343
- // 获取或创建该消息的解析状态
344
- var state = this.messages.get(messageId);
345
- if (!state) {
346
- state = {
347
- position: 0,
348
- stack: [],
349
- buffer: '',
350
- pendingClosingTag: undefined,
351
- pendingOpeningTag: undefined
352
- };
353
- this.messages.set(messageId, state);
354
- }
343
+ // 每次对完整 content 从零解析,保证流式增量与组件 remount 后全量重解析结果一致
344
+ var state = {
345
+ position: 0,
346
+ stack: [],
347
+ buffer: '',
348
+ pendingClosingTag: undefined,
349
+ pendingOpeningTag: undefined
350
+ };
355
351
  var result = [];
356
- var i = state.position;
352
+ var i = 0;
357
353
  // 如果有暂存的不完整闭合标签,先尝试与当前输入合并处理
358
354
  if (state.pendingClosingTag) {
359
355
  var combinedInput = state.pendingClosingTag + input;
@@ -501,13 +497,11 @@ var MDXStreamingParser = /** @class */function () {
501
497
  // 如果部分标签是栈顶组件名的前缀,说明可能是不完整的闭合标签
502
498
  if (topComponentName.startsWith(partialTag) || partialTag.length === 0) {
503
499
  state.pendingClosingTag = input.slice(i);
504
- this.messages.set(messageId, state);
505
500
  break;
506
501
  }
507
502
  }
508
503
  // 否则,可能是其他不完整的标签,暂存起来
509
504
  state.pendingClosingTag = input.slice(i);
510
- this.messages.set(messageId, state);
511
505
  break;
512
506
  }
513
507
  var tagName = input.slice(i + 2, closeTagEnd);
@@ -553,7 +547,6 @@ var MDXStreamingParser = /** @class */function () {
553
547
  // 暂存起来,不添加到文本内容
554
548
  if (topComponentName.startsWith(tagName) && tagName.length < topComponentName.length) {
555
549
  state.pendingClosingTag = input.slice(i, closeTagEnd + 1);
556
- this.messages.set(messageId, state);
557
550
  break;
558
551
  }
559
552
  }
@@ -601,12 +594,10 @@ var MDXStreamingParser = /** @class */function () {
601
594
  // 找到了部分标签,暂存起来
602
595
  var partialTagEnd = i + tagEndMatch[0].length - 1;
603
596
  state.pendingOpeningTag = input.slice(i, partialTagEnd);
604
- this.messages.set(messageId, state);
605
597
  break;
606
598
  } else {
607
599
  // 标签完全不完整,暂存整个片段
608
600
  state.pendingOpeningTag = input.slice(i);
609
- this.messages.set(messageId, state);
610
601
  break;
611
602
  }
612
603
  } else {
@@ -644,18 +635,12 @@ var MDXStreamingParser = /** @class */function () {
644
635
  props = _k.props,
645
636
  endIndex = _k.endIndex,
646
637
  selfClosing = _k.selfClosing;
647
- // 检测组件是否完整:
648
- // 1. 自闭合组件一定是完整的
649
- // 2. 非自闭合组件:如果有 props 且不在 stack 中(已闭合),则是完整的
650
- // 对于流式渲染,如果 props 为空且不是自闭合,说明组件可能还在解析中
651
- var hasProps = props && Object.keys(props).length > 0;
652
- var isComplete = selfClosing || hasProps;
653
638
  var component = {
654
639
  type: "component",
655
640
  value: componentName,
656
641
  props: props || {},
657
642
  selfClosing: selfClosing,
658
- isComplete: isComplete // 自闭合一定完整,非自闭合取决于是否有 props
643
+ isComplete: selfClosing
659
644
  };
660
645
  if (!selfClosing) {
661
646
  state.stack.push(component);
@@ -723,9 +708,35 @@ var MDXStreamingParser = /** @class */function () {
723
708
  state.stack.forEach(function (component) {
724
709
  component.isComplete = false;
725
710
  });
726
- state.position = i;
727
- // 保存状态
728
- this.messages.set(messageId, state);
711
+ // 流式未闭合的根组件可能只在 stack 中,补进 result 供 loader 渲染
712
+ if (state.stack.length > 0) {
713
+ var root_1 = state.stack[0];
714
+ var already = result.some(function (item) {
715
+ return item.type === 'component' && item.value === root_1.value;
716
+ });
717
+ if (!already) {
718
+ result.push(root_1);
719
+ }
720
+ }
721
+ // 流式未闭合的开始标签(尚未入 stack)也产出占位组件,供 loader 渲染
722
+ if (state.pendingOpeningTag) {
723
+ var tagMatch = state.pendingOpeningTag.match(/^<([A-Z][A-Za-z0-9]*)/);
724
+ if (tagMatch && this.isComponentRegistered(tagMatch[1])) {
725
+ var name_1 = tagMatch[1];
726
+ var already = result.some(function (item) {
727
+ return item.type === 'component' && item.value === name_1;
728
+ });
729
+ if (!already) {
730
+ result.push({
731
+ type: 'component',
732
+ value: name_1,
733
+ props: {},
734
+ selfClosing: false,
735
+ isComplete: false
736
+ });
737
+ }
738
+ }
739
+ }
729
740
  return result;
730
741
  };
731
742
  MDXStreamingParser.prototype.findComponentClose = function (input, startIndex) {
@@ -827,33 +838,37 @@ var MDXStreamingParser = /** @class */function () {
827
838
  // 处理 JSON 值(对象或数组)
828
839
  var startChar = input[j];
829
840
  var startBracket = j;
830
- // 使用局部变量跟踪属性值内部的括号嵌套
831
841
  var localBracketCount = 0;
832
842
  var localSquareBracketCount = 0;
833
843
  var inValueQuote = false;
834
844
  var valueQuoteChar = '';
845
+ var inBacktick = false;
846
+ var closingStack = [];
835
847
  if (startChar === '{') {
836
848
  localBracketCount = 1;
849
+ closingStack.push('}');
837
850
  } else {
838
851
  localSquareBracketCount = 1;
852
+ closingStack.push(']');
839
853
  }
840
854
  j++;
841
- // 同时跟踪花括号和方括号的嵌套
842
855
  while (j < input.length && (localBracketCount > 0 || localSquareBracketCount > 0)) {
843
- if (input[j] === '"' || input[j] === "'") {
844
- // 在字符串内,跳过整个字符串
856
+ if (input[j] === '`' && !inValueQuote) {
857
+ inBacktick = !inBacktick;
858
+ j++;
859
+ } else if (inBacktick) {
860
+ j++;
861
+ } else if (input[j] === '"' || input[j] === "'") {
845
862
  if (!inValueQuote) {
846
863
  inValueQuote = true;
847
864
  valueQuoteChar = input[j];
848
865
  } else if (input[j] === valueQuoteChar) {
849
- // 检查是否是转义的引号
850
866
  var escapeCount = 0;
851
867
  var k = j - 1;
852
868
  while (k >= 0 && input[k] === '\\') {
853
869
  escapeCount++;
854
870
  k--;
855
871
  }
856
- // 如果是偶数个反斜杠,说明引号没有被转义
857
872
  if (escapeCount % 2 === 0) {
858
873
  inValueQuote = false;
859
874
  }
@@ -861,15 +876,23 @@ var MDXStreamingParser = /** @class */function () {
861
876
  j++;
862
877
  } else if (input[j] === '{' && !inValueQuote) {
863
878
  localBracketCount++;
879
+ closingStack.push('}');
864
880
  j++;
865
881
  } else if (input[j] === '}' && !inValueQuote) {
866
882
  localBracketCount--;
883
+ if (closingStack.length > 0 && closingStack[closingStack.length - 1] === '}') {
884
+ closingStack.pop();
885
+ }
867
886
  j++;
868
887
  } else if (input[j] === '[' && !inValueQuote) {
869
888
  localSquareBracketCount++;
889
+ closingStack.push(']');
870
890
  j++;
871
891
  } else if (input[j] === ']' && !inValueQuote) {
872
892
  localSquareBracketCount--;
893
+ if (closingStack.length > 0 && closingStack[closingStack.length - 1] === ']') {
894
+ closingStack.pop();
895
+ }
873
896
  j++;
874
897
  } else {
875
898
  j++;
@@ -877,31 +900,46 @@ var MDXStreamingParser = /** @class */function () {
877
900
  }
878
901
  var rawValue = input.slice(startBracket, j);
879
902
  value = input.slice(startBracket + 1, j - 1);
903
+ // 流式修复:输入未结束但括号未闭合,尝试关闭不完整的表达式
904
+ if (j >= input.length && closingStack.length > 0) {
905
+ var healed = rawValue;
906
+ if (inBacktick) healed += '`';
907
+ if (inValueQuote) healed += valueQuoteChar;
908
+ healed += closingStack.reverse().join('');
909
+ // 剥离外层 JSX 表达式括号 {{ → {,用 (...) 包裹强制表达式上下文
910
+ var inner = healed.slice(1, -1);
911
+ try {
912
+ props[propName] = new Function('return (' + inner + ')')();
913
+ } catch (_a) {
914
+ try {
915
+ var jv = inner.replace(/`([^`]*)`/g, function (_, p1) {
916
+ return JSON.stringify(p1);
917
+ }).replace(/'([^'\\]*(\\.[^'\\]*)*)'/g, function (m) {
918
+ var s = m.slice(1, -1).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
919
+ return "\"".concat(s, "\"");
920
+ }).replace(/([{,]\s*)([\p{L}_$][\p{L}\p{N}_$]*)\s*:/gu, '$1"$2":');
921
+ props[propName] = JSON.parse(jv);
922
+ } catch (_b) {
923
+ // 修复失败,不设置 prop,组件以骨架态渲染
924
+ }
925
+ }
926
+ i = j;
927
+ continue;
928
+ }
880
929
  try {
881
- // 直接使用 Function 构造器来评估 JavaScript 表达式
882
- // 这比手动转换 JavaScript 对象字面量为 JSON 更可靠
883
930
  props[propName] = new Function('return ' + rawValue)();
884
931
  } catch (e) {
885
- // 如果 Function 构造器失败,尝试手动转换并解析为 JSON
886
932
  try {
887
- // 将 JavaScript 对象字面量转换为有效的 JSON
888
- // 1. 将单引号字符串转换为双引号字符串
889
933
  var jsonValue = value.replace(/'([^'\\]*(\\.[^'\\]*)*)'/g, function (match) {
890
- // 将单引号内容转换为双引号,并转义内部的双引号和反斜杠
891
934
  var inner = match.slice(1, -1).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
892
935
  return "\"".concat(inner, "\"");
893
936
  });
894
- // 2. 为对象键名添加引号(如果还没有引号)
895
- // 修复:使用 \p{L} 匹配 Unicode 字母(包括中文),使用 u 标志
896
937
  jsonValue = jsonValue.replace(/([{,]\s*)([\p{L}_$][\p{L}\p{N}_$]*)\s*:/gu, '$1"$2":');
897
- // 3. 处理属性值中的模板字符串
898
938
  jsonValue = jsonValue.replace(/`([^`]*)`/g, function (match, p1) {
899
939
  return JSON.stringify(p1);
900
940
  });
901
- // 4. 尝试解析为 JSON
902
941
  props[propName] = JSON.parse(jsonValue);
903
942
  } catch (jsonError) {
904
- // 如果都失败了,保持原值
905
943
  props[propName] = value;
906
944
  }
907
945
  }
@@ -39580,18 +39618,64 @@ function requireZTouch () {
39580
39618
  var _zTouch = _interopRequireDefault(requireZTouch());
39581
39619
  } (prism$1));
39582
39620
 
39583
- var themes = {
39621
+ var CODE_THEME_MAP = {
39622
+ github: "ghcolors",
39623
+ atom: "atom-dark",
39624
+ "atom-dark": "atom-dark",
39625
+ "atom-light": "atom-light",
39626
+ dracula: "dracula",
39627
+ "one-dark": "one-dark",
39628
+ "one-light": "one-light",
39629
+ nord: "nord",
39630
+ "material-dark": "material-dark",
39631
+ "material-light": "material-light",
39632
+ "solarized-light": "solarizedlight",
39633
+ "solarized-dark": "solarized-dark-atom",
39634
+ okaidia: "okaidia",
39635
+ tomorrow: "tomorrow",
39636
+ coy: "coy",
39637
+ "vsc-dark-plus": "vsc-dark-plus",
39638
+ vs: "vs",
39639
+ ghcolors: "ghcolors",
39640
+ prism: "prism",
39641
+ twilight: "twilight",
39642
+ "duotone-dark": "duotone-dark",
39643
+ "duotone-light": "duotone-light",
39644
+ "night-owl": "night-owl",
39645
+ darcula: "darcula",
39646
+ "gruvbox-dark": "gruvbox-dark",
39647
+ "gruvbox-light": "gruvbox-light"
39648
+ };
39649
+ // 预置的默认主题
39650
+ var DEFAULT_THEMES = {
39584
39651
  dark: prism$1.vscDarkPlus,
39585
39652
  light: prism$1.vs
39586
39653
  };
39654
+ /**
39655
+ * 根据 codeTheme 名称加载对应的 prism 样式
39656
+ */
39657
+ function loadCodeStyle(codeTheme) {
39658
+ // 先查映射表
39659
+ var moduleName = CODE_THEME_MAP[codeTheme] || codeTheme;
39660
+ try {
39661
+ // 使用 require 动态加载 prism 样式模块
39662
+ var styles = require("react-syntax-highlighter/dist/cjs/styles/prism/".concat(moduleName));
39663
+ return styles.default || styles;
39664
+ } catch (_a) {
39665
+ // 加载失败时回退到默认暗色主题
39666
+ return prism$1.vscDarkPlus;
39667
+ }
39668
+ }
39587
39669
  var CodeHighlight = function (_a) {
39588
39670
  var textContent = _a.textContent,
39589
39671
  _b = _a.language,
39590
39672
  language = _b === void 0 ? "txt" : _b,
39591
- darkMode = _a.darkMode;
39592
- var _c = __read(React.useState(false), 2),
39593
- showCopy = _c[0],
39594
- setShowCopy = _c[1];
39673
+ _c = _a.theme,
39674
+ theme = _c === void 0 ? "dark" : _c,
39675
+ codeTheme = _a.codeTheme;
39676
+ var _d = __read(React.useState(false), 2),
39677
+ showCopy = _d[0],
39678
+ setShowCopy = _d[1];
39595
39679
  var copyToClipboard = function (text) {
39596
39680
  return __awaiter(void 0, void 0, void 0, function () {
39597
39681
  var textarea;
@@ -39655,6 +39739,11 @@ var CodeHighlight = function (_a) {
39655
39739
  }, Date.now())
39656
39740
  });
39657
39741
  }
39742
+ // 根据 codeTheme / theme 计算最终的代码高亮样式
39743
+ var syntaxStyle = React.useMemo(function () {
39744
+ if (codeTheme) return loadCodeStyle(codeTheme);
39745
+ return DEFAULT_THEMES[theme] || DEFAULT_THEMES.dark;
39746
+ }, [codeTheme, theme]);
39658
39747
  return /*#__PURE__*/runtime.jsxs("div", {
39659
39748
  style: {
39660
39749
  position: "relative"
@@ -39665,7 +39754,7 @@ var CodeHighlight = function (_a) {
39665
39754
  right: "10px",
39666
39755
  top: "5px",
39667
39756
  zIndex: 1,
39668
- background: darkMode ? "#555" : "#333",
39757
+ background: theme === "light" ? "#e8e8e8" : "#555",
39669
39758
  color: "#fff",
39670
39759
  border: "none",
39671
39760
  padding: "4px 8px",
@@ -39685,7 +39774,7 @@ var CodeHighlight = function (_a) {
39685
39774
  },
39686
39775
  children: showCopy ? "点击复制" : "复制"
39687
39776
  }), /*#__PURE__*/runtime.jsx(SyntaxHighlighter, {
39688
- style: themes.dark,
39777
+ style: syntaxStyle,
39689
39778
  language: language,
39690
39779
  PreTag: "div",
39691
39780
  children: String(textContent).replace(/\n$/, "")
@@ -39811,44 +39900,48 @@ var AudioComponent = function (_a) {
39811
39900
  }), "\u4F60\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 audio \u6807\u7B7E"]
39812
39901
  });
39813
39902
  };
39814
- // 代码组件
39815
- var CodeComponent = function (props) {
39816
- var children = props.children,
39817
- className = props.className;
39818
- props.node;
39819
- var rest = __rest(props, ["children", "className", "node"]);
39820
- var match = /language-(\w+)/.exec(className || "");
39821
- String(children).replace(/\n$/, '');
39822
- var extractText = function (children) {
39823
- return React.Children.toArray(children).reduce(function (acc, child) {
39824
- if (typeof child === 'string') {
39825
- return acc + child;
39826
- } else if (/*#__PURE__*/React.isValidElement(child) && child.props && child.props.children) {
39827
- return acc + extractText(child.props.children);
39903
+ // 代码组件(支持 theme 和 codeTheme 透传)
39904
+ var createCodeComponent = function (theme, codeTheme) {
39905
+ var CodeComponent = function (props) {
39906
+ var children = props.children,
39907
+ className = props.className;
39908
+ props.node;
39909
+ var rest = __rest(props, ["children", "className", "node"]);
39910
+ var match = /language-(\w+)/.exec(className || "");
39911
+ var extractText = function (children) {
39912
+ return React.Children.toArray(children).reduce(function (acc, child) {
39913
+ if (typeof child === 'string') {
39914
+ return acc + child;
39915
+ } else if (/*#__PURE__*/React.isValidElement(child) && child.props && child.props.children) {
39916
+ return acc + extractText(child.props.children);
39917
+ }
39918
+ return acc;
39919
+ }, '');
39920
+ };
39921
+ var content = extractText(children);
39922
+ // 增强语言检测逻辑,检查内容中是否包含mermaid特征
39923
+ var language = match ? match[1] : "txt";
39924
+ // 如果内容包含mermaid特征且语言未正确识别,则强制设置为mermaid
39925
+ if (!match || match[1] !== "mermaid") {
39926
+ var trimmedContent = content.trim();
39927
+ 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')) {
39928
+ language = "mermaid";
39828
39929
  }
39829
- return acc;
39830
- }, '');
39930
+ }
39931
+ return language !== "txt" ? /*#__PURE__*/runtime.jsx(CodeHighlight, {
39932
+ ...rest,
39933
+ language: language,
39934
+ textContent: content,
39935
+ theme: theme,
39936
+ codeTheme: codeTheme,
39937
+ children: content
39938
+ }) : /*#__PURE__*/runtime.jsx("code", {
39939
+ className: className,
39940
+ ...props,
39941
+ children: content
39942
+ });
39831
39943
  };
39832
- var content = extractText(children);
39833
- // 增强语言检测逻辑,检查内容中是否包含mermaid特征
39834
- var language = match ? match[1] : "txt";
39835
- // 如果内容包含mermaid特征且语言未正确识别,则强制设置为mermaid
39836
- if (!match || match[1] !== "mermaid") {
39837
- var trimmedContent = content.trim();
39838
- 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')) {
39839
- language = "mermaid";
39840
- }
39841
- }
39842
- return language !== "txt" ? /*#__PURE__*/runtime.jsx(CodeHighlight, {
39843
- ...rest,
39844
- language: language,
39845
- textContent: content,
39846
- children: content
39847
- }) : /*#__PURE__*/runtime.jsx("code", {
39848
- className: className,
39849
- ...props,
39850
- children: content
39851
- });
39944
+ return CodeComponent;
39852
39945
  };
39853
39946
  // 段落组件
39854
39947
  var PComponent = function (pProps) {
@@ -39876,16 +39969,23 @@ var PreComponent = function (props) {
39876
39969
  ...props
39877
39970
  });
39878
39971
  };
39879
- var BuiltInComponents = {
39880
- _THINK: Think,
39881
- // _TOOL_CALL: ToolCall,
39882
- pre: PreComponent,
39883
- code: CodeComponent,
39884
- p: PComponent,
39885
- a: AComponent,
39886
- video: VideoComponent,
39887
- audio: AudioComponent
39888
- };
39972
+ /**
39973
+ * 创建带主题配置的内置组件集合
39974
+ * @param theme 整体主题 (dark / light / 自定义)
39975
+ * @param codeTheme 代码语法主题 (github / atom / 自定义)
39976
+ */
39977
+ function createBuiltInComponents(theme, codeTheme) {
39978
+ var themedCode = createCodeComponent(theme, codeTheme);
39979
+ return {
39980
+ _THINK: Think,
39981
+ pre: PreComponent,
39982
+ code: themedCode,
39983
+ p: PComponent,
39984
+ a: AComponent,
39985
+ video: VideoComponent,
39986
+ audio: AudioComponent
39987
+ };
39988
+ }
39889
39989
 
39890
39990
  var ErrorBoundary = /** @class */function (_super) {
39891
39991
  __extends(ErrorBoundary, _super);
@@ -59412,15 +59512,9 @@ var FallbackView = /** @class */function (_super) {
59412
59512
  function isEnhancedComponentConfig(value) {
59413
59513
  return typeof value === 'object' && value !== null && 'value' in value && typeof value.value !== 'undefined';
59414
59514
  }
59415
- /**
59416
- * 从组件值中提取实际的组件
59417
- */
59418
59515
  function extractComponent(value) {
59419
59516
  return isEnhancedComponentConfig(value) ? value.value : value;
59420
59517
  }
59421
- /**
59422
- * 将 components 转换为 ComponentHandler 数组
59423
- */
59424
59518
  function convertComponentsToHandlers(components, componentHandlers) {
59425
59519
  var e_1, _a;
59426
59520
  var handlers = [];
@@ -59442,7 +59536,8 @@ function convertComponentsToHandlers(components, componentHandlers) {
59442
59536
  onRenderProcess: config.onRenderProcess,
59443
59537
  onRenderFinished: config.onRenderFinished,
59444
59538
  loader: config.loader,
59445
- label: config.label
59539
+ label: config.label,
59540
+ streamable: config.streamable
59446
59541
  });
59447
59542
  } else {
59448
59543
  handlers.push({
@@ -59472,6 +59567,59 @@ function convertComponentsToHandlers(components, componentHandlers) {
59472
59567
  }
59473
59568
  return handlers;
59474
59569
  }
59570
+ function buildLoaderShellFromParsed(parsedData, allComponentHandlers, layoutProps) {
59571
+ if (!parsedData.length) return null;
59572
+ var nodes = [];
59573
+ var _loop_2 = function (i) {
59574
+ var item = parsedData[i];
59575
+ if (item.type === 'text') {
59576
+ var t = String(item.value || '').trim();
59577
+ if (t) {
59578
+ nodes.push(/*#__PURE__*/React.createElement('div', {
59579
+ key: "sync-txt-".concat(i),
59580
+ style: {
59581
+ whiteSpace: 'pre-wrap'
59582
+ }
59583
+ }, t));
59584
+ }
59585
+ return "continue";
59586
+ }
59587
+ if (item.type !== 'component' || item.isComplete === true) return "continue";
59588
+ var handler = allComponentHandlers.find(function (c) {
59589
+ return c.name === item.value;
59590
+ });
59591
+ if (!(handler === null || handler === void 0 ? void 0 : handler.loader)) return "continue";
59592
+ var displayName = handler.label || item.value;
59593
+ nodes.push(/*#__PURE__*/React.createElement(ComponentPlaceholder, {
59594
+ key: "sync-loader-".concat(item.value, "-").concat(i),
59595
+ componentName: displayName,
59596
+ loader: handler.loader
59597
+ }));
59598
+ };
59599
+ for (var i = 0; i < parsedData.length; i++) {
59600
+ _loop_2(i);
59601
+ }
59602
+ if (!nodes.length) return null;
59603
+ return /*#__PURE__*/React.createElement(MdxLayout, __assign(__assign({}, layoutProps), {
59604
+ children: React.createElement.apply(React, __spreadArray([React.Fragment, null], __read(nodes), false))
59605
+ }));
59606
+ }
59607
+ function parsedStructureSignature(parsedData) {
59608
+ return parsedData.map(function (p) {
59609
+ if (p.type === 'text') return "t:".concat(String(p.value || '').length);
59610
+ return "c:".concat(p.value, ":").concat(p.isComplete === true ? '1' : '0');
59611
+ }).join('|');
59612
+ }
59613
+ function hasPendingLoaderComponents(parsedData, handlers) {
59614
+ return parsedData.some(function (item) {
59615
+ if (item.type !== 'component' || item.isComplete === true) return false;
59616
+ var handler = handlers.find(function (h) {
59617
+ return h.name === item.value;
59618
+ });
59619
+ if (handler === null || handler === void 0 ? void 0 : handler.streamable) return false;
59620
+ return Boolean(handler === null || handler === void 0 ? void 0 : handler.loader);
59621
+ });
59622
+ }
59475
59623
  function ReactAIRenderer(_a) {
59476
59624
  var _this = this;
59477
59625
  var content = _a.content,
@@ -59484,14 +59632,19 @@ function ReactAIRenderer(_a) {
59484
59632
  componentHandlers = _d === void 0 ? [] : _d,
59485
59633
  useGithubStyles = _a.useGithubStyles,
59486
59634
  mdxLayoutClassName = _a.mdxLayoutClassName,
59487
- mdxLayoutStyle = _a.mdxLayoutStyle;
59488
- var _e = __read(React.useState(null), 2),
59489
- component = _e[0],
59490
- setComponent = _e[1];
59635
+ mdxLayoutStyle = _a.mdxLayoutStyle,
59636
+ _e = _a.theme,
59637
+ theme = _e === void 0 ? "dark" : _e,
59638
+ codeTheme = _a.codeTheme;
59639
+ var _f = __read(React.useState(null), 2),
59640
+ component = _f[0],
59641
+ setComponent = _f[1];
59491
59642
  var fallbackErrorRef = React.useRef({
59492
59643
  hasError: false
59493
59644
  });
59494
59645
  var completedComponentsCacheRef = React.useRef(new Map());
59646
+ var parserRef = React.useRef(null);
59647
+ var lastLoaderSigRef = React.useRef('');
59495
59648
  var isBrowser = typeof window !== 'undefined';
59496
59649
  content = content || children || '';
59497
59650
  var normalizedComponents = components ? Object.fromEntries(Object.entries(components).filter(function (_a) {
@@ -59505,11 +59658,26 @@ function ReactAIRenderer(_a) {
59505
59658
  value = _b[1];
59506
59659
  return [name, extractComponent(value)];
59507
59660
  })) : {};
59508
- var allComponents = __assign(__assign({}, BuiltInComponents), normalizedComponents);
59661
+ // 根据 theme / codeTheme 创建带主题配置的内置组件
59662
+ var themedBuiltInComponents = React.useMemo(function () {
59663
+ return createBuiltInComponents(theme, codeTheme);
59664
+ }, [theme, codeTheme]);
59665
+ var allComponents = __assign(__assign({}, themedBuiltInComponents), normalizedComponents);
59509
59666
  var allComponentHandlers = __spreadArray(__spreadArray([], __read(components ? convertComponentsToHandlers(components, componentHandlers) : []), false), __read(componentHandlers), false);
59510
- var parser = new MDXStreamingParser(allComponentHandlers);
59667
+ if (!parserRef.current) {
59668
+ parserRef.current = new MDXStreamingParser(allComponentHandlers);
59669
+ }
59670
+ var parser = parserRef.current;
59511
59671
  var mdxContent = content || '';
59512
- // FallbackView 错误状态变化时的回调
59672
+ var handlersRef = React.useRef(allComponentHandlers);
59673
+ handlersRef.current = allComponentHandlers;
59674
+ var layoutProps = React.useMemo(function () {
59675
+ return {
59676
+ useGithubStyles: useGithubStyles,
59677
+ className: mdxLayoutClassName,
59678
+ style: mdxLayoutStyle
59679
+ };
59680
+ }, [useGithubStyles, mdxLayoutClassName, mdxLayoutStyle]);
59513
59681
  var handleFallbackErrorChange = function (hasError, error) {
59514
59682
  fallbackErrorRef.current = {
59515
59683
  hasError: hasError,
@@ -59518,17 +59686,32 @@ function ReactAIRenderer(_a) {
59518
59686
  };
59519
59687
  React.useEffect(function () {
59520
59688
  if (!isBrowser) return;
59689
+ var cancelled = false;
59521
59690
  var parseMDX = function () {
59522
59691
  return __awaiter(_this, void 0, void 0, function () {
59523
- 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;
59692
+ 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;
59524
59693
  var e_2, _b;
59525
59694
  return __generator(this, function (_c) {
59526
59695
  switch (_c.label) {
59527
59696
  case 0:
59528
- ThinkComponent = null;
59529
- ResultComponent = null;
59530
59697
  protectedContent = protectSpecialSyntax(mdxContent);
59531
59698
  _a = remarkThinkUpdate(protectedContent), thinkContent = _a.thinkContent, resultContent = _a.resultContent;
59699
+ if (resultContent) {
59700
+ resultContent = fixMDXContent(resultContent);
59701
+ parsedData_1 = parser.parse('magic', resultContent);
59702
+ loaderSig = parsedStructureSignature(parsedData_1);
59703
+ if (hasPendingLoaderComponents(parsedData_1, handlersRef.current)) {
59704
+ if (loaderSig !== lastLoaderSigRef.current) {
59705
+ lastLoaderSigRef.current = loaderSig;
59706
+ shell = buildLoaderShellFromParsed(parsedData_1, handlersRef.current, layoutProps);
59707
+ if (shell && !cancelled) setComponent(shell);
59708
+ }
59709
+ return [2 /*return*/];
59710
+ }
59711
+ lastLoaderSigRef.current = '';
59712
+ }
59713
+ ThinkComponent = null;
59714
+ ResultComponent = null;
59532
59715
  if (!thinkContent) return [3 /*break*/, 2];
59533
59716
  return [4 /*yield*/, renderMdx(thinkContent, scope, allComponents)];
59534
59717
  case 1:
@@ -59537,7 +59720,6 @@ function ReactAIRenderer(_a) {
59537
59720
  case 2:
59538
59721
  parsedData = [];
59539
59722
  if (!resultContent) return [3 /*break*/, 8];
59540
- resultContent = fixMDXContent(resultContent);
59541
59723
  parsedData = parser.parse('magic', resultContent);
59542
59724
  return [4 /*yield*/, Promise.all(parsedData.map(function (item) {
59543
59725
  return parseComponentRecursively(allComponentHandlers, item, scope);
@@ -59553,7 +59735,6 @@ function ReactAIRenderer(_a) {
59553
59735
  if (indexMatch) {
59554
59736
  index = parseInt(indexMatch[1], 10);
59555
59737
  if (index >= currentComponentCount) {
59556
- // 如果索引超出当前组件数量,删除缓存
59557
59738
  completedComponentsCacheRef.current.delete(key);
59558
59739
  }
59559
59740
  }
@@ -59571,8 +59752,8 @@ function ReactAIRenderer(_a) {
59571
59752
  }
59572
59753
  finalComponent = [];
59573
59754
  fallbackComponent = [];
59574
- _loop_2 = function (i) {
59575
- var item, currentParsedItem, _result, placeholderForFallback, componentNameMatch, componentName_1, componentHandler, displayName, cacheKey;
59755
+ _loop_3 = function (i) {
59756
+ var item, currentParsedItem, _result, placeholderForFallback, componentNameMatch, componentName_1, componentHandler, displayName, cacheKey, cacheKey;
59576
59757
  return __generator(this, function (_d) {
59577
59758
  switch (_d.label) {
59578
59759
  case 0:
@@ -59585,10 +59766,10 @@ function ReactAIRenderer(_a) {
59585
59766
  case 1:
59586
59767
  _result = _d.sent();
59587
59768
  finalComponent.push(_result);
59588
- return [3 /*break*/, 11];
59769
+ return [3 /*break*/, 14];
59589
59770
  case 2:
59590
59771
  componentNameMatch = item.value.match(/<([A-Z][A-Za-z0-9]*)/);
59591
- if (!componentNameMatch) return [3 /*break*/, 9];
59772
+ if (!componentNameMatch) return [3 /*break*/, 12];
59592
59773
  componentName_1 = componentNameMatch[1];
59593
59774
  componentHandler = allComponentHandlers.find(function (c) {
59594
59775
  return c.name === componentName_1;
@@ -59602,18 +59783,22 @@ function ReactAIRenderer(_a) {
59602
59783
  loader: componentHandler === null || componentHandler === void 0 ? void 0 : componentHandler.loader,
59603
59784
  key: "fallback-loader-".concat(componentName_1)
59604
59785
  });
59605
- if (!(currentParsedItem.isComplete === true || !(componentHandler === null || componentHandler === void 0 ? void 0 : componentHandler.loader))) return [3 /*break*/, 6];
59786
+ if (!(currentParsedItem.isComplete === true || !(componentHandler === null || componentHandler === void 0 ? void 0 : componentHandler.loader))) return [3 /*break*/, 7];
59606
59787
  cacheKey = "mdx-component-".concat(componentName_1, "-").concat(i);
59607
59788
  if (!completedComponentsCacheRef.current.has(cacheKey)) return [3 /*break*/, 3];
59608
- // 使用缓存的组件
59609
59789
  _result = completedComponentsCacheRef.current.get(cacheKey);
59610
- return [3 /*break*/, 5];
59790
+ return [3 /*break*/, 6];
59611
59791
  case 3:
59612
- return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59792
+ if (!(componentHandler === null || componentHandler === void 0 ? void 0 : componentHandler.streamable)) return [3 /*break*/, 4];
59793
+ _result = /*#__PURE__*/React.createElement(componentHandler.component, __assign(__assign({}, currentParsedItem.props), {
59794
+ key: cacheKey
59795
+ }));
59796
+ completedComponentsCacheRef.current.set(cacheKey, _result);
59797
+ return [3 /*break*/, 6];
59613
59798
  case 4:
59614
- // 缓存不存在,调用 renderMdx 并存入缓存
59799
+ return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59800
+ case 5:
59615
59801
  _result = _d.sent();
59616
- // 为组件设置 key,确保 React 能正确识别
59617
59802
  if (/*#__PURE__*/React.isValidElement(_result)) {
59618
59803
  _result = /*#__PURE__*/React.cloneElement(_result, {
59619
59804
  key: cacheKey
@@ -59623,30 +59808,38 @@ function ReactAIRenderer(_a) {
59623
59808
  key: cacheKey
59624
59809
  }, _result);
59625
59810
  }
59626
- // 存入缓存
59627
59811
  completedComponentsCacheRef.current.set(cacheKey, _result);
59628
- _d.label = 5;
59629
- case 5:
59630
- finalComponent.push(_result);
59631
- return [3 /*break*/, 8];
59812
+ _d.label = 6;
59632
59813
  case 6:
59633
- return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59814
+ finalComponent.push(_result);
59815
+ return [3 /*break*/, 11];
59634
59816
  case 7:
59635
- // 组件未完成,正常渲染
59636
- _result = _d.sent();
59637
- finalComponent.push(placeholderForFallback);
59638
- _d.label = 8;
59817
+ if (!(componentHandler === null || componentHandler === void 0 ? void 0 : componentHandler.streamable)) return [3 /*break*/, 8];
59818
+ cacheKey = "mdx-component-".concat(componentName_1, "-").concat(i);
59819
+ _result = /*#__PURE__*/React.createElement(componentHandler.component, __assign(__assign({}, currentParsedItem.props), {
59820
+ key: cacheKey
59821
+ }));
59822
+ finalComponent.push(_result);
59823
+ return [3 /*break*/, 11];
59639
59824
  case 8:
59825
+ if (!placeholderForFallback) return [3 /*break*/, 9];
59826
+ finalComponent.push(placeholderForFallback);
59640
59827
  return [3 /*break*/, 11];
59641
59828
  case 9:
59642
59829
  return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59643
59830
  case 10:
59644
- // 没有匹配到组件名,正常渲染
59645
59831
  _result = _d.sent();
59646
59832
  finalComponent.push(_result);
59647
59833
  _d.label = 11;
59648
59834
  case 11:
59649
- // fallbackComponent 应该是 finalComponent 的前 i 个元素 + 当前 item 的 loader
59835
+ return [3 /*break*/, 14];
59836
+ case 12:
59837
+ return [4 /*yield*/, renderMdx(item.value, scope, allComponents)];
59838
+ case 13:
59839
+ _result = _d.sent();
59840
+ finalComponent.push(_result);
59841
+ _d.label = 14;
59842
+ case 14:
59650
59843
  fallbackComponent.length = 0;
59651
59844
  fallbackComponent.push.apply(fallbackComponent, __spreadArray([], __read(finalComponent.slice(0, i)), false));
59652
59845
  if (placeholderForFallback) {
@@ -59660,7 +59853,7 @@ function ReactAIRenderer(_a) {
59660
59853
  _c.label = 4;
59661
59854
  case 4:
59662
59855
  if (!(i < parsedComponents.length)) return [3 /*break*/, 7];
59663
- return [5 /*yield**/, _loop_2(i)];
59856
+ return [5 /*yield**/, _loop_3(i)];
59664
59857
  case 5:
59665
59858
  _c.sent();
59666
59859
  _c.label = 6;
@@ -59683,13 +59876,13 @@ function ReactAIRenderer(_a) {
59683
59876
  MDXComponent = /*#__PURE__*/runtime.jsxs(React.Fragment, {
59684
59877
  children: [ThinkComponent, ResultComponent]
59685
59878
  });
59879
+ if (cancelled) return [2 /*return*/];
59686
59880
  if (!fallbackErrorRef.current.hasError) {
59687
59881
  setComponent(MDXComponent);
59688
59882
  } else {
59689
59883
  parsedDataLength = parsedData.length;
59690
59884
  if (parsedDataLength > 0) {
59691
59885
  lastItem = parsedData[parsedDataLength - 1];
59692
- // 如果最后一个组件是完整的,强制更新
59693
59886
  if (lastItem.isComplete === true) {
59694
59887
  setComponent(MDXComponent);
59695
59888
  } else if (lastItem.type === 'text') {
@@ -59703,7 +59896,10 @@ function ReactAIRenderer(_a) {
59703
59896
  });
59704
59897
  };
59705
59898
  parseMDX();
59706
- }, [content]);
59899
+ return function () {
59900
+ cancelled = true;
59901
+ };
59902
+ }, [content, theme, codeTheme]);
59707
59903
  if (!isBrowser) {
59708
59904
  return null;
59709
59905
  }