import axios from 'axios' import toCamel from 'camelcase-keys' import { useEffect, useState } from 'react' import ReactMarkdown from 'react-markdown' import { Link } from 'react-router-dom' import remarkGFM from 'remark-gfm' import SectionTitle from '@/components/common/SectionTitle' import SubsectionTitle from '@/components/common/SubsectionTitle' import { API_BASE_URL } from '@/config' import type { Components } from 'react-markdown' import type { WikiPage } from '@/types' type Props = { title: string body?: string } const mdComponents = { h1: ({ children }) => {children}, h2: ({ children }) => {children}, ol: ({ children }) =>
    {children}
, ul: ({ children }) => , a: (({ href, children }) => ( ['/', '.'].some (e => href?.startsWith (e)) ? {children} : ( {children} ))) } as const satisfies Components export default ({ title, body }: Props) => { const [pageNames, setPageNames] = useState ([]) const [realBody, setRealBody] = useState ('') useEffect (() => { if (!(body)) return void (async () => { try { const res = await axios.get (`${ API_BASE_URL }/wiki`) const data = toCamel (res.data as any, { deep: true }) as WikiPage[] setPageNames (data.map (page => page.title).sort ((a, b) => b.length - a.length)) } catch { setPageNames ([]) } }) () }, []) useEffect (() => { setRealBody ('') }, [body]) useEffect (() => { if (!(body)) return const matchIndices = (target: string, keyword: string) => { const indices: number[] = [] let pos = 0 let idx while ((idx = target.indexOf (keyword, pos)) >= 0) { indices.push (idx) pos = idx + keyword.length } return indices } const linkIndices = (text: string, names: string[]): [string, [number, number]][] => { const result: [string, [number, number]][] = [] names.forEach (name => { matchIndices (text, name).forEach (idx => { const start = idx const end = idx + name.length const overlaps = result.some (([, [st, ed]]) => start < ed && end > st) if (!(overlaps)) result.push ([name, [start, end]]) }) }) return result.sort (([, [a]], [, [b]]) => b - a) } setRealBody ( linkIndices (body, pageNames).reduce ((acc, [name, [start, end]]) => ( acc.slice (0, start) + `[${ name }](/wiki/${ encodeURIComponent (name) })` + acc.slice (end)), body)) }, [body, pageNames]) return ( {realBody || `このページは存在しません。[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`} ) }