70 lines · 2.1 KB · TypeScript
RawDownload
import { mkdir, writeFile } from "node:fs/promises";import { dirname, join } from "node:path"; interface SnippetSource {  readonly source: string;  readonly outputDir: string;  readonly language: string;} const sources: readonly SnippetSource[] = [  {    source: "examples/docs-sdk-quickstart/src/main.ts",    outputDir: "docs/snippets/sdk/quickstart",    language: "ts",  },]; const markerPattern = /^\s*\/\/ docs:(start|end) ([a-z0-9-]+)\s*$/; const dedent = (lines: readonly string[]): string => {  const nonBlank = lines.filter((line) => line.trim().length > 0);  const indent = Math.min(    ...nonBlank.map((line) => {      const match = line.match(/^\s*/);      return match?.[0].length ?? 0;    }),  );   return lines    .map((line) => line.slice(indent))    .join("\n")    .trim();}; for (const source of sources) {  const text = await Bun.file(source.source).text();  const snippets = new Map<string, string[]>();  let current: { readonly name: string; readonly lines: string[] } | null = null;   for (const line of text.split("\n")) {    const marker = line.match(markerPattern);    if (marker) {      const [, kind, name] = marker;      if (kind === "start") {        if (current) throw new Error(`Nested snippet marker in ${source.source}: ${name}`);        current = { name, lines: [] };      } else {        if (!current || current.name !== name) {          throw new Error(`Unmatched snippet end in ${source.source}: ${name}`);        }        snippets.set(name, current.lines);        current = null;      }      continue;    }     if (current) current.lines.push(line);  }   if (current) throw new Error(`Unclosed snippet marker in ${source.source}: ${current.name}`);   for (const [name, lines] of snippets) {    const output = join(source.outputDir, `${name}.mdx`);    await mkdir(dirname(output), { recursive: true });    await writeFile(      output,      `{/_\nThis file is generated by scripts/generate-doc-snippets.ts.\nEdit ${source.source} between the docs:start/docs:end markers instead.\n_/}\n\n\`\`\`${source.language}\n${dedent(lines)}\n\`\`\`\n`,    );  }}