Files
bmad-code-org__bmad-method/docs-site/scripts/validate-published-implementation-model.mjs
Alex Verkhovsky 2f6e46edbe refactor(docs-site): move the doc tooling out of tools/ (#2831)
* refactor(docs-site): move the doc tooling out of tools/

The five doc scripts and their test exist because of Starlight: sidebar
order frontmatter, the rehype link convention, the built site, and the
Astro build itself. They now live under docs-site/scripts and
docs-site/test, next to the rehype plugins and the site tests, which
leaves tools/ Python-only. ESLint stops ignoring those two directories
and its script rules now target them; the Astro sources stay excluded.

* ci(docs): deploy the site from dev

main moves only by release fast-forward, so a docs deploy tied to it
would lag every doc change until the next release. Deploy on push to
dev instead; main receives the same tree later and needs no deploy.
2026-09-05 12:41:20 -06:00

60 lines
1.7 KiB
JavaScript

import fs from 'node:fs';
import path from 'node:path';
const FORBIDDEN_TERMS = [
/\bbmad-(?:quick-dev|dev-auto)\b/gi,
/\bQuick[ -]?Dev\b/gi,
/\bDev[ -]?Auto\b/gi,
/\bbmad-(?:create|dev)-story\b/gi,
/\b(?:create-story|dev-story)\b/gi,
/\b(?:Create Story|Dev Story)\b/g,
/\b(?:createStory|devStory|create_story|dev_story)\b/g,
/\bquick[ -]?flow\b/gi,
/flux rapide|parcours parallèle/gi,
/paralelní cesta/gi,
/luồng nhanh|nhánh nhanh/gi,
/快速流程|并行快线/g,
];
export function validatePublishedImplementationModel(siteDir) {
const findings = findObsoleteImplementationTerms(siteDir);
if (findings.length > 0) {
const details = findings.map(({ file, line, match }) => `${file}:${line}: ${match}`).join('\n ');
throw new Error(`Obsolete implementation terminology found in deployable documentation:\n ${details}`);
}
}
export function findObsoleteImplementationTerms(siteDir) {
const findings = [];
for (const filePath of getPublishedTextFiles(siteDir)) {
const content = fs.readFileSync(filePath, 'utf-8');
for (const pattern of FORBIDDEN_TERMS) {
for (const match of content.matchAll(pattern)) {
findings.push({
file: path.relative(siteDir, filePath),
line: content.slice(0, match.index).split('\n').length,
match: match[0],
});
}
}
}
return findings;
}
function getPublishedTextFiles(dir) {
const files = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...getPublishedTextFiles(fullPath));
} else if (/\.(?:html|txt|xml|json|svg)$/i.test(entry.name)) {
files.push(fullPath);
}
}
return files;
}