101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
import {
|
|
type RichTextItemResponse,
|
|
type TextRichTextItemResponse,
|
|
} from '@notionhq/client/build/src/api-endpoints'
|
|
import clsx from 'clsx'
|
|
import { type ElementType, type PropsWithChildren } from 'react'
|
|
|
|
import HybridLink from './HybridLink'
|
|
import TeX, { SyncTeX } from './TeX'
|
|
|
|
function wrapWithTag(Element: ElementType, Tag: keyof JSX.IntrinsicElements) {
|
|
return function Wrapped({ children }: PropsWithChildren) {
|
|
return (
|
|
<Tag>
|
|
<Element>{children}</Element>
|
|
</Tag>
|
|
)
|
|
}
|
|
}
|
|
|
|
function getWrapperFromAnnotations(
|
|
annotations: TextRichTextItemResponse['annotations'],
|
|
) {
|
|
let Wrapper = ({ children }: PropsWithChildren) => {
|
|
return <>{children}</>
|
|
}
|
|
|
|
if (annotations.italic) {
|
|
Wrapper = wrapWithTag(Wrapper, 'i')
|
|
}
|
|
if (annotations.bold) {
|
|
Wrapper = wrapWithTag(Wrapper, 'b')
|
|
}
|
|
if (annotations.underline) {
|
|
Wrapper = wrapWithTag(Wrapper, 'u')
|
|
}
|
|
if (annotations.code) {
|
|
Wrapper = wrapWithTag(Wrapper, 'code')
|
|
}
|
|
if (annotations.code) {
|
|
Wrapper = wrapWithTag(Wrapper, 's')
|
|
}
|
|
|
|
return Wrapper
|
|
}
|
|
|
|
export default function RichText({
|
|
richText,
|
|
rss = false,
|
|
}: {
|
|
richText: RichTextItemResponse[]
|
|
rss?: boolean
|
|
}) {
|
|
return (
|
|
<>
|
|
{richText.map((text, index) => {
|
|
if (text.type === 'mention') return null // TODO
|
|
else if (text.type === 'text') {
|
|
const Wrapper = getWrapperFromAnnotations(text.annotations)
|
|
|
|
const className = clsx({
|
|
italic: text.annotations.italic,
|
|
'font-bold': text.annotations.bold,
|
|
underline: text.annotations.underline,
|
|
'dark:bg-neutral-800 border-1 dark:border-neutral-500 font-mono dark:text-red-400 p-1 rounded':
|
|
text.annotations.code,
|
|
strikethrough: text.annotations.strikethrough,
|
|
})
|
|
|
|
if (text.href)
|
|
return (
|
|
<Wrapper key={index}>
|
|
<HybridLink
|
|
href={text.href}
|
|
className={clsx(
|
|
'underline transition-colors hover:text-teal-500',
|
|
className,
|
|
)}
|
|
>
|
|
{text.plain_text}
|
|
</HybridLink>
|
|
</Wrapper>
|
|
)
|
|
else
|
|
return className ? (
|
|
<Wrapper key={index}>
|
|
<span className={className}>{text.plain_text}</span>
|
|
</Wrapper>
|
|
) : (
|
|
<Wrapper key={index}>{text.plain_text}</Wrapper>
|
|
)
|
|
} else if (text.type === 'equation') {
|
|
const Component = rss ? SyncTeX : TeX
|
|
// @ts-expect-error Server Component
|
|
return <Component key={index} math={text.equation.expression} />
|
|
}
|
|
})}
|
|
</>
|
|
)
|
|
}
|