From 64401284aadd7a4462353316a886927159073781 Mon Sep 17 00:00:00 2001 From: Yann Bertrand <5855339+yannbertrand@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:31:45 +0100 Subject: [PATCH 1/2] feat: add no-important rule --- src/index.js | 3 ++ src/rules/no-important.js | 41 ++++++++++++++++++ tests/rules/no-important.test.js | 74 ++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 src/rules/no-important.js create mode 100644 tests/rules/no-important.test.js diff --git a/src/index.js b/src/index.js index b601722..7c30f9f 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ import noEmptyBlocks from "./rules/no-empty-blocks.js"; import noDuplicateImports from "./rules/no-duplicate-imports.js"; import noInvalidProperties from "./rules/no-invalid-properties.js"; import noInvalidAtRules from "./rules/no-invalid-at-rules.js"; +import noImportant from "./rules/no-important.js"; //----------------------------------------------------------------------------- // Plugin @@ -29,6 +30,7 @@ const plugin = { rules: { "no-empty-blocks": noEmptyBlocks, "no-duplicate-imports": noDuplicateImports, + "no-important": noImportant, "no-invalid-at-rules": noInvalidAtRules, "no-invalid-properties": noInvalidProperties, }, @@ -38,6 +40,7 @@ const plugin = { rules: /** @type {const} */ ({ "css/no-empty-blocks": "error", "css/no-duplicate-imports": "error", + "css/no-important": "error", "css/no-invalid-at-rules": "error", "css/no-invalid-properties": "error", }), diff --git a/src/rules/no-important.js b/src/rules/no-important.js new file mode 100644 index 0000000..e278d36 --- /dev/null +++ b/src/rules/no-important.js @@ -0,0 +1,41 @@ +/** + * @fileoverview Rule to prevent !important in CSS. + * @author Yann Bertrand + */ + +//----------------------------------------------------------------------------- +// Rule Definition +//----------------------------------------------------------------------------- + +export default { + meta: { + type: /** @type {const} */ ("problem"), + + docs: { + description: "Disallow !important annotations", + recommended: true, + }, + + messages: { + unexpectedImportant: "Unexpected !important annotation found.", + }, + }, + + create(context) { + return { + "Declaration[important=true]"(node) { + context.report({ + loc: { + start: node.loc.start, + end: { + line: node.loc.start.line, + column: + node.loc.start.column + node.property.length, + }, + }, + messageId: "unexpectedImportant", + }); + }, + }; + }, +}; diff --git a/tests/rules/no-important.test.js b/tests/rules/no-important.test.js new file mode 100644 index 0000000..b9cc2c9 --- /dev/null +++ b/tests/rules/no-important.test.js @@ -0,0 +1,74 @@ +/** + * @fileoverview Tests for no-important rule. + * @author Yann Bertrand + */ + +//------------------------------------------------------------------------------ +// Imports +//------------------------------------------------------------------------------ + +import rule from "../../src/rules/no-important.js"; +import css from "../../src/index.js"; +import { RuleTester } from "eslint"; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + plugins: { + css, + }, + language: "css/css", +}); + +ruleTester.run("no-important", rule, { + valid: [ + "a { color: red; }", + "a { color: red; background-color: blue; }", + "a { color: red; transition: none; }", + "body { --custom-property: red; }", + "body { padding: 0; }", + "a { color: red; -moz-transition: bar }", + "@font-face { font-weight: 100 400 }", + '@property --foo { syntax: "*"; inherits: false; }', + ], + invalid: [ + { + code: "a { color: red !important; }", + errors: [ + { + messageId: "unexpectedImportant", + line: 1, + column: 5, + endLine: 1, + endColumn: 10, + }, + ], + }, + { + code: ".link { width: 100% !important }", + errors: [ + { + messageId: "unexpectedImportant", + line: 1, + column: 9, + endLine: 1, + endColumn: 14, + }, + ], + }, + { + code: "a .link { padding: 10px 20px 30px 40px !important }", + errors: [ + { + messageId: "unexpectedImportant", + line: 1, + column: 11, + endLine: 1, + endColumn: 18, + }, + ], + }, + ], +}); From db8d19e22919abeb3519754947424c8f7eb759db Mon Sep 17 00:00:00 2001 From: Yann Bertrand <5855339+yannbertrand@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:31:58 +0100 Subject: [PATCH 2/2] docs: add no-important rule docs --- README.md | 1 + docs/rules/no-important.md | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 docs/rules/no-important.md diff --git a/README.md b/README.md index 9d9a1d9..f33effb 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ export default [ | :--------------------------------------------------------------- | :------------------------------- | :-------------: | | [`no-duplicate-imports`](./docs/rules/no-duplicate-imports.md) | Disallow duplicate @import rules | yes | | [`no-empty-blocks`](./docs/rules/no-empty-blocks.md) | Disallow empty blocks | yes | +| [`no-important`](./docs/rules/no-important.md) | Disallow !important annotations | yes | | [`no-invalid-at-rules`](./docs/rules/no-invalid-at-rules.md) | Disallow invalid at-rules | yes | | [`no-invalid-properties`](./docs/rules/no-invalid-properties.md) | Disallow invalid properties | yes | diff --git a/docs/rules/no-important.md b/docs/rules/no-important.md new file mode 100644 index 0000000..b2a3a0d --- /dev/null +++ b/docs/rules/no-important.md @@ -0,0 +1,21 @@ +# no-important + +Disallow `!important` annotations. + +## Background + +Needing !important indicates there may be a larger underlying issue. + +## Rule Details + +Examples of incorrect code: + +```css +a { + color: red !important; +} + +a .link { + font-size: padding: 10px 20px 30px 40px !important; +} +```