From 3f2ab266afae67754266198aa9ee12ddb4d388d5 Mon Sep 17 00:00:00 2001 From: sid Date: Fri, 16 Dec 2022 08:00:46 +0530 Subject: [PATCH 1/5] feat: add tests that fail --- .../__tests__/index.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js b/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js index 9049919421..f03f177eec 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js +++ b/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js @@ -187,6 +187,24 @@ testRule({ endLine: 1, endColumn: 55, }, + { + code: 'a { color: red !important; color: blue; }', + fixed: 'a { color: red !important; }', + message: messages.rejected('color'), + line: 1, + column: 28, + endLine: 1, + endColumn: 33, + }, + { + code: 'a { color: red !important; color: blue !important; }', + fixed: 'a { color: blue !important; }', + message: messages.rejected('color'), + line: 1, + column: 28, + endLine: 1, + endColumn: 33, + }, ], }); @@ -231,6 +249,11 @@ testRule({ fixed: 'p { display: inline-block; font-weight: 400; font-size: 1rem; color: red; }', message: messages.rejected('font-size'), }, + { + code: 'p { font-size: 16px !important; font-weight: 400; font-size: 1rem; }', + fixed: 'p { font-size: 16px !important; font-weight: 400; }', + message: messages.rejected('font-size'), + }, ], }); From cefa3d4cc130da959b4aab038563a3ccc138c1db Mon Sep 17 00:00:00 2001 From: sid Date: Fri, 16 Dec 2022 09:03:39 +0530 Subject: [PATCH 2/5] feat: support handling !important --- .../index.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/rules/declaration-block-no-duplicate-properties/index.js b/lib/rules/declaration-block-no-duplicate-properties/index.js index d81addb5ab..c4c947fb71 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/index.js +++ b/lib/rules/declaration-block-no-duplicate-properties/index.js @@ -66,6 +66,7 @@ const rule = (primary, secondaryOptions, context) => { const prop = decl.prop; const lowerProp = decl.prop.toLowerCase(); const value = decl.value; + const important = decl.important; if (!isStandardSyntaxProperty(prop)) { return; @@ -88,6 +89,10 @@ const rule = (primary, secondaryOptions, context) => { const indexDuplicate = decls.findIndex((d) => d.prop.toLowerCase() === lowerProp); if (indexDuplicate !== -1) { + const duplicateDecl = decls[indexDuplicate]; + const duplicateValue = duplicateDecl ? duplicateDecl.value : ''; + const duplicateImportant = duplicateDecl ? duplicateDecl.important : false; + if (ignoreDiffValues || ignorePrefixlessSameValues) { // fails if duplicates are not consecutive if (indexDuplicate !== decls.length - 1) { @@ -108,9 +113,6 @@ const rule = (primary, secondaryOptions, context) => { return; } - const duplicateDecl = decls[indexDuplicate]; - const duplicateValue = duplicateDecl ? duplicateDecl.value : ''; - if (ignorePrefixlessSameValues) { // fails if values of consecutive, unprefixed duplicates are equal if (vendor.unprefixed(value) !== vendor.unprefixed(duplicateValue)) { @@ -159,7 +161,11 @@ const rule = (primary, secondaryOptions, context) => { } if (context.fix) { - removePreviousDuplicate(decls, lowerProp); + if (!important && duplicateImportant) { + decl.remove(); + } else { + removePreviousDuplicate(decls, lowerProp); + } return; } From 941dee593f16426eb38680b286c6c8a8064bdc8c Mon Sep 17 00:00:00 2001 From: sid Date: Mon, 19 Dec 2022 17:23:12 +0530 Subject: [PATCH 3/5] test: add and handle additional cases --- .../__tests__/index.js | 23 +++++++++++++++++++ .../index.js | 12 ++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js b/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js index f03f177eec..1c3322a10b 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js +++ b/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js @@ -275,6 +275,16 @@ testRule({ fixed: 'p { font-size: 16px; font-weight: 400; }', message: messages.rejected('font-size'), }, + { + code: 'p { font-size: 16px !important; font-weight: 400; font-size: 1rem; }', + fixed: 'p { font-size: 16px !important; font-weight: 400; }', + message: messages.rejected('font-size'), + }, + { + code: 'p { font-size: 16px; font-size: 16px !important; font-weight: 400; }', + fixed: 'p { font-size: 16px !important; font-weight: 400; }', + message: messages.rejected('font-size'), + }, ], }); @@ -314,6 +324,11 @@ testRule({ fixed: 'p { width: -moz-fit-content; }', message: messages.rejected('width'), }, + { + code: 'p { width: -moz-fit-content; width: -moz-fit-content !important; }', + fixed: 'p { width: -moz-fit-content !important; }', + message: messages.rejected('width'), + }, ], }); @@ -332,6 +347,9 @@ testRule({ { code: 'p { color: pink; background: orange; color: orange }', }, + { + code: 'p { color: pink; color: orange !important; }', + }, ], reject: [ @@ -345,6 +363,11 @@ testRule({ fixed: 'p { color: pink; background: white; }', message: messages.rejected('background'), }, + { + code: 'p { background: orange; color: pink; background: white !important; }', + fixed: 'p { color: pink; background: white !important; }', + message: messages.rejected('background'), + }, ], }); diff --git a/lib/rules/declaration-block-no-duplicate-properties/index.js b/lib/rules/declaration-block-no-duplicate-properties/index.js index c4c947fb71..31a70524e0 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/index.js +++ b/lib/rules/declaration-block-no-duplicate-properties/index.js @@ -97,7 +97,11 @@ const rule = (primary, secondaryOptions, context) => { // fails if duplicates are not consecutive if (indexDuplicate !== decls.length - 1) { if (context.fix) { - removePreviousDuplicate(decls, lowerProp); + if (!important && duplicateImportant) { + decl.remove(); + } else { + removePreviousDuplicate(decls, lowerProp); + } return; } @@ -117,7 +121,11 @@ const rule = (primary, secondaryOptions, context) => { // fails if values of consecutive, unprefixed duplicates are equal if (vendor.unprefixed(value) !== vendor.unprefixed(duplicateValue)) { if (context.fix) { - removePreviousDuplicate(decls, lowerProp); + if (!important && duplicateImportant) { + decl.remove(); + } else { + removePreviousDuplicate(decls, lowerProp); + } return; } From 01b929e236d13d44f62dc9d16a18069767f0b6c0 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Tue, 20 Dec 2022 10:23:30 +0900 Subject: [PATCH 4/5] Add changelog entry --- .changeset/rude-hornets-begin.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rude-hornets-begin.md diff --git a/.changeset/rude-hornets-begin.md b/.changeset/rude-hornets-begin.md new file mode 100644 index 0000000000..d1aaf43d77 --- /dev/null +++ b/.changeset/rude-hornets-begin.md @@ -0,0 +1,5 @@ +--- +"stylelint": patch +--- + +Fixed: `declaration-block-no-duplicate-properties` autofix for `!important` From c0f91b16194689a11c2ae00958cdc0d233bacd60 Mon Sep 17 00:00:00 2001 From: Sid Date: Tue, 20 Dec 2022 11:22:43 +0530 Subject: [PATCH 5/5] test: add missing test case Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> --- .../__tests__/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js b/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js index 1c3322a10b..d0fe44bb57 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js +++ b/lib/rules/declaration-block-no-duplicate-properties/__tests__/index.js @@ -329,6 +329,11 @@ testRule({ fixed: 'p { width: -moz-fit-content !important; }', message: messages.rejected('width'), }, + { + code: 'p { width: 100% !important; width: -moz-fit-content; }', + fixed: 'p { width: 100% !important; }', + message: messages.rejected('width'), + }, ], });