cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

cat/module-path
012 / website / src / remark / repo-links.ts
repo-links.ts 1.5K
1// A remark plugin for links that leave the docs tree. The docs link to2// files beside them in the repository (../../ROADMAP.md, ../../CLAUDE.md),3// which read on GitHub but aren't pages of the site; this points them at4// the same file on GitHub, so the site's broken-link check still catches5// every link that resolves to nothing.6import path from 'node:path';78type Node = {type: string; url?: string; children?: Node[]};910export default function repoLinks(opts: {docsDir: string; repoDir: string; blobUrl: string}) {11 const docsDir = path.resolve(opts.docsDir);12 const repoDir = path.resolve(opts.repoDir);13 return (tree: Node, file: {path?: string}) => {14 if (!file.path) {15 return;16 }17 const from = path.dirname(file.path);18 const walk = (node: Node) => {19 if ((node.type === 'link' || node.type === 'definition') && node.url) {20 node.url = rewrite(node.url, from, docsDir, repoDir, opts.blobUrl);21 }22 node.children?.forEach(walk);23 };24 walk(tree);25 };26}2728function rewrite(url: string, from: string, docsDir: string, repoDir: string, blobUrl: string): string {29 if (/^[a-z][a-z0-9+.-]*:|^#|^\//i.test(url)) {30 return url;31 }32 const [file, hash] = url.split('#', 2);33 const target = path.resolve(from, decodeURI(file));34 if (target === docsDir || target.startsWith(docsDir + path.sep) || !target.startsWith(repoDir + path.sep)) {35 return url;36 }37 const rel = path.relative(repoDir, target).split(path.sep).join('/');38 return `${blobUrl}/${rel}${hash ? `#${hash}` : ''}`;39}