CoolFace
Apppublic

code2024/bingo

sourceHugging Facemitupdated 3y agoView on Hugging Face
0likes
chat-message.tsx94 linesDownload Raw Back to components
1import remarkGfm from 'remark-gfm'2import remarkMath from 'remark-math'3import supersub from 'remark-supersub'4import remarkBreaks from 'remark-breaks'5import { cn } from '@/lib/utils'6import { CodeBlock } from '@/components/ui/codeblock'7import { MemoizedReactMarkdown } from '@/components/markdown'8import { LearnMore } from './learn-more'9import { ChatMessageModel } from '@/lib/bots/bing/types'10import { useEffect } from 'react'11import { TurnCounter } from './turn-counter'12 13export interface ChatMessageProps {14  message: ChatMessageModel15}16 17export function ChatMessage({ message, ...props }: ChatMessageProps) {18  useEffect(() => {19    if (document.body.scrollHeight - window.innerHeight - window.scrollY - 200 < 0) {20      window.scrollBy(0, 200)21    }22  }, [message.text])23 24  return message.text ? (25    <div26      className={cn('text-message', message.author)}27      {...props}28    >29      <div className="text-message-content">30        <MemoizedReactMarkdown31          linkTarget="_blank"32          className="prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0"33          remarkPlugins={[remarkGfm, remarkMath, supersub, remarkBreaks]}34          components={{35            img(obj) {36              try {37                const uri = new URL(obj.src!)38                const w = uri.searchParams.get('w')39                const h = uri.searchParams.get('h')40                if (w && h) {41                  uri.searchParams.delete('w')42                  uri.searchParams.delete('h')43                  return <a style={{ float: 'left', maxWidth: '50%' }} href={uri.toString()} target="_blank" rel="noopener noreferrer"><img src={obj.src} alt={obj.alt} width={w!} height={h!}/></a>44                }45              } catch (e) {46              }47              return <img src={obj.src} alt={obj.alt} title={obj.title} />48            },49            p({ children }) {50              return <p className="mb-2">{children}</p>51            },52            code({ node, inline, className, children, ...props }) {53              if (children.length) {54                if (children[0] == '▍') {55                  return (56                    <span className="mt-1 animate-pulse cursor-default">▍</span>57                  )58                }59 60                children[0] = (children[0] as string).replace('`▍`', '▍')61              }62 63              const match = /language-(\w+)/.exec(className || '')64 65              if (inline) {66                return (67                  <code className={className} {...props}>68                    {children}69                  </code>70                )71              }72 73              return (74                <CodeBlock75                  key={Math.random()}76                  language={(match && match[1]) || ''}77                  value={String(children).replace(/\n$/, '')}78                  {...props}79                />80              )81            }82          }}83        >84          {message.text}85        </MemoizedReactMarkdown>86      </div>87      <div className="text-message-footer">88        {message.author === 'bot' && <LearnMore sourceAttributions={message.sourceAttributions} />}89        {message.author === 'bot' && <TurnCounter throttling={message.throttling} />}90      </div>91    </div>92  ) : null93}94