diff --git a/.gitignore b/.gitignore index 318ef1b3..6e0cde55 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ docs/.vuepress/dist/ .firebase/ .firebaserc +packages/purgecss-webpack-plugin/__tests__/js +packages/grunt-purgecss/__tests__/tmp + package-lock.json npm-shrinkwrap.json yarn.lock diff --git a/docs/guides/react.md b/docs/guides/react.md index ed234d5e..f677e8a2 100644 --- a/docs/guides/react.md +++ b/docs/guides/react.md @@ -77,6 +77,6 @@ const glob = require('glob-all') // for more information about PurgeCSS. // Specify the path of the html files and source files new PurgecssPlugin({ - paths: [paths.appHtml, ...glob.sync(`${paths.appSrc}/*`)] + paths: [paths.appHtml, ...glob.sync(`${paths.appSrc}/**/*`, { nodir: true })] }), ``` diff --git a/lerna.json b/lerna.json index 81870df9..0db84b17 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": [ "packages/*" ], - "version": "2.0.6" + "version": "2.1.0" } diff --git a/packages/grunt-purgecss/Gruntfile.js b/packages/grunt-purgecss/Gruntfile.js new file mode 100644 index 00000000..4c284074 --- /dev/null +++ b/packages/grunt-purgecss/Gruntfile.js @@ -0,0 +1,24 @@ +module.exports = grunt => { + + // Project configuration. + grunt.initConfig({ + // Configuration to be run (and then tested). + purgecss: { + simple: { + options: { + content: ['./__tests__/fixtures/src/simple/**/*.html'] + }, + files: { + '__tests__/tmp/simple.css': ['__tests__/fixtures/src/simple/simple.css'] + } + } + } + }); + + // Actually load this plugin's task(s). + grunt.loadTasks('tasks'); + + // By default, lint and run all tests. + grunt.registerTask('default', ['purgecss']); + +}; \ No newline at end of file diff --git a/packages/grunt-purgecss/README.md b/packages/grunt-purgecss/README.md new file mode 100644 index 00000000..489fea7c --- /dev/null +++ b/packages/grunt-purgecss/README.md @@ -0,0 +1,126 @@ +# grunt-purgecss + +[![Build Status](https://travis-ci.org/FullHuman/grunt-purgecss.svg?branch=master)](https://travis-ci.org/FullHuman/purgecss) +[![CircleCi](https://circleci.com/gh/FullHuman/grunt-purgecss/tree/master.svg?style=shield)]() +[![dependencies Status](https://david-dm.org/fullhuman/grunt-purgecss/status.svg)](https://david-dm.org/fullhuman/grunt-purgecss) +[![devDependencies Status](https://david-dm.org/fullhuman/grunt-purgecss/dev-status.svg)](https://david-dm.org/fullhuman/grunt-purgecss?type=dev) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7710684c644d4f7cb725dc10a2a5953f)](https://www.codacy.com/app/FullHuman/grunt-purgecss?utm_source=github.com&utm_medium=referral&utm_content=FullHuman/grunt-purgecss&utm_campaign=Badge_Grade) +[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) +[![npm](https://img.shields.io/npm/v/grunt-purgecss.svg)](https://www.npmjs.com/package/grunt-purgecss) +[![license](https://img.shields.io/github/license/fullhuman/grunt-purgecss.svg)]() + +> Grunt plugin for Purgecss. + +## Getting Started + +This plugin requires Grunt `~0.4.5`. + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-purgecss --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-purgecss'); +``` + +## The "purgecss" task + +### Overview + +In your project's Gruntfile, add a section named `purgecss` to the data object passed into `grunt.initConfig()`. + +```js +grunt.initConfig({ + // Configuration to be run (and then tested). + purgecss: { + my_target: { + options: { + content: ['./src/**/*.html'] + }, + files: { + 'dist/app.css': ['src/css/app.css'] + } + } + } + }); +``` + +### Options + +All of the options of purgecss are available to use with the plugins. +You will find below the main options available. For the complete list, go to the [Purgecss documentation website](https://www.purgecss.com/configuration.html#options). + +#### options.content + +Type: `string | Object` + +You can specify content that should be analyzed by Purgecss with an array of filenames or globs. The files can be HTML, Pug, Blade, etc. + +#### options.extractors + +Type: `Array` + +Purgecss can be adapted to suit your needs. If you notice a lot of unused CSS is not being removed, you might want to use a custom extractor. +More information about extractors [here](https://www.purgecss.com/extractors.html). + +#### options.whitelist + +Type: `Array` + +You can whitelist selectors to stop Purgecss from removing them from your CSS. This can be accomplished with the options `whitelist` and `whitelistPatterns`. + +#### options.whitelistPatterns + +Type: `Array` + +You can whitelist selectors based on a regular expression with `whitelistPatterns`. + +#### options.keyframes + +Type: `boolean` +Default value: `false` + +If you are using a CSS animation library such as animate.css, you can remove unused keyframes by setting the `keyframes` option to true. + +#### options.fontFace + +Type: `boolean` +Default value: `false` + +If there are any unused `@font-face` rules in your CSS, you can remove them by setting the `fontFace` option to true. + +### Usage Examples + +The example below is using all of the main options available. + +```js +grunt.initConfig({ + // Configuration to be run (and then tested). + purgecss: { + my_target: { + options: { + content: ['./src/**/*.html', `src/**/*.js`, 'src/**/*.blade', 'src/**/*.vue'], + extractors: { + extractor: class { + static extract(content) { + content.match(/a-Z/) || [] + } + }, + extension: ['html', 'blade'] + }, + whitelist: ['random', 'yep', 'button'], + whitelistPatterns: [/red$/], + keyframes: true, + fontFace: true + }, + files: { + 'dist/app.css': ['src/css/app.css'] + } + } + } + }); +``` diff --git a/packages/grunt-purgecss/__tests__/fixtures/expected/simple.css b/packages/grunt-purgecss/__tests__/fixtures/expected/simple.css new file mode 100644 index 00000000..d0212ee2 --- /dev/null +++ b/packages/grunt-purgecss/__tests__/fixtures/expected/simple.css @@ -0,0 +1,3 @@ +.used-class { + color: black; +} diff --git a/packages/grunt-purgecss/__tests__/fixtures/src/simple/simple.css b/packages/grunt-purgecss/__tests__/fixtures/src/simple/simple.css new file mode 100644 index 00000000..a213a749 --- /dev/null +++ b/packages/grunt-purgecss/__tests__/fixtures/src/simple/simple.css @@ -0,0 +1,11 @@ +.used-class { + color: black; +} + +.unused-class { + color: black; +} + +.another-one-not-found { + color: black; +} diff --git a/packages/grunt-purgecss/__tests__/fixtures/src/simple/simple.html b/packages/grunt-purgecss/__tests__/fixtures/src/simple/simple.html new file mode 100644 index 00000000..56954e7a --- /dev/null +++ b/packages/grunt-purgecss/__tests__/fixtures/src/simple/simple.html @@ -0,0 +1,8 @@ + + + + +
+ + + \ No newline at end of file diff --git a/packages/grunt-purgecss/__tests__/index.test.ts b/packages/grunt-purgecss/__tests__/index.test.ts new file mode 100644 index 00000000..f66f35be --- /dev/null +++ b/packages/grunt-purgecss/__tests__/index.test.ts @@ -0,0 +1,25 @@ +import { execSync } from 'child_process' +import fs from 'fs' + +describe('Purgecss grunt plugin', () => { + + const cwd = process.cwd() + + beforeAll(() => { + process.chdir(__dirname) + execSync('npx grunt') + }) + + afterAll(() => { + process.chdir(cwd) + }) + + const files = ['simple.css'] + for (const file of files) { + it(`remove unused css successfully: ${file}`, () => { + const actual = fs.readFileSync(`${__dirname}/tmp/${file}`).toString() + const expected = fs.readFileSync(`${__dirname}/fixtures/expected/${file}`).toString() + expect(actual).toBe(expected) + }) + } +}) diff --git a/packages/grunt-purgecss/package.json b/packages/grunt-purgecss/package.json new file mode 100644 index 00000000..53a8c67a --- /dev/null +++ b/packages/grunt-purgecss/package.json @@ -0,0 +1,47 @@ +{ + "name": "grunt-purgecss", + "version": "2.1.0", + "description": "Grunt plugin for PurgeCSS", + "author": "Ffloriel", + "homepage": "https://purgecss.com", + "keywords": [ + "optimize", + "optimization", + "remove", + "unused", + "css", + "html", + "rules", + "purge", + "uncss", + "purify" + ], + "license": "MIT", + "main": "lib/grunt-purgecss.js", + "module": "./lib/grunt-purgecss.esm.js", + "types": "./lib/grunt-purgecss.d.ts", + "directories": { + "lib": "lib", + "test": "__tests__" + }, + "files": [ + "lib" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/FullHuman/purgecss.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "dependencies": { + "@types/grunt": "^0.4.25", + "purgecss": "^2.1.0" + }, + "devDependencies": { + "grunt": "~1.0.3" + }, + "bugs": { + "url": "https://github.com/FullHuman/purgecss/issues" + } +} diff --git a/packages/grunt-purgecss/src/index.ts b/packages/grunt-purgecss/src/index.ts new file mode 100644 index 00000000..6620ee41 --- /dev/null +++ b/packages/grunt-purgecss/src/index.ts @@ -0,0 +1,37 @@ +import PurgeCSS, { defaultOptions } from 'purgecss' +import { UserDefinedOptions } from 'purgecss/src/types' + +function getAvailableFiles(grunt: IGrunt, files: string[] | undefined = []) { + return files.filter(filepath => { + // Warn on and remove invalid source files (if nonull was set). + if (!grunt.file.exists(filepath)) { + grunt.log.warn(`Source file "${filepath}" not found.`) + return false + } + return true + }) +} + +function gruntPurgeCSS(grunt: IGrunt) { + grunt.registerMultiTask('purgecss', 'Grunt plugin for PurgeCSS', function() { + const done = this.async(); + const options = this.options(defaultOptions) + for (const file of this.files) { + const source = getAvailableFiles(grunt, file.src) + new PurgeCSS() + .purge({ + ...options, + css: source + }) + .then(purgeCSSResults => { + grunt.file.write(file.dest!, purgeCSSResults[0].css) + // Print a success message + grunt.log.writeln(`File "${file.dest}" created.`) + done() + }) + .catch(() => { done(false) }) + } + }) +} + +export default gruntPurgeCSS diff --git a/packages/grunt-purgecss/src/types/index.d.ts b/packages/grunt-purgecss/src/types/index.d.ts new file mode 100644 index 00000000..0670bb85 --- /dev/null +++ b/packages/grunt-purgecss/src/types/index.d.ts @@ -0,0 +1 @@ +import 'grunt' diff --git a/packages/grunt-purgecss/tasks/purgecss.d.ts b/packages/grunt-purgecss/tasks/purgecss.d.ts new file mode 100644 index 00000000..0c090b5e --- /dev/null +++ b/packages/grunt-purgecss/tasks/purgecss.d.ts @@ -0,0 +1,2 @@ +declare function gruntPurgeCSS(grunt: IGrunt): void; +export { gruntPurgeCSS as default }; diff --git a/packages/grunt-purgecss/tasks/purgecss.js b/packages/grunt-purgecss/tasks/purgecss.js new file mode 100644 index 00000000..fdf014c9 --- /dev/null +++ b/packages/grunt-purgecss/tasks/purgecss.js @@ -0,0 +1 @@ +"use strict";function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var PurgeCSS=require("purgecss"),PurgeCSS__default=_interopDefault(PurgeCSS);function getAvailableFiles(e,t=[]){return t.filter(t=>!!e.file.exists(t)||(e.log.warn(`Source file "${t}" not found.`),!1))}function gruntPurgeCSS(e){e.registerMultiTask("purgecss","Grunt plugin for PurgeCSS",(function(){const t=this.async(),r=this.options(PurgeCSS.defaultOptions);for(const u of this.files){const i=getAvailableFiles(e,u.src);(new PurgeCSS__default).purge({...r,css:i}).then(r=>{e.file.write(u.dest,r[0].css),e.log.writeln(`File "${u.dest}" created.`),t()}).catch(()=>{t(!1)})}}))}module.exports=gruntPurgeCSS; diff --git a/packages/gulp-purgecss/README.md b/packages/gulp-purgecss/README.md index 0370a3ac..e91520a3 100644 --- a/packages/gulp-purgecss/README.md +++ b/packages/gulp-purgecss/README.md @@ -51,7 +51,7 @@ gulp.task('purgecss-rejected', () => { return gulp.src('src/**/*.css') .pipe(rename({ suffix: '.rejected' - }) + })) .pipe(purgecss({ content: ['src/**/*.html'], rejected: true diff --git a/packages/gulp-purgecss/package.json b/packages/gulp-purgecss/package.json index ef5d772f..2d190791 100644 --- a/packages/gulp-purgecss/package.json +++ b/packages/gulp-purgecss/package.json @@ -1,8 +1,8 @@ { "name": "gulp-purgecss", - "version": "2.0.6", + "version": "2.1.0", "description": "Gulp plugin for purgecss", - "author": "Ffloriel ", + "author": "Ffloriel", "homepage": "https://purgecss.com", "keywords": [ "optimize", @@ -37,7 +37,7 @@ "dependencies": { "glob": "^7.1.6", "plugin-error": "^1.0.1", - "purgecss": "^2.0.6", + "purgecss": "^2.1.0", "through2": "^3.0.1" }, "devDependencies": { diff --git a/packages/postcss-purgecss/README.md b/packages/postcss-purgecss/README.md index 99c176fd..8a4a8ec7 100644 --- a/packages/postcss-purgecss/README.md +++ b/packages/postcss-purgecss/README.md @@ -33,11 +33,28 @@ See [PostCSS] docs for examples for your environment. All of the options of purgecss are available to use with the plugins. You will find below the main options available. For the complete list, go to the [purgecss documentation website](https://www.purgecss.com/configuration.html#options). -### `content` (**required**) -Type: `string | Object` +### `content` (**required** or use `contentFunction` instead) +Type: `Array` You can specify content that should be analyzed by Purgecss with an array of filenames or globs. The files can be HTML, Pug, Blade, etc. +### `contentFunction` (as alternative to `content`) +Type: `(sourceInputFile: string) => Array` + +The function receives the current source input file. With this you may provide a specific array of globs for each input. E.g. for +an angular application only scan the components template counterpart for every component scss file: + +```js +purgecss({ + contentFunction: (sourceInputFileName: string) => { + if (/component\.scss$/.test(sourceInputFileName)) + return [sourceInputFileName.replace(/scss$/, 'html')] + else + return ['./src/**/*.html'] + }, +}) +``` + ### `extractors` Type: `Array` diff --git a/packages/postcss-purgecss/__tests__/index.test.ts b/packages/postcss-purgecss/__tests__/index.test.ts index cf44f9aa..c81821d0 100644 --- a/packages/postcss-purgecss/__tests__/index.test.ts +++ b/packages/postcss-purgecss/__tests__/index.test.ts @@ -7,7 +7,7 @@ describe("Purgecss postcss plugin", () => { const files = ["simple", "font-keyframes"]; for (const file of files) { - it(`remove unused css successfully: ${file}`, done => { + it(`remove unused css with content option successfully: ${file}`, done => { const input = fs .readFileSync(`${__dirname}/fixtures/src/${file}/${file}.css`) .toString(); @@ -30,6 +30,38 @@ describe("Purgecss postcss plugin", () => { }); } + for (const file of files) { + it(`remove unused css with contentFunction option successfully: ${file}`, done => { + const input = fs + .readFileSync(`${__dirname}/fixtures/src/${file}/${file}.css`) + .toString(); + const expected = fs + .readFileSync(`${__dirname}/fixtures/expected/${file}.css`) + .toString(); + + const sourceFileName = `src/${file}/${file}.css`; + const contentFunction = jest + .fn() + .mockReturnValue([`${__dirname}/fixtures/src/${file}/${file}.html`]); + + postcss([ + purgeCSSPlugin({ + contentFunction, + fontFace: true, + keyframes: true + }) + ]) + .process(input, { from: sourceFileName }) + .then((result: any) => { + expect(result.css).toBe(expected); + expect(result.warnings().length).toBe(0); + expect(contentFunction).toHaveBeenCalledTimes(1); + expect(contentFunction.mock.calls[0][0]).toContain(sourceFileName); + done(); + }); + }); + } + for (const file of ["simple"]) { it(`queues messages when using reject flag: ${file}`, done => { const input = fs diff --git a/packages/postcss-purgecss/package.json b/packages/postcss-purgecss/package.json index ae154109..efed3f0b 100644 --- a/packages/postcss-purgecss/package.json +++ b/packages/postcss-purgecss/package.json @@ -1,6 +1,6 @@ { "name": "@fullhuman/postcss-purgecss", - "version": "2.0.6", + "version": "2.1.0", "description": "PostCSS plugin for PurgeCSS", "author": "FoundrySH ", "homepage": "https://github.com/FullHuman/purgecss#readme", @@ -26,7 +26,7 @@ "url": "https://github.com/FullHuman/purgecss/issues" }, "dependencies": { - "postcss": "7.0.26", - "purgecss": "^2.0.6" + "postcss": "7.0.27", + "purgecss": "^2.1.0" } } diff --git a/packages/postcss-purgecss/src/index.ts b/packages/postcss-purgecss/src/index.ts index cc30b59e..a3ba7d90 100644 --- a/packages/postcss-purgecss/src/index.ts +++ b/packages/postcss-purgecss/src/index.ts @@ -12,6 +12,13 @@ const purgeCSSPlugin = postcss.plugin>( ...defaultOptions, ...opts }; + + if (opts && typeof opts.contentFunction === "function") { + options.content = opts.contentFunction( + (root.source && root.source.input.file) || "" + ); + } + purgeCSS.options = options; const { content, extractors } = options; @@ -27,7 +34,7 @@ const purgeCSSPlugin = postcss.plugin>( fileFormatContents, extractors ); - const cssRawSelectors = purgeCSS.extractSelectorsFromString( + const cssRawSelectors = await purgeCSS.extractSelectorsFromString( rawFormatContents, extractors ); diff --git a/packages/postcss-purgecss/src/types/index.ts b/packages/postcss-purgecss/src/types/index.ts index ca03b6d2..b96ffca6 100644 --- a/packages/postcss-purgecss/src/types/index.ts +++ b/packages/postcss-purgecss/src/types/index.ts @@ -11,7 +11,8 @@ export interface Extractors { extractor: ExtractorFunction; } export interface UserDefinedOptions { - content: Array; + content?: Array; + contentFunction?: (sourceFile: string) => Array; css: Array; defaultExtractor?: ExtractorFunction; extractors?: Array; diff --git a/packages/purgecss-from-html/package.json b/packages/purgecss-from-html/package.json index d6e90710..106e0056 100644 --- a/packages/purgecss-from-html/package.json +++ b/packages/purgecss-from-html/package.json @@ -1,8 +1,8 @@ { "name": "purgecss-from-html", - "version": "2.0.3", + "version": "2.1.0", "description": "HTML extractor for PurgeCSS", - "author": "Ffloriel ", + "author": "Ffloriel", "homepage": "https://github.com/FullHuman/purgecss#readme", "license": "ISC", "main": "lib/purgecss-from-html.js", diff --git a/packages/purgecss-from-pug/package.json b/packages/purgecss-from-pug/package.json index c80a12ee..efae4b1e 100644 --- a/packages/purgecss-from-pug/package.json +++ b/packages/purgecss-from-pug/package.json @@ -1,8 +1,8 @@ { "name": "purgecss-from-pug", - "version": "2.0.3", + "version": "2.1.0", "description": "Pug extractor for PurgeCSS", - "author": "Ffloriel ", + "author": "Ffloriel", "homepage": "https://github.com/FullHuman/purgecss#readme", "license": "ISC", "main": "lib/purgecss-from-pug.js", diff --git a/packages/purgecss-from-twig/package.json b/packages/purgecss-from-twig/package.json index 4019c809..a660da50 100644 --- a/packages/purgecss-from-twig/package.json +++ b/packages/purgecss-from-twig/package.json @@ -1,8 +1,8 @@ { "name": "purgecss-from-twig", - "version": "2.0.3", + "version": "2.1.0", "description": "Twig extractor for PurgeCSS", - "author": "Ffloriel ", + "author": "Ffloriel", "homepage": "https://github.com/FullHuman/purgecss#readme", "license": "ISC", "main": "lib/purgecss-from-twig.js", diff --git a/packages/purgecss-webpack-plugin/.gitignore b/packages/purgecss-webpack-plugin/.gitignore deleted file mode 100644 index 3d465abb..00000000 --- a/packages/purgecss-webpack-plugin/.gitignore +++ /dev/null @@ -1,61 +0,0 @@ -/__tests__/js - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - diff --git a/packages/purgecss-webpack-plugin/package.json b/packages/purgecss-webpack-plugin/package.json index 7c1e2d4e..06a6341f 100644 --- a/packages/purgecss-webpack-plugin/package.json +++ b/packages/purgecss-webpack-plugin/package.json @@ -1,8 +1,8 @@ { "name": "purgecss-webpack-plugin", - "version": "2.0.6", + "version": "2.1.0", "description": "PurgeCSS plugin for webpack - Remove unused css", - "author": "Ffloriel ", + "author": "Ffloriel", "homepage": "https://purgecss.com", "keywords": [ "webpack-plugin", @@ -36,7 +36,7 @@ "test": "echo \"Error: run tests from root\" && exit 1" }, "dependencies": { - "purgecss": "^2.0.6", + "purgecss": "^2.1.0", "webpack": "^4.41.2", "webpack-sources": "^1.4.3" }, diff --git a/packages/purgecss-with-wordpress/LICENSE b/packages/purgecss-with-wordpress/LICENSE new file mode 100644 index 00000000..07b13efd --- /dev/null +++ b/packages/purgecss-with-wordpress/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Full Human + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/purgecss-with-wordpress/README.md b/packages/purgecss-with-wordpress/README.md new file mode 100644 index 00000000..fc9d9109 --- /dev/null +++ b/packages/purgecss-with-wordpress/README.md @@ -0,0 +1,58 @@ +# PurgeCSS with Wordpress + +Based on the [gist](https://gist.github.com/frnwtr/5647673bb15ca8893642469d3b400cba) made by @frnwtr, `purgecss-with-wordpress` is a set of templates for +Wordpress CMS. + +## Getting Started + +#### Installation + +You need to install [PurgeCSS](https://github.com/FullHuman/purgecss) first. + +Install `purgecss-with-wordpress`: +```sh +npm i --save-dev purgecss-with-wordpress +``` + +## Usage + +```js + +import PurgeCSS from 'purgecss' +import purgecssWordpress from 'purgecss-with-wordpress' + +const purgeCSSResults = await new PurgeCSS().purge({ + content: ['**/*.html'], + css: ['**/*.css'], + whitelist: purgecssWordpress.whitelist, + whitelistPatterns: purgecssWordpress.whitelistPatterns +}) +``` + +If you have additional classes you want to include in either of the `whitelist` or `whitelistPatterns`, you can include them using the spread operator: + +```js +whitelist: [ + ...purgecssWordpress.whitelist, + 'red', + 'blue', +], +whitelistPatterns: [ + ...purgecssWordpress.whitelistPatterns, + /^red/, + /blue$/, +] +``` + +## Versioning + +Purgecss-with-wordpress use [SemVer](http://semver.org/) for versioning. + +## Acknowledgment + +Purgecss-with-wordpress is based on the [gist](https://gist.github.com/frnwtr/5647673bb15ca8893642469d3b400cba) made by @frnwtr + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file +for details. diff --git a/packages/purgecss-with-wordpress/index.js b/packages/purgecss-with-wordpress/index.js new file mode 100644 index 00000000..790938aa --- /dev/null +++ b/packages/purgecss-with-wordpress/index.js @@ -0,0 +1,38 @@ +module.exports = { + whitelist: [ + 'rtl', + 'home', + 'blog', + 'archive', + 'date', + 'error404', + 'logged-in', + 'admin-bar', + 'no-customize-support', + 'custom-background', + 'wp-custom-logo', + 'alignnone', + 'alignright', + 'alignleft', + 'wp-caption', + 'wp-caption-text', + 'screen-reader-text', + 'comment-list', + ], + whitelistPatterns: [ + /^search(-.*)?$/, + /^(.*)-template(-.*)?$/, + /^(.*)?-?single(-.*)?$/, + /^postid-(.*)?$/, + /^attachmentid-(.*)?$/, + /^attachment(-.*)?$/, + /^page(-.*)?$/, + /^(post-type-)?archive(-.*)?$/, + /^author(-.*)?$/, + /^category(-.*)?$/, + /^tag(-.*)?$/, + /^tax-(.*)?$/, + /^term-(.*)?$/, + /^(.*)?-?paged(-.*)?$/, + ], +}; diff --git a/packages/purgecss-with-wordpress/package.json b/packages/purgecss-with-wordpress/package.json new file mode 100644 index 00000000..83648a4e --- /dev/null +++ b/packages/purgecss-with-wordpress/package.json @@ -0,0 +1,32 @@ +{ + "name": "purgecss-with-wordpress", + "version": "2.1.0", + "description": "PurgeCSS with wordpress", + "author": "Ffloriel", + "homepage": "https://purgecss.com", + "keywords": [ + "wordpress", + "optimize", + "optimization", + "remove", + "unused", + "css", + "html", + "rules", + "purge", + "uncss", + "purify" + ], + "license": "MIT", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/FullHuman/purgecss.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/FullHuman/purgecss/issues" + } +} diff --git a/packages/purgecss/package.json b/packages/purgecss/package.json index 444ebbb8..cc898f9a 100644 --- a/packages/purgecss/package.json +++ b/packages/purgecss/package.json @@ -1,8 +1,8 @@ { "name": "purgecss", - "version": "2.0.6", + "version": "2.1.0", "description": "Remove unused css selectors", - "author": "Ffloriel ", + "author": "Ffloriel", "homepage": "https://purgecss.com", "keywords": [ "optimize", @@ -41,7 +41,7 @@ "dependencies": { "commander": "^4.0.0", "glob": "^7.0.0", - "postcss": "7.0.26", + "postcss": "7.0.27", "postcss-selector-parser": "^6.0.2" }, "devDependencies": { diff --git a/packages/purgecss/src/index.ts b/packages/purgecss/src/index.ts index ecc8f18e..e3b5bfe8 100644 --- a/packages/purgecss/src/index.ts +++ b/packages/purgecss/src/index.ts @@ -63,11 +63,11 @@ export async function setOptions( * @param content content (e.g. html file) * @param extractor PurgeCSS extractor used to extract the selectors */ -function extractSelectors( +async function extractSelectors( content: string, extractor: ExtractorFunction -): ExtractorResultDetailed { - const selectors = extractor(content); +): Promise { + const selectors = await extractor(content); return Array.isArray(selectors) ? { attributes: { @@ -409,7 +409,7 @@ class PurgeCSS { for (const file of filesNames) { const content = await asyncFs.readFile(file, "utf-8"); const extractor = this.getFileExtractor(file, extractors); - const extractedSelectors = extractSelectors(content, extractor); + const extractedSelectors = await extractSelectors(content, extractor); selectors = mergeExtractorSelectors(selectors, extractedSelectors); } } @@ -421,10 +421,10 @@ class PurgeCSS { * @param content Array of content * @param extractors Array of extractors */ - public extractSelectorsFromString( + public async extractSelectorsFromString( content: RawContent[], extractors: Extractors[] - ): ExtractorResultDetailed { + ): Promise { let selectors: ExtractorResultDetailed = { attributes: { names: [], @@ -438,7 +438,7 @@ class PurgeCSS { for (const { raw, extension } of content) { const extractor = this.getFileExtractor(`.${extension}`, extractors); - const extractedSelectors = extractSelectors(raw, extractor); + const extractedSelectors = await extractSelectors(raw, extractor); selectors = mergeExtractorSelectors(selectors, extractedSelectors); } return selectors; @@ -652,7 +652,7 @@ class PurgeCSS { fileFormatContents, extractors ); - const cssRawSelectors = this.extractSelectorsFromString( + const cssRawSelectors = await this.extractSelectorsFromString( rawFormatContents, extractors ); diff --git a/packages/vue-cli-plugin-purgecss/README.md b/packages/vue-cli-plugin-purgecss/README.md new file mode 100644 index 00000000..a0713ab9 --- /dev/null +++ b/packages/vue-cli-plugin-purgecss/README.md @@ -0,0 +1,53 @@ +# vue-cli-plugin-purgecss + +> A [Vue CLI 3 Plugin](https://github.com/vuejs/vue-cli) for installing PurgeCSS + +## Install + +If you haven't yet installed vue-cli 3, first follow the install instructions here: https://github.com/vuejs/vue-cli + +Generate a project using vue-cli 3.0: + +```bash +vue create my-app +``` + +Before installing the PurgeCSS plugin, make sure to commit or stash your changes in case you need to revert the changes. + +To install the PurgeCSS plugin simply navigate to your application folder and add PurgeCSS. + +```bash +cd my-app + +vue add purgecss +``` + +### Usage + +Below are the PurgeCSS options set by this plugin: + +```js +{ + content: [ `./public/**/*.html`, `./src/**/*.vue` ], + defaultExtractor (content) { + const contentWithoutStyleBlocks = content.replace(//gi, '') + return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || [] + }, + whitelist: [], + whitelistPatterns: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/ ], +} +``` + +## Contributing + +Please read [CONTRIBUTING.md](./../../CONTRIBUTING.md) for details on our code of +conduct, and the process for submitting pull requests to us. + +## Versioning + +PurgeCSS use [SemVer](http://semver.org/) for versioning. + +## License + +This project is licensed under the MIT License - see the [LICENSE](./../../LICENSE) file +for details. diff --git a/packages/vue-cli-plugin-purgecss/generator/index.js b/packages/vue-cli-plugin-purgecss/generator/index.js new file mode 100644 index 00000000..8daedbdd --- /dev/null +++ b/packages/vue-cli-plugin-purgecss/generator/index.js @@ -0,0 +1,8 @@ +module.exports = (api, options) => { + api.extendPackage({ + devDependencies: { + '@fullhuman/postcss-purgecss': '^2.1.0' + } + }) + api.render('./templates', options) +} \ No newline at end of file diff --git a/packages/vue-cli-plugin-purgecss/generator/templates/postcss.config.js b/packages/vue-cli-plugin-purgecss/generator/templates/postcss.config.js new file mode 100644 index 00000000..1353779a --- /dev/null +++ b/packages/vue-cli-plugin-purgecss/generator/templates/postcss.config.js @@ -0,0 +1,15 @@ +const IN_PRODUCTION = process.env.NODE_ENV === 'production' + +module.exports = { + plugins: [ + IN_PRODUCTION && require('@fullhuman/postcss-purgecss')({ + content: [ `./public/**/*.html`, `./src/**/*.vue` ], + defaultExtractor (content) { + const contentWithoutStyleBlocks = content.replace(//gi, '') + return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || [] + }, + whitelist: [], + whitelistPatterns: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/ ], + }) + ], +} \ No newline at end of file diff --git a/packages/vue-cli-plugin-purgecss/logo.png b/packages/vue-cli-plugin-purgecss/logo.png new file mode 100644 index 00000000..2417a4b9 Binary files /dev/null and b/packages/vue-cli-plugin-purgecss/logo.png differ diff --git a/packages/vue-cli-plugin-purgecss/package.json b/packages/vue-cli-plugin-purgecss/package.json new file mode 100644 index 00000000..bbb3ad39 --- /dev/null +++ b/packages/vue-cli-plugin-purgecss/package.json @@ -0,0 +1,28 @@ +{ + "name": "@fullhuman/vue-cli-plugin-purgecss", + "version": "2.1.0", + "description": "vue-cli plugin to add PurgeCSS", + "author": "Ffloriel", + "homepage": "https://purgecss.com", + "keywords": [ + "vue-cli", + "vue-cli-3", + "purgecss", + "plugin", + "remove", + "unused", + "css", + "optimization" + ], + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/FullHuman/purgecss.git" + }, + "bugs": { + "url": "https://github.com/FullHuman/purgecss/issues" + } +} diff --git a/scripts/build.ts b/scripts/build.ts index 75b78c95..5332d4b8 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -61,6 +61,17 @@ async function build() { format: 'cjs' }) } + + // grunt plugin + const gruntBundle = await rollup.rollup({ + input: path.resolve(packagesDirectory, './grunt-purgecss/src/index.ts'), + plugins: [typescript({}), terser()], + external: ['purgecss'] + }) + await gruntBundle.write({ + file: path.resolve(packagesDirectory, 'grunt-purgecss', './tasks/purgecss.js'), + format: 'cjs' + }) } ;(async () => {