|
- import type { Content, Parent, Root, RootContent } from 'mdast'
-
- const escapeForRegExp = (s: string) => s.replace (/[.*+?^${}()|[\]\\]/g, '\\$&')
-
-
- export default (pageNames: string[], basePath = '/wiki'): ((tree: Root) => void) => {
- const names = [...pageNames].sort ((a, b) => b.length - a.length)
-
- if (names.length === 0)
- {
- return () => {
- ;
- }
- }
-
- const re = new RegExp (`(${ names.map (escapeForRegExp).join ('|') })`, 'g')
-
- return (tree: Root) => {
- const edits: { parent: Parent; index: number; parts: RootContent[] }[] = []
-
- const walk = (node: Content | Root, ancestors: Parent[]) => {
- if (!(node) || (typeof node !== 'object'))
- return
-
- if (!(ancestors.some (ancestor => ['link',
- 'linkReference',
- 'image',
- 'imageReference',
- 'code',
- 'inlineCode'].includes (ancestor?.type)))
- && (node.type === 'text'))
- {
- const value = node.value ?? ''
- if (value)
- {
- re.lastIndex = 0
- let m: RegExpExecArray | null
- let last = 0
- const parts: RootContent[] = []
-
- while (m = re.exec (value))
- {
- const start = m.index
- const end = start + m[0].length
-
- if (start > last)
- parts.push ({ type: 'text', value: value.slice (last, start) })
-
- const name = m[1]
- parts.push ({ type: 'link',
- url: `${ basePath }/${ encodeURIComponent (name) }`,
- title: null,
- children: [{ type: 'text', value: name }],
- data: { hProperties: { 'data-wiki': '1' } } })
- last = end
- }
-
- if (parts.length)
- {
- if (last < value.length)
- parts.push ({ type: 'text', value: value.slice (last) })
- const parent = ancestors[ancestors.length - 1]
- if (parent && Array.isArray (parent.children))
- {
- const index = parent.children.indexOf (node)
- if (index >= 0)
- edits.push ({ parent, index, parts })
- }
- }
- }
- }
-
- const maybeChidren = (node as any).children
- if (Array.isArray (maybeChidren))
- {
- const parent = node as Parent
-
- for (let i = 0; i < maybeChidren.length; ++i)
- {
- const child: Content | undefined = maybeChidren[i]
- if (!(child))
- continue
- walk (child, ancestors.concat (parent))
- }
- }
- }
-
- walk (tree, [])
-
- for (let i = edits.length - 1; i >= 0; --i)
- {
- const { parent, index, parts } = edits[i]
-
- if (!(parent) || !(Array.isArray (parent.children)))
- continue
-
- if (0 <= index && index < parent.children.length)
- parent.children.splice (index, 1, ...parts)
- }
- }
- }
|