Skip to content

Commit

Permalink
✨ improve(minor): reasonable defaults for purgecss (@roots/bud-purgec…
Browse files Browse the repository at this point in the history
…ss) (#2443)

You don't have to call `bud.purgecss` in order to purge styles. 

Shouldn't be a problem for anyone for any reason I can foresee but still a minor bump. 

- Deprecates `bud.purgecss` method. Removal of this method constitutes a major bump imho, will save for v7.
- Provide reasonable defaults for purgecss
- Improve exports organization
- Improve typings (options API type hinting)
- Improve tests
- Improve [examples/purgecss](https://github.com/roots/bud/tree/main/examples/purgecss)

Default behavior:

- purgecss is enabled in `development` mode only
- `content` is set to:
  - `bud.path('@src/*.{html,js,jsx,php,pug,rb,ts,tsx,vue}')`
  - `bud.path('@src/**/*.{html,js,jsx,php,pug,rb,ts,tsx,vue}')`

## Updating config

This is pretty easy. The old setup involved calling 

```ts
bud.purgecss({
  content: [bud.path('src/*.html')],
  css: [bud.path('src/**/*.css')],
})
```

This is now:

```ts
bud.purge
  .setContent([bud.path(`src/*.html`)])
  .setCss([bud.path(`src/**/*.css`)])
```

Or, as with all extensions, you can use the `Options` API directly:

```ts
bud.purge
  .set(`content`, [bud.path(`src/*.html`)])
  .set(`css`, [bud.path(`src/**/*.css`)])
```

I really like this style but the type hinting isn't as good.

If you really want to use the plugin in `development` mode for some reason, you can just call `enable`:

```ts
bud.purge
  .setContent([bud.path(`src/*.html`)])
  .setCss([bud.path(`src/**/*.css`)])
  .enable()
```

## Type of change

**PATCH: backwards compatible change**
  • Loading branch information
kellymears authored Sep 22, 2023
1 parent 106d786 commit 5a39384
Show file tree
Hide file tree
Showing 20 changed files with 322 additions and 162 deletions.
11 changes: 0 additions & 11 deletions examples/purgecss/bud.config.js

This file was deleted.

5 changes: 5 additions & 0 deletions examples/purgecss/bud.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {bud} from '@roots/bud'

bud.html({
template: bud.path('src/index.html'),
})
38 changes: 37 additions & 1 deletion examples/purgecss/src/index.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,47 @@
/**
* This element is present in `index.html` and can be found in the final CSS file.
*/
h1 {
color: black;
}

/**
* This element is present in `index.html` and can be found in the final CSS file.
*/
h2 {
color: red;
}

h3.exclude {
/**
* This element is not found in any source file and will not be found in the final CSS file.
*/
h3 {
color: yellow;
}

/**
* This element is dynamically inserted into the DOM in `index.js` and
* can be found in the final CSS file.
*/
.include {
color: green;
}

/**
* This is a test of postcss syntax. There is no `.li` element within a `div` in any source file,
* but there is a `.li` element within a `section`. This will not be found in the final CSS file.
*/
div {
.li {
color: purple;
}
}

/**
* This is a test of comment hinting. There is a dynamically inserted element in `index.js`
* which matches this selector. However, the class name is constructed by joining multiple
* strings together. We use a comment to make sure that this rule is preserved.
*/
.comment-test {
color: orange;
}
22 changes: 10 additions & 12 deletions examples/purgecss/src/index.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>

<title>%APP_TITLE%</title>
<meta name="theme-color" content="%APP_COLOR%" />
<meta name="description" content="%APP_DESCRIPTION%" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PurgeCSS Test</title>
</head>

<body>
<h1>PostCSS</h1>
<h2>PurgeCss test</h2>
<!-- note the intentionally omitted h3 -->
<h1>This element has a matching css selector</h1>
<h2>This element has a matching css selector</h2>
<section>
<ul>
<li class="bar">This element has no matching css selector</li>
</ul>
</section>
</body>
</html>
14 changes: 14 additions & 0 deletions examples/purgecss/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import '@src/index.css'

/**
* This dynamically inserted element is not present in `./index.html` but the matching
* CSS selector will be included in the final bundle because it matches.
*/
document.querySelector(`h2`)?.insertAdjacementHTML(`afterend`, `<h4 class="include">Paragraph</h4>`)

/**
* This dynamically inserted element's classname is constructed from multiple strings
* so we'll include a comment to ensure it's not purged.
*/
const classname = [`comment`, `test`].join(`-`) // comment-test
document.querySelector(`h2`)?.insertAdjacentHTML(`afterend`, `<h5 class="${classname}">Paragraph</h5>`)
5 changes: 2 additions & 3 deletions examples/purgecss/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"webpack/module",
]
},
"files": ["bud.config.js"],
"include": ["src"],
"exclude": ["node_modules"]
"files": ["bud.config.ts"],
"include": ["src"]
}
5 changes: 5 additions & 0 deletions sources/@roots/bud-postcss/src/extension/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ class BudPostCss extends BudPostCssOptionsApi {
return plugin[0]
}

@bind
public hasPlugin(name: string): boolean {
return this.normalizePluginName(name) in this.plugins
}

@bind
protected normalizePluginName(name: string): string {
if (name.startsWith(`postcss-`)) name = name.replace(`postcss-`, ``)
Expand Down
1 change: 1 addition & 0 deletions sources/@roots/bud-postcss/src/extension/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type BudPostCssPublicInterface = StrictPublicExtensionApi<
getPlugin(name: string): PluginReference
getPluginOptions(name: string): Record<string, any>
getPluginPath(name: string): string
hasPlugin(name: string): boolean
setConfig(config: boolean): BudPostCssPublicInterface
setPlugin(name: string, plugin?: PluginInput): BudPostCssPublicInterface
setPluginOptions(
Expand Down
12 changes: 5 additions & 7 deletions sources/@roots/bud-purgecss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,31 @@
"type": "module",
"exports": {
".": "./lib/index.js",
"./api": "./lib/api.js",
"./extension": "./lib/extension.js"
"./facade": "./lib/facade/index.js",
"./extension": "./lib/extension/index.js"
},
"typesVersions": {
"*": {
".": [
"./lib/index.d.ts"
],
"api": [
"./lib/api.d.ts"
"facade": [
"./lib/facade/index.d.ts"
],
"extension": [
"./lib/extension.d.ts"
"./lib/extension/index.d.ts"
]
}
},
"types": "./lib/index.d.ts",
"module": "./lib/index.js",
"devDependencies": {
"@roots/bud": "workspace:*",
"@roots/bud-postcss": "workspace:*",
"@skypack/package-check": "0.2.2",
"@types/node": "18.17.18"
},
"dependencies": {
"@fullhuman/postcss-purgecss": "5.0.0",
"@roots/bud": "workspace:*",
"@roots/bud-framework": "workspace:*",
"postcss": "8.4.30",
"tslib": "2.6.2"
Expand Down
91 changes: 0 additions & 91 deletions sources/@roots/bud-purgecss/src/api.ts

This file was deleted.

20 changes: 0 additions & 20 deletions sources/@roots/bud-purgecss/src/extension.ts

This file was deleted.

75 changes: 75 additions & 0 deletions sources/@roots/bud-purgecss/src/extension/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { UserDefinedOptions as Options } from '@fullhuman/postcss-purgecss'

import {Extension} from '@roots/bud-framework/extension'

import type { BudPurgeCSSPublicInterface } from './model.js'

export default class BudPurgeCSSPublicAPI extends Extension<Options> {
public declare blocklist: BudPurgeCSSPublicInterface[`blocklist`]
public declare getBlocklist: BudPurgeCSSPublicInterface[`getBlocklist`]
public declare setBlocklist: BudPurgeCSSPublicInterface[`setBlocklist`]

public declare content: BudPurgeCSSPublicInterface[`content`]
public declare getContent: BudPurgeCSSPublicInterface[`getContent`]
public declare setContent: BudPurgeCSSPublicInterface[`setContent`]

public declare contentFunction: BudPurgeCSSPublicInterface[`contentFunction`]
public declare getContentFunction: BudPurgeCSSPublicInterface[`getContentFunction`]
public declare setContentFunction: BudPurgeCSSPublicInterface[`setContentFunction`]

public declare dynamicAttributes: BudPurgeCSSPublicInterface[`dynamicAttributes`]
public declare getDynamicAttributes: BudPurgeCSSPublicInterface[`getDynamicAttributes`]
public declare setDynamicAttributes: BudPurgeCSSPublicInterface[`setDynamicAttributes`]

public declare defaultExtractor: BudPurgeCSSPublicInterface[`defaultExtractor`]
public declare getDefaultExtractor: BudPurgeCSSPublicInterface[`getDefaultExtractor`]
public declare setDefaultExtractor: BudPurgeCSSPublicInterface[`setDefaultExtractor`]

public declare extractors: BudPurgeCSSPublicInterface[`extractors`]
public declare getExtractors: BudPurgeCSSPublicInterface[`getExtractors`]
public declare setExtractors: BudPurgeCSSPublicInterface[`setExtractors`]

public declare fontFace: BudPurgeCSSPublicInterface[`fontFace`]
public declare getFontFace: BudPurgeCSSPublicInterface[`getFontFace`]
public declare setFontFace: BudPurgeCSSPublicInterface[`setFontFace`]

public declare keyframes: BudPurgeCSSPublicInterface[`keyframes`]
public declare getKeyframes: BudPurgeCSSPublicInterface[`getKeyframes`]
public declare setKeyframes: BudPurgeCSSPublicInterface[`setKeyframes`]

public declare output: BudPurgeCSSPublicInterface[`output`]
public declare getOutput: BudPurgeCSSPublicInterface[`getOutput`]
public declare setOutput: BudPurgeCSSPublicInterface[`setOutput`]

public declare rejected: BudPurgeCSSPublicInterface[`rejected`]
public declare getRejected: BudPurgeCSSPublicInterface[`getRejected`]
public declare setRejected: BudPurgeCSSPublicInterface[`setRejected`]

public declare rejectedCss: BudPurgeCSSPublicInterface[`rejectedCss`]
public declare getRejectedCss: BudPurgeCSSPublicInterface[`getRejectedCss`]
public declare setRejectedCss: BudPurgeCSSPublicInterface[`setRejectedCss`]

public declare safelist: BudPurgeCSSPublicInterface[`safelist`]
public declare getSafelist: BudPurgeCSSPublicInterface[`getSafelist`]
public declare setSafelist: BudPurgeCSSPublicInterface[`setSafelist`]

public declare skippedContentGlobs: BudPurgeCSSPublicInterface[`skippedContentGlobs`]
public declare getSkippedContentGlobs: BudPurgeCSSPublicInterface[`getSkippedContentGlobs`]
public declare setSkippedContentGlobs: BudPurgeCSSPublicInterface[`setSkippedContentGlobs`]

public declare sourceMap: BudPurgeCSSPublicInterface[`sourceMap`]
public declare getSourceMap: BudPurgeCSSPublicInterface[`getSourceMap`]
public declare setSourceMap: BudPurgeCSSPublicInterface[`setSourceMap`]

public declare stdin: BudPurgeCSSPublicInterface[`stdin`]
public declare getStdin: BudPurgeCSSPublicInterface[`getStdin`]
public declare setStdin: BudPurgeCSSPublicInterface[`setStdin`]

public declare stdout: BudPurgeCSSPublicInterface[`stdout`]
public declare getStdout: BudPurgeCSSPublicInterface[`getStdout`]
public declare setStdout: BudPurgeCSSPublicInterface[`setStdout`]

public declare variables: BudPurgeCSSPublicInterface[`variables`]
public declare getVariables: BudPurgeCSSPublicInterface[`getVariables`]
public declare setVariables: BudPurgeCSSPublicInterface[`setVariables`]
}
Loading

0 comments on commit 5a39384

Please sign in to comment.