diff --git a/lib/rules/declaration-block-no-duplicate-properties/README.md b/lib/rules/declaration-block-no-duplicate-properties/README.md index a8bd6b7980..258f9d5cdd 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/README.md +++ b/lib/rules/declaration-block-no-duplicate-properties/README.md @@ -11,6 +11,8 @@ a { color: pink; color: orange; } This rule ignores variables (`$sass`, `@less`, `--custom-property`). +The [`fix` option](../../../docs/user-guide/usage/options.md#fix) can automatically fix all of the problems reported by this rule. + ## Options ### `true` diff --git a/lib/rules/declaration-block-no-duplicate-properties/index.js b/lib/rules/declaration-block-no-duplicate-properties/index.js index 30784f3aac..81253bf7bf 100644 --- a/lib/rules/declaration-block-no-duplicate-properties/index.js +++ b/lib/rules/declaration-block-no-duplicate-properties/index.js @@ -18,6 +18,7 @@ const messages = ruleMessages(ruleName, { const meta = { url: 'https://stylelint.io/user-guide/rules/list/declaration-block-no-duplicate-properties', + fixable: true, }; /** @type {import('stylelint').Rule} */ @@ -60,13 +61,10 @@ const rule = (primary, secondaryOptions, context) => { eachDeclarationBlock(root, (eachDecl) => { /** @type {import('postcss').Declaration[]} */ const decls = []; - /** @type {string[]} */ - const declsProps = []; - /** @type {string[]} */ - const values = []; eachDecl((decl) => { const prop = decl.prop; + const lowerProp = decl.prop.toLowerCase(); const value = decl.value; if (!isStandardSyntaxProperty(prop)) { @@ -83,18 +81,18 @@ const rule = (primary, secondaryOptions, context) => { } // Ignore the src property as commonly duplicated in at-fontface - if (prop.toLowerCase() === 'src') { + if (lowerProp === 'src') { return; } - const indexDuplicate = declsProps.indexOf(prop.toLowerCase()); + const indexDuplicate = decls.findIndex((d) => d.prop.toLowerCase() === lowerProp); if (indexDuplicate !== -1) { if (ignoreDiffValues || ignorePrefixlessSameValues) { // fails if duplicates are not consecutive - if (indexDuplicate !== declsProps.length - 1) { + if (indexDuplicate !== decls.length - 1) { if (context.fix) { - removePreviousDuplicate(decls, prop); + removePreviousDuplicate(decls, lowerProp); return; } @@ -110,13 +108,14 @@ const rule = (primary, secondaryOptions, context) => { return; } - const duplicateValue = values[indexDuplicate] || ''; + 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)) { if (context.fix) { - removePreviousDuplicate(decls, prop); + removePreviousDuplicate(decls, lowerProp); return; } @@ -136,7 +135,7 @@ const rule = (primary, secondaryOptions, context) => { // fails if values of consecutive duplicates are equal if (value === duplicateValue) { if (context.fix) { - removePreviousDuplicate(decls, prop); + removePreviousDuplicate(decls, lowerProp); return; } @@ -155,12 +154,12 @@ const rule = (primary, secondaryOptions, context) => { return; } - if (ignoreDuplicates && indexDuplicate === declsProps.length - 1) { + if (ignoreDuplicates && indexDuplicate === decls.length - 1) { return; } if (context.fix) { - removePreviousDuplicate(decls, prop); + removePreviousDuplicate(decls, lowerProp); return; } @@ -175,8 +174,6 @@ const rule = (primary, secondaryOptions, context) => { } decls.push(decl); - declsProps.push(prop.toLowerCase()); - values.push(value.toLowerCase()); }); }); }; @@ -184,11 +181,11 @@ const rule = (primary, secondaryOptions, context) => { /** * @param {import('postcss').Declaration[]} declarations - * @param {string} property + * @param {string} lowerProperty * @returns {void} * */ -function removePreviousDuplicate(declarations, property) { - const declToRemove = declarations.find((d) => d.prop.toLowerCase() === property.toLowerCase()); +function removePreviousDuplicate(declarations, lowerProperty) { + const declToRemove = declarations.find((d) => d.prop.toLowerCase() === lowerProperty); if (declToRemove) declToRemove.remove(); }