Skip to content

Commit 1a83312

Browse files
committed
fix(whitelist): allow whitelisting of attributes
also added a test
1 parent 06e4995 commit 1a83312

File tree

3 files changed

+27
-14
lines changed

3 files changed

+27
-14
lines changed

packages/purgecss/__tests__/test_examples/whitelist/whitelist.css

+5-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ button {
2020

2121
.nav-red {
2222
background-color: red;
23-
}
23+
}
24+
25+
.random[data-v-test] {
26+
color: green;
27+
}

packages/purgecss/__tests__/whitelist.test.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ describe("whitelist", () => {
99
content: [`${root}whitelist/whitelist.html`],
1010
css: [`${root}whitelist/whitelist.css`],
1111
whitelist: ["random", "h1", "yep", "button"],
12-
whitelistPatterns: [/nav-/]
12+
whitelistPatterns: [/nav-/, /data-v-.*/]
1313
});
1414
purgedCSS = resultsPurge[0].css;
1515
done();
1616
});
1717

18+
it("finds attr", () => {
19+
expect(purgedCSS.includes("[data-v-test]")).toBe(true);
20+
});
21+
1822
it("finds random class", () => {
1923
expect(purgedCSS.includes(".random")).toBe(true);
2024
});

packages/purgecss/src/index.ts

+17-12
Original file line numberDiff line numberDiff line change
@@ -705,21 +705,22 @@ class PurgeCSS {
705705
if (isInPseudoClass(selector)) return true;
706706

707707
let isPresent = false;
708+
708709
for (const nodeSelector of selector.nodes) {
710+
const val =
711+
(nodeSelector.type === "attribute" && nodeSelector.attribute) ||
712+
nodeSelector.value;
713+
709714
// if the selector is whitelisted with children
710715
// returns true to keep all children selectors
711-
if (
712-
nodeSelector.value &&
713-
this.isSelectorWhitelistedChildren(nodeSelector.value)
714-
) {
716+
if (val && this.isSelectorWhitelistedChildren(val)) {
715717
return true;
716718
}
717719

718720
// The selector is found in the internal and user-defined whitelist
719721
if (
720-
nodeSelector.value &&
721-
(CSS_WHITELIST.includes(nodeSelector.value) ||
722-
this.isSelectorWhitelisted(nodeSelector.value))
722+
val &&
723+
(CSS_WHITELIST.includes(val) || this.isSelectorWhitelisted(val))
723724
) {
724725
isPresent = true;
725726
continue;
@@ -730,10 +731,11 @@ class PurgeCSS {
730731
// `value` is a dynamic attribute, highly used in input element
731732
// the choice is to always leave `value` as it can change based on the user
732733
// idem for `checked`, `selected`
733-
isPresent =
734-
["value", "checked", "selected"].includes(nodeSelector.attribute)
735-
? true
736-
: isAttributeFound(nodeSelector, selectorsFromExtractor);
734+
isPresent = ["value", "checked", "selected"].includes(
735+
nodeSelector.attribute
736+
)
737+
? true
738+
: isAttributeFound(nodeSelector, selectorsFromExtractor);
737739
break;
738740
case "class":
739741
isPresent = isClassFound(nodeSelector, selectorsFromExtractor);
@@ -747,9 +749,12 @@ class PurgeCSS {
747749
default:
748750
break;
749751
}
752+
750753
// selector is not in whitelist children or in whitelist
751754
// and it has not been found as an attribute/class/identifier/tag
752-
if (!isPresent) return false;
755+
if (!isPresent) {
756+
return false;
757+
}
753758
}
754759
return isPresent;
755760
}

0 commit comments

Comments
 (0)