File size: 2,523 Bytes
85a4a41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import React, { useEffect, useRef } from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import './Streaming.css';

// Streaming component for rendering markdown content
const Streaming = ({ content, isStreaming, onContentRef }) => {
  const contentRef = useRef(null);
  
  useEffect(() => {
    if (contentRef.current && onContentRef) {
      onContentRef(contentRef.current);
    }
  }, [content, onContentRef]);

  const displayContent = isStreaming ? `${content}▌` : (content || '');

  return (
    <div className="streaming-content" ref={contentRef}>
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        rehypePlugins={[rehypeRaw]}
        components={{
          code({node, inline, className, children, ...props}) {
            const match = /language-(\w+)/.exec(className || '');
            return !inline ? (
              <div className="code-block-container">
                <div className="code-block-header">
                  <span>{match ? match[1] : 'code'}</span>
                </div>
                <SyntaxHighlighter
                  style={atomDark}
                  language={match ? match[1] : 'text'}
                  PreTag="div"
                  {...props}
                >
                  {String(children).replace(/\n$/, '')}
                </SyntaxHighlighter>
              </div>
            ) : (
              <code className={className} {...props}>
                {children}
              </code>
            );
          },
          table({node, ...props}) {
            return (
              <div className="table-container">
                <table {...props} />
              </div>
            );
          },
          a({node, children, href, ...props}) {
            return (
              <a 
                href={href}
                target="_blank"
                rel="noopener noreferrer"
                className="markdown-link"
                {...props}
              >
                {children}
              </a>
            );
          },
          blockquote({node, ...props}) {
            return (
              <blockquote className="markdown-blockquote" {...props} />
            );
          }
        }}
      >
        {displayContent}
      </ReactMarkdown>
    </div>
  );
};

export default Streaming;