diff --git a/frontend/src/components/WikiBody.tsx b/frontend/src/components/WikiBody.tsx index 06bc39e..e3f2fdb 100644 --- a/frontend/src/components/WikiBody.tsx +++ b/frontend/src/components/WikiBody.tsx @@ -17,21 +17,8 @@ export default ({ title, body }: Props) => { const [realBody, setRealBody] = useState ('') useEffect (() => { - const matchIndices = (target: string, keyword: string) => { - 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 - } + if (!(body)) + return void (async () => { try @@ -45,19 +32,47 @@ export default ({ title, body }: Props) => { setPageNames ([]) } }) () + }, []) + + 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 + } - 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]]) + 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]]) + }) }) - }) - 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 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)) + }, [pageNames]) return (