mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
94cfb3b58d
Add scripts/check-css-import-graph.mjs and run it from npm test and test:coverage so missing relative CSS imports fail CI like Vite/postcss. Document the step in src/test/README.md; trigger frontend workflow when the script changes.
64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Walk the same root CSS entrypoints as src/main.tsx and ensure every
|
|
* relative @import target exists on disk. Catches postcss-import ENOENT
|
|
* that Vitest does not surface (CSS is not fully resolved like vite build).
|
|
*/
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const repoRoot = path.resolve(__dirname, '..');
|
|
const stylesRoot = path.join(repoRoot, 'src', 'styles');
|
|
|
|
const ENTRY_RELS = [
|
|
'themes/index.css',
|
|
'layout/index.css',
|
|
'components/index.css',
|
|
'tracks/index.css',
|
|
];
|
|
|
|
/** Quoted path in @import '...' or "..." (postcss-import style in this repo). */
|
|
const IMPORT_RE = /@import\s+(['"])([^'"]+)\1/g;
|
|
|
|
function isFilesystemImport(spec) {
|
|
if (spec.startsWith('http://') || spec.startsWith('https://') || spec.startsWith('data:')) {
|
|
return false;
|
|
}
|
|
if (spec.startsWith('@')) return false;
|
|
return spec.startsWith('./') || spec.startsWith('../');
|
|
}
|
|
|
|
function walk(absPath, visited, missing) {
|
|
const key = path.resolve(absPath);
|
|
if (visited.has(key)) return;
|
|
if (!fs.existsSync(key)) {
|
|
missing.add(path.relative(repoRoot, key));
|
|
visited.add(key);
|
|
return;
|
|
}
|
|
visited.add(key);
|
|
const text = fs.readFileSync(key, 'utf8');
|
|
let m;
|
|
IMPORT_RE.lastIndex = 0;
|
|
while ((m = IMPORT_RE.exec(text)) !== null) {
|
|
const spec = m[2];
|
|
if (!isFilesystemImport(spec)) continue;
|
|
const next = path.resolve(path.dirname(key), spec);
|
|
walk(next, visited, missing);
|
|
}
|
|
}
|
|
|
|
const visited = new Set();
|
|
const missing = new Set();
|
|
for (const rel of ENTRY_RELS) {
|
|
walk(path.join(stylesRoot, rel), visited, missing);
|
|
}
|
|
|
|
if (missing.size > 0) {
|
|
const list = [...missing].sort().join('\n ');
|
|
console.error(`check-css-import-graph: missing @import target(s):\n ${list}`);
|
|
process.exit(1);
|
|
}
|