pax_global_header00006660000000000000000000000064134520724270014520gustar00rootroot0000000000000052 comment=2e5e48333266a7ebe16cf76c612426e93259f1db clean-css-cli-4.3.0/000077500000000000000000000000001345207242700141415ustar00rootroot00000000000000clean-css-cli-4.3.0/.gitignore000066400000000000000000000000161345207242700161260ustar00rootroot00000000000000/node_modules clean-css-cli-4.3.0/.jshintignore000066400000000000000000000000221345207242700166370ustar00rootroot00000000000000.git node_modules clean-css-cli-4.3.0/.jshintrc000066400000000000000000000003411345207242700157640ustar00rootroot00000000000000{ "camelcase": true, "curly": false, "eqeqeq": false, "immed": true, "indent": 2, "noarg": true, "node": true, "plusplus": false, "quotmark": "single", "strict": false, "undef": true, "unused": true } clean-css-cli-4.3.0/.travis.yml000066400000000000000000000001401345207242700162450ustar00rootroot00000000000000sudo: false language: node_js cache: npm node_js: - 4 - 6 - 8 matrix: fast_finish: true clean-css-cli-4.3.0/CONTRIBUTING.md000066400000000000000000000024371345207242700164000ustar00rootroot00000000000000# Bug reports Every piece of software has bugs, and squashing them should always be the priority. If you spotted an incorrect behavior, knowing the following facts will help fixing it: * What's your input CSS and expected output? * What options do you pass to `cleancss`? * What version of clean-css-cli do you use? * What operating system do you use? # Pull requests We love pull requests! To contribute to clean-css first fork, then clone the repo: ```shell git clone git@github.com:your-username/clean-css-cli.git ``` Make sure you have node 4.0+ installed so npm can download all dependencies for you: ```shell npm install ``` Make sure the tests pass: ```shell npm test ``` Then add tests for your change. Check if tests fail. Make your change. Make the tests pass. At the end make sure code styling validation passes: ```shell npm run check ``` Finally push to your fork and [submit a pull request](https://github.com/jakubpawlowicz/clean-css-cli/compare/). At this point you're waiting for a PR review which should not thake more than a day. Some things that will increase the chance that your pull request is accepted: * Write tests. * Write self-documenting code. * Squash commits. * Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). clean-css-cli-4.3.0/History.md000066400000000000000000000116521345207242700161310ustar00rootroot00000000000000[4.3.0 / 2019-04-06](https://github.com/jakubpawlowicz/clean-css-cli/compare/4.2...v4.3.0) ================== * Bumps clean-css dependency to 4.2.1. * Fixed issue [#21](https://github.com/jakubpawlowicz/clean-css-cli/issues/21) - sanity check for printing out help. * Fixed issue [#27](https://github.com/jakubpawlowicz/clean-css-cli/issues/27) - way to provide input source map. [4.2.0 / 2018-08-02](https://github.com/jakubpawlowicz/clean-css-cli/compare/4.1...v4.2.0) ================== * Bumps clean-css dependency to 4.2.0. [4.1.11 / 2018-03-02](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.10...v4.1.11) ================== * Fixed issue [#17](https://github.com/jakubpawlowicz/clean-css-cli/issues/17) - empty `--inline` switch. [4.1.10 / 2017-09-19](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.9...v4.1.10) ================== * Bumps clean-css dependency to 4.1.9. [4.1.9 / 2017-09-03](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.8...v4.1.9) ================== * Bumps clean-css dependency to 4.1.8. [4.1.8 / 2017-09-03](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.7...v4.1.8) ================== * Bumps clean-css dependency to 4.1.7. [4.1.7 / 2017-09-03](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.6...v4.1.7) ================== * Bumps clean-css dependency to 4.1.6. [4.1.6 / 2017-06-29](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.5...v4.1.6) ================== * Bumps clean-css dependency to 4.1.5. [4.1.5 / 2017-06-14](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.4...v4.1.5) ================== * Bumps clean-css dependency to 4.1.4. [4.1.4 / 2017-06-09](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.3...v4.1.4) ================== * Fixed issue [#10](https://github.com/jakubpawlowicz/clean-css-cli/issues/10) - IE/Edge source maps. [4.1.3 / 2017-05-18](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.2...v4.1.3) ================== * Bumps clean-css dependency to 4.1.3. [4.1.2 / 2017-05-10](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.1...v4.1.2) ================== * Bumps clean-css dependency to 4.1.2. [4.1.1 / 2017-05-10](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.1.0...v4.1.1) ================== * Bumps clean-css dependency to 4.1.1. [4.1.0 / 2017-05-08](https://github.com/jakubpawlowicz/clean-css-cli/compare/4.0...v4.1.0) ================== * Bumps clean-css dependency to 4.1.x. * Fixed issue [#1](https://github.com/jakubpawlowicz/clean-css-cli/issues/1) - option to remove inlined files. * Fixed issue [#2](https://github.com/jakubpawlowicz/clean-css-cli/issues/2) - glob matching source paths. * Fixed issue [#5](https://github.com/jakubpawlowicz/clean-css-cli/issues/5) - non-boolean compatibility options. * Fixed issue [#7](https://github.com/jakubpawlowicz/clean-css-cli/issues/7) - using CLI as a module. [4.0.12 / 2017-04-12](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.11...v4.0.12) ================== * Bumps clean-css dependency to 4.0.12. [4.0.11 / 2017-04-11](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.10...v4.0.11) ================== * Bumps clean-css dependency to 4.0.11. [4.0.10 / 2017-03-22](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.9...v4.0.10) ================== * Bumps clean-css dependency to 4.0.10. [4.0.9 / 2017-03-15](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.8...v4.0.9) ================== * Bumps clean-css dependency to 4.0.9. [4.0.8 / 2017-02-22](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.7...v4.0.8) ================== * Bumps clean-css dependency to 4.0.8. [4.0.7 / 2017-02-14](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.6...v4.0.7) ================== * Bumps clean-css dependency to 4.0.7. [4.0.6 / 2017-02-10](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.5...v4.0.6) ================== * Bumps clean-css dependency to 4.0.6. [4.0.5 / 2017-02-07](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.4...v4.0.5) ================== * Bumps clean-css dependency to 4.0.5. [4.0.4 / 2017-02-07](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.3...v4.0.4) ================== * Bumps clean-css dependency to 4.0.4. [4.0.3 / 2017-02-07](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.2...v4.0.3) ================== * Bumps clean-css dependency to 4.0.3. [4.0.2 / 2017-02-07](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.1...v4.0.2) ================== * Bumps clean-css dependency to 4.0.2. [4.0.1 / 2017-02-07](https://github.com/jakubpawlowicz/clean-css-cli/compare/v4.0.0...v4.0.1) ================== * Bumps clean-css dependency to 4.0.1. 4.0.0 / 2017-01-23 ================== * Initial release of separate clean-css-cli. * See [clean-css release notes](https://github.com/jakubpawlowicz/clean-css/blob/master/History.md#400--2017-01-23) for a full list of changes. clean-css-cli-4.3.0/LICENSE000066400000000000000000000020601345207242700151440ustar00rootroot00000000000000MIT License Copyright (c) 2017 Jakub Pawlowicz 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. clean-css-cli-4.3.0/README.md000066400000000000000000000444221345207242700154260ustar00rootroot00000000000000


clean-css logo

[![NPM version](https://img.shields.io/npm/v/clean-css-cli.svg?style=flat)](https://www.npmjs.com/package/clean-css-cli) [![Linux Build Status](https://img.shields.io/travis/jakubpawlowicz/clean-css-cli/master.svg?style=flat&label=Linux%20build)](https://travis-ci.org/jakubpawlowicz/clean-css) [![Dependency Status](https://img.shields.io/david/jakubpawlowicz/clean-css-cli.svg?style=flat)](https://david-dm.org/jakubpawlowicz/clean-css-cli) [![NPM Downloads](https://img.shields.io/npm/dm/clean-css-cli.svg)](https://www.npmjs.com/package/clean-css-cli) [![Twitter](https://img.shields.io/badge/Twitter-@cleancss-blue.svg)](https://twitter.com/cleancss) clean-css-cli is a command-line interface to [clean-css](https://github.com/jakubpawlowicz/clean-css) - fast and efficient CSS optimizer for [Node.js](http://nodejs.org/). Previously a part of clean-css it's a separate package since clean-css 4.0. **Table of Contents** - [Node.js version support](#nodejs-version-support) - [Install](#install) - [Use](#use) * [Important: 4.0 breaking changes](#important-40-breaking-changes) * [What's new in version 4.1](#whats-new-in-version-41) * [CLI options](#cli-options) * [Compatibility modes](#compatibility-modes) * [Formatting options](#formatting-options) * [Inlining options](#inlining-options) * [Optimization levels](#optimization-levels) + [Level 0 optimizations](#level-0-optimizations) + [Level 1 optimizations](#level-1-optimizations) + [Level 2 optimizations](#level-2-optimizations) * [As a module](#as-a-module) - [FAQ](#faq) * [How to optimize multiple files?](#how-to-optimize-multiple-files) * [How to specify a custom rounding precision?](#how-to-specify-a-custom-rounding-precision) * [How to rebase relative image URLs?](#how-to-rebase-relative-image-urls) * [How to apply level 1 & 2 optimizations at the same time?](#how-to-apply-level-1--2-optimizations-at-the-same-time) - [Contributing](#contributing) * [How to get started?](#how-to-get-started) - [License](#license) # Node.js version support clean-css-cli requires Node.js 4.0+ (tested on Linux, OS X, and Windows) # Install ```shell npm install clean-css-cli -g ``` Note: Global install via -g option is recommended unless you want to execute the binary via a relative path, i.e. ./node_modules/.bin/cleancss # Use ```shell cleancss -o one.min.css one.css ``` ## Important: 4.0 breaking changes clean-css-cli 4.0 introduces some breaking changes: * API and CLI interfaces are split, so CLI has been moved to this repository while API stays at [clean-css](https://github.com/jakubpawlowicz/clean-css); * `--root` and `--relativeTo` options are replaced by a single option taken from `--output` path - this means that rebasing URLs and import inlining is much simpler but may not be (YMMV) as powerful as in 3.x; * `--rounding-precision` is disabled by default; * `--rounding-precision` applies to **all** units now, not only `px` as in 3.x; * `--skip-import` and `--skip-import-from` are merged into `--inline` option which defaults to `local`. Remote `@import` rules are **NOT** inlined by default anymore; * renames `--timeout` option to `--inline-timeout`; * remote resources without a protocol, e.g. `//fonts.googleapis.com/css?family=Domine:700`, are not inlined anymore; * changes default Internet Explorer compatibility from 9+ to 10+, to revert the old default use `--compatibility ie9` option; * moves `--rounding-precision`, `--s0`, and `--s1` options to level 1 optimization options, see examples; * moves `--skip-media-merging`, `--skip-restructuring`, `--semantic-merging`, and `--skip-shorthand-compacting` to level 2 optimizations options, see examples below; * level 1 optimizations are the new default, up to 3.x it was level 2; * `--keep-breaks` option is replaced with `--format keep-breaks` to ease transition; * `--skip-aggressive-merging` option is removed as aggressive merging is replaced by smarter override merging. ## What's new in version 4.1 clean-css-cli 4.1 introduces the following changes / features: * [clean-css 4.1](https://github.com/jakubpawlowicz/clean-css#whats-new-in-version-41) as a dependency; * `--remove-inlined-files` option for removing files inlined in or via `@import` statements; * adds glob pattern matching to source paths, see [example](#how-to-optimize-multiple-files); * allows non-boolean compatibility options, e.g. `--compatibility selectors.mergeLimit=512`; * extracts CLI into an importable module, so it can be reused and enhanced if needed; * adds `beforeMinify` callback as a second argument to CLI module, see [example use case](#as-a-module). ## CLI options ```shell -h, --help output usage information -v, --version output the version number -c, --compatibility [ie7|ie8] Force compatibility mode (see Readme for advanced examples) -d, --debug Shows debug information (minification time & compression efficiency) -f, --format Controls output formatting, see examples below -o, --output [output-file] Use [output-file] as output instead of STDOUT -O [optimizations] Turn on level optimizations; optionally accepts a list of fine-grained options, defaults to `1`, see examples below --inline [rules] Enables inlining for listed sources (defaults to `local`) --inline-timeout [seconds] Per connection timeout when fetching remote stylesheets (defaults to 5 seconds) --remove-inlined-files Remove files inlined in or via `@import` statements --skip-rebase Disable URLs rebasing --source-map Enables building input's source map --source-map-inline-sources Enables inlining sources inside source maps --input-source-map [file] Specifies the path of the input source map file ``` ## Compatibility modes There is a certain number of compatibility mode shortcuts, namely: * `--compatibility '*'` (default) - Internet Explorer 10+ compatibility mode * `--compatibility ie9` - Internet Explorer 9+ compatibility mode * `--compatibility ie8` - Internet Explorer 8+ compatibility mode * `--compatibility ie7` - Internet Explorer 7+ compatibility mode Each of these modes is an alias to a [fine grained configuration](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/options/compatibility.js), with the following options available: ```shell cleancss --compatibility '*,-properties.urlQuotes' cleancss --compatibility '*,+properties.ieBangHack,+properties.ieFilters' # [+-]colors.opacity controls `rgba()` / `hsla()` color support; defaults to `on` (+) # [+-]properties.backgroundClipMerging controls background-clip merging into shorthand; defaults to `on` (+) # [+-]properties.backgroundOriginMerging controls background-origin merging into shorthand; defaults to `on` (+) # [+-]properties.backgroundSizeMerging controls background-size merging into shorthand; defaults to `on` (+) # [+-]properties.colors controls color optimizations; defaults to `on` (+) # [+-]properties.ieBangHack controls keeping IE bang hack; defaults to `off` (-) # [+-]properties.ieFilters controls keeping IE `filter` / `-ms-filter`; defaults to `off` (-) # [+-]properties.iePrefixHack controls keeping IE prefix hack; defaults to `off` (-) # [+-]properties.ieSuffixHack controls keeping IE suffix hack; defaults to `off` (-) # [+-]properties.merging controls property merging based on understandability; defaults to `on` (+) # [+-]properties.shorterLengthUnits controls shortening pixel units into `pc`, `pt`, or `in` units; defaults to `off` (-) # [+-]properties.spaceAfterClosingBrace controls keeping space after closing brace - `url() no-repeat` cleancss --compatibility '*,into `url('roperties.no-repeat`; defaults to `on` (+) # [+-]properties.urlQuotes controls keeping quoting inside `url()`; defaults to `off` (-) # [+-]properties.zeroUnitsf units `0` value; defaults to `on` (+) # [+-]selectors.adjacentSpace controls extra space before `nav` element; defaults to `off` (-) # [+-]selectors.ie7Hack controls removal of IE7 selector hacks, e.g. `*+html...`; defaults to `on` (+) # [+-]units.ch controls treating `ch` as a supported unit; defaults to `on` (+) # [+-]units.in controls treating `in` as a supported unit; defaults to `on` (+) # [+-]units.pc controls treating `pc` as a supported unit; defaults to `on` (+) # [+-]units.pt controls treating `pt` as a supported unit; defaults to `on` (+) # [+-]units.rem controls treating `rem` as a supported unit; defaults to `on` (+) # [+-]units.vh controls treating `vh` as a supported unit; defaults to `on` (+) # [+-]units.vm controls treating `vm` as a supported unit; defaults to `on` (+) # [+-]units.vmax controls treating `vmax` as a supported unit; defaults to `on` (+) # [+-]units.vmin controls treating `vmin` as a supported unit; defaults to `on` (+) ``` You can also chain more rules after a shortcut when setting a compatibility: ```shell cleancss --compatibility 'ie9,-colors.opacity,-units.rem' one.css ``` ## Formatting options The `--format` option accept the following options: ```shell cleancss --format beautify one.css cleancss --format keep-breaks one.css cleancss --format 'indentBy:1;indentWith:tab' one.css cleancss --format 'breaks:afterBlockBegins=on;spaces:aroundSelectorRelation=on' one.css # `breaks` controls where to insert breaks # `afterAtRule` controls if a line break comes after an at-rule; e.g. `@charset`; defaults to `off` (alias to `false`) # `afterBlockBegins` controls if a line break comes after a block begins; e.g. `@media`; defaults to `off` # `afterBlockEnds` controls if a line break comes after a block ends, defaults to `off` # `afterComment` controls if a line break comes after a comment; defaults to `off` # `afterProperty` controls if a line break comes after a property; defaults to `off` # `afterRuleBegins` controls if a line break comes after a rule begins; defaults to `off` # `afterRuleEnds` controls if a line break comes after a rule ends; defaults to `off` # `beforeBlockEnds` controls if a line break comes before a block ends; defaults to `off` # `betweenSelectors` controls if a line break comes between selectors; defaults to `off` # `breakWith` controls the new line character, can be `windows` or `unix` (aliased via `crlf` and `lf`); defaults to system one, so former on Windows and latter on Unix # `indentBy` controls number of characters to indent with; defaults to `0` # `indentWith` controls a character to indent with, can be `space` or `tab`; defaults to `space` # `spaces` controls where to insert spaces # `aroundSelectorRelation` controls if spaces come around selector relations; e.g. `div > a`; defaults to `off` # `beforeBlockBegins` controls if a space comes before a block begins; e.g. `.block {`; defaults to `off` # `beforeValue` controls if a space comes before a value; e.g. `width: 1rem`; defaults to `off` # `wrapAt` controls maximum line length; defaults to `off` ``` ## Inlining options `--inline` option whitelists which `@import` rules will be processed, e.g. ```shell cleancss --inline local one.css # default ``` ```shell cleancss --inline all # same as local,remote ``` ```shell cleancss --inline local,mydomain.example.com one.css ``` ```shell cleancss --inline 'local,remote,!fonts.googleapis.com' one.css ``` ## Optimization levels The `--level` option can be either `0`, `1` (default), or `2`, e.g. ```shell cleancss --level 2 one.css ``` or a fine-grained configuration given via a string. Please note that level 1 optimization options are generally safe while level 2 optimizations should be safe for most users. ### Level 0 optimizations Level 0 optimizations simply means "no optimizations". Use it when you'd like to inline imports and / or rebase URLs but skip everything else, e.g. ```shell cleancss -O0 one.css ``` ### Level 1 optimizations Level 1 optimizations (default) operate on single properties only, e.g. can remove units when not required, turn rgb colors to a shorter hex representation, remove comments, etc Here is a full list of available options: ```shell cleancss -O1 one.css cleancss -O1 removeQuotes:off;roundingPrecision:4;specialComments:1 one.css # `cleanupCharsets` controls `@charset` moving to the front of a stylesheet; defaults to `on` # `normalizeUrls` controls URL normalzation; default to `on` # `optimizeBackground` controls `background` property optimizatons; defaults to `on` # `optimizeBorderRadius` controls `border-radius` property optimizatons; defaults to `on` # `optimizeFilter` controls `filter` property optimizatons; defaults to `on` # `optimizeFontWeight` controls `font-weight` property optimizatons; defaults to `on` # `optimizeOutline` controls `outline` property optimizatons; defaults to `on` # `removeEmpty` controls removing empty rules and nested blocks; defaults to `on` (since 4.1.0) # `removeNegativePaddings` controls removing negative paddings; defaults to `on` # `removeQuotes` controls removing quotes when unnecessary; defaults to `on` # `removeWhitespace` controls removing unused whitespace; defaults to `on` # `replaceMultipleZeros` contols removing redundant zeros; defaults to `on` # `replaceTimeUnits` controls replacing time units with shorter values; defaults to `on # `replaceZeroUnits` controls replacing zero values with units; defaults to `on` # `roundingPrecision` rounds pixel values to `N` decimal places; `off` disables rounding; defaults to `off` # `selectorsSortingMethod` denotes selector sorting method; can be `natural` or `standard`; defaults to `standard` # `specialComments` denotes a number of /*! ... */ comments preserved; defaults to `all` # `tidyAtRules` controls at-rules (e.g. `@charset`, `@import`) optimizing; defaults to `on` # `tidyBlockScopes` controls block scopes (e.g. `@media`) optimizing; defaults to `on` # `tidySelectors` controls selectors optimizing; defaults to `on` ``` There is an `all` shortcut for toggling all options at the same time, e.g. ```shell cleancss -O1 'all:off;tidySelectors:on' one.css ``` ### Level 2 optimizations Level 2 optimizations operate at rules or multiple properties level, e.g. can remove duplicate rules, remove properties redefined further down a stylesheet, or restructure rules by moving them around. Please note that if level 2 optimizations are turned on then, unless explicitely disabled, level 1 optimizations are applied as well. Here is a full list of available options: ```shell cleancss -O2 one.css cleancss -O2 mergeMedia:off;restructureRules:off;mergeSemantically:on;mergeIntoShorthands:off one.css # `mergeAdjacentRules` controls adjacent rules merging; defaults to `on` # `mergeIntoShorthands` controls merging properties into shorthands; defaults to `on` # `mergeMedia` controls `@media` merging; defaults to `on` # `mergeNonAdjacentRules` controls non-adjacent rule merging; defaults to `on` # `mergeSemantically` controls semantic merging; defaults to `off` # `overrideProperties` controls property overriding based on understandability; defaults to `on` # `reduceNonAdjacentRules` controls non-adjacent rule reducing; defaults to `on` # `removeDuplicateFontRules` controls duplicate `@font-face` removing; defaults to `on` # `removeDuplicateMediaBlocks` controls duplicate `@media` removing; defaults to `on` # `removeDuplicateRules` controls duplicate rules removing; defaults to `on` # `removeEmpty` controls removing empty rules and nested blocks; defaults to `on` (since 4.1.0) # `removeUnusedAtRules` controls unused at rule removing; defaults to `off` (since 4.1.0) # `restructureRules` controls rule restructuring; defaults to `off` # `skipProperties` controls which properties won\'t be optimized, defaults to empty list which means all will be optimized (since 4.1.0) ``` There is an `all` shortcut for toggling all options at the same time, e.g. ```shell cleancss -O2 'all:off;removeDuplicateRules:on' one.css ``` # As a module clean-css-cli can also be used as a module in a way of enhancing its functionality in a programmatic way, e.g. ```js #!/usr/bin/env node var cleanCssCli = require('clean-css-cli'); return cleanCssCli(process, function beforeMinify(cleanCss) { cleanCss.options.level['1'].transform = function (propertyName, propertyValue) { if (propertyName == 'background-image' && propertyValue.indexOf('../valid/path/to') == -1) { return propertyValue.replace('url(', 'url(../valid/path/to/'); } } }); ``` # FAQ More answers can be found in [clean-css FAQ section](https://github.com/jakubpawlowicz/clean-css#faq). ## How to optimize multiple files? It can be done by passing in paths to multiple files, e.g. ```shell cleancss -o merged.min.css one.css two.css three.css ``` Since version 4.1.0 it can also be done using glob pattern matching, e.g. ```shell cleancss -o merged.min.css *.css ``` ## How to specify a custom rounding precision? The level 1 `roundingPrecision` optimization option accept a string with per-unit rounding precision settings, e.g. ```shell cleancss -O1 roundingPrecision:all=3,px=5 ``` which sets all units rounding precision to 3 digits except `px` unit precision of 5 digits. ## How to rebase relative image URLs? clean-css-cli will handle it automatically for you when full paths to input files are passed in and `--output` option is used, e.g ```css /*! one.css */ a { background:url(image.png) } ``` ```shell cleancss -o build/one.min.css one.css ``` ```css /*! build/one.min.css */ a{background:url(../image.png)} ``` ## How to apply level 1 & 2 optimizations at the same time? Using `-O` option twice and specifying optimization options in each, e.g. ```shell cleancss -O1 all:on,normalizeUrls:off -O2 restructureRules:on one.css ``` will apply level 1 optimizations, except url normalization, and default level 2 optimizations with rule restructuring. # Contributing See [CONTRIBUTING.md](https://github.com/jakubpawlowicz/clean-css-cli/blob/master/CONTRIBUTING.md). ## How to get started? First clone the sources: ```shell git clone git@github.com:jakubpawlowicz/clean-css-cli.git ``` then install dependencies: ```shell cd clean-css-cli npm install ``` then use any of the following commands to verify your copy: ```shell npm run check # to lint JS sources with [JSHint](https://github.com/jshint/jshint/) npm test # to run all tests ``` # License clean-css-cli is released under the [MIT License](https://github.com/jakubpawlowicz/clean-css-cli/blob/master/LICENSE). clean-css-cli-4.3.0/bin/000077500000000000000000000000001345207242700147115ustar00rootroot00000000000000clean-css-cli-4.3.0/bin/cleancss000077500000000000000000000001311345207242700164250ustar00rootroot00000000000000#!/usr/bin/env node var cleanCssCli = require('../index'); return cleanCssCli(process); clean-css-cli-4.3.0/index.js000066400000000000000000000356141345207242700156170ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var CleanCSS = require('clean-css'); var commands = require('commander'); var glob = require('glob'); var COMPATIBILITY_PATTERN = /([\w\.]+)=(\w+)/g; var lineBreak = require('os').EOL; function cli(process, beforeMinifyCallback) { var packageConfig = fs.readFileSync(path.join(__dirname, 'package.json')); var buildVersion = JSON.parse(packageConfig).version; var fromStdin; var debugMode; var removeInlinedFiles; var options; var stdin; var data; beforeMinifyCallback = beforeMinifyCallback || Function.prototype; // Specify commander options to parse command line params correctly commands .version(buildVersion, '-v, --version') .usage('[options] ') .option('-c, --compatibility [ie7|ie8]', 'Force compatibility mode (see Readme for advanced examples)') .option('-d, --debug', 'Shows debug information (minification time & compression efficiency)') .option('-f, --format ', 'Controls output formatting, see examples below') .option('-o, --output [output-file]', 'Use [output-file] as output instead of STDOUT') .option('-O [optimizations]', 'Turn on level optimizations; optionally accepts a list of fine-grained options, defaults to `1`, see examples below', function (val) { return Math.abs(parseInt(val)); }) .option('--inline [rules]', 'Enables inlining for listed sources (defaults to `local`)') .option('--inline-timeout [seconds]', 'Per connection timeout when fetching remote stylesheets (defaults to 5 seconds)', parseFloat) .option('--remove-inlined-files', 'Remove files inlined in or via `@import` statements') .option('--skip-rebase', 'Disable URLs rebasing') .option('--source-map', 'Enables building input\'s source map') .option('--source-map-inline-sources', 'Enables inlining sources inside source maps') .option('--input-source-map [file]', 'Specifies the path of the input source map file'); commands.on('--help', function () { console.log(' Examples:\n'); console.log(' %> cleancss one.css'); console.log(' %> cleancss -o one-min.css one.css'); console.log(' %> cleancss -o merged-and-minified.css one.css two.css three.css'); console.log(' %> cleancss one.css two.css three.css | gzip -9 -c > merged-minified-and-gzipped.css.gz'); console.log(''); console.log(' Formatting options:'); console.log(' %> cleancss --format beautify one.css'); console.log(' %> cleancss --format keep-breaks one.css'); console.log(' %> cleancss --format \'indentBy:1;indentWith:tab\' one.css'); console.log(' %> cleancss --format \'breaks:afterBlockBegins=on;spaces:aroundSelectorRelation=on\' one.css'); console.log(' %> # `breaks` controls where to insert breaks'); console.log(' %> # `afterAtRule` controls if a line break comes after an at-rule; e.g. `@charset`; defaults to `off` (alias to `false`)'); console.log(' %> # `afterBlockBegins` controls if a line break comes after a block begins; e.g. `@media`; defaults to `off`'); console.log(' %> # `afterBlockEnds` controls if a line break comes after a block ends, defaults to `off`'); console.log(' %> # `afterComment` controls if a line break comes after a comment; defaults to `off`'); console.log(' %> # `afterProperty` controls if a line break comes after a property; defaults to `off`'); console.log(' %> # `afterRuleBegins` controls if a line break comes after a rule begins; defaults to `off`'); console.log(' %> # `afterRuleEnds` controls if a line break comes after a rule ends; defaults to `off`'); console.log(' %> # `beforeBlockEnds` controls if a line break comes before a block ends; defaults to `off`'); console.log(' %> # `betweenSelectors` controls if a line break comes between selectors; defaults to `off`'); console.log(' %> # `indentBy` controls number of characters to indent with; defaults to `0`'); console.log(' %> # `indentWith` controls a character to indent with, can be `space` or `tab`; defaults to `space`'); console.log(' %> # `spaces` controls where to insert spaces'); console.log(' %> # `aroundSelectorRelation` controls if spaces come around selector relations; e.g. `div > a`; defaults to `off`'); console.log(' %> # `beforeBlockBegins` controls if a space comes before a block begins; e.g. `.block {`; defaults to `off`'); console.log(' %> # `beforeValue` controls if a space comes before a value; e.g. `width: 1rem`; defaults to `off`'); console.log(' %> # `wrapAt` controls maximum line length; defaults to `off`'); console.log(''); console.log(' Level 0 optimizations:'); console.log(' %> cleancss -O0 one.css'); console.log(''); console.log(' Level 1 optimizations:'); console.log(' %> cleancss -O1 one.css'); console.log(' %> cleancss -O1 removeQuotes:off;roundingPrecision:4;specialComments:1 one.css'); console.log(' %> cleancss -O1 all:off;specialComments:1 one.css'); console.log(' %> # `cleanupCharsets` controls `@charset` moving to the front of a stylesheet; defaults to `on`'); console.log(' %> # `normalizeUrls` controls URL normalzation; default to `on`'); console.log(' %> # `optimizeBackground` controls `background` property optimizatons; defaults to `on`'); console.log(' %> # `optimizeBorderRadius` controls `border-radius` property optimizatons; defaults to `on`'); console.log(' %> # `optimizeFilter` controls `filter` property optimizatons; defaults to `on`'); console.log(' %> # `optimizeFontWeight` controls `font-weight` property optimizatons; defaults to `on`'); console.log(' %> # `optimizeOutline` controls `outline` property optimizatons; defaults to `on`'); console.log(' %> # `removeEmpty` controls removing empty rules and nested blocks; defaults to `on` (since 4.1.0)'); console.log(' %> # `removeNegativePaddings` controls removing negative paddings; defaults to `on`'); console.log(' %> # `removeQuotes` controls removing quotes when unnecessary; defaults to `on`'); console.log(' %> # `removeWhitespace` controls removing unused whitespace; defaults to `on`'); console.log(' %> # `replaceMultipleZeros` contols removing redundant zeros; defaults to `on`'); console.log(' %> # `replaceTimeUnits` controls replacing time units with shorter values; defaults to `on'); console.log(' %> # `replaceZeroUnits` controls replacing zero values with units; defaults to `on`'); console.log(' %> # `roundingPrecision` rounds pixel values to `N` decimal places; `off` disables rounding; defaults to `off`'); console.log(' %> # `selectorsSortingMethod` denotes selector sorting method; can be `natural` or `standard`; defaults to `standard`'); console.log(' %> # `specialComments` denotes a number of /*! ... */ comments preserved; defaults to `all`'); console.log(' %> # `tidyAtRules` controls at-rules (e.g. `@charset`, `@import`) optimizing; defaults to `on`'); console.log(' %> # `tidyBlockScopes` controls block scopes (e.g. `@media`) optimizing; defaults to `on`'); console.log(' %> # `tidySelectors` controls selectors optimizing; defaults to `on`'); console.log(''); console.log(' Level 2 optimizations:'); console.log(' %> cleancss -O2 one.css'); console.log(' %> cleancss -O2 mergeMedia:off;restructureRules:off;mergeSemantically:on;mergeIntoShorthands:off one.css'); console.log(' %> cleancss -O2 all:off;removeDuplicateRules:on one.css'); console.log(' %> # `mergeAdjacentRules` controls adjacent rules merging; defaults to `on`'); console.log(' %> # `mergeIntoShorthands` controls merging properties into shorthands; defaults to `on`'); console.log(' %> # `mergeMedia` controls `@media` merging; defaults to `on`'); console.log(' %> # `mergeNonAdjacentRules` controls non-adjacent rule merging; defaults to `on`'); console.log(' %> # `mergeSemantically` controls semantic merging; defaults to `off`'); console.log(' %> # `overrideProperties` controls property overriding based on understandability; defaults to `on`'); console.log(' %> # `reduceNonAdjacentRules` controls non-adjacent rule reducing; defaults to `on`'); console.log(' %> # `removeDuplicateFontRules` controls duplicate `@font-face` removing; defaults to `on`'); console.log(' %> # `removeDuplicateMediaBlocks` controls duplicate `@media` removing; defaults to `on`'); console.log(' %> # `removeDuplicateRules` controls duplicate rules removing; defaults to `on`'); console.log(' %> # `removeEmpty` controls removing empty rules and nested blocks; defaults to `on` (since 4.1.0)'); console.log(' %> # `removeUnusedAtRules` controls unused at rule removing; defaults to `off` (since 4.1.0)'); console.log(' %> # `restructureRules` controls rule restructuring; defaults to `off`'); console.log(' %> # `skipProperties` controls which properties won\'t be optimized, defaults to empty list which means all will be optimized (since 4.1.0)'); process.exit(); }); commands.parse(process.argv); if (commands.rawArgs.indexOf('-O0') > -1) { commands.O0 = true; } if (commands.rawArgs.indexOf('-O1') > -1) { commands.O1 = findArgumentTo('-O1', commands.rawArgs, commands.args); } if (commands.rawArgs.indexOf('-O2') > -1) { commands.O2 = findArgumentTo('-O2', commands.rawArgs, commands.args); } // If no sensible data passed in just print help and exit if (commands.args.length === 0) { fromStdin = !process.env.__DIRECT__ && !process.stdin.isTTY; if (!fromStdin) { commands.outputHelp(); return 0; } } // Now coerce commands into CleanCSS configuration... debugMode = commands.debug; removeInlinedFiles = commands.removeInlinedFiles; options = { compatibility: commands.compatibility, format: commands.format, inline: typeof commands.inline == 'string' ? commands.inline : 'local', inlineTimeout: commands.inlineTimeout * 1000, level: commands.O0 || commands.O1 || commands.O2 ? { '0': commands.O0, '1': commands.O1, '2': commands.O2 } : undefined, output: commands.output, rebase: commands.skipRebase ? false : true, rebaseTo: ('output' in commands) && commands.output.length > 0 ? path.dirname(path.resolve(commands.output)) : process.cwd(), sourceMap: commands.sourceMap, sourceMapInlineSources: commands.sourceMapInlineSources }; if (commands.inputSourceMap && !options.sourceMap) { options.sourceMap = true; } if (options.sourceMap && !options.output) { outputFeedback(['Source maps will not be built because you have not specified an output file.'], true); options.sourceMap = false; } var configurations = { beforeMinifyCallback: beforeMinifyCallback, debugMode: debugMode, removeInlinedFiles: removeInlinedFiles, inputSourceMap: commands.inputSourceMap }; // ... and do the magic! if (commands.args.length > 0) { minify(process, options, configurations, expandGlobs(commands.args)); } else { stdin = process.openStdin(); stdin.setEncoding('utf-8'); data = ''; stdin.on('data', function (chunk) { data += chunk; }); stdin.on('end', function () { minify(process, options, configurations, data); }); } } function findArgumentTo(option, rawArgs, args) { var value = true; var optionAt = rawArgs.indexOf(option); var nextOption = rawArgs[optionAt + 1]; var looksLikePath; var asArgumentAt; if (!nextOption) { return value; } looksLikePath = nextOption.indexOf('.css') > -1 || /\//.test(nextOption) || /\\[^\-]/.test(nextOption) || /^https?:\/\//.test(nextOption); asArgumentAt = args.indexOf(nextOption); if (!looksLikePath) { value = nextOption; } if (!looksLikePath && asArgumentAt > -1) { args.splice(asArgumentAt, 1); } return value; } function expandGlobs(paths) { return paths.reduce(function (accumulator, path) { return accumulator.concat(glob.sync(path, { nodir: true, nonull: true})); }, []); } function minify(process, options, configurations, data) { var cleanCss = new CleanCSS(options); applyNonBooleanCompatibilityFlags(cleanCss, options.compatibility); configurations.beforeMinifyCallback(cleanCss); cleanCss.minify(data, getSourceMapContent(configurations.inputSourceMap), function (errors, minified) { var mapFilename; if (configurations.debugMode) { console.error('Original: %d bytes', minified.stats.originalSize); console.error('Minified: %d bytes', minified.stats.minifiedSize); console.error('Efficiency: %d%', ~~(minified.stats.efficiency * 10000) / 100.0); console.error('Time spent: %dms', minified.stats.timeSpent); if (minified.inlinedStylesheets.length > 0) { console.error('Inlined stylesheets:'); minified.inlinedStylesheets.forEach(function (uri) { console.error('- %s', uri); }); } } outputFeedback(minified.errors, true); outputFeedback(minified.warnings); if (minified.errors.length > 0) { process.exit(1); } if (configurations.removeInlinedFiles) { minified.inlinedStylesheets.forEach(fs.unlinkSync); } if (minified.sourceMap) { mapFilename = path.basename(options.output) + '.map'; output(process, options, minified.styles + lineBreak + '/*# sourceMappingURL=' + mapFilename + ' */'); outputMap(options, minified.sourceMap, mapFilename); } else { output(process, options, minified.styles); } }); } function applyNonBooleanCompatibilityFlags(cleanCss, compatibility) { var match; var scope; var parts; var i, l; if (!compatibility) { return; } patternLoop: while ((match = COMPATIBILITY_PATTERN.exec(compatibility)) !== null) { scope = cleanCss.options.compatibility; parts = match[1].split('.'); for (i = 0, l = parts.length - 1; i < l; i++) { scope = scope[parts[i]]; if (!scope) { continue patternLoop; } } scope[parts.pop()] = match[2]; } } function outputFeedback(messages, isError) { var prefix = isError ? '\x1B[31mERROR\x1B[39m:' : 'WARNING:'; messages.forEach(function (message) { console.error('%s %s', prefix, message); }); } function getSourceMapContent(sourceMapPath) { if (!sourceMapPath || !fs.existsSync(sourceMapPath)) { return null; } var content = null; try { content = fs.readFileSync(sourceMapPath).toString(); } catch (e) { console.error('Failed to read the input source map file.'); } return content; } function output(process, options, minified) { if (options.output) { fs.writeFileSync(options.output, minified, 'utf8'); } else { process.stdout.write(minified); } } function outputMap(options, sourceMap, mapFilename) { var mapPath = path.join(path.dirname(options.output), mapFilename); fs.writeFileSync(mapPath, sourceMap.toString(), 'utf-8'); } module.exports = cli; clean-css-cli-4.3.0/package-lock.json000066400000000000000000000270161345207242700173630ustar00rootroot00000000000000{ "name": "clean-css-cli", "version": "4.3.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "clean-css": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "requires": { "source-map": "~0.6.0" }, "dependencies": { "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, "cli": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", "dev": true, "requires": { "exit": "0.1.2", "glob": "^7.1.1" } }, "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { "date-now": "^0.1.4" } }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" } }, "diff": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz", "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=", "dev": true }, "dom-serializer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "dev": true, "requires": { "domelementtype": "^1.3.0", "entities": "^1.1.1" }, "dependencies": { "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true } } }, "domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, "domhandler": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", "dev": true, "requires": { "domelementtype": "1" } }, "domutils": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "dev": true, "requires": { "dom-serializer": "0", "domelementtype": "1" } }, "entities": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", "dev": true }, "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", "dev": true }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", "dev": true }, "follow-redirects": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, "requires": { "debug": "^3.2.6" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "htmlparser2": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", "dev": true, "requires": { "domelementtype": "1", "domhandler": "2.3", "domutils": "1.5", "entities": "1.0", "readable-stream": "1.1" } }, "http-proxy": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", "dev": true, "requires": { "eventemitter3": "^3.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "jshint": { "version": "2.10.2", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz", "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==", "dev": true, "requires": { "cli": "~1.0.0", "console-browserify": "1.1.x", "exit": "0.1.x", "htmlparser2": "3.8.x", "lodash": "~4.17.11", "minimatch": "~3.0.2", "shelljs": "0.3.x", "strip-json-comments": "1.0.x" } }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" } }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, "shelljs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", "dev": true }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "strip-json-comments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", "dev": true }, "vows": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.2.tgz", "integrity": "sha1-aR95qybM3oC6cm3en+yOc9a88us=", "dev": true, "requires": { "diff": "~1.0.8", "eyes": "~0.1.6", "glob": "^7.1.2" } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } clean-css-cli-4.3.0/package.json000066400000000000000000000021151345207242700164260ustar00rootroot00000000000000{ "name": "clean-css-cli", "version": "4.3.0", "description": "A command-line interface to clean-css CSS optimization library", "scripts": { "check": "jshint ./bin/cleancss .", "prepublish": "npm run check", "test": "vows" }, "repository": { "type": "git", "url": "git+https://github.com/jakubpawlowicz/clean-css-cli.git" }, "keywords": [ "css", "optimizer", "minifier" ], "bin": { "cleancss": "./bin/cleancss" }, "author": "Jakub Pawlowicz (http://twitter.com/jakubpawlowicz)", "license": "MIT", "bugs": { "url": "https://github.com/jakubpawlowicz/clean-css-cli/issues" }, "main": "index.js", "files": [ "bin", "History.md", "index.js", "LICENSE" ], "homepage": "https://github.com/jakubpawlowicz/clean-css-cli#readme", "dependencies": { "clean-css": "^4.2.1", "commander": "2.x", "glob": "7.x" }, "devDependencies": { "http-proxy": "1.x", "jshint": "2.x", "source-map": "0.5.x", "vows": "0.8.x" }, "engines": { "node": ">= 4.0" } } clean-css-cli-4.3.0/test/000077500000000000000000000000001345207242700151205ustar00rootroot00000000000000clean-css-cli-4.3.0/test/binary-test.js000066400000000000000000000704371345207242700177320ustar00rootroot00000000000000var assert = require('assert'); var exec = require('child_process').exec; var fs = require('fs'); var http = require('http'); var path = require('path'); var url = require('url'); var httpProxy = require('http-proxy'); var lineBreak = require('os').EOL; var SourceMapConsumer = require('source-map').SourceMapConsumer; var vows = require('vows'); function binaryContext(options, context) { context.topic = function () { // We add __DIRECT__=1 to force binary into 'non-piped' mode exec('__DIRECT__=1 ./bin/cleancss ' + options, this.callback); }; return context; } function pipedContext(css, options, context) { context.topic = function () { exec('echo "' + css + '" | ./bin/cleancss ' + options, this.callback); }; return context; } function deleteFile(filename) { exec('rm ' + filename); } vows.describe('cleancss') .addBatch({ 'no options': binaryContext('', { 'should output help': function (stdout) { assert.match(stdout, /Usage[:]/); } }) }) .addBatch({ 'help': binaryContext('-h', { 'should output help': function (error, stdout) { assert.match(stdout, /Usage[:]/); }, 'should output one file example': function (error, stdout) { assert.include(stdout, 'cleancss -o one-min.css one.css'); }, 'should output multiple files example': function (error, stdout) { assert.include(stdout, 'cleancss -o merged-and-minified.css one.css two.css three.css'); }, 'should output gzipping multiple files example': function (error, stdout) { assert.include(stdout, 'cleancss one.css two.css three.css | gzip -9 -c > merged-minified-and-gzipped.css.gz'); } }) }) .addBatch({ 'version': binaryContext('-v', { 'should output help': function (error, stdout) { var version = JSON.parse(fs.readFileSync('./package.json', 'utf-8')).version; assert.equal(stdout, version + '\n'); } }) }) .addBatch({ 'stdin': pipedContext('a{color: #f00}', '', { 'should output data': function (error, stdout) { assert.equal(stdout, 'a{color:red}'); } }) }) .addBatch({ 'format': pipedContext('a{color: #f00}', '--format beautify', { 'outputs right styles': function (error, stdout) { assert.equal(stdout, 'a {\n color: red\n}'); } }) }) .addBatch({ 'strip all but first comment': pipedContext('/*!1st*//*! 2nd */a{display:block}', '-O1 specialComments:1', { 'should keep the 2nd comment': function (error, stdout) { assert.equal(stdout, '/*!1st*/a{display:block}'); } }) }) .addBatch({ 'strip all comments': pipedContext('/*!1st*//*! 2nd */a{display:block}', '-O1 specialComments:0', { 'should keep the 2nd comment': function (error, stdout) { assert.equal(stdout, 'a{display:block}'); } }) }) .addBatch({ 'piped with debug info': pipedContext('a{color: #f00;}', '-d', { 'should output content to stdout and debug info to stderr': function (error, stdout, stderr) { assert.equal(stdout, 'a{color:red}'); assert.notEqual(stderr, ''); assert.include(stderr, 'Time spent:'); assert.include(stderr, 'Original: 16 bytes'); assert.include(stderr, 'Minified: 12 bytes'); assert.include(stderr, 'Efficiency: 25%'); } }) }) .addBatch({ 'piped with debug info on inlining': pipedContext('@import url(test/fixtures/imports-min.css);', '-d', { 'should output inlining info': function (error, stdout, stderr) { assert.include(stderr, path.join(process.cwd(), 'test/fixtures/imports-min.css')); } }) }) .addBatch({ 'piped with correct debug info on inlining': pipedContext('@import url(test/fixtures/imports.css);', '-d', { 'should output correct info': function (error, stdout, stderr) { assert.include(stderr, 'Original: 339 bytes'); assert.include(stderr, 'Minified: 86 bytes'); assert.include(stderr, 'Efficiency: 74.63%'); } }) }) .addBatch({ 'to output file with debug info': pipedContext('a{color: #f00;}', '-d -o debug.css', { 'should output nothing to stdout and debug info to stderr': function (error, stdout, stderr) { assert.isEmpty(stdout); assert.notEqual(stderr, ''); assert.include(stderr, 'Time spent:'); assert.include(stderr, 'Original: 16 bytes'); assert.include(stderr, 'Minified: 12 bytes'); assert.include(stderr, 'Efficiency: 25%'); }, 'should output content to file': function () { var minimized = fs.readFileSync('debug.css', 'utf-8'); assert.equal(minimized, 'a{color:red}'); }, teardown: function () { deleteFile('debug.css'); } }) }) .addBatch({ 'skip level 2 optimizations': pipedContext('a{color:red}p{color:red}', '-O1', { 'should do basic optimizations only': function (error, stdout) { assert.equal(stdout, 'a{color:red}p{color:red}'); } }) }) .addBatch({ 'level 1 and 2 optimizations': pipedContext('a{font:16px "Arial"}a{color:red}', '-O1 all:false,removeQuotes:true -O2 all:false', { 'should do basic optimizations only': function (error, stdout) { assert.equal(stdout, 'a{font:16px Arial}a{color:red}'); } }) }) .addBatch({ 'enable restructuring optimizations': pipedContext('div{margin-top:0}.one{margin:0}.two{display:block;margin-top:0}', '-O2 restructureRules:on', { 'should do basic optimizations only': function (error, stdout) { assert.equal(stdout, '.two,div{margin-top:0}.one{margin:0}.two{display:block}'); } }) }) .addBatch({ 'no relative to path': binaryContext('./fixtures/partials-absolute/base.css', { 'should not be able to resolve it fully': function (error, stdout, stderr) { assert.isEmpty(stdout); assert.notEqual(error, null); assert.notEqual(stderr, ''); } }) }) .addBatch({ 'from source': binaryContext('--format keep-breaks -O2 ./test/fixtures/reset.css', { 'should minimize': function (error, stdout) { var minimized = fs.readFileSync('./test/fixtures/reset-min.css', 'utf-8'); assert.equal(stdout, minimized); } }) }) .addBatch({ 'from multiple sources': binaryContext('./test/fixtures/partials/one.css ./test/fixtures/partials/five.css', { 'should minimize all': function (error, stdout) { assert.equal(stdout, '.one{color:red}.five{background:url(data:image/jpeg;base64,/9j/)}'); } }) }) .addBatch({ 'to file': binaryContext('--format keep-breaks -O2 -o ./reset1-min.css ./test/fixtures/reset.css', { 'should give no output': function (error, stdout) { assert.isEmpty(stdout); }, 'should minimize': function () { var preminified = fs.readFileSync('./test/fixtures/reset-min.css', 'utf-8'); var minified = fs.readFileSync('./reset1-min.css', 'utf-8'); assert.equal(minified, preminified); }, teardown: function () { deleteFile('./reset1-min.css'); } }) }) .addBatch({ 'disable @import': binaryContext('--inline none ./test/fixtures/imports.css', { 'should disable the import processing': function (error, stdout) { assert.equal(stdout, '@import url(test/fixtures/partials/one.css);@import url(test/fixtures/partials/two.css);.imports{color:#000}'); } }) }) .addBatch({ 'disable all @import': pipedContext('@import url(http://127.0.0.1/remote.css);@import url(test/fixtures/partials/one.css);', '--inline none', { 'keeps original import rules': function (error, stdout) { assert.equal(stdout, '@import url(http://127.0.0.1/remote.css);@import url(test/fixtures/partials/one.css);'); } }), 'disable remote @import': pipedContext('@import url(http://127.0.0.1/remote.css);@import url(test/fixtures/partials/one.css);', '--inline !remote', { 'keeps remote import rule': function (error, stdout) { assert.equal(stdout, '@import url(http://127.0.0.1/remote.css);.one{color:red}'); } }), 'disable remote @import as default': pipedContext('@import url(http://127.0.0.1/remote.css);@import url(test/fixtures/partials/one.css);', '', { 'keeps remote import rule': function (error, stdout) { assert.equal(stdout, '@import url(http://127.0.0.1/remote.css);.one{color:red}'); } }), 'disable remote @import as default #2': pipedContext('@import url(http://127.0.0.1/remote.css);@import url(test/fixtures/partials/one.css);', '--inline', { 'keeps remote import rule': function (error, stdout) { assert.equal(stdout, '@import url(http://127.0.0.1/remote.css);.one{color:red}'); } }), 'disable remote @import by host': pipedContext('@import url(http://127.0.0.1/remote.css);@import url(test/fixtures/partials/one.css);', '--inline !127.0.0.1', { 'keeps remote import rule': function (error, stdout) { assert.equal(stdout, '@import url(http://127.0.0.1/remote.css);.one{color:red}'); } }) }) .addBatch({ 'relative image paths': { 'no output': binaryContext('./test/fixtures/partials-relative/base.css', { 'should leave paths': function (error, stdout) { assert.equal(stdout, 'a{background:url(test/fixtures/partials/extra/down.gif) 0 0 no-repeat}'); } }), 'output': binaryContext('-o ./base1-min.css ./test/fixtures/partials-relative/base.css', { 'should rewrite path relative to current path': function () { var minimized = fs.readFileSync('./base1-min.css', 'utf-8'); assert.equal(minimized, 'a{background:url(test/fixtures/partials/extra/down.gif) 0 0 no-repeat}'); }, teardown: function () { deleteFile('./base1-min.css'); } }), 'piped with output': pipedContext('a{background:url(test/fixtures/partials/extra/down.gif)}', '-o base3-min.css', { 'should keep paths as they are': function () { var minimized = fs.readFileSync('base3-min.css', 'utf-8'); assert.equal(minimized, 'a{background:url(test/fixtures/partials/extra/down.gif)}'); }, teardown: function () { deleteFile('base3-min.css'); } }) } }) .addBatch({ 'import rebasing': binaryContext('test/fixtures/partials/quoted-svg.css', { 'should keep quoting intact': function (error, stdout) { assert.include(stdout, 'div{background:url("data:image'); assert.include(stdout, 'svg%3E")}'); } }) }) .addBatch({ 'complex import and url rebasing': { 'absolute': binaryContext('./test/fixtures/rebasing/assets/ui.css', { 'should rebase urls correctly': function (error, stdout) { assert.include(stdout, 'url(test/fixtures/rebasing/components/bootstrap/images/glyphs.gif)'); assert.include(stdout, 'url(test/fixtures/rebasing/components/jquery-ui/images/prev.gif)'); assert.include(stdout, 'url(test/fixtures/rebasing/components/jquery-ui/images/next.gif)'); } }), 'relative': binaryContext('-o test/ui.bundled.css ./test/fixtures/rebasing/assets/ui.css', { 'should rebase urls correctly': function () { var minimized = fs.readFileSync('test/ui.bundled.css', 'utf-8'); assert.include(minimized, 'url(fixtures/rebasing/components/bootstrap/images/glyphs.gif)'); assert.include(minimized, 'url(fixtures/rebasing/components/jquery-ui/images/prev.gif)'); assert.include(minimized, 'url(fixtures/rebasing/components/jquery-ui/images/next.gif)'); }, teardown: function () { deleteFile('test/ui.bundled.css'); } }) } }) .addBatch({ 'complex import and skipped url rebasing': { 'absolute': binaryContext('--skip-rebase ./test/fixtures/rebasing/assets/ui.css', { 'should rebase urls correctly': function (error, stdout) { assert.isNull(error); assert.include(stdout, 'url(../images/glyphs.gif)'); assert.include(stdout, 'url(../images/prev.gif)'); assert.include(stdout, 'url(../images/next.gif)'); } }) } }) .addBatch({ 'remote import': { topic: function () { this.server = http.createServer(function (req, res) { res.writeHead(200); res.end('p{font-size:13px}'); }).listen(31991, '127.0.0.1'); this.callback(null); }, 'of a file': binaryContext('http://127.0.0.1:31991/present.css', { succeeds: function (error, stdout) { assert.isNull(error); assert.equal(stdout, 'p{font-size:13px}'); } }), teardown: function () { this.server.close(); } } }) .addBatch({ 'timeout': { topic: function () { var self = this; var source = '@import url(http://localhost:24682/timeout.css);'; this.server = http.createServer(function () { setTimeout(function () {}, 1000); }); this.server.listen('24682', function () { exec('echo "' + source + '" | ./bin/cleancss --inline all --inline-timeout 0.01', self.callback); }); }, 'should raise warning': function (error, stdout, stderr) { assert.include(stderr, 'Broken @import declaration of "http://localhost:24682/timeout.css" - timeout'); }, 'should output empty response': function (error, stdout) { assert.isEmpty(stdout); }, teardown: function () { this.server.close(); } } }) .addBatch({ 'HTTP proxy': { topic: function () { var self = this; this.proxied = false; var proxy = httpProxy.createProxyServer(); this.proxyServer = http.createServer(function (req, res) { self.proxied = true; proxy.web(req, res, { target: 'http://' + url.parse(req.url).host }, function () {}); }); this.proxyServer.listen(8081); this.server = http.createServer(function (req, res) { res.writeHead(200); res.end('a{color:red}'); }); this.server.listen(8080); exec('echo "@import url(http://127.0.0.1:8080/test.css);" | HTTP_PROXY=http://127.0.0.1:8081 ./bin/cleancss --inline all', this.callback); }, 'proxies the connection': function () { assert.isTrue(this.proxied); }, 'gives right output': function (error, stdout) { assert.equal(stdout, 'a{color:red}'); }, teardown: function () { this.proxyServer.close(); this.server.close(); } } }) .addBatch({ 'ie7 compatibility': binaryContext('--format keep-breaks --compatibility ie7 ./test/fixtures/unsupported/selectors-ie7.css', { 'should not transform source': function (error, stdout) { assert.equal(stdout, fs.readFileSync('./test/fixtures/unsupported/selectors-ie7.css', 'utf-8').trim()); } }) }) .addBatch({ 'ie8 compatibility': binaryContext('--format keep-breaks --compatibility ie8 ./test/fixtures/unsupported/selectors-ie8.css', { 'should not transform source': function (error, stdout) { assert.equal(stdout, fs.readFileSync('./test/fixtures/unsupported/selectors-ie8.css', 'utf-8').trim()); } }) }) .addBatch({ 'custom compatibility': pipedContext('a{_color:red}', '--compatibility "+properties.iePrefixHack"', { 'should not transform source': function (error, stdout) { assert.equal(stdout, 'a{_color:red}'); } }) }) .addBatch({ 'custom compatibility non-boolean options': pipedContext('.block-1{color:red}.block-2{color:red}', '--compatibility "selectors.mergeLimit=1,unknown.option=all" -O2', { 'keeps source intact': function (error, stdout) { assert.equal(stdout, '.block-1{color:red}.block-2{color:red}'); } }) }) .addBatch({ 'rounding precision': { 'default': pipedContext('div{width:0.10051px}', '', { 'should keep 2 decimal places': function (error, stdout) { assert.equal(stdout, 'div{width:.10051px}'); } }), 'custom': pipedContext('div{width:0.00051px}', '-O1 roundingPrecision:4', { 'should keep 4 decimal places': function (error, stdout) { assert.equal(stdout, 'div{width:.0005px}'); } }), 'zero': pipedContext('div{width:1.5051px}', '-O1 roundingPrecision:0', { 'should keep 0 decimal places': function (error, stdout) { assert.equal(stdout, 'div{width:2px}'); } }), 'disabled': pipedContext('div{width:0.12345px}', '-O1 roundingPrecision:off', { 'should keep all decimal places': function (error, stdout) { assert.equal(stdout, 'div{width:.12345px}'); } }), 'disabled via -1': pipedContext('div{width:0.12345px}', '-O1 roundingPrecision:\\\\-1', { 'should keep all decimal places': function (error, stdout) { assert.equal(stdout, 'div{width:.12345px}'); } }), 'fine-grained': pipedContext('div{height:10.515rem;width:12.12345px}', '-O1 roundingPrecision:rem=2,px=1', { 'should keep all decimal places': function (error, stdout) { assert.equal(stdout, 'div{height:10.52rem;width:12.1px}'); } }) } }) .addBatch({ 'neighbour merging': { 'of unmergeable properties': pipedContext('a{display:inline-block;color:red;display:-moz-block}', '-O2', { 'gets right result': function (error, stdout) { assert.equal(stdout, 'a{display:inline-block;color:red;display:-moz-block}'); } }), 'of mergeable properties': pipedContext('a{background:red;display:block;background:white}', '-O2', { 'gets right result': function (error, stdout) { assert.equal(stdout, 'a{background:#fff;display:block}'); } }) } }) .addBatch({ '@media merging': pipedContext('@media screen{a{color:red}}@media screen{a{display:block}}', '-O2 mergeMedia:off', { 'gets right result': function (error, stdout) { assert.equal(stdout, '@media screen{a{color:red}}@media screen{a{display:block}}'); } }) }) .addBatch({ 'shorthand merging': { 'of mergeable properties with overriding off': pipedContext('a{background:url(image.png);background-color:red}', '-O2 overrideProperties:off', { 'gets right result': function (error, stdout) { assert.equal(stdout, 'a{background:url(image.png);background-color:red}'); } }) } }) .addBatch({ 'source maps - no target file': binaryContext('--source-map ./test/fixtures/reset.css', { 'warns about source map not being build': function (error, stdout, stderr) { assert.include(stderr, 'Source maps will not be built because you have not specified an output file.'); }, 'does not include map in stdout': function (error, stdout) { assert.notInclude(stdout, '/*# sourceMappingURL'); } }) }) .addBatch({ 'source maps - output file': binaryContext('--source-map -o ./reset.min.css ./test/fixtures/reset.css', { 'includes map in minified file': function () { assert.include(fs.readFileSync('./reset.min.css', 'utf-8'), lineBreak + '/*# sourceMappingURL=reset.min.css.map */'); }, 'creates a map file': function () { assert.isTrue(fs.existsSync('./reset.min.css.map')); }, 'includes right content in map file': function () { var sourceMap = new SourceMapConsumer(fs.readFileSync('./reset.min.css.map', 'utf-8')); assert.deepEqual( sourceMap.originalPositionFor({ line: 1, column: 1 }), { source: 'test/fixtures/reset.css', line: 4, column: 0, name: null } ); }, 'teardown': function () { deleteFile('reset.min.css'); deleteFile('reset.min.css.map'); } }) }) .addBatch({ 'source maps - output file in same folder as input': { topic: function () { var self = this; exec('cp test/fixtures/reset.css .', function () { exec('__DIRECT__=1 ./bin/cleancss --source-map -o ./reset.min.css ./reset.css', self.callback); }); }, 'includes right content in map file': function () { var sourceMap = new SourceMapConsumer(fs.readFileSync('./reset.min.css.map', 'utf-8')); assert.deepEqual( sourceMap.originalPositionFor({ line: 1, column: 1 }), { source: 'reset.css', line: 4, column: 0, name: null } ); }, 'teardown': function () { deleteFile('reset.css'); deleteFile('reset.min.css'); deleteFile('reset.min.css.map'); } } }) .addBatch({ 'source maps - output file with existing map': binaryContext('--source-map -o ./styles.min.css ./test/fixtures/source-maps/styles.css', { 'includes right content in map file': function () { var sourceMap = new SourceMapConsumer(fs.readFileSync('./styles.min.css.map', 'utf-8')); assert.deepEqual( sourceMap.originalPositionFor({ line: 1, column: 1 }), { source: 'test/fixtures/source-maps/styles.less', line: 1, column: 4, name: null } ); }, 'teardown': function () { deleteFile('styles.min.css'); deleteFile('styles.min.css.map'); } }) }) .addBatch({ 'source maps - output file for existing map in different folder': binaryContext('--source-map -o ./styles-relative.min.css ./test/fixtures/source-maps/relative.css', { 'includes right content in map file': function () { var sourceMap = new SourceMapConsumer(fs.readFileSync('./styles-relative.min.css.map', 'utf-8')); assert.deepEqual( sourceMap.originalPositionFor({ line: 1, column: 1 }), { source: 'test/fixtures/source-maps/sub/styles.less', line: 2, column: 2, name: null } ); }, 'teardown': function () { deleteFile('styles-relative.min.css'); deleteFile('styles-relative.min.css.map'); } }) }) .addBatch({ 'source maps - with input source map': binaryContext('--source-map -o ./import.min.css ./test/fixtures/source-maps/import.css', { 'includes map in minified file': function () { assert.include(fs.readFileSync('./import.min.css', 'utf-8'), lineBreak + '/*# sourceMappingURL=import.min.css.map */'); }, 'includes right content in map file': function () { var sourceMap = new SourceMapConsumer(fs.readFileSync('./import.min.css.map', 'utf-8')); var count = 0; sourceMap.eachMapping(function () { count++; }); assert.equal(count, 6); }, 'teardown': function () { deleteFile('import.min.css'); deleteFile('import.min.css.map'); } }) }) .addBatch({ 'source maps - with input source map and source inlining': binaryContext('--source-map --source-map-inline-sources -o ./import-inline.min.css ./test/fixtures/source-maps/import.css', { 'includes map in minified file': function () { assert.include(fs.readFileSync('./import-inline.min.css', 'utf-8'), lineBreak + '/*# sourceMappingURL=import-inline.min.css.map */'); }, 'includes embedded sources': function () { var sourceMap = new SourceMapConsumer(fs.readFileSync('./import-inline.min.css.map', 'utf-8')); var count = 0; sourceMap.eachMapping(function () { count++; }); assert.equal(count, 6); }, 'teardown': function () { deleteFile('import-inline.min.css'); deleteFile('import-inline.min.css.map'); } }) }) .addBatch({ 'semantic merging': { 'disabled': pipedContext('.a{margin:0}.b{margin:10px;padding:0}.c{margin:0}', '', { 'should output right data': function (error, stdout) { assert.equal(stdout, '.a{margin:0}.b{margin:10px;padding:0}.c{margin:0}'); } }), 'enabled': pipedContext('.a{margin:0}.b{margin:10px;padding:0}.c{margin:0}', '-O2 mergeSemantically:on', { 'should output right data': function (error, stdout) { assert.equal(stdout, '.a,.c{margin:0}.b{margin:10px;padding:0}'); } }) } }) .addBatch({ 'custom CLI': { 'topic': function () { exec('echo ".block{background-image:url(image.png)}" | ./test/custom-cli/custom-cleancss', this.callback); }, 'outputs transformed url': function (error, stdout) { assert.equal(stdout, '.block{background-image:url(../valid/path/to/image.png)}'); } } }) .addBatch({ 'wildcard paths': { 'files': binaryContext('./test/fixtures/partials/on*.css ./test/fixtures/partials/f?ve.css', { 'outputs all matched sources minified': function (error, stdout) { assert.equal(stdout, '.one{color:red}.five{background:url(data:image/jpeg;base64,/9j/)}'); } }), 'directories': binaryContext('./test/fixtures/partials/**/*.css', { 'outputs all matched sources minified': function (error, stdout) { assert.equal(stdout, '.one{color:red}.three{color:#0f0}.two{color:#fff}.four{color:#00f}'); } }) } }) .addBatch({ 'removing inlined stylesheets - off': { 'topic': function() { var self = this; exec('cp test/fixtures/reset.css test/fixtures/reset-removing.css', function () { exec('__DIRECT__=1 ./bin/cleancss test/fixtures/reset-removing.css', self.callback); }); }, 'keeps the file': function () { assert.isTrue(fs.existsSync('test/fixtures/reset-removing.css')); }, 'teardown': function () { deleteFile('test/fixtures/reset-removing.css'); } } }) .addBatch({ 'removing inlined stylesheets - on': { 'topic': function() { var self = this; exec('cp test/fixtures/reset.css test/fixtures/reset-removing.css', function () { exec('__DIRECT__=1 ./bin/cleancss --remove-inlined-files test/fixtures/reset-removing.css', self.callback); }); }, 'removes the file': function () { assert.isFalse(fs.existsSync('test/fixtures/reset-removing.css')); } } }) .addBatch({ 'removing inlined stylesheets - on via @import': { 'topic': function() { var self = this; exec('cp test/fixtures/reset.css test/fixtures/reset-removing.css', function () { exec('echo "@import \'test/fixtures/reset-removing.css\';" | ./bin/cleancss --remove-inlined-files', self.callback); }); }, 'removes the file': function () { assert.isFalse(fs.existsSync('test/fixtures/reset-removing.css')); } } }) .addBatch({ 'process an input-source-map': pipedContext(fs.readFileSync('./test/fixtures/source-maps/map/styles.css'), '-o ./test/styles.min.css --input-source-map ./test/fixtures/source-maps/map/input.map', { 'enables the source map flag': function() { assert.isTrue(fs.existsSync('test/styles.min.css')); assert.isTrue(fs.existsSync('test/styles.min.css.map')); }, 'teardown': function () { deleteFile('test/styles.min.css'); deleteFile('test/styles.min.css.map'); } }) }) .addBatch({ 'missing an input-source-map': pipedContext(fs.readFileSync('./test/fixtures/source-maps/map/styles.css'), '-o ./test/styles.min.css', { 'does not generate a source map if the parameter is missing': function() { assert.isTrue(fs.existsSync('test/styles.min.css')); assert.isFalse(fs.existsSync('test/styles.min.css.map')); }, 'teardown': function () { deleteFile('test/styles.min.css'); } }) }) .addBatch({ 'content of input-source-map': pipedContext(fs.readFileSync('./test/fixtures/source-maps/map/styles.css'), '-o ./test/styles.min.css --input-source-map ./test/fixtures/source-maps/map/input.map', { 'includes the right content of the source map': function() { assert.isTrue(fs.existsSync('test/styles.min.css.map')); var sourceMap = new SourceMapConsumer(fs.readFileSync('./test/styles.min.css.map', 'utf-8')); assert.deepEqual( sourceMap.originalPositionFor({ line: 1, column: 1 }), { source: 'styles.less', line: 1, column: 4, name: null } ); }, 'teardown': function () { deleteFile('test/styles.min.css'); deleteFile('test/styles.min.css.map'); } }) }) .export(module); clean-css-cli-4.3.0/test/custom-cli/000077500000000000000000000000001345207242700171775ustar00rootroot00000000000000clean-css-cli-4.3.0/test/custom-cli/custom-cleancss000077500000000000000000000005701345207242700222320ustar00rootroot00000000000000#!/usr/bin/env node var cleanCssCli = require('../../index'); return cleanCssCli(process, function (cleanCss) { cleanCss.options.level['1'].transform = function (propertyName, propertyValue) { if (propertyName == 'background-image' && propertyValue.indexOf('../valid/path/to') == -1) { return propertyValue.replace('url(', 'url(../valid/path/to/'); } } }); clean-css-cli-4.3.0/test/fixtures/000077500000000000000000000000001345207242700167715ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/imports-min.css000066400000000000000000000001321345207242700217550ustar00rootroot00000000000000.one{color:red} .three{color:#0f0} .four{color:#00f} .two{color:#fff} .imports{color:#000}clean-css-cli-4.3.0/test/fixtures/imports.css000066400000000000000000000001401345207242700211730ustar00rootroot00000000000000@import url('./partials/one.css'); @import url("./partials/two.css"); .imports { color: #000; }clean-css-cli-4.3.0/test/fixtures/partials-relative/000077500000000000000000000000001345207242700224215ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/partials-relative/base.css000066400000000000000000000001021345207242700240360ustar00rootroot00000000000000a { background:url(../partials/extra/down.gif) 0 0 no-repeat; } clean-css-cli-4.3.0/test/fixtures/partials-relative/extra/000077500000000000000000000000001345207242700235445ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/partials-relative/extra/included.css000066400000000000000000000000271345207242700260440ustar00rootroot00000000000000@import '../base.css'; clean-css-cli-4.3.0/test/fixtures/partials/000077500000000000000000000000001345207242700206105ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/partials/extra/000077500000000000000000000000001345207242700217335ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/partials/extra/four.css000066400000000000000000000000611345207242700234150ustar00rootroot00000000000000@import url('../two.css'); .four { color:#00f; }clean-css-cli-4.3.0/test/fixtures/partials/extra/three.css000066400000000000000000000000261345207242700235520ustar00rootroot00000000000000.three { color:#0f0; }clean-css-cli-4.3.0/test/fixtures/partials/five.css000066400000000000000000000000631345207242700222520ustar00rootroot00000000000000.five{background:url(data:image/jpeg;base64,/9j/)} clean-css-cli-4.3.0/test/fixtures/partials/one.css000066400000000000000000000000251345207242700221000ustar00rootroot00000000000000.one { color:#f00; } clean-css-cli-4.3.0/test/fixtures/partials/quoted-svg.css000066400000000000000000000013341345207242700234210ustar00rootroot00000000000000div { background: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmD%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%22100%22%20height%3D%22100%22%20viewBox%3D%220%200%20100%20100%22%20overflow%3D%22visible%22%3E%3Cdefs%3E%3Cellipse%20id%3D%22a%22%20cx%3D%2250%22%20cy%3D%2250%22%20rx%3D%2250%22%20ry%3D%2250%22%2F%3E%3C%2Fdefs%3E%3Cuse%20xlink%3Ahref%3D%22%23a%22%20overflow%3D%22visible%22%20fill%3D%22%2300f%22%2F%3E%3CclipPath%20id%3D%22b%22%3E%3Cuse%20xlink%3Ahref%3D%22%23a%22%20overflow%3D%22visible%22%2F%3E%3C%2FclipPath%3E%3Cg%20clip-path%3D%22url(%23b)%22%3E%3Cpath%20d%3D%22M0%20100h50V50H0z%22%20fill%3D%22%230f0%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); } clean-css-cli-4.3.0/test/fixtures/partials/two.css000066400000000000000000000001571345207242700221360ustar00rootroot00000000000000@import url('one.css'); @import url('extra/three.css'); @import url('./extra/four.css'); .two { color:#fff; } clean-css-cli-4.3.0/test/fixtures/rebasing/000077500000000000000000000000001345207242700205635ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/assets/000077500000000000000000000000001345207242700220655ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/assets/ui.css000066400000000000000000000001541345207242700232140ustar00rootroot00000000000000@import url(../components/bootstrap/css/bootstrap.css); @import url(../components/jquery-ui/css/style.css); clean-css-cli-4.3.0/test/fixtures/rebasing/components/000077500000000000000000000000001345207242700227505ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/bootstrap/000077500000000000000000000000001345207242700247655ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/bootstrap/css/000077500000000000000000000000001345207242700255555ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/bootstrap/css/bootstrap.css000066400000000000000000000001001345207242700302730ustar00rootroot00000000000000.icon { background:url(../images/glyphs.gif) 0 0 no-repeat; } clean-css-cli-4.3.0/test/fixtures/rebasing/components/bootstrap/images/000077500000000000000000000000001345207242700262325ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/bootstrap/images/glyphs.gif000066400000000000000000000000001345207242700302150ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/jquery-ui/000077500000000000000000000000001345207242700247025ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/jquery-ui/css/000077500000000000000000000000001345207242700254725ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/jquery-ui/css/style.css000066400000000000000000000001741345207242700273460ustar00rootroot00000000000000.prev { background:url(../images/prev.gif) 0 0 no-repeat; } .next { background:url(../images/next.gif) 0 0 no-repeat; } clean-css-cli-4.3.0/test/fixtures/rebasing/components/jquery-ui/images/000077500000000000000000000000001345207242700261475ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/jquery-ui/images/next.gif000066400000000000000000000000001345207242700276020ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/rebasing/components/jquery-ui/images/prev.gif000066400000000000000000000000001345207242700276000ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/reset-duplicate.css000066400000000000000000000022621345207242700225770ustar00rootroot00000000000000/*reset*/ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } /* remember to define focus styles! */ :focus { outline: 0; } body { line-height: 1; color: black; background: white; } ol, ul { list-style: none; } /* tables still need 'cellspacing="0"' in the markup */ table { border-collapse: separate; border-spacing: 0; } caption, th, td { text-align: left; font-weight: normal; } blockquote:before, blockquote:after, q:before, q:after { content: ""; } blockquote, q { quotes: "" ""; } .clear { clear:both; display: inline-block; } .clear:after, .container:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } * html .clear { height: 1%; } .clear { display: block; }clean-css-cli-4.3.0/test/fixtures/reset-min.css000066400000000000000000000015021345207242700214040ustar00rootroot00000000000000a,abbr,acronym,address,applet,big,blockquote,body,caption,cite,code,dd,del,dfn,div,dl,dt,em,fieldset,font,form,h1,h2,h3,h4,h5,h6,html,iframe,img,ins,kbd,label,legend,li,object,ol,p,pre,q,s,samp,small,span,strike,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,tt,ul,var{margin:0;padding:0;border:0;outline:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline} :focus{outline:0} body{line-height:1;color:#000;background:#fff} ol,ul{list-style:none} table{border-collapse:separate;border-spacing:0} caption,td,th{text-align:left;font-weight:400} blockquote:after,blockquote:before,q:after,q:before{content:""} blockquote,q{quotes:"" ""} .clear{clear:both;display:block} .clear:after,.container:after{content:".";display:block;height:0;clear:both;visibility:hidden} * html .clear{height:1%}clean-css-cli-4.3.0/test/fixtures/reset.css000066400000000000000000000022621345207242700206270ustar00rootroot00000000000000/*reset*/ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } /* remember to define focus styles! */ :focus { outline: 0; } body { line-height: 1; color: black; background: white; } ol, ul { list-style: none; } /* tables still need 'cellspacing="0"' in the markup */ table { border-collapse: separate; border-spacing: 0; } caption, th, td { text-align: left; font-weight: normal; } blockquote:before, blockquote:after, q:before, q:after { content: ""; } blockquote, q { quotes: "" ""; } .clear { clear:both; display: inline-block; } .clear:after, .container:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } * html .clear { height: 1%; } .clear { display: block; }clean-css-cli-4.3.0/test/fixtures/source-maps/000077500000000000000000000000001345207242700212275ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/source-maps/import.css000066400000000000000000000000601345207242700232470ustar00rootroot00000000000000@import url(some.css); @import url(styles.css); clean-css-cli-4.3.0/test/fixtures/source-maps/map/000077500000000000000000000000001345207242700220045ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/source-maps/map/input.map000066400000000000000000000001501345207242700236360ustar00rootroot00000000000000{"version":3,"sources":["styles.less"],"names":[],"mappings":"AAAA,GAAI;EACF,WAAA","file":"styles.css"} clean-css-cli-4.3.0/test/fixtures/source-maps/map/styles.css000066400000000000000000000000331345207242700240350ustar00rootroot00000000000000div > a { color: blue; } clean-css-cli-4.3.0/test/fixtures/source-maps/relative.css000066400000000000000000000000351345207242700235520ustar00rootroot00000000000000@import url(sub/styles.css); clean-css-cli-4.3.0/test/fixtures/source-maps/some.css000066400000000000000000000000721345207242700227030ustar00rootroot00000000000000div { color: red; } /*# sourceMappingURL=some.css.map */clean-css-cli-4.3.0/test/fixtures/source-maps/some.css.map000066400000000000000000000001361345207242700234600ustar00rootroot00000000000000{"version":3,"sources":["some.less"],"names":[],"mappings":"AAAA;EACE,UAAA","file":"some.css"}clean-css-cli-4.3.0/test/fixtures/source-maps/styles.css000066400000000000000000000001011345207242700232540ustar00rootroot00000000000000div > a { color: blue; } /*# sourceMappingURL=styles.css.map */clean-css-cli-4.3.0/test/fixtures/source-maps/styles.css.map000066400000000000000000000001471345207242700240420ustar00rootroot00000000000000{"version":3,"sources":["styles.less"],"names":[],"mappings":"AAAA,GAAI;EACF,WAAA","file":"styles.css"}clean-css-cli-4.3.0/test/fixtures/source-maps/styles.less000066400000000000000000000000331345207242700234360ustar00rootroot00000000000000div > a { color: blue; } clean-css-cli-4.3.0/test/fixtures/source-maps/sub/000077500000000000000000000000001345207242700220205ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/source-maps/sub/styles.css000066400000000000000000000001021345207242700240460ustar00rootroot00000000000000div > a { color: blue; } /*# sourceMappingURL=styles.css.map */ clean-css-cli-4.3.0/test/fixtures/source-maps/sub/styles.css.map000066400000000000000000000001471345207242700246330ustar00rootroot00000000000000{"version":3,"sources":["styles.less"],"names":[],"mappings":"AAAA,GACE;EACE,WAAA","file":"styles.css"}clean-css-cli-4.3.0/test/fixtures/unsupported/000077500000000000000000000000001345207242700213615ustar00rootroot00000000000000clean-css-cli-4.3.0/test/fixtures/unsupported/selectors-ie7.css000066400000000000000000000006151345207242700245620ustar00rootroot00000000000000p:focus{top:0} p:before{top:0} p:after{top:0} p:root{top:0} p:nth-of-type(1){top:0} p:nth-last-of-type(1){top:0} p:first-of-type{top:0} p:last-of-type{top:0} p:only-of-type{top:0} p:only-child{top:0} p:last-child{top:0} p:nth-child(1){top:0} p:nth-last-child(1){top:0} p:empty{top:0} p:target{top:0} p:checked{top:0} p::selection{top:0} input:enabled{top:0} input:disabled{top:0} p:not(.x){top:0} clean-css-cli-4.3.0/test/fixtures/unsupported/selectors-ie8.css000066400000000000000000000005371345207242700245660ustar00rootroot00000000000000p:root{top:0} p:nth-of-type(1){top:0} p:nth-last-of-type(1){top:0} p:first-of-type{top:0} p:last-of-type{top:0} p:only-of-type{top:0} p:only-child{top:0} p:last-child{top:0} p:nth-child(1){top:0} p:nth-last-child(1){top:0} p:empty{top:0} p:target{top:0} p:checked{top:0} p::selection{top:0} input:enabled{top:0} input:disabled{top:0} p:not(.x){top:0}