mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 21:46:49 +00:00
242756708e
theme:lint only reported a total and exited 0, skipped whole files by name and never ran in CI. It now counts per file under src/ against scripts/theme-baseline.json, which only shrinks, like lint:rtl: the colour literals, arbitrary colour classes and numeric font sizes it already saw, plus palette classes (bg-gray-100, text-indigo-600, bg-white), raw text sizes (text-sm, text-[13px]) instead of the type tiers, z-index literals above z-50 instead of a step of the layering scale, and reads of the dark_mode setting. The file exemptions are gone; the map, PDF and brand files carry their count in the baseline instead. theme-lint-disable markers stay valid in a comment and are counted against scripts/theme-disable-baseline.json, like rtl-lint-disable in lint:rtl; a new one raises its file's entry by hand, where review sees it. The comment handling lint:rtl already had moves into scripts/lib/source.mjs so both read source the same way. The check runs in the client-quality job.
54 lines
2.0 KiB
JavaScript
54 lines
2.0 KiB
JavaScript
/*
|
|
* Reading source the way the line ratchets need it: with the comments blanked
|
|
* out, and telling a disable marker in a comment from the same text in code.
|
|
* Shared by lint:rtl (scripts/lib/rtl.mjs) and theme:lint (scripts/lib/theme.mjs).
|
|
*/
|
|
import ts from 'typescript';
|
|
|
|
/**
|
|
* The source with its comments blanked out, so prose like "top right" or
|
|
* "left out" is no side. TypeScript finds the comments in a .ts/.tsx file,
|
|
* which keeps `/*` and `//` inside strings and JSX text where they belong
|
|
* (accept="image/*", a URL); a stylesheet only has block comments.
|
|
*/
|
|
export function withoutComments(source, file) {
|
|
const chars = source.split('');
|
|
const blank = (pos, end) => {
|
|
for (let i = pos; i < end; i++) if (chars[i] !== '\n') chars[i] = ' ';
|
|
};
|
|
if (file.endsWith('.css')) {
|
|
for (const m of source.matchAll(/\/\*[\s\S]*?\*\//g)) blank(m.index, m.index + m[0].length);
|
|
return chars.join('');
|
|
}
|
|
const kind = file.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
|
|
const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, kind);
|
|
const seen = new Set();
|
|
const take = (ranges) => {
|
|
for (const r of ranges ?? []) {
|
|
if (seen.has(r.pos)) continue;
|
|
seen.add(r.pos);
|
|
blank(r.pos, r.end);
|
|
}
|
|
};
|
|
const visit = (node) => {
|
|
take(ts.getLeadingCommentRanges(source, node.pos));
|
|
take(ts.getTrailingCommentRanges(source, node.end));
|
|
// JSX text holds no comments, and asking for them there would read `//` in a URL as one.
|
|
if (!ts.isJsxText(node)) for (const child of node.getChildren(sf)) visit(child);
|
|
};
|
|
visit(sf);
|
|
take(ts.getLeadingCommentRanges(source, sf.endOfFileToken.pos));
|
|
return chars.join('');
|
|
}
|
|
|
|
/**
|
|
* Whether line carries marker inside a comment; in a string or in code it is no
|
|
* marker. code is the same line from withoutComments.
|
|
*/
|
|
export function markedInComment(line, code, marker) {
|
|
for (let at = line.indexOf(marker); at !== -1; at = line.indexOf(marker, at + 1)) {
|
|
if (!code.slice(at, at + marker.length).trim()) return true;
|
|
}
|
|
return false;
|
|
}
|