28 lines
1.3 KiB
TypeScript
28 lines
1.3 KiB
TypeScript
import type { ReactElement } from 'react'
|
|
import type { MarkdownKind } from './markdown'
|
|
import type { PreviewText } from './types'
|
|
import { createContext, useContext, useMemo } from 'react'
|
|
import { cn } from '@/lib/utils'
|
|
import { renderMarkdown } from './markdown'
|
|
import { SegmentText } from './SegmentText'
|
|
|
|
/** 卡片里的 Markdown 说明按哪种渲染:页面上是注释;定义卡片浮窗里是 peek(别的文件的注释,不认不带路径的引用)。 */
|
|
export const MarkdownKindContext = createContext<Exclude<MarkdownKind, 'answer'>>('comment')
|
|
|
|
/** 预览里的一段文字:着色的词按源码排版;Markdown 说明渲染成段落、列表、代码块。 */
|
|
export function TextPreview({ text, className }: { text: PreviewText, className?: string }): ReactElement {
|
|
const kind = useContext(MarkdownKindContext)
|
|
if ('markdown' in text)
|
|
return <MarkdownPreview html={renderMarkdown(text.markdown, kind)} className={className} />
|
|
return (
|
|
<p className={cn('cr-code', className)}>
|
|
<SegmentText segments={text} />
|
|
</p>
|
|
)
|
|
}
|
|
|
|
export function MarkdownPreview({ html, className }: { html: string, className?: string }): ReactElement {
|
|
const content = useMemo(() => ({ __html: html }), [html])
|
|
return <div className={cn('cr-markdown', className)} dangerouslySetInnerHTML={content} />
|
|
}
|