spice.css sets body, *, button and canvas for the whole document. Bundled
into the App chunk since 43ebacd (deployed as v0.1.0-188), it turned every
button into a gradient pill, shifted 15% right and 8% up with a 150px
minimum width, broke the rail and header layout, and bordered every graph
canvas. The console is already styled by the .vga rules in styles.css.
The file is removed from the vendored copy, and a new web test fails on any
stylesheet import outside an allow-list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
21 lines
1.2 KiB
JavaScript
21 lines
1.2 KiB
JavaScript
// node scripts/test-css-imports.mjs — every stylesheet the UI imports is one somebody has read.
|
|
// A third-party stylesheet usually carries its demo page's global rules (body, *, button); on
|
|
// 2026-10-09 one restyled every button in the app. Add a file here only once its rules are
|
|
// known to touch nothing but its own component.
|
|
import { readdirSync, readFileSync, statSync } from 'node:fs'
|
|
import { join, relative } from 'node:path'
|
|
|
|
const allowed = new Set(['./styles.css', '@xterm/xterm/css/xterm.css'])
|
|
const src = new URL('../src', import.meta.url).pathname
|
|
const files = []
|
|
const walk = (d) => { for (const n of readdirSync(d)) { const p = join(d, n); if (statSync(p).isDirectory()) { if (n !== 'vendor') walk(p) } else if (/\.(ts|tsx)$/.test(n)) files.push(p) } }
|
|
walk(src)
|
|
const fails = []
|
|
for (const f of files) {
|
|
for (const m of readFileSync(f, 'utf8').matchAll(/import\s+(?:[^'"]*from\s+)?['"]([^'"]+\.css)['"]/g)) {
|
|
if (!allowed.has(m[1])) fails.push(`${relative(src, f)} imports ${m[1]}`)
|
|
}
|
|
}
|
|
if (fails.length) { console.error('css imports: not allowed:\n ' + fails.join('\n ')); process.exit(1) }
|
|
console.log(`css imports: ok (${files.length} files)`)
|