diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..2801def3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment (please complete the following information):** + - OS: [e.g. iOS] + - Package [e.g. purgecss, postcss-purgecss] + - Version [e.g. 4.0.1] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..9d347210 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: Feature request +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/CHANGELOG.md b/CHANGELOG.md index b6ff6cca..8de5c654 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# [](https://github.com/FullHuman/purgecss/compare/v4.0.0...v) (2021-01-17) + +### Breaking Changes +Drop PostCSS 7 support, use @fullhuman/postcss-purgecss 3.0 with PostCSS 7. + # [](https://github.com/FullHuman/purgecss/compare/v3.1.3-alpha.0...v) (2020-12-15) * **postcss-purgecss** remove postcss 8 as peer dependency diff --git a/README.md b/README.md index 205b7420..96b5992b 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ This repository is a monorepo that we manage using [Lerna](https://github.com/le | [purgecss-webpack-plugin](/packages/purgecss-webpack-plugin) |  | Webpack plugin for PurgeCSS | | [gulp-purgecss](/packages/gulp-purgecss) |  | Gulp plugin for PurgeCSS | | [grunt-purgecss](/packages/grunt-purgecss) |  | Grunt plugin for PurgeCSS | +| [rollup-plugin-purgecss](/packages/rollup-plugin-purgecss) |  | Rollup plugin for PurgeCSS | | [purgecss-from-html](/packages/purgecss-from-html) |  | Html extractor for PurgeCSS | | [purgecss-from-pug](/packages/purgecss-from-pug) |  | Pug extractor for PurgeCSS | | [purgecss-with-wordpress](/packages/purgecss-with-wordpress) |  | Collection of safelist items for WordPress | diff --git a/docs/api.md b/docs/api.md index be4236e4..276168ce 100644 --- a/docs/api.md +++ b/docs/api.md @@ -36,7 +36,7 @@ In the following examples, the options passed to PurgeCSS are the same as the on ### ES Module Import Syntax ```javascript -import PurgeCSS from 'purgecss' +import { PurgeCSS } from 'purgecss' const purgeCSSResult = await new PurgeCSS().purge({ content: ['**/*.html'], css: ['**/*.css'] diff --git a/docs/guides/next.md b/docs/guides/next.md index 198bd7e9..972f1095 100644 --- a/docs/guides/next.md +++ b/docs/guides/next.md @@ -34,6 +34,8 @@ To customize the PostCSS configuration, create a postcss.config.js file in the r > Warning: When you define a custom PostCSS configuration file, Next.js completely disables the default behavior. Be sure to manually configure all the features you need compiled, including [Autoprefixer](https://github.com/postcss/autoprefixer). You also need to install any plugins included in your custom configuration manually, i.e. `npm install postcss-flexbugs-fixes postcss-preset-env`. +> By default, the outer document containing `html` and `body` is inside nextjs node module. Add `safelist:["html", "body"]` to make sure PurgeCSS does not remove those style. + Add PurgeCSS to the default configuration: ```js @@ -59,7 +61,8 @@ module.exports = { './pages/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}' ], - defaultExtractor: content => content.match(/[\w-/:]+(? content.match(/[\w-/:]+(?", "homepage": "https://purgecss.com", @@ -26,7 +26,7 @@ "url": "https://github.com/FullHuman/purgecss/issues" }, "dependencies": { - "purgecss": "^4.0.0" + "purgecss": "^4.0.1" }, "devDependencies": { "postcss": "^8.2.1" diff --git a/packages/purgecss-webpack-plugin/package-lock.json b/packages/purgecss-webpack-plugin/package-lock.json index 4ba495a0..3e0113e3 100644 --- a/packages/purgecss-webpack-plugin/package-lock.json +++ b/packages/purgecss-webpack-plugin/package-lock.json @@ -1,6 +1,6 @@ { "name": "purgecss-webpack-plugin", - "version": "4.0.0", + "version": "4.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -23,9 +23,9 @@ } }, "@types/estree": { - "version": "0.0.45", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", - "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==" + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", + "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==" }, "@types/json-schema": { "version": "7.0.6", @@ -204,9 +204,9 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "acorn": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", - "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==" + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz", + "integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==" }, "ajv": { "version": "6.12.6", @@ -245,15 +245,15 @@ } }, "browserslist": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", - "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", "requires": { - "caniuse-lite": "^1.0.30001173", + "caniuse-lite": "^1.0.30001181", "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.634", + "electron-to-chromium": "^1.3.649", "escalade": "^3.1.1", - "node-releases": "^1.1.69" + "node-releases": "^1.1.70" } }, "buffer-from": { @@ -268,9 +268,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001174", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", - "integrity": "sha512-tqClL/4ThQq6cfFXH3oJL4rifFBeM6gTkphjao5kgwMaW9yn0tKgQLAEfKzDwj6HQWCB/aWo8kTFlSvIN8geEA==" + "version": "1.0.30001181", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001181.tgz", + "integrity": "sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ==" }, "chrome-trace-event": { "version": "1.0.2", @@ -321,9 +321,9 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "electron-to-chromium": { - "version": "1.3.635", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.635.tgz", - "integrity": "sha512-RRriZOLs9CpW6KTLmgBqyUdnY0QNqqWs0HOtuQGGEMizOTNNn1P7sGRBxARnUeLejOsgwjDyRqT3E/CSst02ZQ==" + "version": "1.3.649", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.649.tgz", + "integrity": "sha512-ojGDupQ3UMkvPWcTICe4JYe17+o9OLiFMPoduoR72Zp2ILt1mRVeqnxBEd6s/ptekrnsFU+0A4lStfBe/wyG/A==" }, "emojis-list": { "version": "3.0.0", @@ -332,14 +332,19 @@ "dev": true }, "enhanced-resolve": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.4.1.tgz", - "integrity": "sha512-4GbyIMzYktTFoRSmkbgZ1LU+RXwf4AQ8Z+rSuuh1dC8plp0PPeaWvx6+G4hh4KnUJ48VoxKbNyA1QQQIUpXjYA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", + "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, + "es-module-lexer": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.3.26.tgz", + "integrity": "sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==" + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -537,9 +542,9 @@ } }, "mini-css-extract-plugin": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.3.tgz", - "integrity": "sha512-7lvliDSMiuZc81kI+5/qxvn47SCM7BehXex3f2c6l/pR3Goj58IQxZh9nuPQ3AkGQgoETyXuIqLDaO5Oa0TyBw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.5.tgz", + "integrity": "sha512-tvmzcwqJJXau4OQE5vT72pRT18o2zF+tQJp8CWchqvfQnTlflkzS+dANYcRdyPRWUWRkfmeNTKltx0NZI/b5dQ==", "dev": true, "requires": { "loader-utils": "^2.0.0", @@ -584,9 +589,9 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node-releases": { - "version": "1.1.69", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", - "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==" + "version": "1.1.70", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", + "integrity": "sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==" }, "once": { "version": "1.4.0", @@ -698,9 +703,9 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "purgecss": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-3.1.3.tgz", - "integrity": "sha512-hRSLN9mguJ2lzlIQtW4qmPS2kh6oMnA9RxdIYK8sz18QYqd6ePp4GNDl18oWHA1f2v2NEQIh51CO8s/E3YGckQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.0.0.tgz", + "integrity": "sha512-j/y6OtNpEiggw/ipCJUOMNLgLpeAv9L8q+SqzEdDzyVEZOfdWjg8yvgOxhBflNyYgJ8SZ+tTwPxrHT9vQUpEPw==", "requires": { "commander": "^6.0.0", "glob": "^7.0.0", @@ -850,19 +855,20 @@ } }, "webpack": { - "version": "5.12.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.12.3.tgz", - "integrity": "sha512-7tiQmcTnKhZwbf7X7sEfXe0pgkGjUZjT6JfYkZHvvIb4/ZsXl1rJu5PxsJoN7W3v5sNSP/8TgBoiOdDqVdvK5w==", + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.19.0.tgz", + "integrity": "sha512-egX19vAQ8fZ4cVYtA9Y941eqJtcZAK68mQq87MMv+GTXKZOc3TpKBBxdGX+HXUYlquPxiluNsJ1VHvwwklW7CQ==", "requires": { "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.45", + "@types/estree": "^0.0.46", "@webassemblyjs/ast": "1.11.0", "@webassemblyjs/wasm-edit": "1.11.0", "@webassemblyjs/wasm-parser": "1.11.0", "acorn": "^8.0.4", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.3.1", + "enhanced-resolve": "^5.7.0", + "es-module-lexer": "^0.3.26", "eslint-scope": "^5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", diff --git a/packages/purgecss-webpack-plugin/package.json b/packages/purgecss-webpack-plugin/package.json index a9245567..6e34f7bb 100644 --- a/packages/purgecss-webpack-plugin/package.json +++ b/packages/purgecss-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "purgecss-webpack-plugin", - "version": "4.0.0", + "version": "4.0.1", "description": "PurgeCSS plugin for webpack - Remove unused css", "author": "Ffloriel", "homepage": "https://purgecss.com", @@ -36,7 +36,7 @@ "test": "echo \"Error: run tests from root\" && exit 1" }, "dependencies": { - "purgecss": "^4.0.0", + "purgecss": "^4.0.1", "webpack": "^5.4.0", "webpack-sources": "^2.0.0" }, diff --git a/packages/purgecss-webpack-plugin/src/index.ts b/packages/purgecss-webpack-plugin/src/index.ts index e1c7b9ad..f5b6fcf3 100644 --- a/packages/purgecss-webpack-plugin/src/index.ts +++ b/packages/purgecss-webpack-plugin/src/index.ts @@ -103,6 +103,10 @@ export default class PurgeCSSPlugin { options.safelist = options.safelist(); } + if (typeof options.blocklist === "function") { + options.blocklist = options.blocklist(); + } + const purgecss = await new PurgeCSS().purge({ content: options.content, css: options.css, @@ -114,6 +118,7 @@ export default class PurgeCSSPlugin { rejected: options.rejected, variables: options.variables, safelist: options.safelist, + blocklist: options.blocklist, }); const purged = purgecss[0]; diff --git a/packages/purgecss-webpack-plugin/src/types/index.ts b/packages/purgecss-webpack-plugin/src/types/index.ts index fc85bb69..6de1a09c 100644 --- a/packages/purgecss-webpack-plugin/src/types/index.ts +++ b/packages/purgecss-webpack-plugin/src/types/index.ts @@ -17,8 +17,8 @@ export interface Extractors { } type PathFunction = () => string[]; - type SafelistFunction = () => ComplexSafelist; +type BlocklistFunction = () => StringRegExpArray; export interface UserDefinedOptions { paths: string[] | PathFunction; @@ -34,7 +34,7 @@ export interface UserDefinedOptions { variables?: boolean; verbose?: boolean; safelist?: StringRegExpArray | ComplexSafelist | SafelistFunction; - blocklist?: StringRegExpArray; + blocklist?: StringRegExpArray | BlocklistFunction; only?: string[]; } diff --git a/packages/purgecss/__tests__/attributes.test.ts b/packages/purgecss/__tests__/attributes.test.ts index 87bcf189..421605a7 100644 --- a/packages/purgecss/__tests__/attributes.test.ts +++ b/packages/purgecss/__tests__/attributes.test.ts @@ -63,8 +63,13 @@ describe("attributes", () => { it("handles [attribute*=value]", () => { // keep used css - expect(purgedCSS.includes('a[title~="thin"]')).toBe(true); + expect(purgedCSS.includes('a[title*="thin"]')).toBe(true); // remove unused css - expect(purgedCSS.includes('a[title~="fat"]')).toBe(false); + expect(purgedCSS.includes('a[title*="fat"]')).toBe(false); + }); + + it("handles spaces in attribute selector", () => { + expect(purgedCSS.includes('[class*=" class2"]')).toBe(true); + expect(purgedCSS.includes('[class*="class1 class2 "]')).toBe(true); }); }); diff --git a/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.css b/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.css index 57dc6dcf..5a3f5362 100644 --- a/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.css +++ b/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.css @@ -66,10 +66,18 @@ a[href$="http"] { /* CSS [attribute*="value"] Selector */ -a[title~="thin"] { +a[title*="thin"] { border: 5px solid yellow; } -a[title~="fat"] { +a[title*="fat"] { border: 5px solid yellow; +} + +/* CSS [attribute*="value"] Selector with spaces */ +[class*=" class2"] { + color: green; +} +[class*="class1 class2 "] { + color: blue; } \ No newline at end of file diff --git a/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.html b/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.html index 3ceee0a8..feb101ad 100644 --- a/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.html +++ b/packages/purgecss/__tests__/test_examples/attributes/attribute_selector.html @@ -5,4 +5,5 @@ pdf go to website hello +