1
1
import { FC , memo } from 'react' ;
2
- import ReactMarkdown , { Options } from 'react-markdown' ;
2
+ import ReactMarkdown , { Options } from 'react-markdown' ;
3
+
4
+ const ProcessContent = ( { children } : { children : string } ) => {
5
+ const parts = [ ] ;
6
+ let currentIndex = 0 ;
7
+ // First check if there's a lone </think> tag
8
+ const endThinkMatch = children . match ( / < \/ t h i n k > / ) ;
9
+ if ( endThinkMatch && ! children . slice ( 0 , endThinkMatch . index ) . includes ( '<think>' ) ) {
10
+ // If we find a lone </think>, treat all content before it as think content
11
+ if ( children . slice ( 0 , endThinkMatch . index ) && children . slice ( 0 , endThinkMatch . index ) . trim ( ) !== "" ) {
12
+ if ( endThinkMatch . index ! > 0 ) {
13
+ parts . push (
14
+ < div key = "think-start" className = "bg-gray-200 dark:bg-gray-600 p-4 my-2 rounded-lg border-l-4 border-gray-500 dark:border-gray-200" >
15
+ < ReactMarkdown > { children . slice ( 0 , endThinkMatch . index ) } </ ReactMarkdown >
16
+ </ div >
17
+ ) ;
18
+ }
19
+ }
20
+ // Add remaining content after </think>
21
+ if ( endThinkMatch . index ! + 8 < children . length ) {
22
+ parts . push (
23
+ < ReactMarkdown key = "after-think" >
24
+ { children . slice ( endThinkMatch . index ! + 8 ) }
25
+ </ ReactMarkdown >
26
+ ) ;
27
+ }
28
+ } else {
29
+ // Regular processing for properly paired think tags
30
+ const regex = / < t h i n k > ( [ \s \S ] * ?) < \/ t h i n k > / g;
31
+ let match ;
32
+ while ( ( match = regex . exec ( children ) ) !== null ) {
33
+ // Add content before the think tag
34
+ if ( match . index > currentIndex ) {
35
+ parts . push (
36
+ < ReactMarkdown key = { `text-${ currentIndex } ` } >
37
+ { children . slice ( currentIndex , match . index ) }
38
+ </ ReactMarkdown >
39
+ ) ;
40
+ }
41
+ if ( match [ 1 ] . trim ( ) !== "" ) {
42
+ parts . push (
43
+ < div key = { `think-${ match . index } ` }
44
+ className = "bg-gray-200 dark:bg-gray-600 p-4 my-2 rounded-lg border-l-4 border-gray-500 dark:border-gray-200" >
45
+ < ReactMarkdown > { match [ 1 ] } </ ReactMarkdown >
46
+ </ div >
47
+ ) ;
48
+ }
49
+
50
+ currentIndex = match . index + match [ 0 ] . length ;
51
+ }
52
+
53
+ // Add any remaining content
54
+ if ( currentIndex < children . length ) {
55
+ parts . push (
56
+ < ReactMarkdown key = { `text-${ currentIndex } ` } >
57
+ { children . slice ( currentIndex ) }
58
+ </ ReactMarkdown >
59
+ ) ;
60
+ }
61
+ }
62
+
63
+ return < div > { parts } </ div > ;
64
+ } ;
3
65
4
66
export const MemoizedReactMarkdown : FC < Options > = memo (
5
- ReactMarkdown ,
6
- ( prevProps , nextProps ) => (
7
- prevProps . children === nextProps . children
8
- )
67
+ ( { children, ...props } ) => (
68
+ < ProcessContent { ...props } >
69
+ { typeof children === 'string' ? children : '' }
70
+ </ ProcessContent >
71
+ ) ,
72
+ ( prevProps , nextProps ) => prevProps . children === nextProps . children
9
73
) ;
74
+
75
+ MemoizedReactMarkdown . displayName = 'MemoizedReactMarkdown' ;
0 commit comments