├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .jshintrc ├── .npmrc ├── AUTHORS ├── CHANGELOG ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE-MIT ├── README.md ├── docs ├── cssmin-examples.md ├── cssmin-options.md └── overview.md ├── package-lock.json ├── package.json ├── tasks └── cssmin.js └── test ├── expected ├── absolute.css ├── inline_import.css ├── no-rebase.css ├── rebase.css └── style.css ├── fixtures ├── inner │ ├── input_inline_import.css │ └── input_inline_import2.css ├── input_inline_import.css ├── input_inline_import2.css ├── input_one.css ├── input_two.css ├── no-rebase.css └── rebase.css └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - "**" 7 | - "!dependabot/**" 8 | pull_request: 9 | workflow_dispatch: 10 | 11 | env: 12 | FORCE_COLOR: 2 13 | 14 | jobs: 15 | run: 16 | name: Node ${{ matrix.node }} on ${{ matrix.os }} 17 | runs-on: ${{ matrix.os }} 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | os: [ubuntu-latest, windows-latest] 23 | node: [14, 16, 18, 20] 24 | 25 | steps: 26 | - name: Clone repository 27 | uses: actions/checkout@v3 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Set up Node.js 32 | uses: actions/setup-node@v3 33 | with: 34 | node-version: ${{ matrix.node }} 35 | 36 | - name: Install npm dependencies 37 | run: npm ci 38 | 39 | - name: Run tests 40 | run: npm test 41 | 42 | # We test multiple Windows shells because of prior stdout buffering issues 43 | # filed against Grunt. https://github.com/joyent/node/issues/3584 44 | - name: Run PowerShell tests 45 | run: "npm test # PowerShell" # Pass comment to PS for easier debugging 46 | shell: powershell 47 | if: startsWith(matrix.os, 'windows') 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | tmp -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "boss": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "eqnull": true, 6 | "immed": true, 7 | "latedef": true, 8 | "newcap": true, 9 | "noarg": true, 10 | "node": true, 11 | "sub": true, 12 | "undef": true, 13 | "unused": true 14 | } 15 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | lockfile-version=2 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Tim Branyen (http://tbranyen.com/) 2 | Chris Talkington (http://christalkington.com/) 3 | Thomas Boyt (http://www.thomasboyt.com/) 4 | Liam Kaufman (http://liamkaufman.com/) 5 | Jörn Zaefferer (http://bassistance.de) 6 | Braden Anderson (http://google.com/profiles/bluej100) 7 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v5.0.0: 2 | date: 2023-05-01 3 | changes: 4 | - Update dependencies. 5 | - Drop Node.js < 14 support. 6 | v4.0.0: 7 | date: 2021-02-15 8 | changes: 9 | - Update all dependencies including clean-css v5.x. 10 | - Drop Node.js < 10 support. 11 | v3.0.0: 12 | date: 2018-09-07 13 | changes: 14 | - Update all dependencies. 15 | - Drop Node.js < 6 support. 16 | v2.2.1: 17 | date: 2017-07-27 18 | changes: 19 | - Fix issue with `relativeTo` for clean-css v4.x. 20 | v2.2.0: 21 | date: 2017-05-10 22 | changes: 23 | - Update clean-css to v4.1.1. 24 | v2.1.0: 25 | date: 2017-04-17 26 | changes: 27 | - Set required Node.js version to >=4 since clean-css 4.x requires that. 28 | v2.0.0: 29 | date: 2017-02-02 30 | changes: 31 | - Update clean-css to v4.0.3. 32 | v1.0.2: 33 | date: 2016-08-31 34 | changes: 35 | - Fix issues for node 6. 36 | v1.0.1: 37 | date: 2016-03-16 38 | changes: 39 | - Downgrade maxmin to support Node.js 0.10. 40 | v1.0.0: 41 | date: 2016-03-04 42 | changes: 43 | - Updated docs. 44 | - Point main to task and removed peerDeps. 45 | - Update clean-css to v3.4.1. 46 | v0.14.0: 47 | date: 2015-09-15 48 | changes: 49 | - Bump to cssmin ~3.4.0. 50 | - Minor test fixes. 51 | v0.13.0: 52 | date: 2015-07-27 53 | changes: 54 | - Bump to cssmin ~3.3.0. 55 | v0.12.3: 56 | date: 2015-05-09 57 | changes: 58 | - Improve reporting of errors and warnings. 59 | - Log out written files and the saved size. 60 | - Fix absolute paths. 61 | v0.12.2: 62 | date: 2015-02-20 63 | changes: 64 | - Set the `rebase` option to `false` by default. 65 | v0.12.0: 66 | date: 2015-02-09 67 | changes: 68 | - Add `sourceMap` option. 69 | v0.11.0: 70 | date: 2014-12-24 71 | changes: 72 | - Bump `clean-css` to 3.0.1. 73 | - Remove `banner` option. 74 | v0.10.0: 75 | date: 2014-06-11 76 | changes: 77 | - Update clean-css v2.2.0. 78 | v0.9.0: 79 | date: 2014-02-01 80 | changes: 81 | - Refactor. Remove grunt-lib-contrib dependency. Backwards-compatibly remove `false` choice from `report`. 82 | v0.8.0: 83 | date: 2014-02-14 84 | changes: 85 | - Update clean-css v2.1.0. 86 | v0.7.0: 87 | date: 2013-11-23 88 | changes: 89 | - Update clean-css v2.0.0. 90 | v0.6.2: 91 | date: 2013-09-14 92 | changes: 93 | - Support relative URLs via clean-css ~1.1.1. 94 | v0.6.1: 95 | date: 2013-05-25 96 | changes: 97 | - Support import in-lining via clean-css ~1.0.4. 98 | v0.6.0: 99 | date: 2013-04-05 100 | changes: 101 | - Update clean-css dependency to ~1.0.0. 102 | v0.5.0: 103 | date: 2013-03-14 104 | changes: 105 | - Support for `report` option (false by default). 106 | v0.4.2: 107 | date: 2013-03-10 108 | changes: 109 | - Add `banner` option. 110 | - Support clean-css `keepSpecialComments`. 111 | v0.4.1: 112 | date: 2013-02-17 113 | changes: 114 | - Update clean-css dependency to ~0.10.0. 115 | v0.4.0: 116 | date: 2013-02-15 117 | changes: 118 | - First official release for Grunt 0.4.0. 119 | v0.4.0rc7: 120 | date: 2013-01-23 121 | changes: 122 | - Updating grunt/gruntplugin dependencies to rc7. 123 | - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. 124 | v0.4.0rc5: 125 | date: 2013-01-09 126 | changes: 127 | - Updating to work with grunt v0.4.0rc5. 128 | - Switching to `this.files` API. 129 | v0.3.2: 130 | date: 2012-11-01 131 | changes: 132 | - Update clean-css dep. 133 | v0.3.1: 134 | date: 2012-10-12 135 | changes: 136 | - Rename grunt-contrib-lib dep to grunt-lib-contrib. 137 | v0.3.0: 138 | date: 2012-09-23 139 | changes: 140 | - Options no longer accepted from global config key. 141 | v0.2.0: 142 | date: 2012-09-10 143 | changes: 144 | - Refactored from grunt-contrib into individual repo. 145 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please see the [Contributing to grunt](https://gruntjs.com/contributing) guide for information on contributing to this project. 2 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | function absolutePath(file) { 4 | return path.join(__dirname, file); 5 | } 6 | module.exports = function (grunt) { 7 | grunt.initConfig({ 8 | jshint: { 9 | all: [ 10 | 'Gruntfile.js', 11 | 'tasks/*.js', 12 | '<%= nodeunit.tests %>' 13 | ], 14 | options: { 15 | jshintrc: '.jshintrc' 16 | } 17 | }, 18 | clean: { 19 | test: ['tmp'] 20 | }, 21 | cssmin: { 22 | options: { 23 | sourceMap: true 24 | }, 25 | absolute: { 26 | files: [{ 27 | src: [ 28 | 'test/fixtures/input_one.css', 29 | 'test/fixtures/input_two.css' 30 | ].map(absolutePath), 31 | dest: absolutePath('tmp/absolute.css') 32 | }] 33 | }, 34 | compress: { 35 | files: { 36 | 'tmp/style.css': [ 37 | 'test/fixtures/input_one.css', 38 | 'test/fixtures/input_two.css' 39 | ] 40 | } 41 | }, 42 | empty: { 43 | files: { 44 | 'tmp/idontexist.css': [ 45 | 'test/fixtures/idontexist.css' 46 | ] 47 | } 48 | }, 49 | inlineImport: { 50 | files: { 51 | 'tmp/inline_import.css': [ 52 | 'test/fixtures/input_inline_import.css', 53 | 'test/fixtures/inner/input_inline_import.css' 54 | ] 55 | } 56 | }, 57 | noRebase: { 58 | files: { 59 | 'tmp/no-rebase.css': [ 60 | 'test/fixtures/no-rebase.css' 61 | ] 62 | } 63 | }, 64 | rebase: { 65 | options: { 66 | rebase: true 67 | }, 68 | files: { 69 | 'tmp/rebase.css': [ 70 | 'test/fixtures/rebase.css' 71 | ] 72 | } 73 | } 74 | }, 75 | nodeunit: { 76 | tests: ['test/test.js'] 77 | } 78 | }); 79 | 80 | grunt.loadTasks('tasks'); 81 | grunt.loadNpmTasks('grunt-contrib-clean'); 82 | grunt.loadNpmTasks('grunt-contrib-jshint'); 83 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 84 | grunt.loadNpmTasks('grunt-contrib-internal'); 85 | 86 | grunt.registerTask('test', [ 87 | 'jshint', 88 | 'clean', 89 | 'cssmin', 90 | 'cssmin', 91 | 'nodeunit' 92 | ]); 93 | 94 | grunt.registerTask('default', [ 95 | 'test', 96 | 'build-contrib' 97 | ]); 98 | }; 99 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Tim Branyen, contributors 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # grunt-contrib-cssmin v4.0.0 [![Build Status](https://github.com/gruntjs/grunt-contrib-cssmin/workflows/Tests/badge.svg)](https://github.com/gruntjs/grunt-contrib-cssmin/actions?workflow=Tests) 2 | 3 | > Minify CSS 4 | 5 | 6 | 7 | ## Getting Started 8 | 9 | If you haven't used [Grunt](https://gruntjs.com/) before, be sure to check out the [Getting Started](https://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](https://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: 10 | 11 | ```shell 12 | npm install grunt-contrib-cssmin --save-dev 13 | ``` 14 | 15 | Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: 16 | 17 | ```js 18 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 19 | ``` 20 | 21 | **Issues with the output should be reported on the clean-css [issue tracker](https://github.com/jakubpawlowicz/clean-css/issues).** 22 | 23 | 24 | 25 | ## Cssmin task 26 | _Run this task with the `grunt cssmin` command._ 27 | 28 | 29 | ### Options 30 | 31 | Options are passed to [clean-css](https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-api). In addition this task defines some extra options: 32 | 33 | 34 | #### report 35 | 36 | Type: `string` 37 | Choices: `'min'`, `'gzip'` 38 | Default: `'min'` 39 | 40 | Report minification result or both minification and gzip results. 41 | This is useful to see exactly how well clean-css is performing but using `'gzip'` will make the task take 5-10x longer to complete. [Example output](https://github.com/sindresorhus/maxmin#readme). 42 | 43 | 44 | #### sourceMap 45 | 46 | Type: `boolean` 47 | Choices: `true`, `false` 48 | Default: `false` 49 | 50 | Enable Source Maps. 51 | 52 | ### Usage 53 | 54 | #### Combine two files into one output file 55 | 56 | ```js 57 | cssmin: { 58 | options: { 59 | mergeIntoShorthands: false, 60 | roundingPrecision: -1 61 | }, 62 | target: { 63 | files: { 64 | 'output.css': ['foo.css', 'bar.css'] 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | #### Minify all contents of a release directory and add a `.min.css` extension 71 | 72 | ```js 73 | cssmin: { 74 | target: { 75 | files: [{ 76 | expand: true, 77 | cwd: 'release/css', 78 | src: ['*.css', '!*.min.css'], 79 | dest: 'release/css', 80 | ext: '.min.css' 81 | }] 82 | } 83 | } 84 | ``` 85 | 86 | 87 | ## Release History 88 | 89 | * 2023-05-01   v5.0.0   Update dependencies. Drop Node.js < 14 support. 90 | * 2021-02-15   v4.0.0   Update all dependencies including clean-css v5.x. Drop Node.js < 10 support. 91 | * 2018-09-07   v3.0.0   Update all dependencies. Drop Node.js < 6 support. 92 | * 2017-07-27   v2.2.1   Fix issue with `relativeTo` for clean-css v4.x. 93 | * 2017-05-10   v2.2.0   Update clean-css to v4.1.1. 94 | * 2017-04-17   v2.1.0   Set required Node.js version to >=4 since clean-css 4.x requires that. 95 | * 2017-02-02   v2.0.0   Update clean-css to v4.0.3. 96 | * 2016-08-31   v1.0.2   Fix issues for node 6. 97 | * 2016-03-16   v1.0.1   Downgrade maxmin to support Node.js 0.10. 98 | * 2016-03-04   v1.0.0   Updated docs. Point main to task and removed peerDeps. Update clean-css to v3.4.1. 99 | * 2015-09-15   v0.14.0   Bump to cssmin ~3.4.0. Minor test fixes. 100 | * 2015-07-27   v0.13.0   Bump to cssmin ~3.3.0. 101 | * 2015-05-09   v0.12.3   Improve reporting of errors and warnings. Log out written files and the saved size. Fix absolute paths. 102 | * 2015-02-20   v0.12.2   Set the `rebase` option to `false` by default. 103 | * 2015-02-09   v0.12.0   Add `sourceMap` option. 104 | * 2014-12-24   v0.11.0   Bump `clean-css` to 3.0.1. Remove `banner` option. 105 | * 2014-06-11   v0.10.0   Update clean-css v2.2.0. 106 | * 2014-02-01   v0.9.0   Refactor. Remove grunt-lib-contrib dependency. Backwards-compatibly remove `false` choice from `report`. 107 | * 2014-02-14   v0.8.0   Update clean-css v2.1.0. 108 | * 2013-11-23   v0.7.0   Update clean-css v2.0.0. 109 | * 2013-09-14   v0.6.2   Support relative URLs via clean-css ~1.1.1. 110 | * 2013-05-25   v0.6.1   Support import in-lining via clean-css ~1.0.4. 111 | * 2013-04-05   v0.6.0   Update clean-css dependency to ~1.0.0. 112 | * 2013-03-14   v0.5.0   Support for `report` option (false by default). 113 | * 2013-03-10   v0.4.2   Add `banner` option. Support clean-css `keepSpecialComments`. 114 | * 2013-02-17   v0.4.1   Update clean-css dependency to ~0.10.0. 115 | * 2013-02-15   v0.4.0   First official release for Grunt 0.4.0. 116 | * 2013-01-23   v0.4.0rc7   Updating grunt/gruntplugin dependencies to rc7. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. 117 | * 2013-01-09   v0.4.0rc5   Updating to work with grunt v0.4.0rc5. Switching to `this.files` API. 118 | * 2012-11-01   v0.3.2   Update clean-css dep. 119 | * 2012-10-12   v0.3.1   Rename grunt-contrib-lib dep to grunt-lib-contrib. 120 | * 2012-09-23   v0.3.0   Options no longer accepted from global config key. 121 | * 2012-09-10   v0.2.0   Refactored from grunt-contrib into individual repo. 122 | 123 | --- 124 | 125 | Task submitted by [Tim Branyen](http://tbranyen.com/) 126 | 127 | *This is a generated file.* 128 | -------------------------------------------------------------------------------- /docs/cssmin-examples.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ## Combine two files into one output file 4 | 5 | ```js 6 | cssmin: { 7 | options: { 8 | mergeIntoShorthands: false, 9 | roundingPrecision: -1 10 | }, 11 | target: { 12 | files: { 13 | 'output.css': ['foo.css', 'bar.css'] 14 | } 15 | } 16 | } 17 | ``` 18 | 19 | ## Minify all contents of a release directory and add a `.min.css` extension 20 | 21 | ```js 22 | cssmin: { 23 | target: { 24 | files: [{ 25 | expand: true, 26 | cwd: 'release/css', 27 | src: ['*.css', '!*.min.css'], 28 | dest: 'release/css', 29 | ext: '.min.css' 30 | }] 31 | } 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/cssmin-options.md: -------------------------------------------------------------------------------- 1 | # Options 2 | 3 | Options are passed to [clean-css](https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-api). In addition this task defines some extra options: 4 | 5 | 6 | ## report 7 | 8 | Type: `string` 9 | Choices: `'min'`, `'gzip'` 10 | Default: `'min'` 11 | 12 | Report minification result or both minification and gzip results. 13 | This is useful to see exactly how well clean-css is performing but using `'gzip'` will make the task take 5-10x longer to complete. [Example output](https://github.com/sindresorhus/maxmin#readme). 14 | 15 | 16 | ## sourceMap 17 | 18 | Type: `boolean` 19 | Choices: `true`, `false` 20 | Default: `false` 21 | 22 | Enable Source Maps. 23 | -------------------------------------------------------------------------------- /docs/overview.md: -------------------------------------------------------------------------------- 1 | **Issues with the output should be reported on the clean-css [issue tracker](https://github.com/jakubpawlowicz/clean-css/issues).** 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-contrib-cssmin", 3 | "description": "Minify CSS", 4 | "version": "5.0.0", 5 | "author": { 6 | "name": "Grunt Team", 7 | "url": "https://gruntjs.com/" 8 | }, 9 | "repository": "gruntjs/grunt-contrib-cssmin", 10 | "license": "MIT", 11 | "engines": { 12 | "node": ">=14.0" 13 | }, 14 | "main": "tasks/cssmin.js", 15 | "scripts": { 16 | "test": "grunt test" 17 | }, 18 | "dependencies": { 19 | "chalk": "^4.1.2", 20 | "clean-css": "^5.3.2", 21 | "maxmin": "^3.0.0" 22 | }, 23 | "devDependencies": { 24 | "grunt": "^1.6.1", 25 | "grunt-contrib-clean": "^2.0.1", 26 | "grunt-contrib-internal": "^8.1.0", 27 | "grunt-contrib-jshint": "^3.2.0", 28 | "grunt-contrib-nodeunit": "^5.0.0" 29 | }, 30 | "keywords": [ 31 | "gruntplugin", 32 | "cssmin", 33 | "css", 34 | "style", 35 | "styles", 36 | "stylesheet", 37 | "minify", 38 | "compress" 39 | ], 40 | "files": [ 41 | "tasks" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /tasks/cssmin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var util = require('util'); 5 | var CleanCSS = require('clean-css'); 6 | var chalk = require('chalk'); 7 | var maxmin = require('maxmin'); 8 | 9 | module.exports = function (grunt) { 10 | var getAvailableFiles = function (filesArray) { 11 | return filesArray.filter(function (filepath) { 12 | if (!grunt.file.exists(filepath)) { 13 | grunt.log.warn('Source file ' + chalk.cyan(filepath) + ' not found'); 14 | return false; 15 | } 16 | return true; 17 | }); 18 | }; 19 | 20 | grunt.registerMultiTask('cssmin', 'Minify CSS', function () { 21 | var created = { 22 | maps: 0, 23 | files: 0 24 | }; 25 | var size = { 26 | before: 0, 27 | after: 0 28 | }; 29 | 30 | this.files.forEach(function (file) { 31 | var options = this.options({ 32 | report: 'min', 33 | sourceMap: false 34 | }); 35 | 36 | var availableFiles = getAvailableFiles(file.src); 37 | var compiled = ''; 38 | 39 | if (Boolean(options.rebase)) { 40 | options.rebaseTo = path.dirname(file.dest); 41 | } 42 | 43 | try { 44 | compiled = new CleanCSS(options).minify(availableFiles); 45 | 46 | if (compiled.errors.length) { 47 | grunt.warn(compiled.errors.toString()); 48 | return; 49 | } 50 | 51 | if (compiled.warnings.length) { 52 | grunt.log.error(compiled.warnings.toString()); 53 | } 54 | 55 | if (options.debug) { 56 | grunt.log.writeln(util.format(compiled.stats)); 57 | } 58 | } catch (err) { 59 | grunt.log.error(err); 60 | grunt.warn('CSS minification failed at ' + availableFiles + '.'); 61 | } 62 | 63 | var compiledCssString = compiled.styles; 64 | 65 | var unCompiledCssString = availableFiles.map(function (file) { 66 | return grunt.file.read(file); 67 | }).join(''); 68 | 69 | size.before += unCompiledCssString.length; 70 | 71 | if (options.sourceMap) { 72 | compiledCssString += '\n' + '/*# sourceMappingURL=' + path.basename(file.dest) + '.map */'; 73 | grunt.file.write(file.dest + '.map', compiled.sourceMap.toString()); 74 | created.maps++; 75 | grunt.verbose.writeln('File ' + chalk.cyan(file.dest + '.map') + ' created'); 76 | } 77 | 78 | grunt.file.write(file.dest, compiledCssString); 79 | created.files++; 80 | size.after += compiledCssString.length; 81 | grunt.verbose.writeln('File ' + chalk.cyan(file.dest) + ' created ' + chalk.dim(maxmin(unCompiledCssString, compiledCssString, options.report === 'gzip'))); 82 | 83 | }, this); 84 | 85 | if (created.maps > 0) { 86 | grunt.log.ok(created.maps + ' source' + grunt.util.pluralize(this.files.length, 'map/maps') + ' created.'); 87 | } 88 | 89 | if (created.files > 0) { 90 | grunt.log.ok(created.files + ' ' + grunt.util.pluralize(this.files.length, 'file/files') + ' created. ' + chalk.dim(maxmin(size.before, size.after))); 91 | } else { 92 | grunt.log.warn('No files created.'); 93 | } 94 | }); 95 | }; 96 | -------------------------------------------------------------------------------- /test/expected/absolute.css: -------------------------------------------------------------------------------- 1 | body{margin:0;font-size:18px}a{color:#00f}h1{font-size:48px;font-weight:700} 2 | /*# sourceMappingURL=absolute.css.map */ -------------------------------------------------------------------------------- /test/expected/inline_import.css: -------------------------------------------------------------------------------- 1 | body{color:#00f}body{background-color:red}p{color:#0f0}p{background-color:#f0f} 2 | /*# sourceMappingURL=inline_import.css.map */ -------------------------------------------------------------------------------- /test/expected/no-rebase.css: -------------------------------------------------------------------------------- 1 | body{background:url('test.jpg')}/*# sourceMappingURL=no-rebase.css.map */ 2 | -------------------------------------------------------------------------------- /test/expected/rebase.css: -------------------------------------------------------------------------------- 1 | body{background:url('../test/fixtures/test.jpg')}/*# sourceMappingURL=rebase.css.map */ 2 | -------------------------------------------------------------------------------- /test/expected/style.css: -------------------------------------------------------------------------------- 1 | body{margin:0;font-size:18px}a{color:#00f}h1{font-size:48px;font-weight:700} 2 | /*# sourceMappingURL=style.css.map */ -------------------------------------------------------------------------------- /test/fixtures/inner/input_inline_import.css: -------------------------------------------------------------------------------- 1 | @import url(input_inline_import2.css); 2 | p { 3 | background-color: #f0f; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/inner/input_inline_import2.css: -------------------------------------------------------------------------------- 1 | p { 2 | color: #0f0; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/input_inline_import.css: -------------------------------------------------------------------------------- 1 | @import url(input_inline_import2.css); 2 | body { 3 | background-color: #f00; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/input_inline_import2.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #00f; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/input_one.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-size: 18px; 4 | } 5 | a { color: #00f; } 6 | -------------------------------------------------------------------------------- /test/fixtures/input_two.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 48px; 3 | font-weight: bold; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/no-rebase.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: url('test.jpg'); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/rebase.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: url('test.jpg'); 3 | } 4 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var grunt = require('grunt'); 4 | 5 | function readFileAndRemoveNewlines(file) { 6 | return grunt.file.read(file).replace(/\r\n/g, '\n').replace(/\n/g, ''); 7 | } 8 | 9 | exports.cssmin = { 10 | main: function(test) { 11 | test.expect(1); 12 | 13 | var expect = readFileAndRemoveNewlines('test/expected/style.css'); 14 | var result = readFileAndRemoveNewlines('tmp/style.css'); 15 | test.equal(expect, result, 'should concat and minify an array of CSS files in order using clean-css'); 16 | 17 | test.done(); 18 | }, 19 | imports: function(test) { 20 | test.expect(1); 21 | 22 | var expect = readFileAndRemoveNewlines('test/expected/inline_import.css'); 23 | var result = readFileAndRemoveNewlines('tmp/inline_import.css'); 24 | test.equal(expect, result, 'should inline @import'); 25 | 26 | test.done(); 27 | }, 28 | absolute: function(test) { 29 | test.expect(1); 30 | 31 | var expect = readFileAndRemoveNewlines('test/expected/absolute.css'); 32 | var result = readFileAndRemoveNewlines('tmp/absolute.css'); 33 | test.equal(expect, result, 'should perform the standard tasks when given absolute paths'); 34 | 35 | test.done(); 36 | }, 37 | noRebase: function(test) { 38 | test.expect(1); 39 | 40 | var expect = readFileAndRemoveNewlines('test/expected/no-rebase.css'); 41 | var result = readFileAndRemoveNewlines('tmp/no-rebase.css'); 42 | test.equal(expect, result, 'should not rebase url imports'); 43 | 44 | test.done(); 45 | }, 46 | rebase: function(test) { 47 | test.expect(1); 48 | 49 | var expect = readFileAndRemoveNewlines('test/expected/rebase.css'); 50 | var result = readFileAndRemoveNewlines('tmp/rebase.css'); 51 | test.equal(expect, result, 'should rebase url imports correctly'); 52 | 53 | test.done(); 54 | } 55 | }; 56 | --------------------------------------------------------------------------------