// What the docs need beyond Markdown: their links, written to read on // GitHub and in the repository's pages, made the site's; and their // Mermaid blocks drawn by Pele, as the repository's pages draw them. import { dirname, join, posix, relative } from 'node:path' import { fileURLToPath } from 'node:url' import { render } from 'pele' const here = dirname(fileURLToPath(import.meta.url)) const content = join(here, 'src/content/docs') /** Where a file outside docs/ is read: its page on knotless.dev. */ const REPO = 'https://knotless.dev/chadtmiller.com/knotless' const walk = (node, visit) => { visit(node) for (const child of node.children ?? []) walk(child, visit) } /** The page a link in `page`, a path under docs/, lands on, as a URL. */ function resolve(page, url, base) { if (/^[a-z]+:|^#|^\//.test(url)) return url const [path, anchor] = url.split('#') const target = posix.normalize(posix.join('docs', posix.dirname(page), path)) const hash = anchor ? `#${anchor}` : '' if (target.startsWith('docs/') && target.endsWith('.md') && target !== 'docs/design.md') { const slug = target.slice('docs/'.length).replace(/\.md$/, '').replace(/(^|\/)README$/, '') return `${base}/${slug ? `${slug.toLowerCase()}/` : ''}${hash}` } if (target === 'docs/design.md') return `${base}/design/${hash}` // A directory has no extension: lexicons/dev/knotless, web. const kind = posix.extname(target) ? 'blob' : 'tree' return `${REPO}/${kind}/main/${target}${hash}` } /** Links between pages go to the site's pages; links out of docs/, to the repository. */ export function remarkLinks({ base }) { return (tree, file) => { const page = relative(content, file.path).replace(/(^|\/)index\.md$/, '$1README.md') walk(tree, (node) => { if (node.type === 'link' || node.type === 'definition') node.url = resolve(page, node.url, base) }) } } /** Each ```mermaid block, drawn: an SVG whose colours follow the page's. */ export function remarkMermaid() { return (tree, file) => { walk(tree, (node) => { if (node.type !== 'code' || node.lang !== 'mermaid') return let svg try { ;({ svg } = render(node.value)) } catch (e) { throw new Error(`${file.path}: a diagram does not draw: ${e.message}`) } node.type = 'html' node.value = `
${svg}
` delete node.lang delete node.meta }) } }