Files
STM32F4-Base/IEC60870-Slave/.build/command-docs/check-structure.cjs
T
STF cd42b4d61d
CI / L0 静态门禁 (pre-commit) (push) Failing after 2m51s
CI / L0.5 主机侧单测 (MSVC) (push) Successful in 18s
添加遥控业务代码
2026-10-30 20:03:19 -07:00

47 lines
2.3 KiB
JavaScript

const fs = require('node:fs');
const path = require('node:path');
const assert = require('node:assert/strict');
const root = path.resolve(__dirname, '../..');
const files = ['docs/104/IEC104_API接口汇总.md', 'docs/104/IEC104_完整调用流程.md'];
for (const file of files) {
const bytes = fs.readFileSync(path.join(root, file));
const source = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
const baseline = fs.readFileSync(path.join(__dirname, path.basename(file) + '.before'));
assert.equal(bytes.subarray(0, 3).equals(Buffer.from([0xef, 0xbb, 0xbf])),
baseline.subarray(0, 3).equals(Buffer.from([0xef, 0xbb, 0xbf])), `${file}: BOM changed`);
assert(!source.includes('\ufffd') && !source.includes('\r'), `${file}: encoding or line ending`);
assert(source.endsWith('\n') && !/[\t ]+$/m.test(source), `${file}: whitespace`);
const ids = new Set();
let fence = '', details = 0, blocks = 0;
const tableProblems = [];
let tableColumns = 0;
for (const [index, line] of source.split('\n').entries()) {
const marker = /^(`{3,}|~{3,})/.exec(line);
if (marker) {
if (!fence) { fence = marker[1]; blocks++; }
else if (marker[1][0] === fence[0] && marker[1].length >= fence.length) fence = '';
tableColumns = 0;
continue;
}
if (fence) continue;
for (const match of line.matchAll(/<a\s+id="([^"]+)"\s*>/g)) {
assert(!ids.has(match[1]), `${file}:${index + 1}: duplicate id ${match[1]}`);
ids.add(match[1]);
}
if (line.includes('<details>')) details++;
if (line.includes('</details>')) details--;
assert(details >= 0, `${file}:${index + 1}: unexpected details close`);
if (/^\|/.test(line)) {
const columns = (line.replace(/\\\|/g, '').match(/\|/g) || []).length;
if (tableColumns && columns !== tableColumns) tableProblems.push(index + 1);
tableColumns = columns;
} else tableColumns = 0;
}
assert(!fence && details === 0, `${file}: unclosed fence/details`);
assert.deepEqual(tableProblems, [], `${file}: inconsistent table column count`);
for (const id of baseline.toString('utf8').matchAll(/<a\s+id="([^"]+)"\s*>/g)) {
assert(ids.has(id[1]), `${file}: removed existing anchor ${id[1]}`);
}
console.log(`${file}: ${blocks} fenced blocks, ${ids.size} stable anchors, UTF-8/LF and tables OK`);
}