mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 20:16:15 -08:00
Split epg.events.ts (514), the embedded MPV frame-copy adapter (428) and two of its specs (547, 539) below the 400-line hard limit, and teach the baseline generator to skip files that already carry a justified file-wide eslint-disable max-lines. The generated baseline list is unchanged: 128 entries before and after. No behavior change.
112 lines
4.0 KiB
JavaScript
112 lines
4.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Regenerates tools/eslint/max-lines-baseline.mjs: the list of TypeScript
|
|
* files that already exceed the max-lines limit enforced in eslint.config.mjs.
|
|
* Baselined files are exempt from the rule; the list should only shrink.
|
|
*
|
|
* Files that carry their own file-wide `eslint-disable max-lines` comment are
|
|
* skipped: they are already exempt with a written justification next to the
|
|
* code, which is the preferred escape hatch for a file that genuinely cannot
|
|
* be split (for example a function serialized into another process).
|
|
*
|
|
* Usage: node tools/eslint/generate-max-lines-baseline.mjs
|
|
*/
|
|
|
|
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
import process from 'node:process';
|
|
|
|
export const MAX_LINES = 400;
|
|
|
|
const workspaceRoot = process.cwd();
|
|
const scanRoots = ['apps', 'libs', 'tools'];
|
|
const skipDirs = new Set(['node_modules', 'dist', '.nx', 'coverage']);
|
|
|
|
function collectTsFiles(dir, results) {
|
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
if (entry.isDirectory()) {
|
|
if (!skipDirs.has(entry.name)) {
|
|
collectTsFiles(path.join(dir, entry.name), results);
|
|
}
|
|
} else if (
|
|
(entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) &&
|
|
!entry.name.endsWith('.d.ts')
|
|
) {
|
|
results.push(path.join(dir, entry.name));
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
function countLines(content) {
|
|
if (content.length === 0) {
|
|
return 0;
|
|
}
|
|
const lines = content.split('\n').length;
|
|
return content.endsWith('\n') ? lines - 1 : lines;
|
|
}
|
|
|
|
/**
|
|
* True when the file already suppresses max-lines with a file-wide
|
|
* `/* eslint-disable *\/` comment. Those files are deliberately exempt with a
|
|
* reviewed justification, so baselining them too would be redundant — and
|
|
* would wrongly imply they merely predate the rule.
|
|
*/
|
|
function hasInlineMaxLinesDisable(content) {
|
|
// Only a file-wide `eslint-disable` block comment can suppress max-lines;
|
|
// the rule reports at the line where the limit is exceeded, so
|
|
// `eslint-disable-next-line` cannot apply to it.
|
|
const disableComments = content.matchAll(
|
|
/\/\*\s*eslint-disable\s*([^*]*?)\*\//g
|
|
);
|
|
for (const [, ruleList = ''] of disableComments) {
|
|
// `/* eslint-disable */` with no rules disables everything.
|
|
const rules = ruleList.split('--')[0].trim();
|
|
if (rules === '') {
|
|
return true;
|
|
}
|
|
if (
|
|
rules
|
|
.split(',')
|
|
.some((rule) => rule.trim() === 'max-lines')
|
|
) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const offenders = scanRoots
|
|
.flatMap((root) => collectTsFiles(path.join(workspaceRoot, root), []))
|
|
.map((filePath) => {
|
|
const content = readFileSync(filePath, 'utf8');
|
|
return {
|
|
file: path
|
|
.relative(workspaceRoot, filePath)
|
|
.split(path.sep)
|
|
.join('/'),
|
|
lines: countLines(content),
|
|
disabled: hasInlineMaxLinesDisable(content),
|
|
};
|
|
})
|
|
.filter(({ lines, disabled }) => lines > MAX_LINES && !disabled)
|
|
.sort((a, b) => a.file.localeCompare(b.file));
|
|
|
|
const banner = `// Generated by tools/eslint/generate-max-lines-baseline.mjs — do not edit by hand.
|
|
// TypeScript files that predate the max-lines (${MAX_LINES}) ESLint rule.
|
|
// This list should only shrink: split a file below the limit, rerun the
|
|
// generator, and commit the result. Never add new files here.
|
|
// A new file that genuinely cannot be split takes a file-wide
|
|
// \`/* eslint-disable max-lines -- <why> */\` instead; the generator skips those.
|
|
`;
|
|
|
|
const body = offenders.map(({ file }) => ` '${file}',`).join('\n');
|
|
|
|
writeFileSync(
|
|
path.join(workspaceRoot, 'tools/eslint/max-lines-baseline.mjs'),
|
|
`${banner}export const maxLinesBaseline = [\n${body}\n];\n`
|
|
);
|
|
|
|
console.log(`Baselined ${offenders.length} files over ${MAX_LINES} lines.`);
|