Skip to content

Commit

Permalink
Merge pull request #424 from benface/whitelist-patterns-greedy
Browse files Browse the repository at this point in the history
feat(purgecss): add `whitelistPatternsGreedy` option
  • Loading branch information
Ffloriel committed Jun 13, 2020
2 parents 5314e41 + 331e893 commit adacfd7
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 33 deletions.
31 changes: 22 additions & 9 deletions docs/configuration.md
Expand Up @@ -51,6 +51,7 @@ interface UserDefinedOptions {
whitelist?: string[]
whitelistPatterns?: Array<RegExp>
whitelistPatternsChildren?: Array<RegExp>
whitelistPatternsGreedy?: Array<RegExp>
}

interface RawContent {
Expand Down Expand Up @@ -168,7 +169,7 @@ You can learn more about extractors [here](extractors.md).

- **fontFace \(default: false\)**

If there are any unused @font-face rules in your css, you can remove them by setting the `fontFace` option to `true`
If there are any unused @font-face rules in your css, you can remove them by setting the `fontFace` option to `true`.

```js
await new PurgeCSS().purge({
Expand All @@ -192,7 +193,7 @@ await new PurgeCSS().purge({

- **variables \(default: false\)**

If your are using Custom Properties (CSS variables), or a library using them such as Bootstrap, you can remove unused CSS variables by setting the `variables` option to `true`.
If you are using Custom Properties (CSS variables), or a library using them such as Bootstrap, you can remove unused CSS variables by setting the `variables` option to `true`.

```js
await new PurgeCSS().purge({
Expand All @@ -204,8 +205,7 @@ await new PurgeCSS().purge({

- **rejected \(default: false\)**

It can sometimes be more practical to scan through the removed list to see if there's anything obviously wrong.
If you want to do it, use the `rejected` option.
It can sometimes be more practical to scan through the removed list to see if there's anything obviously wrong. If you want to do it, use the `rejected` option.

```js
await new PurgeCSS().purge({
Expand All @@ -217,7 +217,7 @@ await new PurgeCSS().purge({

- **whitelist**

You can whitelist selectors to stop PurgeCSS from removing them from your CSS. This can be accomplished with the options `whitelist` and `whitelistPatterns`.
You can whitelist selectors to stop PurgeCSS from removing them from your CSS. This can be accomplished with the options `whitelist`, `whitelistPatterns`, `whitelistPatternsChildren`, and `whitelistPatternsGreedy`.

```js
const purgecss = await new PurgeCSS().purge({
Expand All @@ -227,7 +227,7 @@ const purgecss = await new PurgeCSS().purge({
})
```

In the example, the selectors `.random`, `#yep`, `button` will be left in the final CSS.
In this example, the selectors `.random`, `#yep`, `button` will be left in the final CSS.

- **whitelistPatterns**

Expand All @@ -241,11 +241,11 @@ const purgecss = await new PurgeCSS().purge({
})
```

In the example, selectors ending with `red` such as `.bg-red` will be left in the final CSS.
In this example, selectors ending with `red` such as `.bg-red` will be left in the final CSS.

- **whitelistPatternsChildren**

You can whitelist selectors based on a regular expression with `whitelistPatternsChildren`. Contrary to `whitelistPatterns`, it will also whitelist children of the selectors.
You can whitelist selectors and their children based on a regular expression with `whitelistPatternsChildren`.

```js
const purgecss = await new PurgeCSS().purge({
Expand All @@ -255,5 +255,18 @@ const purgecss = await new PurgeCSS().purge({
})
```

In the example, selectors such as `red p` or `.bg-red .child-of-bg` will be left in the final CSS.
In this example, selectors such as `.bg-red .child-of-bg` will be left in the final CSS, even if `child-of-bg` is not found.

- **whitelistPatternsGreedy**

Finally, you can whitelist whole selectors if any part of that selector matches a regular expression with `whitelistPatternsGreedy`.

```js
const purgecss = await new PurgeCSS().purge({
content: [], // content
css: [], // css
whitelistPatternsGreedy: [/red$/]
})
```

In this example, selectors such as `button.bg-red.nonexistent-class` will be left in the final CSS, even if `button` and `nonexistent-class` are not found.
10 changes: 8 additions & 2 deletions docs/plugins/webpack.md
Expand Up @@ -125,7 +125,7 @@ new PurgecssPlugin({
})
```

* #### whitelist, whitelistPatterns and whitelistPatternsChildren
* #### whitelist, whitelistPatterns, whitelistPatternsChildren, and whitelistPatternsGreedy

Similar as for the `paths` option, you can also define functions for the following options:

Expand All @@ -145,11 +145,17 @@ function collectWhitelistPatternsChildren() {
return [/^whitelisted-/];
}

function collectWhitelistPatternsGreedy() {
// do something to collect the whitelist
return [/^whitelisted-/];
}

// In the webpack configuration
new PurgecssPlugin({
whitelist: collectWhitelist,
whitelistPatterns: collectWhitelistPatterns,
whitelistPatternsChildren: collectWhitelistPatternsChildren
whitelistPatternsChildren: collectWhitelistPatternsChildren,
whitelistPatternsGreedy: collectWhitelistPatternsGreedy
})
```

Expand Down
9 changes: 5 additions & 4 deletions docs/whitelisting.md
Expand Up @@ -10,7 +10,7 @@ meta:

# Whitelisting

You can whitelist selectors to stop PurgeCSS from removing them from your CSS. This can be accomplished with the PurgeCSS options `whitelist`, `whitelistPatterns`, `whitelistPatternsChildren`, or directly in your CSS with a special comment.
You can whitelist selectors to stop PurgeCSS from removing them from your CSS. This can be accomplished with the PurgeCSS options `whitelist`, `whitelistPatterns`, `whitelistPatternsChildren`, `whitelistPatternsGreedy`, or directly in your CSS with a special comment.

## Specific selectors

Expand All @@ -28,18 +28,19 @@ In the example, the selectors `.random`, `#yep`, `button` will be left in the fi

## Patterns

You can whitelist selectors based on a regular expression with `whitelistPatterns` and `whitelistPatternsChildren`.
You can whitelist selectors based on a regular expression with `whitelistPatterns`, `whitelistPatternsChildren`, and `whitelistPatternsGreedy`.

```javascript
const purgecss = new Purgecss({
content: [], // content
css: [], // css
whitelistPatterns: [/red$/],
whitelistPatternsChildren: [/blue$/]
whitelistPatternsChildren: [/blue$/],
whitelistPatternsGreedy: [/yellow$/]
})
```

In the example, selectors ending with `red` such as `.bg-red`, and children of selectors ending with `blue` such as `blue p` or `.bg-blue .child-of-bg`, will be left in the final CSS.
In the example, selectors ending with `red` such as `.bg-red`, selectors ending with `blue` as well as their children such as `blue p` or `.bg-blue .child-of-bg`, and selectors that have any part ending with `yellow` such as `button.bg-yellow.other-class`, will be left in the final CSS.

Patterns are regular expressions. You can use [regexr](https://regexr.com) to verify the regular expressions correspond to what you are looking for.

Expand Down
1 change: 1 addition & 0 deletions packages/gulp-purgecss/src/types/index.ts
Expand Up @@ -24,4 +24,5 @@ export interface UserDefinedOptions {
whitelist?: string[];
whitelistPatterns?: Array<RegExp>;
whitelistPatternsChildren?: Array<RegExp>;
whitelistPatternsGreedy?: Array<RegExp>;
}
1 change: 1 addition & 0 deletions packages/postcss-purgecss/src/types/index.ts
Expand Up @@ -26,4 +26,5 @@ export interface UserDefinedOptions {
whitelist?: string[];
whitelistPatterns?: Array<RegExp>;
whitelistPatternsChildren?: Array<RegExp>;
whitelistPatternsGreedy?: Array<RegExp>;
}
10 changes: 8 additions & 2 deletions packages/purgecss-webpack-plugin/README.md
Expand Up @@ -157,7 +157,7 @@ new PurgecssPlugin({
})
```

* #### whitelist, whitelistPatterns and whitelistPatternsChildren
* #### whitelist, whitelistPatterns, whitelistPatternsChildren, and whitelistPatternsGreedy

Similar as for the `paths` option, you also can define functions for the these options:

Expand All @@ -176,11 +176,17 @@ function collectWhitelistPatternsChildren() {
return [/^whitelisted-/];
}

function collectWhitelistPatternsGreedy() {
// do something to collect the whitelist
return [/^whitelisted-/];
}

// In the webpack configuration
new PurgecssPlugin({
whitelist: collectWhitelist,
whitelistPatterns: collectWhitelistPatterns,
whitelistPatternsChildren: collectWhitelistPatternsChildren
whitelistPatternsChildren: collectWhitelistPatternsChildren,
whitelistPatternsGreedy: collectWhitelistPatternsGreedy
})
```

Expand Down
Expand Up @@ -42,6 +42,7 @@ module.exports = {
whitelist: () => ['whitelisted'],
whitelistPatterns: () => [/^whitelistedPat/],
whitelistPatternsChildren: () => [/^whitelistedPatternChildren/],
whitelistPatternsGreedy: () => [/^whitelistedPatternGreedy/],
extractors: [
{
extractor: customExtractor,
Expand Down
4 changes: 4 additions & 0 deletions packages/purgecss-webpack-plugin/src/index.ts
Expand Up @@ -116,6 +116,9 @@ export default class PurgeCSSPlugin {
if (typeof options.whitelistPatternsChildren === "function") {
options.whitelistPatternsChildren = options.whitelistPatternsChildren();
}
if (typeof options.whitelistPatternsGreedy === "function") {
options.whitelistPatternsGreedy = options.whitelistPatternsGreedy();
}

const purgecss = await new PurgeCSS().purge({
content: options.content,
Expand All @@ -130,6 +133,7 @@ export default class PurgeCSSPlugin {
whitelist: options.whitelist,
whitelistPatterns: options.whitelistPatterns,
whitelistPatternsChildren: options.whitelistPatternsChildren,
whitelistPatternsGreedy: options.whitelistPatternsGreedy,
});
const purged = purgecss[0];

Expand Down
1 change: 1 addition & 0 deletions packages/purgecss-webpack-plugin/src/types/index.ts
Expand Up @@ -31,6 +31,7 @@ export interface UserDefinedOptions {
whitelist?: string[] | WhitelistFunction;
whitelistPatterns?: Array<RegExp> | WhitelistPatternsFunction;
whitelistPatternsChildren?: Array<RegExp> | WhitelistPatternsFunction;
whitelistPatternsGreedy?: Array<RegExp> | WhitelistPatternsFunction;
only?: string[];
}

Expand Down
@@ -0,0 +1,6 @@
.card {}
.card[data-v-test] {}
.card.card--large {}
.card[data-v-test].card--large {}
.card .card-content {}
.card[data-v-test] .card-content {}
@@ -0,0 +1,5 @@
<html>
<body>
<div class="card"></div>
</body>
</html>
38 changes: 38 additions & 0 deletions packages/purgecss/__tests__/whitelist.test.ts
Expand Up @@ -87,3 +87,41 @@ describe("whitelistPatternsChildren", () => {
expect(purgedCSS.includes(".btn__green")).toBe(false);
});
});

describe("whitelistPatternsGreedy", () => {
let purgedCSS: string;
beforeAll(async () => {
const resultsPurge = await new PurgeCSS().purge({
content: [
`${root}whitelist_patterns_greedy/whitelist_patterns_greedy.html`,
],
css: [`${root}whitelist_patterns_greedy/whitelist_patterns_greedy.css`],
whitelistPatternsGreedy: [/data-v-.*/],
});
purgedCSS = resultsPurge[0].css;
});

it("finds card", () => {
expect(purgedCSS.includes(".card")).toBe(true);
});

it("finds card with data-v attribute", () => {
expect(purgedCSS.includes(".card[data-v-test]")).toBe(true);
});

it("excludes card--large", () => {
expect(purgedCSS.includes(".card.card--large")).toBe(false);
});

it("finds card--large with data-v attribute", () => {
expect(purgedCSS.includes(".card[data-v-test].card--large")).toBe(true);
});

it("excludes card-content", () => {
expect(purgedCSS.includes(".card .card-content")).toBe(false);
});

it("finds card-content inside card with data-v attribute", () => {
expect(purgedCSS.includes(".card[data-v-test] .card-content")).toBe(true);
});
});

0 comments on commit adacfd7

Please sign in to comment.