personal-website/components/server/RichText.tsx
Filipe Medeiros 1aa2b2c599
fix: RSS feed
Signed-off-by: Filipe Medeiros <hello@filipesm.eu>
2023-12-03 12:25:55 +01:00

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} />
}
})}
</>
)
}