~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

7
62 lines · 2.4 KB Raw History
// 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 = `<div class="diagram">${svg}</div>`
      delete node.lang
      delete node.meta
    })
  }
}