feat(cli): Complete the check rule catalog

Add D002 (malformed attribute blocks), R004 (skipped declare rows), and V001-V005 (CSV data files). CSV checks run once per referenced file and also cover inline spark-table bodies.

Generate docs/reference.md from the known.ts catalog via npm run gen:reference, and add drift guards asserting the catalog matches the customElement call sites and the committed reference.
This commit is contained in:
2026-09-12 17:01:49 +08:00
parent ca6d8d1d14
commit 71542e7453
17 changed files with 1167 additions and 16 deletions
+52
View File
@@ -0,0 +1,52 @@
/**
* Drift guard: `KNOWN_ELEMENTS` in `known.ts` must match the `customElement`
* registrations under `src/components`. This is what would have caught
* `:md-card` — matched by the completion scanner but registered nowhere.
*/
import { readdirSync, readFileSync } from "fs";
import { join } from "path";
import { ELEMENT_NAMES } from "./known.js";
import { renderReference } from "./reference.js";
const COMPONENTS_DIR = join(process.cwd(), "src", "components");
const CUSTOM_ELEMENT_RE = /customElement(?:<[^>]*>)?\(\s*["'](md-[\w-]+)["']/g;
function sourceFiles(dir: string): string[] {
const files: string[] = [];
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const full = join(dir, entry.name);
if (entry.isDirectory()) files.push(...sourceFiles(full));
else if (/\.tsx?$/.test(entry.name)) files.push(full);
}
return files;
}
function registeredElements(): Set<string> {
const names = new Set<string>();
for (const file of sourceFiles(COMPONENTS_DIR)) {
const source = readFileSync(file, "utf-8");
for (const match of source.matchAll(CUSTOM_ELEMENT_RE)) {
names.add(match[1]);
}
}
return names;
}
describe("known element catalog", () => {
test("matches the customElement registrations under src/components", () => {
const registered = [...registeredElements()].sort();
const known = [...ELEMENT_NAMES].sort();
expect(known).toEqual(registered);
});
test("docs/reference.md is up to date", () => {
const committed = readFileSync(
join(process.cwd(), "docs", "reference.md"),
"utf-8",
);
expect(committed).toBe(renderReference());
});
});