ttrpg-tools/src/cli/completions/sources/links.ts

56 lines
1.5 KiB
TypeScript

/**
* Link completion source — extracts markdown headings from all .md files.
*
* Produces two entries per heading section, plus one for the file itself.
* Uses github-slugger to match marked-gfm-heading-id's generated IDs.
*/
import Slugger from "github-slugger";
import type { CompletionSource, LinkCompletion } from "../types.js";
export const linksSource: CompletionSource = {
key: "links",
scan(index) {
const items: LinkCompletion[] = [];
for (const [filePath, content] of Object.entries(index)) {
if (!filePath.endsWith(".md")) continue;
// Strip .md extension for the router-friendly path
const basePath = filePath.replace(/\.md$/, "");
const fileName = fileNameFromPath(basePath);
const slugger = new Slugger();
// Add the file itself as a link (whole article)
items.push({
path: basePath,
label: fileName,
section: null,
});
// Parse headings for section-scoped links
const headingRegex = /^(#{1,6})\s+(.+)$/gm;
let match: RegExpExecArray | null;
while ((match = headingRegex.exec(content)) !== null) {
const title = match[2].trim();
const id = slugger.slug(title.toLowerCase());
items.push({
path: basePath,
label: `${fileName} § ${title}`,
section: id,
});
}
}
return items;
},
};
function fileNameFromPath(path: string): string {
const parts = path.split("/").filter(Boolean);
return parts[parts.length - 1] || path;
}