This commit is contained in:
@@ -1,14 +1,69 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import toCamel from 'camelcase-keys'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
import ReactMarkdown from 'react-markdown'
|
import ReactMarkdown from 'react-markdown'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { API_BASE_URL } from '@/config'
|
||||||
|
|
||||||
|
import type { WikiPage } from '@/types'
|
||||||
|
|
||||||
type Props = { title: string
|
type Props = { title: string
|
||||||
body?: string }
|
body?: string }
|
||||||
|
|
||||||
|
|
||||||
export default ({ title, body }: Props) => (
|
export default ({ title, body }: Props) => {
|
||||||
<ReactMarkdown components={{ a: (
|
const [pageNames, setPageNames] = useState<string[]> ([])
|
||||||
({ href, children }) => (['/', '.'].some (e => href?.startsWith (e))
|
const [realBody, setRealBody] = useState<string> ('')
|
||||||
? <Link to={href!}>{children}</Link>
|
|
||||||
: <a href={href} target="_blank" rel="noopener noreferrer">{children}</a>)) }}>
|
useEffect (() => {
|
||||||
{body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`}
|
const matchIndices = (target: string, keyword: string) => {
|
||||||
</ReactMarkdown>)
|
const indices: number[] = []
|
||||||
|
let pos = 0
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const idx = target.indexOf (keyword, pos)
|
||||||
|
if (idx < 0)
|
||||||
|
break
|
||||||
|
indices.push (idx)
|
||||||
|
pos = idx + keyword.length
|
||||||
|
}
|
||||||
|
|
||||||
|
return indices
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ([])
|
||||||
|
}
|
||||||
|
}) ()
|
||||||
|
|
||||||
|
const linkIndices: [string, [number, number]][] = []
|
||||||
|
pageNames.forEach (name => {
|
||||||
|
matchIndices (body ?? '', name).map (idx => [idx, idx + name.length]).forEach (([start, end]) => {
|
||||||
|
if (linkIndices.every (([, [st, ed]]) => (start < st || ed <= start) && (end < st || ed <= end)))
|
||||||
|
linkIndices.push ([name, [start, end]])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
linkIndices.sort (([, [a]], [, [b]]) => b - a)
|
||||||
|
linkIndices.forEach (([name, [start, end]]) => {
|
||||||
|
setRealBody (prev => `${ prev.slice (0, start) }[${ name }](/wiki/${ encodeURIComponent (name) })${ prev.slice (end) }`)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactMarkdown components={{ a: (
|
||||||
|
({ href, children }) => (['/', '.'].some (e => href?.startsWith (e))
|
||||||
|
? <Link to={href!}>{children}</Link>
|
||||||
|
: <a href={href} target="_blank" rel="noopener noreferrer">{children}</a>)) }}>
|
||||||
|
{realBody || `このページは存在しません。[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`}
|
||||||
|
</ReactMarkdown>)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user