// one-line descriptions for the home banner, taken from the docs' own index pages: the
// "what's here" list in README.md and each section README's list of its pages. nothing is
// written for the site, a page with no line in any index just shows its title.
import fs from "node:fs";
import path from "node:path";
import { toHtml } from "hast-util-to-html";
import type { Element } from "hast";
import { DOCS_DIR, type Doc } from "./docs";
const ITEM = /^\s*-\s*\[[^\]]*\]\(([^)#\s]+\.md)(?:#[^)]*)?\):\s*(.+)$/;
function inline(md: string): string {
return md
.replace(/[&<>]/g, (c) => ({ "&": "&", "<": "<", ">": ">" })[c]!)
.replace(/`([^`]+)`/g, "<code>$1</code>")
.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1");
}
/** doc id -> blurb html, from every README's list items */
export function blurbs(docs: Map<string, Doc>): Map<string, string> {
const out = new Map<string, string>();
for (const id of docs.keys()) {
if (id !== "README" && !id.endsWith("/README")) continue;
const dir = path.posix.dirname(id);
for (const line of fs.readFileSync(path.join(DOCS_DIR, `${id}.md`), "utf8").split("\n")) {
const m = ITEM.exec(line);
if (!m) continue;
const target = path.posix.normalize(path.posix.join(dir === "." ? "" : dir, m[1].slice(0, -3)));
if (!out.has(target)) out.set(target, inline(m[2].trim()));
}
}
return out;
}
/** the first paragraph of a doc, for the section and home banners */
export function firstParagraph(doc: Doc): string | undefined {
const p = doc.tree.children.find((n): n is Element => n.type === "element" && n.tagName === "p");
return p && toHtml(p);
}