Files
reader/web/test/media-css-classes.test.ts
T
hectorqinandClaude Opus 5.5 cdce43f98f refactor(web): remove ~320 lines of media CSS for classes nothing renders
The media styles grew in layers and replaced screens left their rules behind
(old channel switcher, details-based menus, manager tabs/toolbar, match
confirm box, resume cover, settings groups, …). 56 class names had no
reference in the source; rules naming only them are gone, and dead members
of :is()/:where() lists are dropped while the live ones stay. Screenshots of
every ui:review scene match the previous build apart from timing noise.

media-css-classes.test.ts now fails when a media stylesheet names a class the
source never renders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 03:59:39 +00:00

27 lines
1.6 KiB
TypeScript

import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { expect, it } from 'vitest';
/**
* The media stylesheets grew by layering (media → presentation → v2 → manager), and
* screens that were replaced left their rules behind: ~300 lines styled class names no
* component renders any more. A rule for a class nothing uses is not harmless — it is
* where the next change gets made, to no effect. Every class the media styles name must
* appear somewhere in the source; DPlayer's own classes are its markup, not ours.
*/
const src = join(import.meta.dirname, '..', 'src');
const files = (dir: string): string[] => readdirSync(dir, { withFileTypes: true }).flatMap(entry =>
entry.isDirectory() ? files(join(dir, entry.name)) : [join(dir, entry.name)]);
it('styles only classes that the source renders (media stylesheets)', () => {
const code = files(src).filter(file => /\.tsx?$/.test(file)).map(file => readFileSync(file, 'utf8')).join('\n');
const styles = join(src, 'features', 'media', 'styles');
const unused = readdirSync(styles).filter(name => name.endsWith('.css')).flatMap(name => {
// A class inside :not() is matched by its absence, so it need not exist.
const css = readFileSync(join(styles, name), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '').replace(/:not\([^)]*\)/g, '');
const names = new Set([...css.matchAll(/\.(-?[a-zA-Z_][\w-]*)/g)].map(match => match[1]!));
return [...names].filter(cls => !cls.startsWith('dplayer') && !code.includes(cls)).map(cls => `${name}: .${cls}`);
});
expect(unused).toEqual([]);
});