ファイル
btrc-hub/frontend/src/components/WikiBody.tsx
T
2026-02-04 23:08:28 +09:00

59 行
2.0 KiB
TypeScript

import { useEffect, useMemo, useState } from 'react'
import ReactMarkdown from 'react-markdown'
import remarkGFM from 'remark-gfm'
import PrefetchLink from '@/components/PrefetchLink'
import SectionTitle from '@/components/common/SectionTitle'
import SubsectionTitle from '@/components/common/SubsectionTitle'
import { apiGet } from '@/lib/api'
import remarkWikiAutoLink from '@/lib/remark-wiki-autolink'
import type { FC } from 'react'
import type { Components } from 'react-markdown'
import type { WikiPage } from '@/types'
type Props = { title: string
body?: string }
const mdComponents = { h1: ({ children }) => <SectionTitle>{children}</SectionTitle>,
h2: ({ children }) => <SubsectionTitle>{children}</SubsectionTitle>,
ol: ({ children }) => <ol className="list-decimal pl-6">{children}</ol>,
ul: ({ children }) => <ul className="list-disc pl-6">{children}</ul>,
a: (({ href, children }) => (
['/', '.'].some (e => href?.startsWith (e))
? <PrefetchLink to={href!}>{children}</PrefetchLink>
: (
<a href={href}
target="_blank"
rel="noopener noreferrer">
{children}
</a>))) } as const satisfies Components
export default (({ title, body }: Props) => {
const [pageNames, setPageNames] = useState<string[]> ([])
const remarkPlugins = useMemo (
() => [() => remarkWikiAutoLink (pageNames), remarkGFM], [pageNames])
useEffect (() => {
void (async () => {
try
{
const data = await apiGet<WikiPage[]> ('/wiki')
setPageNames (data.map (page => page.title).sort ((a, b) => b.length - a.length))
}
catch
{
setPageNames ([])
}
}) ()
}, [])
return (
<ReactMarkdown components={mdComponents} remarkPlugins={remarkPlugins}>
{body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`}
</ReactMarkdown>)
}) satisfies FC<Props>