Render documentation diagrams as static Mermaid assets

This commit is contained in:
Ruslan Bakiev
2026-05-01 15:09:02 +07:00
parent b7a5018c6e
commit 542ad1b648
23 changed files with 1105 additions and 134 deletions

View File

@@ -0,0 +1,9 @@
{
"theme": "neutral",
"securityLevel": "loose",
"flowchart": {
"useMaxWidth": true,
"htmlLabels": true
},
"fontFamily": "Inter, Arial, sans-serif"
}

View File

@@ -0,0 +1,9 @@
{
"headless": true,
"executablePath": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"args": [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage"
]
}

View File

@@ -0,0 +1,80 @@
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { spawn } from 'node:child_process';
import { diagramSources } from '../.vitepress/theme/components/diagramSources.ts';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const docsRoot = path.resolve(__dirname, '..');
const publicRoot = path.join(docsRoot, 'public');
const diagramsDir = path.join(publicRoot, 'diagrams');
const prototypesDir = path.join(publicRoot, 'prototypes');
const puppeteerConfig = path.join(__dirname, 'puppeteer-config.json');
const mermaidConfig = path.join(__dirname, 'mermaid-config.json');
const prototypeNames = new Set([
'dashboard',
'catalog-grid',
'product-card',
'cart',
'client-order',
'bonus-cabinet',
'manager-order',
'manager-orders',
]);
function runCommand(command, args) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
cwd: docsRoot,
stdio: 'inherit',
});
child.on('exit', (code) => {
if (code === 0) {
resolve();
return;
}
reject(new Error(`${command} ${args.join(' ')} exited with code ${code ?? 'unknown'}`));
});
child.on('error', reject);
});
}
async function renderDiagram(name, source) {
const targetDir = prototypeNames.has(name) ? prototypesDir : diagramsDir;
const tmpDir = await mkdtemp(path.join(os.tmpdir(), `mermaid-${name}-`));
const inputFile = path.join(tmpDir, `${name}.mmd`);
const outputFile = path.join(targetDir, `${name}.svg`);
try {
await writeFile(inputFile, source, 'utf8');
await runCommand('pnpm', [
'exec',
'mmdc',
'-i',
inputFile,
'-o',
outputFile,
'-b',
'transparent',
'-c',
mermaidConfig,
'-p',
puppeteerConfig,
]);
} finally {
await rm(tmpDir, { recursive: true, force: true });
}
}
await mkdir(diagramsDir, { recursive: true });
await mkdir(prototypesDir, { recursive: true });
for (const [name, source] of Object.entries(diagramSources)) {
await renderDiagram(name, source);
}