markdown-code-example-inserter
Version:
Syncs code examples with markdown documentation.
81 lines (74 loc) • 2.75 kB
text/typescript
import {readFile, writeFile} from 'node:fs/promises';
import {join} from 'node:path';
import {extractLinks} from '../parsing-markdown/extract-links.js';
import {fixCodeIndents} from './code-indent.js';
import {extractExampleCode} from './extract-example.js';
import {fixPackageImports} from './fix-package-imports.js';
import {getFileLanguageName} from './get-file-language-name.js';
import {insertCodeExample} from './insert-code.js';
/**
* Create a new string from the given markdown file with all code example links inserted.
*
* @category Internals
*/
export async function generateAllExamples(
markdownPath: string,
packageDir: string,
forceIndexPath: string | undefined,
): Promise<string> {
let markdownContents = (await readFile(markdownPath)).toString();
await extractLinks(markdownContents)
.sort((a, b) => a.node.position.end.offset - b.node.position.end.offset)
/**
* Reverse the array so that we're working from the bottom of the file upwards so we don't
* mess up line numbers for other comments.
*/
.reverse()
.reduce(async (lastPromise, linkComment) => {
await lastPromise;
const originalCode = (await extractExampleCode(markdownPath, linkComment)).toString();
const language = getFileLanguageName(linkComment.linkPath);
const importFixedCode = await fixPackageImports(
originalCode,
join(packageDir, linkComment.linkPath),
packageDir,
forceIndexPath,
language,
);
const indentFixedCode = fixCodeIndents(importFixedCode, linkComment.indent);
markdownContents = insertCodeExample(
markdownContents,
language,
indentFixedCode,
linkComment,
);
}, Promise.resolve());
return markdownContents;
}
/**
* Check if the given markdown file has all code examples updated.
*
* @category Main
*/
export async function isCodeUpdated(
markdownPath: string,
packageDir: string,
forceIndexPath: string | undefined,
): Promise<boolean> {
const oldText = (await readFile(markdownPath)).toString();
const newText = await generateAllExamples(markdownPath, packageDir, forceIndexPath);
return oldText === newText;
}
/**
* Overwrite the given markdown file with all code examples updated.
*
* @category Main
*/
export async function writeAllExamples(
markdownPath: string,
packageDir: string,
forceIndexPath: string | undefined,
) {
const newText = await generateAllExamples(markdownPath, packageDir, forceIndexPath);
await writeFile(markdownPath, newText);
}