ci: fix mermaid parse — use jsdom to provide browser globals required by mermaid.core.mjs
This commit is contained in:
@@ -43,20 +43,29 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: "22"
|
node-version: "22"
|
||||||
|
|
||||||
- name: Install mermaid
|
- name: Install mermaid and jsdom
|
||||||
run: npm install mermaid
|
run: npm install mermaid jsdom
|
||||||
|
|
||||||
- name: Extract and validate Mermaid diagrams
|
- name: Extract and validate Mermaid diagrams
|
||||||
run: |
|
run: |
|
||||||
cat > check-mermaid.mjs << 'SCRIPT'
|
cat > check-mermaid.cjs << 'SCRIPT'
|
||||||
import { readFileSync, readdirSync } from 'fs';
|
const { JSDOM } = require('jsdom');
|
||||||
import { join } from 'path';
|
const fs = require('fs');
|
||||||
import mermaid from './node_modules/mermaid/dist/mermaid.core.mjs';
|
const path = require('path');
|
||||||
|
|
||||||
|
// Provide minimal browser globals so mermaid.parse() works in Node
|
||||||
|
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>', { url: 'http://localhost' });
|
||||||
|
globalThis.window = dom.window;
|
||||||
|
globalThis.document = dom.window.document;
|
||||||
|
globalThis.DOMPurify = {
|
||||||
|
addHook: () => {}, removeHook: () => {}, setConfig: () => {},
|
||||||
|
sanitize: (s) => s, isValidAttribute: () => true,
|
||||||
|
};
|
||||||
|
|
||||||
function findMdFiles(dir) {
|
function findMdFiles(dir) {
|
||||||
const out = [];
|
const out = [];
|
||||||
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||||
const full = join(dir, e.name);
|
const full = path.join(dir, e.name);
|
||||||
if (e.isDirectory() && e.name !== 'node_modules' && !e.name.startsWith('.'))
|
if (e.isDirectory() && e.name !== 'node_modules' && !e.name.startsWith('.'))
|
||||||
out.push(...findMdFiles(full));
|
out.push(...findMdFiles(full));
|
||||||
else if (e.isFile() && e.name.endsWith('.md'))
|
else if (e.isFile() && e.name.endsWith('.md'))
|
||||||
@@ -65,32 +74,35 @@ jobs:
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
let errors = 0, total = 0;
|
import('./node_modules/mermaid/dist/mermaid.core.mjs').then(async (m) => {
|
||||||
|
const mermaid = m.default;
|
||||||
|
let errors = 0, total = 0;
|
||||||
|
|
||||||
for (const mdFile of findMdFiles('.')) {
|
for (const mdFile of findMdFiles('.')) {
|
||||||
const content = readFileSync(mdFile, 'utf8');
|
const content = fs.readFileSync(mdFile, 'utf8');
|
||||||
const blocks = [...content.matchAll(/^```mermaid\n([\s\S]*?)^```/gm)];
|
const blocks = [...content.matchAll(/^```mermaid\n([\s\S]*?)^```/gm)];
|
||||||
if (!blocks.length) continue;
|
if (!blocks.length) continue;
|
||||||
console.log(`\nChecking ${mdFile} (${blocks.length} diagram(s))`);
|
console.log(`\nChecking ${mdFile} (${blocks.length} diagram(s))`);
|
||||||
for (let i = 0; i < blocks.length; i++) {
|
for (let i = 0; i < blocks.length; i++) {
|
||||||
total++;
|
total++;
|
||||||
const diagram = blocks[i][1].trim();
|
const diagram = blocks[i][1].trim();
|
||||||
try {
|
try {
|
||||||
await mermaid.parse(diagram);
|
await mermaid.parse(diagram);
|
||||||
console.log(` [OK] diagram ${i + 1}`);
|
console.log(` [OK] diagram ${i + 1}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const msg = String(err.message || err).split('\n')[0];
|
const msg = String(err.message || err).split('\n')[0];
|
||||||
console.error(` [FAIL] diagram ${i + 1}: ${msg}`);
|
console.error(` [FAIL] diagram ${i + 1}: ${msg}`);
|
||||||
console.log(`::warning file=${mdFile}::Mermaid diagram ${i + 1} failed: ${msg}`);
|
console.log(`::warning file=${mdFile}::Mermaid diagram ${i + 1} failed: ${msg}`);
|
||||||
errors++;
|
errors++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`\nTotal: ${total}. Failures: ${errors}`);
|
console.log(`\nTotal: ${total}. Failures: ${errors}`);
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
console.log(`::warning::${errors} Mermaid diagram(s) failed to parse.`);
|
console.log(`::warning::${errors} Mermaid diagram(s) failed to parse.`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
}).catch(e => { console.error('Fatal:', e.message); process.exit(1); });
|
||||||
SCRIPT
|
SCRIPT
|
||||||
node check-mermaid.mjs
|
node check-mermaid.cjs
|
||||||
|
|||||||
Reference in New Issue
Block a user