Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 6x 6x 6x 6x 15x 15x 10x 10x 22x 12x 12x 4x 10x 7x 3x | /**
* Structural rule: no `!important` on hook write declarations.
*
* `!important` on a `--slds-c-*` declaration defeats cascade-layer
* ordering: a customer's `@layer customization` write can never win
* against an `!important` in `@layer theme` or unlayered code.
* Every hook assignment must be overridable by the customization layer.
*/
import type { ComplianceCheck, ComplianceRow, Offender } from '../../types.js';
import {
declLocation,
failRow,
notRunYetRow,
passRow,
sourceFilesFor,
visitHookWriteRules,
} from './internals.js';
const ID = 'structural-no-important';
const LABEL = 'No `!important` on hook write declarations';
const CATEGORY = 'customer-reach' as const;
export const noImportant: ComplianceCheck = (input): ComplianceRow => {
const files = sourceFilesFor(input);
if (!files) return notRunYetRow(ID, LABEL, CATEGORY);
const offenders: Offender[] = [];
for (const file of files) {
visitHookWriteRules(file, ({ rule, hookDecls }) => {
for (const decl of hookDecls) {
if (!decl.important) continue;
offenders.push({
selector: rule.selector,
hook: decl.prop,
location: declLocation(file, decl),
fix: `Remove \`!important\` from \`${decl.prop}\`. Hook assignments must be overridable; \`!important\` defeats the cascade-layer contract and prevents customer \`@layer customization\` overrides from landing.`,
});
}
});
}
if (offenders.length === 0) {
return passRow(ID, LABEL, 'No hook write declarations use `!important`.', CATEGORY);
}
return failRow(
ID,
LABEL,
`${offenders.length} hook write declaration${offenders.length === 1 ? '' : 's'} use \`!important\`. ` +
`\`!important\` overrides cascade-layer ordering and prevents customer overrides in \`@layer customization\` from landing.`,
offenders,
);
};
|