Retire the single-font rule

One family with weight and size contrast carrying the hierarchy is a
legitimate type system, and in practice the rule mostly punished
minimal pages: it was the loudest cross-rule noise on the fixture
corpus's should-pass columns. Removed from the registry, both engine
paths, the regex page analyzers, and the devtools category map; the
negative assertions stay as resurrection guards, and the text-content
analyzer index base shifts down one with the removal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-29 17:45:45 -07:00
co-authored by Claude Fable 5
parent 10d16c3c87
commit 19e400e392
7 changed files with 7 additions and 75 deletions
+3 -21
View File
@@ -241,24 +241,6 @@ const REGEX_MATCHERS = [
];
const REGEX_ANALYZERS = [
// Single font
(content, filePath) => {
const fontFamilyRe = /font-family\s*:\s*([^;}]+)/gi;
const fonts = new Set();
let m;
while ((m = fontFamilyRe.exec(content)) !== null) {
for (const f of m[1].split(',').map(f => f.trim().replace(/^['"]|['"]$/g, '').toLowerCase())) {
if (f && !GENERIC_FONTS.has(f)) fonts.add(f);
}
}
for (const f of extractGoogleFontFamilies(content)) fonts.add(f);
if (fonts.size !== 1 || content.split('\n').length < 20) return [];
const name = [...fonts][0];
const lines = content.split('\n');
let line = 1;
for (let i = 0; i < lines.length; i++) { if (lines[i].toLowerCase().includes(name)) { line = i + 1; break; } }
return [finding('single-font', filePath, `only font used is ${name}`, line)];
},
// Flat type hierarchy
(content, filePath) => {
const sizes = new Set();
@@ -626,10 +608,11 @@ const TEXT_CONTENT_ANALYZER_IDS = [
function runTextContentAnalyzers(content, filePath, options = {}) {
const profile = options?.profile;
if (!shouldRunPageAnalyzers(content, filePath)) return [];
// The 3 text-content analyzers are at indices 3-5 in REGEX_ANALYZERS.
// The 3 text-content analyzers are at indices 2-4 in REGEX_ANALYZERS
// (single-font's removal on 2026-07-29 shifted every index down one).
const findings = [];
for (let i = 0; i < TEXT_CONTENT_ANALYZER_IDS.length; i++) {
const analyzer = REGEX_ANALYZERS[3 + i];
const analyzer = REGEX_ANALYZERS[2 + i];
const ruleId = TEXT_CONTENT_ANALYZER_IDS[i];
findings.push(...profileFindings(profile, {
engine: 'regex',
@@ -750,7 +733,6 @@ function detectText(content, filePath, options = {}) {
// Page-level analyzers only run on full pages
if (shouldRunPageAnalyzers(content, filePath)) {
const analyzerIds = [
'single-font',
'flat-type-hierarchy',
'monotonous-spacing',
'em-dash-overuse',