// Гейт «одно место для цвета и размера», половина в CSS (STACK_DECISIONS §3). // TSX-половина — в eslint.config.js. // // Двухслойно: запрет литеральных цветов ловит их в ЛЮБОМ свойстве, включая сокращённые // записи вроде `border: 1px solid #fff`, а allowed-list добавляет свойства, где литерал // не цвет (`font-size`, `z-index`). reportDisables делает ошибкой и попытку отключить // правило комментарием. const gate = { reportDisables: true }; const token = '/^var\\(--/'; const colorValues = [token, 'inherit', 'currentColor', 'currentcolor', 'transparent']; export default { extends: ['stylelint-config-standard'], // reportDisables на правиле ловит только ИМЕНОВАННОЕ отключение // (`/* stylelint-disable color-no-hex */`). Голое `/* stylelint-disable */` в шапке файла // снимало гейт целиком и молча — проверено. Эта опция требует, чтобы отключение всегда // называло правило, и тем самым закрывает обход. reportUnscopedDisables: true, rules: { 'color-no-hex': [true, gate], 'color-named': ['never', gate], // color() и light-dark() тоже задают цвет литералом, а в сокращённой записи // (`border: 1px solid color(...)`) их не ловит ничто другое. color-mix() оставлен: // смешивать ему нечего, кроме токенов. 'function-disallowed-list': [ ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color', 'light-dark'], gate, ], 'declaration-property-value-allowed-list': [ { color: colorValues, 'background-color': colorValues, 'border-color': colorValues, background: [...colorValues, 'none'], fill: [...colorValues, 'none'], stroke: [...colorValues, 'none'], 'font-size': [token, 'inherit'], 'z-index': [token], }, { ...gate, message: 'Значение только из токена: var(--...) из src/tokens/tokens.css' }, ], // CSS Modules читаются из TS как styles.panelHeader, поэтому классы camelCase. 'selector-class-pattern': ['^[a-z][a-zA-Z0-9]*$', { message: 'Имя класса — camelCase' }], }, overrides: [ { // Единственное место, где литеральный цвет легален: сами токены. files: ['src/tokens/tokens.css'], rules: { 'color-no-hex': null, 'color-named': null, 'function-disallowed-list': null, 'declaration-property-value-allowed-list': null, }, }, ], };