Skip to content

Commit 589b432

Browse files
Merge pull request #534 from MoltenCoffee/main
feat: add option to only remove exact duplicate property/values
2 parents 9a696c0 + 0ccfb82 commit 589b432

File tree

3 files changed

+114
-12
lines changed

3 files changed

+114
-12
lines changed

README.md

+34
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,40 @@ will combine into
110110
}
111111
```
112112

113+
In order to limit this to only combining properties when the values are equal, set the `removeDuplicatedValues` option to `true` instead. This could clean up duplicated properties, but allow for conscious duplicates such as fallbacks for custom properties.
114+
115+
```js
116+
const postcss = require('postcss');
117+
const combineSelectors = require('postcss-combine-duplicated-selectors');
118+
119+
postcss([combineSelectors({removeDuplicatedValues: true})]);
120+
```
121+
122+
This will transform the following css
123+
124+
```css
125+
.a {
126+
height: 10px;
127+
}
128+
129+
.a {
130+
width: 20px;
131+
background: var(--custom-color);
132+
background: rgba(255, 165, 0, 0.5);
133+
}
134+
```
135+
136+
into
137+
138+
```css
139+
.a {
140+
height: 10px;
141+
width: 20px;
142+
background: var(--custom-color);
143+
background: rgba(255, 165, 0, 0.5);
144+
}
145+
```
146+
113147
### Media Queries
114148

115149
If you have code with media queries, pass code through [_postcss-combine-media-query_](https://github.com/SassNinja/postcss-combine-media-query) or [_css-mquery-packer_](https://github.com/n19htz/css-mquery-packer) before _postcss-combine-duplicated-selectors_ to ensure optimal results.

src/index.js

+24-9
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,21 @@ function sortGroups(selector) {
3838
/**
3939
* Remove duplicated properties
4040
* @param {Object} selector - postcss selector node
41+
* @param {Boolean} exact
4142
*/
42-
function removeDupProperties(selector) {
43+
function removeDupProperties(selector, exact) {
4344
// Remove duplicated properties from bottom to top ()
4445
for (let actIndex = selector.nodes.length - 1; actIndex >= 1; actIndex--) {
4546
for (let befIndex = actIndex - 1; befIndex >= 0; befIndex--) {
4647
if (selector.nodes[actIndex].prop === selector.nodes[befIndex].prop) {
47-
selector.nodes[befIndex].remove();
48-
actIndex--;
48+
if (
49+
!exact ||
50+
(exact &&
51+
selector.nodes[actIndex].value === selector.nodes[befIndex].value)
52+
) {
53+
selector.nodes[befIndex].remove();
54+
actIndex--;
55+
}
4956
}
5057
}
5158
}
@@ -79,8 +86,8 @@ module.exports = postcss.plugin(name, (options) => {
7986

8087
// See if this query key is already in the map table
8188
map = mapTable.has(query) ? // If it is use it
82-
mapTable.get(query) : // if not set it and get it
83-
mapTable.set(query, new Map()).get(query);
89+
mapTable.get(query) : // if not set it and get it
90+
mapTable.set(query, new Map()).get(query);
8491
} else {
8592
// Otherwise we are dealing with a selector in the root
8693
map = mapTable.get('root');
@@ -100,12 +107,20 @@ module.exports = postcss.plugin(name, (options) => {
100107
// remove duplicated rule
101108
rule.remove();
102109

103-
if (options.removeDuplicatedProperties) {
104-
removeDupProperties(destination);
110+
if (options.removeDuplicatedProperties ||
111+
options.removeDuplicatedValues) {
112+
removeDupProperties(
113+
destination,
114+
options.removeDuplicatedValues,
115+
);
105116
}
106117
} else {
107-
if (options.removeDuplicatedProperties) {
108-
removeDupProperties(rule);
118+
if (options.removeDuplicatedProperties ||
119+
options.removeDuplicatedValues) {
120+
removeDupProperties(
121+
rule,
122+
options.removeDuplicatedValues,
123+
);
109124
}
110125
// add new selector to symbol table
111126
map.set(selector, rule);

test/duplicated-properties.js

+56-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const plugin = require('../src');
88
*/
99

1010
/**
11-
* Take string literals are remove newlines and extra spacing so results print
11+
* Take string literals and remove newlines and extra spacing so results print
1212
* as expected in logs
1313
* @return {string} string without newlines and tabs
1414
*/
@@ -23,7 +23,7 @@ const removeDuplicates = testFactory(
2323
);
2424

2525
test(
26-
'remove duplicated properties when combine selectors',
26+
'remove duplicated properties when combining selectors',
2727
removeDuplicates,
2828
'.a {height: 10px; color: black;} .a {color: blue; width: 20px;}',
2929
'.a {height: 10px;color: blue; width: 20px;}',
@@ -54,7 +54,7 @@ const keepDuplicates = testFactory(
5454
);
5555

5656
test(
57-
'maintain duplicated properties when combine selectors',
57+
'maintain duplicated properties when combining selectors',
5858
keepDuplicates,
5959
'.a {height: 10px; color: black;} .a {color: blue; width: 20px;}',
6060
'.a {height: 10px; color: black;color: blue; width: 20px;}',
@@ -78,3 +78,56 @@ test(
7878
}
7979
`,
8080
);
81+
82+
// Only duplicated properties with matching values should be removed
83+
const removeExactDuplicates = testFactory(
84+
'css',
85+
[plugin({removeDuplicatedValues: true})],
86+
);
87+
88+
test(
89+
'remove duplicated properties with matching values with combined selectors',
90+
removeExactDuplicates,
91+
'.a {height: 10px; color: red;} .a {color: red; color: blue; width: 20px;}',
92+
'.a {height: 10px;color: red; color: blue; width: 20px;}',
93+
);
94+
95+
test(
96+
'remove duplicated properties with matching values in a selector',
97+
removeExactDuplicates,
98+
minify`
99+
.a {
100+
height: 10px;
101+
background: orange;
102+
background: orange;
103+
background: rgba(255, 165, 0, 0.5);
104+
}
105+
`,
106+
minify`
107+
.a {
108+
height: 10px;
109+
background: orange;
110+
background: rgba(255, 165, 0, 0.5);
111+
}
112+
`,
113+
);
114+
115+
test(
116+
'remove duplicate property with matching value, allow fallback',
117+
removeExactDuplicates,
118+
minify`
119+
.a {
120+
height: 10px;
121+
}
122+
.a {
123+
height: 10px;
124+
height: var(--linkHeight);
125+
}
126+
`,
127+
minify`
128+
.a {
129+
height: 10px;
130+
height: var(--linkHeight);
131+
}
132+
`,
133+
);

0 commit comments

Comments
 (0)