diff --git a/packages/purgecss/__tests__/safelist.test.ts b/packages/purgecss/__tests__/safelist.test.ts
index 71a4a8d4..6b669cac 100644
--- a/packages/purgecss/__tests__/safelist.test.ts
+++ b/packages/purgecss/__tests__/safelist.test.ts
@@ -176,3 +176,27 @@ describe("safelist option: variables", () => {
notFindInCSS(expect, ["--tertiary-color:"], purgedCSS);
});
});
+
+describe("blocklist option", () => {
+ let purgedCSS: string;
+ beforeAll(async () => {
+ const resultsPurge = await new PurgeCSS().purge({
+ content: [`${ROOT_TEST_EXAMPLES}safelist/blocklist.html`],
+ css: [`${ROOT_TEST_EXAMPLES}safelist/blocklist.css`],
+ blocklist: ["h1", "yep", "button", /nav-/],
+ });
+ purgedCSS = resultsPurge[0].css;
+ });
+
+ it("excludes blocklisted selectors", () => {
+ notFindInCSS(
+ expect,
+ ["h1", "yep", "button", "nav-blue", "nav-red"],
+ purgedCSS
+ );
+ });
+
+ it("includes non-blocklisted selectors", () => {
+ findInCSS(expect, ["data-v-test", ".random"], purgedCSS);
+ });
+});
diff --git a/packages/purgecss/__tests__/test_examples/safelist/blocklist.css b/packages/purgecss/__tests__/test_examples/safelist/blocklist.css
new file mode 100644
index 00000000..f28ae760
--- /dev/null
+++ b/packages/purgecss/__tests__/test_examples/safelist/blocklist.css
@@ -0,0 +1,28 @@
+h1 {
+ color: blue;
+ }
+
+ .random {
+ color: green;
+ }
+
+ #yep {
+ color: red;
+ }
+
+ button {
+ color: rebeccapurple;
+ }
+
+ .nav-blue {
+ background-color: blue;
+ }
+
+ .nav-red {
+ background-color: red;
+ }
+
+ [data-v-test] {
+ color: green;
+ }
+
\ No newline at end of file
diff --git a/packages/purgecss/__tests__/test_examples/safelist/blocklist.html b/packages/purgecss/__tests__/test_examples/safelist/blocklist.html
new file mode 100644
index 00000000..985eb619
--- /dev/null
+++ b/packages/purgecss/__tests__/test_examples/safelist/blocklist.html
@@ -0,0 +1,11 @@
+
+
+
+ is it blue?
+ is it red?
+ Title
+ random
+
+
+
+
\ No newline at end of file
diff --git a/packages/purgecss/src/index.ts b/packages/purgecss/src/index.ts
index 7b76fe02..f922f69c 100644
--- a/packages/purgecss/src/index.ts
+++ b/packages/purgecss/src/index.ts
@@ -554,6 +554,18 @@ class PurgeCSS {
});
}
+ /**
+ * Check if the selector is blocklisted with the option blocklist
+ * @param selector css selector
+ */
+ private isSelectorBlocklisted(selector: string): boolean {
+ return this.options.blocklist.some((blocklistItem) => {
+ return typeof blocklistItem === "string"
+ ? blocklistItem === selector
+ : blocklistItem.test(selector);
+ });
+ }
+
/**
* Check if the selector is safelisted with the option safelist standard
* @param selector css selector
@@ -718,6 +730,12 @@ class PurgeCSS {
continue;
}
+ // The selector is present in the blocklist
+ if (selectorValue && this.isSelectorBlocklisted(selectorValue)) {
+ isPresent = false;
+ continue;
+ }
+
switch (selectorNode.type) {
case "attribute":
// `value` is a dynamic attribute, highly used in input element
diff --git a/packages/purgecss/src/options.ts b/packages/purgecss/src/options.ts
index e96afa20..1d416bd8 100644
--- a/packages/purgecss/src/options.ts
+++ b/packages/purgecss/src/options.ts
@@ -19,4 +19,5 @@ export const defaultOptions: Options = {
variables: [],
keyframes: [],
},
+ blocklist: [],
};
diff --git a/packages/purgecss/src/types/index.ts b/packages/purgecss/src/types/index.ts
index 42adc1cb..5b52ae1e 100644
--- a/packages/purgecss/src/types/index.ts
+++ b/packages/purgecss/src/types/index.ts
@@ -65,6 +65,7 @@ export interface UserDefinedOptions {
stdout?: boolean;
variables?: boolean;
safelist?: UserDefinedSafelist;
+ blocklist?: StringRegExpArray;
}
export interface Options {
@@ -80,6 +81,7 @@ export interface Options {
stdout: boolean;
variables: boolean;
safelist: Required;
+ blocklist: StringRegExpArray;
}
export interface ResultPurge {