From 6cf01f55300ca8570f7869b7f2ca47da21e1f648 Mon Sep 17 00:00:00 2001 From: Gronod Date: Sun, 17 May 2026 18:50:46 +0100 Subject: [PATCH] =?UTF-8?q?ci:=20fix=20mermaid=20parse=20check=20=E2=80=94?= =?UTF-8?q?=20use=20mermaid.core.mjs=20(no=20Puppeteer/Chromium=20needed)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/docs-check.yml | 67 +++++++++++++-------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/.gitea/workflows/docs-check.yml b/.gitea/workflows/docs-check.yml index 4e62b34..f05352b 100644 --- a/.gitea/workflows/docs-check.yml +++ b/.gitea/workflows/docs-check.yml @@ -43,67 +43,54 @@ jobs: with: node-version: "22" - - name: Install mermaid-js CLI - run: npm install -g @mermaid-js/mermaid-cli - - - name: Write Puppeteer config (no-sandbox for CI) - run: | - echo '{"args":["--no-sandbox","--disable-setuid-sandbox"]}' > /tmp/puppeteer-config.json + - name: Install mermaid + run: npm install mermaid - name: Extract and validate Mermaid diagrams run: | - node - <<'EOF' - const fs = require('fs'); - const path = require('path'); - const { execSync } = require('child_process'); - const os = require('os'); + cat > check-mermaid.mjs << 'SCRIPT' + import { readFileSync, readdirSync } from 'fs'; + import { join } from 'path'; + import mermaid from './node_modules/mermaid/dist/mermaid.core.mjs'; - function findMarkdownFiles(dir) { - const results = []; - for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { - const full = path.join(dir, entry.name); - if (entry.isDirectory() && entry.name !== 'node_modules' && !entry.name.startsWith('.')) { - results.push(...findMarkdownFiles(full)); - } else if (entry.isFile() && entry.name.endsWith('.md')) { - results.push(full); - } + function findMdFiles(dir) { + const out = []; + for (const e of readdirSync(dir, { withFileTypes: true })) { + const full = join(dir, e.name); + if (e.isDirectory() && e.name !== 'node_modules' && !e.name.startsWith('.')) + out.push(...findMdFiles(full)); + else if (e.isFile() && e.name.endsWith('.md')) + out.push(full); } - return results; + return out; } - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mermaid-')); - let errors = 0; - let total = 0; + let errors = 0, total = 0; - for (const mdFile of findMarkdownFiles('.')) { - const content = fs.readFileSync(mdFile, 'utf8'); - const blocks = [...content.matchAll(/^```mermaid\n([\s\S]*?)^```/gm)]; + for (const mdFile of findMdFiles('.')) { + const content = readFileSync(mdFile, 'utf8'); + const blocks = [...content.matchAll(/^```mermaid\n([\s\S]*?)^```/gm)]; if (!blocks.length) continue; console.log(`\nChecking ${mdFile} (${blocks.length} diagram(s))`); - - blocks.forEach((match, i) => { + for (let i = 0; i < blocks.length; i++) { total++; - const mmdFile = path.join(tmpDir, `diagram-${total}.mmd`); - const svgFile = path.join(tmpDir, `diagram-${total}.svg`); - fs.writeFileSync(mmdFile, match[1]); + const diagram = blocks[i][1].trim(); try { - execSync( - `mmdc -i "${mmdFile}" -o "${svgFile}" --puppeteerConfigFile /tmp/puppeteer-config.json`, - { stdio: 'pipe' } - ); + await mermaid.parse(diagram); console.log(` [OK] diagram ${i + 1}`); } catch (err) { - const msg = (err.stderr || err.stdout || '').toString().split('\n')[0]; + const msg = String(err.message || err).split('\n')[0]; console.error(` [FAIL] diagram ${i + 1}: ${msg}`); console.log(`::warning file=${mdFile}::Mermaid diagram ${i + 1} failed: ${msg}`); errors++; } - }); + } } - console.log(`\nTotal diagrams checked: ${total}. Failures: ${errors}`); + console.log(`\nTotal: ${total}. Failures: ${errors}`); if (errors > 0) { console.log(`::warning::${errors} Mermaid diagram(s) failed to parse.`); process.exit(1); } - EOF + SCRIPT + node check-mermaid.mjs