Skip to content

Commit

Permalink
feat: new extractExamplesProcessor
Browse files Browse the repository at this point in the history
fixes #59
  • Loading branch information
ext committed Nov 2, 2024
1 parent 7cb6a44 commit ea63c76
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 0 deletions.
11 changes: 11 additions & 0 deletions etc/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ export interface DocumentOutlineEntry {
title: string;
}

// @public
export interface ExtractExamplesOptions extends ProcessorOptions {
// (undocumented)
languages?: string[];
// (undocumented)
output: string;
}

// @public
export function extractExamplesProcessor(options: ExtractExamplesOptions): Processor;

// @public (undocumented)
export interface FileInfo {
fullPath: string;
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ export {
export { processorRuntimeName } from "./processor-runtime-name";
export { type ProcessorStage } from "./processor-stage";
export {
type ExtractExamplesOptions,
type ManifestProcessorOptions,
type MOTDOptions,
type TopnavEntry,
type VersionProcessorOptions,
type SelectableVersionProcessorOptions,
type SourceUrlProcessorOptions,
extractExamplesProcessor,
manifestProcessor,
motdProcessor,
selectableVersionProcessor,
Expand Down
119 changes: 119 additions & 0 deletions src/processors/extract-examples-processor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import fs from "node:fs/promises";
import path from "node:path/posix";
import markdownIt from "markdown-it";
import { type Document } from "../document";
import { ProcessorOptions, type Processor } from "../processor";
import { haveOutput, normalizePath } from "../utils";
import { parseInfostring } from "../examples";

/**
* Options for `extractExamplesProcessor`.
*
* @public
*/
export interface ExtractExamplesOptions extends ProcessorOptions {
output: string;
languages?: string[];
}

interface Example {
content: string;
language: string;
tags: string[];
}

type DocumentWithOutput = Document & { fileInfo: { outputName: string } };
type DocumentLike = Pick<DocumentWithOutput, "fileInfo" | "body" | "format">;

const md = markdownIt();

md.renderer.rules.fence = (tokens, idx, _options, collected: Example[]) => {
const { content, info } = tokens[idx];
const { language, tags } = parseInfostring(info);

if (language === "import") {
return "";
}

collected.push({
content,
language,
tags,
});

return "";
};

function findExamples(doc: DocumentLike): Example[] {
if (doc.format !== "markdown") {
return [];
}
const collected: Example[] = [];
md.render(doc.body, collected);
return collected;
}

function getExtension(lang: string): string {
switch (lang) {
case "typescript":
return "ts";
case "javascript":
return "js";
default:
return lang;
}
}

/**
* Processor to extract and write examples to separate files.
*
* @public
*/
export function extractExamplesProcessor(
options: ExtractExamplesOptions,
): Processor {
const {
enabled = true,
output,
languages = ["javascript", "typescript", "css", "scss"],
} = options;

function isRelevant(example: Example): boolean {
return languages.includes(example.language);
}

return {
stage: "render",
name: "extract-examples-processor",
async handler(context) {
if (!enabled) {
return;
}

let total = 0;
for (const doc of context.docs.filter(haveOutput)) {
const examples = findExamples(doc).filter(isRelevant);
if (examples.length === 0) {
continue;
}

/* create a directory matching the filename the examples is contained in */
const dir = normalizePath(output, doc.fileInfo.fullPath);
await fs.rm(dir, { recursive: true, force: true });
await fs.mkdir(dir, { recursive: true });

/* write each example into the directory */
let n = 1;
for (const example of examples) {
const extension = getExtension(example.language);
const filename = `example-${String(n++)}.${extension}`;
const filePath = path.join(dir, filename);
await fs.writeFile(filePath, example.content, "utf-8");
total++;
}
}

context.log(total, "examples extracted");
},
};
}
4 changes: 4 additions & 0 deletions src/processors/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export {
type ExtractExamplesOptions,
extractExamplesProcessor,
} from "./extract-examples-processor";
export {
type ManifestProcessorOptions,
manifestProcessor,
Expand Down

0 comments on commit ea63c76

Please sign in to comment.