fix: generate package examples from usage guides

This commit is contained in:
2026-07-13 20:48:22 +05:30
parent 55438f2672
commit b07ef5058a
+48 -14
View File
@@ -171,23 +171,57 @@ function markdown(source: string): { html: string; headings: DocHeading[] } {
}
function examplesFrom(readme: string, name: string): string {
const examples = [...readme.matchAll(/```([^\n]*)\n([\s\S]*?)```/g)]
.map((match) => ({ language: match[1]!.trim(), code: match[2]!.trim() }))
.filter((example) => example.code)
.filter(
(example, index, all) => all.findIndex((value) => value.code === example.code) === index,
)
.slice(0, 4);
if (!examples.length) {
examples.push({
language: "ts",
code: `import * as packageApi from "@wrnexus/${name}";\n\nconsole.log(packageApi);`,
});
const usage = /^## Usage\s*$([\s\S]*?)(?=^##\s|\s*$)/m.exec(readme)?.[1];
if (!usage) throw new Error(`@wrnexus/${name} README must contain a Usage section`);
const examples: { title: string; language: string; code: string }[] = [];
const lines = usage.replace(/\r/g, "").split("\n");
let title = "Typical usage";
let prose = "";
for (let index = 0; index < lines.length; index++) {
const line = lines[index]!;
const heading = /^#{3,4}\s+(.+)$/.exec(line);
if (heading) {
title = heading[1]!.replace(/[`*_]/g, "").trim();
prose = "";
continue;
}
const fence = /^```(.*)$/.exec(line);
if (fence) {
const code: string[] = [];
index++;
while (index < lines.length && !/^```/.test(lines[index]!)) {
code.push(lines[index]!);
index++;
}
const value = code.join("\n").trim();
const language = fence[1]!.trim();
if (value && language !== "text" && !examples.some((example) => example.code === value)) {
examples.push({
title: title === "Typical usage" && prose ? prose : title,
language,
code: value,
});
}
prose = "";
continue;
}
if (line.trim() && !/^[-*>|]/.test(line.trim())) {
prose = line
.replace(/[`*_]/g, "")
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
.replace(/:\s*$/, "")
.trim();
}
}
if (examples.length < 2) {
throw new Error(`@wrnexus/${name} README needs at least two Usage code examples`);
}
return examples
.slice(0, 6)
.map(
(example, index) =>
`<article class="example-card"><h3>Example ${index + 1}</h3><pre data-language="${escape(example.language || "text")}"><code>${escape(example.code)}</code></pre></article>`,
(example) =>
`<article class="example-card"><h3>${inline(example.title)}</h3><pre data-language="${escape(example.language || "text")}"><code>${escape(example.code)}</code></pre></article>`,
)
.join("");
}