css.test.ts

1.2 kB · typescript · 40 lines

1import { test } from "bun:test";2import { readdirSync, readFileSync } from "node:fs";3import { join } from "node:path";45/* SELECTORS */67const selectors = (css: string) => {8  const out: string[] = [];9  let depth = 0;10  let buf = "";11  for (const c of css.replace(/\/\*[\s\S]*?\*\//g, "")) {12    if (c === "{") {13      if (depth === 0) out.push(buf.trim().replace(/\s+/g, " "));14      depth++;15      buf = "";16    } else if (c === "}") {17      depth--;18      if (depth < 0) throw new Error("stray brace");19      buf = "";20    } else if (depth === 0) buf += c;21  }22  if (depth !== 0) throw new Error("unclosed brace");23  return out;24};2526/* CSS */2728test("the site css never repeats a top-level selector with another rule between", () => {29  const home = import.meta.dir;30  for (const name of readdirSync(home).filter((one) => one.endsWith(".css")).sort()) {31    const file = join(home, name);32    const list = selectors(readFileSync(file, "utf8"));33    const last = new Map<string, number>();34    list.forEach((sel, n) => {35      const was = last.get(sel);36      if (was !== undefined && list.slice(was + 1, n).some((other) => other !== sel)) throw new Error(`${file}: '${sel}' at ${was} and ${n}`);37      last.set(sel, n);38    });39  }40});