ci: add docs-check workflow with Markdown lint and Mermaid diagram parse validation #8
108
.gitea/workflows/docs-check.yml
Normal file
108
.gitea/workflows/docs-check.yml
Normal file
@@ -0,0 +1,108 @@
|
||||
name: Docs Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
paths:
|
||||
- "**.md"
|
||||
- ".gitea/workflows/docs-check.yml"
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
paths:
|
||||
- "**.md"
|
||||
- ".gitea/workflows/docs-check.yml"
|
||||
|
||||
jobs:
|
||||
markdown-lint:
|
||||
name: Markdown lint
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Install markdownlint-cli
|
||||
run: npm install -g markdownlint-cli
|
||||
|
||||
- name: Lint all Markdown files
|
||||
run: markdownlint "**/*.md" --ignore node_modules
|
||||
|
||||
mermaid-parse:
|
||||
name: Mermaid diagram parse check
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Install mermaid and jsdom
|
||||
run: npm install mermaid jsdom
|
||||
|
||||
- name: Extract and validate Mermaid diagrams
|
||||
run: |
|
||||
cat > check-mermaid.cjs << 'SCRIPT'
|
||||
const { JSDOM } = require('jsdom');
|
||||
const fs = require('fs');
|
||||
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) {
|
||||
const out = [];
|
||||
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const full = path.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 out;
|
||||
}
|
||||
|
||||
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('.')) {
|
||||
const content = fs.readFileSync(mdFile, 'utf8');
|
||||
const blocks = [...content.matchAll(/^```mermaid\n([\s\S]*?)^```/gm)];
|
||||
if (!blocks.length) continue;
|
||||
console.log(`\nChecking ${mdFile} (${blocks.length} diagram(s))`);
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
total++;
|
||||
const diagram = blocks[i][1].trim();
|
||||
try {
|
||||
await mermaid.parse(diagram);
|
||||
console.log(` [OK] diagram ${i + 1}`);
|
||||
} catch (err) {
|
||||
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: ${total}. Failures: ${errors}`);
|
||||
if (errors > 0) {
|
||||
console.log(`::warning::${errors} Mermaid diagram(s) failed to parse.`);
|
||||
process.exit(1);
|
||||
}
|
||||
}).catch(e => { console.error('Fatal:', e.message); process.exit(1); });
|
||||
SCRIPT
|
||||
node check-mermaid.cjs
|
||||
17
.markdownlint.json
Normal file
17
.markdownlint.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"default": true,
|
||||
"MD009": false,
|
||||
"MD012": false,
|
||||
"MD013": false,
|
||||
"MD022": false,
|
||||
"MD029": false,
|
||||
"MD031": false,
|
||||
"MD032": false,
|
||||
"MD033": false,
|
||||
"MD034": false,
|
||||
"MD036": false,
|
||||
"MD040": false,
|
||||
"MD041": false,
|
||||
"MD058": false,
|
||||
"MD060": false
|
||||
}
|
||||
@@ -342,3 +342,4 @@ MIT
|
||||
---
|
||||
|
||||
*sofarr: See what has downloaded "so far" from the comfort of your "sofa"*
|
||||
|
||||
|
||||
@@ -1469,3 +1469,6 @@ flowchart TD
|
||||
style AF fill:#d4edda
|
||||
style AG fill:#f8d7da
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user