aboutsummaryrefslogtreecommitdiff
path: root/node_modules/clean-css
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-24 15:10:37 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-24 15:11:17 +0200
commit7a3df06eb573d36142bd1a8e03c5ce8752d300b3 (patch)
tree70bfaea8884c374876f607774850a3a51c0cb381 /node_modules/clean-css
parentaca1143cb9eed16cf37f04e475e4257418dd18ac (diff)
fix build issues and add typedoc
Diffstat (limited to 'node_modules/clean-css')
-rw-r--r--node_modules/clean-css/History.md45
-rw-r--r--node_modules/clean-css/README.md130
-rw-r--r--node_modules/clean-css/lib/clean.js2
-rw-r--r--node_modules/clean-css/lib/optimizer/level-1/optimize.js67
-rw-r--r--node_modules/clean-css/lib/optimizer/level-1/sort-selectors.js12
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/break-up.js242
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/can-override.js145
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/compactable.js221
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js41
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js7
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js5
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/optimize.js12
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js11
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js450
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js11
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js65
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js2
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js6
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js232
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/restore.js54
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/restructure.js5
-rw-r--r--node_modules/clean-css/lib/optimizer/validator.js393
-rw-r--r--node_modules/clean-css/lib/optimizer/wrap-for-optimizing.js6
-rw-r--r--node_modules/clean-css/lib/options/compatibility.js4
-rw-r--r--node_modules/clean-css/lib/options/fetch.js7
-rw-r--r--node_modules/clean-css/lib/options/inline.js4
-rw-r--r--node_modules/clean-css/lib/options/optimization-level.js12
-rw-r--r--node_modules/clean-css/lib/reader/apply-source-maps.js4
-rw-r--r--node_modules/clean-css/lib/reader/load-original-sources.js4
-rw-r--r--node_modules/clean-css/lib/reader/read-sources.js29
-rw-r--r--node_modules/clean-css/lib/reader/rebase.js2
-rw-r--r--node_modules/clean-css/lib/tokenizer/marker.js1
-rw-r--r--node_modules/clean-css/lib/tokenizer/tokenize.js11
-rw-r--r--node_modules/clean-css/lib/writer/helpers.js2
-rw-r--r--node_modules/clean-css/package.json4
35 files changed, 1764 insertions, 484 deletions
diff --git a/node_modules/clean-css/History.md b/node_modules/clean-css/History.md
index 3cf6682ef..2a4bab0c3 100644
--- a/node_modules/clean-css/History.md
+++ b/node_modules/clean-css/History.md
@@ -1,3 +1,39 @@
+[4.1.3 / 2017-05-18](https://github.com/jakubpawlowicz/clean-css/compare/v4.1.2...v4.1.3)
+==================
+
+* Fixed issue [#946](https://github.com/jakubpawlowicz/clean-css/issues/946) - tokenizing `-ms-grid-columns` repeat syntax.
+
+[4.1.2 / 2017-05-10](https://github.com/jakubpawlowicz/clean-css/compare/v4.1.1...v4.1.2)
+==================
+
+* Fixed issue [#939](https://github.com/jakubpawlowicz/clean-css/issues/939) - semicolon after `@apply` at rule.
+* Fixed issue [#940](https://github.com/jakubpawlowicz/clean-css/issues/940) - handling more `font` keywords.
+* Fixed issue [#941](https://github.com/jakubpawlowicz/clean-css/issues/941) - breaking up vendor prefixed `animation`.
+
+[4.1.1 / 2017-05-08](https://github.com/jakubpawlowicz/clean-css/compare/v4.1.0...v4.1.1)
+==================
+
+* Fixed issue [#938](https://github.com/jakubpawlowicz/clean-css/issues/938) - removing unused at-rules with `!important`.
+
+[4.1.0 / 2017-05-07](https://github.com/jakubpawlowicz/clean-css/compare/4.0...v4.1.0)
+==================
+
+* Improves longhand-into-shorthand merging mechanism in complex cases as with `border-*` shorthands.
+* Fixed issue [#254](https://github.com/jakubpawlowicz/clean-css/issues/254) - adds `font` property optimizer.
+* Fixed issue [#525](https://github.com/jakubpawlowicz/clean-css/issues/525) - restores `inherit`-based merging.
+* Fixed issue [#755](https://github.com/jakubpawlowicz/clean-css/issues/755) - adds custom handling of remote requests.
+* Fixed issue [#860](https://github.com/jakubpawlowicz/clean-css/issues/860) - adds `animation` property optimizer.
+* Fixed issue [#862](https://github.com/jakubpawlowicz/clean-css/issues/862) - allows removing unused at rules.
+* Fixed issue [#886](https://github.com/jakubpawlowicz/clean-css/issues/886) - better multi pseudo class / element merging.
+* Fixed issue [#890](https://github.com/jakubpawlowicz/clean-css/issues/890) - adds toggle to disable empty tokens removal.
+* Fixed issue [#893](https://github.com/jakubpawlowicz/clean-css/issues/893) - `inline: false` as alias to `inline: 'none'`.
+* Fixed issue [#905](https://github.com/jakubpawlowicz/clean-css/issues/905) - allows disabling selector sorting.
+* Fixed issue [#906](https://github.com/jakubpawlowicz/clean-css/issues/906) - improves usability of web UI settings.
+* Fixed issue [#908](https://github.com/jakubpawlowicz/clean-css/issues/908) - improved `minify` method signature.
+* Fixed issue [#916](https://github.com/jakubpawlowicz/clean-css/issues/916) - maximum number of merged selectors.
+* Fixed issue [#920](https://github.com/jakubpawlowicz/clean-css/issues/920) - allows skipping certain properties in level 2 optimizations.
+* Fixed issue [#934](https://github.com/jakubpawlowicz/clean-css/issues/934) - smarter longhand into shorthand merging.
+
[4.0.12 / 2017-04-12](https://github.com/jakubpawlowicz/clean-css/compare/v4.0.11...v4.0.12)
==================
@@ -13,7 +49,7 @@
* Fixed issue [#917](https://github.com/jakubpawlowicz/clean-css/issues/917) - prevents grid area unquoting.
* Backported [#916](https://github.com/jakubpawlowicz/clean-css/issues/916) - maximum number of merged selectors.
-* Refixed issue [#556](https://github.com/jakubpawlowicz/clean-css/issues/917) - IE backslash hacks.
+* Refixed issue [#556](https://github.com/jakubpawlowicz/clean-css/issues/556) - IE backslash hacks.
[4.0.9 / 2017-03-15](https://github.com/jakubpawlowicz/clean-css/compare/v4.0.8...v4.0.9)
==================
@@ -55,7 +91,7 @@
[4.0.3 / 2017-01-30](https://github.com/jakubpawlowicz/clean-css/compare/v4.0.2...v4.0.3)
==================
-* Fixed issue [#875](https://github.com/jakubpawlowicz/clean-css/issues/875) - invalid traversing in semanting merging.
+* Fixed issue [#875](https://github.com/jakubpawlowicz/clean-css/issues/875) - invalid traversing in semantic merging.
[4.0.2 / 2017-01-26](https://github.com/jakubpawlowicz/clean-css/compare/v4.0.1...v4.0.2)
==================
@@ -120,6 +156,11 @@
* Fixed issue [#857](https://github.com/jakubpawlowicz/clean-css/issues/857) - normalizes CleanCSS API interface.
* Fixed issue [#863](https://github.com/jakubpawlowicz/clean-css/issues/863) - adds `transform` callback for custom optimizations.
+[3.4.25 / 2017-02-22](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.24...v3.4.25)
+==================
+
+* Fixed issue [#897](https://github.com/jakubpawlowicz/clean-css/issues/897) - tokenization with escaped markers.
+
[3.4.24 / 2017-01-20](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.23...v3.4.24)
==================
diff --git a/node_modules/clean-css/README.md b/node_modules/clean-css/README.md
index a19594801..b240f4381 100644
--- a/node_modules/clean-css/README.md
+++ b/node_modules/clean-css/README.md
@@ -22,8 +22,10 @@ According to [tests](http://goalsmashers.github.io/css-minification-benchmark/)
- [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)
* [Constructor options](#constructor-options)
* [Compatibility modes](#compatibility-modes)
+ * [Fetch option](#fetch-option)
* [Formatting options](#formatting-options)
* [Inlining options](#inlining-options)
* [Optimization levels](#optimization-levels)
@@ -32,6 +34,7 @@ According to [tests](http://goalsmashers.github.io/css-minification-benchmark/)
+ [Level 2 optimizations](#level-2-optimizations)
* [Minify method](#minify-method)
* [Promise interface](#promise-interface)
+ * [CLI utility](#cli-utility)
- [FAQ](#faq)
* [How to optimize multiple files?](#how-to-optimize-multiple-files)
* [How to process remote `@import`s correctly?](#how-to-process-remote-imports-correctly)
@@ -90,11 +93,31 @@ clean-css 4.0 introduces some breaking changes:
* `sourceMap` option has to be a boolean from now on - to specify an input source map pass it a 2nd argument to `minify` method or via a hash instead;
* `aggressiveMerging` option is removed as aggressive merging is replaced by smarter override merging.
+## What's new in version 4.1
+
+clean-css 4.1 introduces the following changes / features:
+
+* `inline: false` as an alias to `inline: ['none']`;
+* `multiplePseudoMerging` compatibility flag controlling merging of rules with multiple pseudo classes / elements;
+* `removeEmpty` flag in level 1 optimizations controlling removal of rules and nested blocks;
+* `removeEmpty` flag in level 2 optimizations controlling removal of rules and nested blocks;
+* `compatibility: { selectors: { mergeLimit: <number> } }` flag in compatibility settings controlling maximum number of selectors in a single rule;
+* `minify` method improved signature accepting a list of hashes for a predictable traversal;
+* `selectorsSortingMethod` level 1 optimization allows `false` or `'none'` for disabling selector sorting;
+* `fetch` option controlling a function for handling remote requests;
+* new `font` shorthand and `font-*` longhand optimizers;
+* removal of `optimizeFont` flag in level 1 optimizations due to new `font` shorthand optimizer;
+* `skipProperties` flag in level 2 optimizations controlling which properties won't be optimized;
+* new `animation` shorthand and `animation-*` longhand optimizers;
+* `removeUnusedAtRules` level 2 optimization controlling removal of unused `@counter-style`, `@font-face`, `@keyframes`, and `@namespace` at rules;
+* the [web interface](https://jakubpawlowicz.github.io/clean-css) gets an improved settings panel with "reset to defaults", instant option changes, and settings being persisted across sessions.
+
## Constructor options
clean-css constructor accepts a hash as a parameter with the following options available:
* `compatibility` - controls compatibility mode used; defaults to `ie10+`; see [compatibility modes](#compatibility-modes) for examples;
+* `fetch` - controls a function for handling remote requests; see [fetch option](#fetch-option) for examples (since 4.1.0);
* `format` - controls output CSS formatting; defaults to `false`; see [formatting options](#formatting-options) for examples;
* `inline` - controls `@import` inlining rules; defaults to `'local'`; see [inlining options](#inlining-options) for examples;
* `inlineRequest` - controls extra options for inlining remote `@import` rules, can be any of [HTTP(S) request options](https://nodejs.org/api/http.html#http_http_request_options_callback);
@@ -142,7 +165,9 @@ new CleanCSS({
adjacentSpace: false, // controls extra space before `nav` element
ie7Hack: true, // controls removal of IE7 selector hacks, e.g. `*+html...`
mergeablePseudoClasses: [':active', ...], // controls a whitelist of mergeable pseudo classes
- mergeablePseudoElements: ['::after', ...] // controls a whitelist of mergeable pseudo elements
+ mergeablePseudoElements: ['::after', ...], // controls a whitelist of mergeable pseudo elements
+ mergeLimit: 8191, // controls maximum number of selectors in a single rule (since 4.1.0)
+ multiplePseudoMerging: true // controls merging of rules with multiple pseudo classes / elements (since 4.1.0)
},
units: {
ch: true, // controls treating `ch` as a supported unit
@@ -167,9 +192,52 @@ new CleanCSS({
})
```
+## Fetch option
+
+The `fetch` option accepts a function which handles remote resource fetching, e.g.
+
+```js
+var request = require('request');
+var source = '@import url(http://example.com/path/to/stylesheet.css);';
+new CleanCSS({
+ fetch: function (uri, inlineRequest, inlineTimeout, callback) {
+ request(uri, function (error, response, body) {
+ if (error) {
+ callback(error, null);
+ } else if (response && response.statusCode != 200) {
+ callback(response.statusCode, null);
+ } else {
+ callback(null, body);
+ }
+ });
+ }
+}).minify(source);
+```
+
+This option provides a convenient way of overriding the default fetching logic if it doesn't support a particular feature, say CONNECT proxies.
+
+Unless given, the default [loadRemoteResource](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/reader/load-remote-resource.js) logic is used.
+
## Formatting options
-The `format` option accept the following options:
+By default output CSS is formatted without any whitespace unless a `format` option is given.
+First of all there are two shorthands:
+
+```js
+new CleanCSS({
+ format: 'beautify' // formats output in a really nice way
+})
+```
+
+and
+
+```js
+new CleanCSS({
+ format: 'keep-breaks' // formats output the default way but adds line breaks for improved readability
+})
+```
+
+however `format` option also accept a fine-grained set of options:
```js
new CleanCSS({
@@ -203,25 +271,39 @@ new CleanCSS({
```js
new CleanCSS({
- inline: ['local'] // default
+ inline: ['local'] // default; enables local inlining only
+})
+```
+
+```js
+new CleanCSS({
+ inline: ['none'] // disables all inlining
+})
+```
+
+```js
+// introduced in clean-css 4.1.0
+
+new CleanCSS({
+ inline: false // disables all inlining (alias to `['none']`)
})
```
```js
new CleanCSS({
- inline: ['all'] // same as ['local', 'remote']
+ inline: ['all'] // enables all inlining, same as ['local', 'remote']
})
```
```js
new CleanCSS({
- inline: ['local', 'mydomain.example.com']
+ inline: ['local', 'mydomain.example.com'] // enables local inlining plus given remote source
})
```
```js
new CleanCSS({
- inline: ['local', 'remote', '!fonts.googleapis.com']
+ inline: ['local', 'remote', '!fonts.googleapis.com'] // enables all inlining but from given remote source
})
```
@@ -255,12 +337,13 @@ new CleanCSS({
1: {
cleanupCharsets: true, // controls `@charset` moving to the front of a stylesheet; defaults to `true`
normalizeUrls: true, // controls URL normalization; defaults to `true`
- optimizeBackground: true, // controls `background` property optimizatons; defaults to `true`
- optimizeBorderRadius: true, // controls `border-radius` property optimizatons; defaults to `true`
- optimizeFilter: true, // controls `filter` property optimizatons; defaults to `true`
- optimizeFont: true, // ontrols `font` property optimizatons; defaults to `true`
- optimizeFontWeight: true, // controls `font-weight` property optimizatons; defaults to `true`
- optimizeOutline: true, // controls `outline` property optimizatons; defaults to `true`
+ optimizeBackground: true, // controls `background` property optimizations; defaults to `true`
+ optimizeBorderRadius: true, // controls `border-radius` property optimizations; defaults to `true`
+ optimizeFilter: true, // controls `filter` property optimizations; defaults to `true`
+ optimizeFont: true, // controls `font` property optimizations; defaults to `true`
+ optimizeFontWeight: true, // controls `font-weight` property optimizations; defaults to `true`
+ optimizeOutline: true, // controls `outline` property optimizations; defaults to `true`
+ removeEmpty: true, // controls removing empty rules and nested blocks; defaults to `true`
removeNegativePaddings: true, // controls removing negative paddings; defaults to `true`
removeQuotes: true, // controls removing quotes when unnecessary; defaults to `true`
removeWhitespace: true, // controls removing unused whitespace; defaults to `true`
@@ -268,7 +351,7 @@ new CleanCSS({
replaceTimeUnits: true, // controls replacing time units with shorter values; defaults to `true`
replaceZeroUnits: true, // controls replacing zero values with units; defaults to `true`
roundingPrecision: false, // rounds pixel values to `N` decimal places; `false` disables rounding; defaults to `false`
- selectorsSortingMethod: 'standard', // denotes selector sorting method; can be `natural` or `standard`; defaults to `standard`
+ selectorsSortingMethod: 'standard', // denotes selector sorting method; can be `'natural'` or `'standard'`, `'none'`, or false (the last two since 4.1.0); defaults to `'standard'`
specialComments: 'all', // denotes a number of /*! ... */ comments preserved; defaults to `all`
tidyAtRules: true, // controls at-rules (e.g. `@charset`, `@import`) optimizing; defaults to `true`
tidyBlockScopes: true, // controls block scopes (e.g. `@media`) optimizing; defaults to `true`
@@ -310,11 +393,14 @@ new CleanCSS({
mergeNonAdjacentRules: true, // controls non-adjacent rule merging; defaults to true
mergeSemantically: false, // controls semantic merging; defaults to false
overrideProperties: true, // controls property overriding based on understandability; defaults to true
+ removeEmpty: true, // controls removing empty rules and nested blocks; defaults to `true`
reduceNonAdjacentRules: true, // controls non-adjacent rule reducing; defaults to true
removeDuplicateFontRules: true, // controls duplicate `@font-face` removing; defaults to true
removeDuplicateMediaBlocks: true, // controls duplicate `@media` removing; defaults to true
removeDuplicateRules: true, // controls duplicate rules removing; defaults to true
- restructureRules: false // controls rule restructuring; defaults to false
+ removeUnusedAtRules: false, // controls unused at rule removing; defaults to false (available since 4.1.0)
+ restructureRules: false, // controls rule restructuring; defaults to false
+ skipProperties: [] // controls which properties won't be optimized, defaults to `[]` which means all will be optimized (since 4.1.0)
}
}
});
@@ -379,11 +465,15 @@ new CleanCSS({ returnPromise: true })
.catch(function (error) { // deal with errors });
```
+## CLI utility
+
+Clean-css has an associated command line utility that can be installed separately using `npm install clean-css-cli`. For more detailed information, please visit https://github.com/jakubpawlowicz/clean-css-cli.
+
# FAQ
## How to optimize multiple files?
-It can be done either by passing an array of paths, or, when sources are already available, a hash:
+It can be done either by passing an array of paths, or, when sources are already available, a hash or an array of hashes:
```js
new CleanCSS().minify(['path/to/file/one', 'path/to/file/two']);
@@ -400,6 +490,15 @@ new CleanCSS().minify({
});
```
+```js
+new CleanCSS().minify([
+ {'path/to/file/one': {styles: 'contents of file one'}},
+ {'path/to/file/two': {styles: 'contents of file two'}}
+]);
+```
+
+Passing an array of hashes allows you to explicitly specify the order in which the input files are concatenated. Whereas when you use a single hash the order is determined by the [traversal order of object properties](http://2ality.com/2015/10/property-traversal-order-es6.html) - available since 4.1.0.
+
Important note - any `@import` rules already present in the hash will be resolved in memory.
## How to process remote `@import`s correctly?
@@ -604,6 +703,7 @@ Sorted alphabetically by GitHub handle:
* [@altschuler](https://github.com/altschuler) (Simon Altschuler) for fixing `@import` processing inside comments;
* [@ben-eb](https://github.com/ben-eb) (Ben Briggs) for sharing ideas about CSS optimizations;
* [@facelessuser](https://github.com/facelessuser) (Isaac) for pointing out a flaw in clean-css' stateless mode;
+* [@grandrath](https://github.com/grandrath) (Martin Grandrath) for improving `minify` method source traversal in ES6;
* [@jmalonzo](https://github.com/jmalonzo) (Jan Michael Alonzo) for a patch removing node.js' old `sys` package;
* [@lukeapage](https://github.com/lukeapage) (Luke Page) for suggestions and testing the source maps feature;
Plus everyone else involved in [#125](https://github.com/jakubpawlowicz/clean-css/issues/125) for pushing it forward;
diff --git a/node_modules/clean-css/lib/clean.js b/node_modules/clean-css/lib/clean.js
index f8268777b..62308efec 100644
--- a/node_modules/clean-css/lib/clean.js
+++ b/node_modules/clean-css/lib/clean.js
@@ -11,6 +11,7 @@ var level2Optimize = require('./optimizer/level-2/optimize');
var validator = require('./optimizer/validator');
var compatibilityFrom = require('./options/compatibility');
+var fetchFrom = require('./options/fetch');
var formatFrom = require('./options/format').formatFrom;
var inlineFrom = require('./options/inline');
var inlineRequestFrom = require('./options/inline-request');
@@ -31,6 +32,7 @@ var CleanCSS = module.exports = function CleanCSS(options) {
this.options = {
compatibility: compatibilityFrom(options.compatibility),
+ fetch: fetchFrom(options.fetch),
format: formatFrom(options.format),
inline: inlineFrom(options.inline),
inlineRequest: inlineRequestFrom(options.inlineRequest),
diff --git a/node_modules/clean-css/lib/optimizer/level-1/optimize.js b/node_modules/clean-css/lib/optimizer/level-1/optimize.js
index e7a9bbb47..5a6da47c0 100644
--- a/node_modules/clean-css/lib/optimizer/level-1/optimize.js
+++ b/node_modules/clean-css/lib/optimizer/level-1/optimize.js
@@ -26,10 +26,6 @@ var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');
var DEFAULT_ROUNDING_PRECISION = require('../../options/rounding-precision').DEFAULT;
-var FONT_NUMERAL_WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];
-var FONT_NAME_WEIGHTS = ['normal', 'bold', 'bolder', 'lighter'];
-var FONT_NAME_WEIGHTS_WITHOUT_NORMAL = ['bold', 'bolder', 'lighter'];
-
var WHOLE_PIXEL_VALUE = /(?:^|\s|\()(-?\d+)px/;
var TIME_VALUE = /^(\-?[\d\.]+)(m?s)$/;
@@ -159,63 +155,6 @@ function optimizeFilter(property) {
.replace(/ ?= ?/g, '=');
}
-function optimizeFont(property, options) {
- var values = property.value;
- var hasNumeral = FONT_NUMERAL_WEIGHTS.indexOf(values[0][1]) > -1 ||
- values[1] && FONT_NUMERAL_WEIGHTS.indexOf(values[1][1]) > -1 ||
- values[2] && FONT_NUMERAL_WEIGHTS.indexOf(values[2][1]) > -1;
- var canOptimizeFontWeight = options.level[OptimizationLevel.One].optimizeFontWeight;
- var normalCount = 0;
- var toOptimize;
-
- if (!canOptimizeFontWeight) {
- return;
- }
-
- if (hasNumeral) {
- return;
- }
-
- if (values[1] && values[1][1] == '/') {
- return;
- }
-
- if (values[0][1] == 'normal') {
- normalCount++;
- }
-
- if (values[1] && values[1][1] == 'normal') {
- normalCount++;
- }
-
- if (values[2] && values[2][1] == 'normal') {
- normalCount++;
- }
-
- if (normalCount > 1) {
- return;
- }
-
- if (FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[0][1]) > -1) {
- toOptimize = 0;
- } else if (values[1] && FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[1][1]) > -1) {
- toOptimize = 1;
- } else if (values[2] && FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[2][1]) > -1) {
- toOptimize = 2;
- } else if (FONT_NAME_WEIGHTS.indexOf(values[0][1]) > -1) {
- toOptimize = 0;
- } else if (values[1] && FONT_NAME_WEIGHTS.indexOf(values[1][1]) > -1) {
- toOptimize = 1;
- } else if (values[2] && FONT_NAME_WEIGHTS.indexOf(values[2][1]) > -1) {
- toOptimize = 2;
- }
-
- if (toOptimize !== undefined && canOptimizeFontWeight) {
- optimizeFontWeight(property, toOptimize);
- property.dirty = true;
- }
-}
-
function optimizeFontWeight(property, atIndex) {
var value = property.value[atIndex][1];
@@ -483,7 +422,7 @@ function optimizeBody(properties, context) {
break;
}
- if (valueIsUrl && !context.validator.isValidUrl(value)) {
+ if (valueIsUrl && !context.validator.isUrl(value)) {
property.unused = true;
context.warnings.push('Broken URL \'' + value + '\' at ' + formatPosition(property.value[j][2][0]) + '. Ignoring.');
break;
@@ -543,8 +482,6 @@ function optimizeBody(properties, context) {
optimizeBorderRadius(property);
} else if (name == 'filter'&& levelOptions.optimizeFilter && options.compatibility.properties.ieFilters) {
optimizeFilter(property);
- } else if (name == 'font' && levelOptions.optimizeFont) {
- optimizeFont(property, options);
} else if (name == 'font-weight' && levelOptions.optimizeFontWeight) {
optimizeFontWeight(property, 0);
} else if (name == 'outline' && levelOptions.optimizeOutline) {
@@ -717,7 +654,7 @@ function level1Optimize(tokens, context) {
break;
}
- if (token[1].length === 0 || (token[2] && token[2].length === 0)) {
+ if (levelOptions.removeEmpty && (token[1].length === 0 || (token[2] && token[2].length === 0))) {
tokens.splice(i, 1);
i--;
l--;
diff --git a/node_modules/clean-css/lib/optimizer/level-1/sort-selectors.js b/node_modules/clean-css/lib/optimizer/level-1/sort-selectors.js
index 2f179e6ef..5b261dfb0 100644
--- a/node_modules/clean-css/lib/optimizer/level-1/sort-selectors.js
+++ b/node_modules/clean-css/lib/optimizer/level-1/sort-selectors.js
@@ -9,17 +9,15 @@ function standardSorter(scope1, scope2) {
}
function sortSelectors(selectors, method) {
- var sorter;
-
switch (method) {
case 'natural':
- sorter = naturalSorter;
- break;
+ return selectors.sort(naturalSorter);
case 'standard':
- sorter = standardSorter;
+ return selectors.sort(standardSorter);
+ case 'none':
+ case false:
+ return selectors;
}
-
- return selectors.sort(sorter);
}
module.exports = sortSelectors;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/break-up.js b/node_modules/clean-css/lib/optimizer/level-2/break-up.js
index 9e44d5a1f..b48ccf23d 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/break-up.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/break-up.js
@@ -3,20 +3,31 @@ var InvalidPropertyError = require('./invalid-property-error');
var wrapSingle = require('../wrap-for-optimizing').single;
var Token = require('../../tokenizer/token');
+var Marker = require('../../tokenizer/marker');
var formatPosition = require('../../utils/format-position');
-var MULTIPLEX_SEPARATOR = ',';
+function _anyIsInherit(values) {
+ var i, l;
+
+ for (i = 0, l = values.length; i < l; i++) {
+ if (values[i][1] == 'inherit') {
+ return true;
+ }
+ }
+
+ return false;
+}
function _colorFilter(validator) {
return function (value) {
- return value[1] == 'invert' || validator.isValidColor(value[1]) || validator.isValidVendorPrefixedValue(value[1]);
+ return value[1] == 'invert' || validator.isColor(value[1]) || validator.isPrefixed(value[1]);
};
}
function _styleFilter(validator) {
return function (value) {
- return value[1] != 'inherit' && validator.isValidStyle(value[1]) && !validator.isValidColorValue(value[1]);
+ return value[1] != 'inherit' && validator.isStyleKeyword(value[1]) && !validator.isColorFunction(value[1]);
};
}
@@ -46,10 +57,80 @@ function _wrapDefault(name, property, compactable) {
function _widthFilter(validator) {
return function (value) {
- return value[1] != 'inherit' && validator.isValidWidth(value[1]) && !validator.isValidStyle(value[1]) && !validator.isValidColorValue(value[1]);
+ return value[1] != 'inherit' &&
+ (validator.isWidth(value[1]) || validator.isUnit(value[1]) && !validator.isDynamicUnit(value[1])) &&
+ !validator.isStyleKeyword(value[1]) &&
+ !validator.isColorFunction(value[1]);
};
}
+function animation(property, compactable, validator) {
+ var duration = _wrapDefault(property.name + '-duration', property, compactable);
+ var timing = _wrapDefault(property.name + '-timing-function', property, compactable);
+ var delay = _wrapDefault(property.name + '-delay', property, compactable);
+ var iteration = _wrapDefault(property.name + '-iteration-count', property, compactable);
+ var direction = _wrapDefault(property.name + '-direction', property, compactable);
+ var fill = _wrapDefault(property.name + '-fill-mode', property, compactable);
+ var play = _wrapDefault(property.name + '-play-state', property, compactable);
+ var name = _wrapDefault(property.name + '-name', property, compactable);
+ var components = [duration, timing, delay, iteration, direction, fill, play, name];
+ var values = property.value;
+ var value;
+ var durationSet = false;
+ var timingSet = false;
+ var delaySet = false;
+ var iterationSet = false;
+ var directionSet = false;
+ var fillSet = false;
+ var playSet = false;
+ var nameSet = false;
+ var i;
+ var l;
+
+ if (property.value.length == 1 && property.value[0][1] == 'inherit') {
+ duration.value = timing.value = delay.value = iteration.value = direction.value = fill.value = play.value = name.value = property.value;
+ return components;
+ }
+
+ if (values.length > 1 && _anyIsInherit(values)) {
+ throw new InvalidPropertyError('Invalid animation values at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ for (i = 0, l = values.length; i < l; i++) {
+ value = values[i];
+
+ if (validator.isTime(value[1]) && !durationSet) {
+ duration.value = [value];
+ durationSet = true;
+ } else if (validator.isTime(value[1]) && !delaySet) {
+ delay.value = [value];
+ delaySet = true;
+ } else if ((validator.isGlobal(value[1]) || validator.isAnimationTimingFunction(value[1])) && !timingSet) {
+ timing.value = [value];
+ timingSet = true;
+ } else if ((validator.isAnimationIterationCountKeyword(value[1]) || validator.isPositiveNumber(value[1])) && !iterationSet) {
+ iteration.value = [value];
+ iterationSet = true;
+ } else if (validator.isAnimationDirectionKeyword(value[1]) && !directionSet) {
+ direction.value = [value];
+ directionSet = true;
+ } else if (validator.isAnimationFillModeKeyword(value[1]) && !fillSet) {
+ fill.value = [value];
+ fillSet = true;
+ } else if (validator.isAnimationPlayStateKeyword(value[1]) && !playSet) {
+ play.value = [value];
+ playSet = true;
+ } else if ((validator.isAnimationNameKeyword(value[1]) || validator.isIdentifier(value[1])) && !nameSet) {
+ name.value = [value];
+ nameSet = true;
+ } else {
+ throw new InvalidPropertyError('Invalid animation value at ' + formatPosition(value[2][0]) + '. Ignoring.');
+ }
+ }
+
+ return components;
+}
+
function background(property, compactable, validator) {
var image = _wrapDefault('background-image', property, compactable);
var position = _wrapDefault('background-position', property, compactable);
@@ -82,10 +163,10 @@ function background(property, compactable, validator) {
for (var i = values.length - 1; i >= 0; i--) {
var value = values[i];
- if (validator.isValidBackgroundAttachment(value[1])) {
+ if (validator.isBackgroundAttachmentKeyword(value[1])) {
attachment.value = [value];
anyValueSet = true;
- } else if (validator.isValidBackgroundClip(value[1]) || validator.isValidBackgroundOrigin(value[1])) {
+ } else if (validator.isBackgroundClipKeyword(value[1]) || validator.isBackgroundOriginKeyword(value[1])) {
if (clipSet) {
origin.value = [value];
originSet = true;
@@ -94,7 +175,7 @@ function background(property, compactable, validator) {
clipSet = true;
}
anyValueSet = true;
- } else if (validator.isValidBackgroundRepeat(value[1])) {
+ } else if (validator.isBackgroundRepeatKeyword(value[1])) {
if (repeatSet) {
repeat.value.unshift(value);
} else {
@@ -102,13 +183,13 @@ function background(property, compactable, validator) {
repeatSet = true;
}
anyValueSet = true;
- } else if (validator.isValidBackgroundPositionPart(value[1]) || validator.isValidBackgroundSizePart(value[1])) {
+ } else if (validator.isBackgroundPositionKeyword(value[1]) || validator.isBackgroundSizeKeyword(value[1]) || validator.isUnit(value[1]) || validator.isDynamicUnit(value[1])) {
if (i > 0) {
var previousValue = values[i - 1];
- if (previousValue[1] == '/') {
+ if (previousValue[1] == Marker.FORWARD_SLASH) {
size.value = [value];
- } else if (i > 1 && values[i - 2][1] == '/') {
+ } else if (i > 1 && values[i - 2][1] == Marker.FORWARD_SLASH) {
size.value = [previousValue, value];
i -= 2;
} else {
@@ -126,10 +207,10 @@ function background(property, compactable, validator) {
positionSet = true;
}
anyValueSet = true;
- } else if ((color.value[0][1] == compactable[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isValidColor(value[1]) || validator.isValidVendorPrefixedValue(value[1]))) {
+ } else if ((color.value[0][1] == compactable[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isColor(value[1]) || validator.isPrefixed(value[1]))) {
color.value = [value];
anyValueSet = true;
- } else if (validator.isValidUrl(value[1]) || validator.isValidFunction(value[1])) {
+ } else if (validator.isUrl(value[1]) || validator.isFunction(value[1])) {
image.value = [value];
anyValueSet = true;
}
@@ -150,7 +231,7 @@ function borderRadius(property, compactable) {
var splitAt = -1;
for (var i = 0, l = values.length; i < l; i++) {
- if (values[i][1] == '/') {
+ if (values[i][1] == Marker.FORWARD_SLASH) {
splitAt = i;
break;
}
@@ -180,6 +261,122 @@ function borderRadius(property, compactable) {
return target.components;
}
+function font(property, compactable, validator) {
+ var style = _wrapDefault('font-style', property, compactable);
+ var variant = _wrapDefault('font-variant', property, compactable);
+ var weight = _wrapDefault('font-weight', property, compactable);
+ var stretch = _wrapDefault('font-stretch', property, compactable);
+ var size = _wrapDefault('font-size', property, compactable);
+ var height = _wrapDefault('line-height', property, compactable);
+ var family = _wrapDefault('font-family', property, compactable);
+ var components = [style, variant, weight, stretch, size, height, family];
+ var values = property.value;
+ var fuzzyMatched = 4; // style, variant, weight, and stretch
+ var index = 0;
+ var isStretchSet = false;
+ var isStretchValid;
+ var isStyleSet = false;
+ var isStyleValid;
+ var isVariantSet = false;
+ var isVariantValid;
+ var isWeightSet = false;
+ var isWeightValid;
+ var isSizeSet = false;
+ var appendableFamilyName = false;
+
+ if (!values[index]) {
+ throw new InvalidPropertyError('Missing font values at ' + formatPosition(property.all[property.position][1][2][0]) + '. Ignoring.');
+ }
+
+ if (values.length == 1 && values[0][1] == 'inherit') {
+ style.value = variant.value = weight.value = stretch.value = size.value = height.value = family.value = values;
+ return components;
+ }
+
+ if (values.length == 1 && (validator.isFontKeyword(values[0][1]) || validator.isGlobal(values[0][1]) || validator.isPrefixed(values[0][1]))) {
+ values[0][1] = Marker.INTERNAL + values[0][1];
+ style.value = variant.value = weight.value = stretch.value = size.value = height.value = family.value = values;
+ return components;
+ }
+
+ if (values.length > 1 && _anyIsInherit(values)) {
+ throw new InvalidPropertyError('Invalid font values at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ // fuzzy match style, variant, weight, and stretch on first elements
+ while (index < fuzzyMatched) {
+ isStretchValid = validator.isFontStretchKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+ isStyleValid = validator.isFontStyleKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+ isVariantValid = validator.isFontVariantKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+ isWeightValid = validator.isFontWeightKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+
+ if (isStyleValid && !isStyleSet) {
+ style.value = [values[index]];
+ isStyleSet = true;
+ } else if (isVariantValid && !isVariantSet) {
+ variant.value = [values[index]];
+ isVariantSet = true;
+ } else if (isWeightValid && !isWeightSet) {
+ weight.value = [values[index]];
+ isWeightSet = true;
+ } else if (isStretchValid && !isStretchSet) {
+ stretch.value = [values[index]];
+ isStretchSet = true;
+ } else if (isStyleValid && isStyleSet || isVariantValid && isVariantSet || isWeightValid && isWeightSet || isStretchValid && isStretchSet) {
+ throw new InvalidPropertyError('Invalid font style / variant / weight / stretch value at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ } else {
+ break;
+ }
+
+ index++;
+ }
+
+ // now comes font-size ...
+ if (validator.isFontSizeKeyword(values[index][1]) || validator.isUnit(values[index][1]) && !validator.isDynamicUnit(values[index][1])) {
+ size.value = [values[index]];
+ isSizeSet = true;
+ index++;
+ } else {
+ throw new InvalidPropertyError('Missing font size at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ if (!values[index]) {
+ throw new InvalidPropertyError('Missing font family at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ // ... and perhaps line-height
+ if (isSizeSet && values[index] && values[index][1] == Marker.FORWARD_SLASH && values[index + 1] && (validator.isLineHeightKeyword(values[index + 1][1]) || validator.isUnit(values[index + 1][1]) || validator.isNumber(values[index + 1][1]))) {
+ height.value = [values[index + 1]];
+ index++;
+ index++;
+ }
+
+ // ... and whatever comes next is font-family
+ family.value = [];
+
+ while (values[index]) {
+ if (values[index][1] == Marker.COMMA) {
+ appendableFamilyName = false;
+ } else {
+ if (appendableFamilyName) {
+ family.value[family.value.length - 1][1] += Marker.SPACE + values[index][1];
+ } else {
+ family.value.push(values[index]);
+ }
+
+ appendableFamilyName = true;
+ }
+
+ index++;
+ }
+
+ if (family.value.length === 0) {
+ throw new InvalidPropertyError('Missing font family at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ return components;
+}
+
function fourValues(property, compactable) {
var componentNames = compactable[property.name].components;
var components = [];
@@ -242,7 +439,7 @@ function multiplex(splitWith) {
components[i].multiplex = true;
for (j = 1, m = splitComponents.length; j < m; j++) {
- components[i].value.push([Token.PROPERTY_VALUE, MULTIPLEX_SEPARATOR]);
+ components[i].value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
Array.prototype.push.apply(components[i].value, splitComponents[j][i].value);
}
}
@@ -268,25 +465,26 @@ function listStyle(property, compactable, validator) {
// `image` first...
for (index = 0, total = values.length; index < total; index++) {
- if (validator.isValidUrl(values[index][1]) || values[index][1] == '0') {
+ if (validator.isUrl(values[index][1]) || values[index][1] == '0') {
image.value = [values[index]];
values.splice(index, 1);
break;
}
}
- // ... then `type`...
+ // ... then `position`
for (index = 0, total = values.length; index < total; index++) {
- if (validator.isValidListStyleType(values[index][1])) {
- type.value = [values[index]];
+ if (validator.isListStylePositionKeyword(values[index][1])) {
+ position.value = [values[index]];
values.splice(index, 1);
break;
}
}
- // ... and what's left is a `position`
- if (values.length > 0 && validator.isValidListStylePosition(values[0][1]))
- position.value = [values[0]];
+ // ... and what's left is a `type`
+ if (values.length > 0 && (validator.isListStyleTypeKeyword(values[0][1]) || validator.isIdentifier(values[0][1]))) {
+ type.value = [values[0]];
+ }
return components;
}
@@ -352,9 +550,11 @@ function widthStyleColor(property, compactable, validator) {
}
module.exports = {
+ animation: animation,
background: background,
border: widthStyleColor,
borderRadius: borderRadius,
+ font: font,
fourValues: fourValues,
listStyle: listStyle,
multiplex: multiplex,
diff --git a/node_modules/clean-css/lib/optimizer/level-2/can-override.js b/node_modules/clean-css/lib/optimizer/level-2/can-override.js
index 2617234ca..10d3bba17 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/can-override.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/can-override.js
@@ -1,11 +1,52 @@
var understandable = require('./properties/understandable');
+function animationIterationCount(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationIterationCountKeyword(value2) || validator.isPositiveNumber(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isAnimationIterationCountKeyword(value2) || validator.isPositiveNumber(value2);
+}
+
+function animationName(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationNameKeyword(value2) || validator.isIdentifier(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isAnimationNameKeyword(value2) || validator.isIdentifier(value2);
+}
+
+function animationTimingFunction(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationTimingFunction(value2) || validator.isGlobal(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isAnimationTimingFunction(value2) || validator.isGlobal(value2);
+}
+
+function areSameFunction(validator, value1, value2) {
+ if (!validator.isFunction(value1) || !validator.isFunction(value2)) {
+ return false;
+ }
+
+ var function1Name = value1.substring(0, value1.indexOf('('));
+ var function2Name = value2.substring(0, value2.indexOf('('));
+
+ return function1Name === function2Name;
+}
+
function backgroundPosition(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue('background-position', value2, true)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isBackgroundPositionKeyword(value2) || validator.isGlobal(value2))) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidKeywordValue('background-position', value2, true)) {
+ } else if (validator.isBackgroundPositionKeyword(value2) || validator.isGlobal(value2)) {
return true;
}
@@ -13,11 +54,11 @@ function backgroundPosition(validator, value1, value2) {
}
function backgroundSize(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue('background-size', value2, true)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isBackgroundSizeKeyword(value2) || validator.isGlobal(value2))) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidKeywordValue('background-size', value2, true)) {
+ } else if (validator.isBackgroundSizeKeyword(value2) || validator.isGlobal(value2)) {
return true;
}
@@ -25,15 +66,15 @@ function backgroundSize(validator, value1, value2) {
}
function color(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidColor(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isColor(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (!validator.colorOpacity && (validator.isValidRgbaColor(value1) || validator.isValidHslaColor(value1))) {
+ } else if (!validator.colorOpacity && (validator.isRgbColor(value1) || validator.isHslColor(value1))) {
return false;
- } else if (!validator.colorOpacity && (validator.isValidRgbaColor(value2) || validator.isValidHslaColor(value2))) {
+ } else if (!validator.colorOpacity && (validator.isRgbColor(value2) || validator.isHslColor(value2))) {
return false;
- } else if (validator.isValidColor(value1) && validator.isValidColor(value2)) {
+ } else if (validator.isColor(value1) && validator.isColor(value2)) {
return true;
}
@@ -46,14 +87,18 @@ function components(overrideCheckers) {
};
}
+function fontFamily(validator, value1, value2) {
+ return understandable(validator, value1, value2, 0, true);
+}
+
function image(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidImage(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isImage(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidImage(value2)) {
+ } else if (validator.isImage(value2)) {
return true;
- } else if (validator.isValidImage(value1)) {
+ } else if (validator.isImage(value1)) {
return false;
}
@@ -62,56 +107,76 @@ function image(validator, value1, value2) {
function keyword(propertyName) {
return function(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue(propertyName, value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isKeyword(propertyName)(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
}
- return validator.isValidKeywordValue(propertyName, value2, false);
+ return validator.isKeyword(propertyName)(value2);
};
}
function keywordWithGlobal(propertyName) {
return function(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue(propertyName, value2, true)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isKeyword(propertyName)(value2) || validator.isGlobal(value2))) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
}
- return validator.isValidKeywordValue(propertyName, value2, true);
+ return validator.isKeyword(propertyName)(value2) || validator.isGlobal(value2);
};
}
function sameFunctionOrValue(validator, value1, value2) {
- return validator.areSameFunction(value1, value2) ?
+ return areSameFunction(validator, value1, value2) ?
true :
value1 === value2;
}
+
+
function textShadow(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidTextShadow(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2);
+}
+
+function time(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isTime(value2)) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ } else if (validator.isTime(value1) && !validator.isTime(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isTime(value2)) {
+ return true;
+ } else if (validator.isTime(value1)) {
+ return false;
+ } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
return true;
}
- return validator.isValidTextShadow(value2);
+ return sameFunctionOrValue(validator, value1, value2);
}
function unit(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidUnitWithoutFunction(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isUnit(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidUnitWithoutFunction(value1) && !validator.isValidUnitWithoutFunction(value2)) {
+ } else if (validator.isUnit(value1) && !validator.isUnit(value2)) {
return false;
- } else if (validator.isValidUnitWithoutFunction(value2)) {
+ } else if (validator.isUnit(value2)) {
return true;
- } else if (validator.isValidUnitWithoutFunction(value1)) {
+ } else if (validator.isUnit(value1)) {
return false;
- } else if (validator.isValidFunctionWithoutVendorPrefix(value1) && validator.isValidFunctionWithoutVendorPrefix(value2)) {
+ } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
return true;
}
@@ -127,13 +192,13 @@ function unitOrKeywordWithGlobal(propertyName) {
}
function zIndex(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidZIndex(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isZIndex(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
}
- return validator.isValidZIndex(value2);
+ return validator.isZIndex(value2);
}
module.exports = {
@@ -141,9 +206,16 @@ module.exports = {
color: color,
components: components,
image: image,
+ time: time,
unit: unit
},
property: {
+ animationDirection: keywordWithGlobal('animation-direction'),
+ animationFillMode: keyword('animation-fill-mode'),
+ animationIterationCount: animationIterationCount,
+ animationName: animationName,
+ animationPlayState: keywordWithGlobal('animation-play-state'),
+ animationTimingFunction: animationTimingFunction,
backgroundAttachment: keyword('background-attachment'),
backgroundClip: keywordWithGlobal('background-clip'),
backgroundOrigin: keyword('background-origin'),
@@ -157,8 +229,11 @@ module.exports = {
cursor: keywordWithGlobal('cursor'),
display: keywordWithGlobal('display'),
float: keywordWithGlobal('float'),
- fontStyle: keywordWithGlobal('font-style'),
left: unitOrKeywordWithGlobal('left'),
+ fontFamily: fontFamily,
+ fontStretch: keywordWithGlobal('font-stretch'),
+ fontStyle: keywordWithGlobal('font-style'),
+ fontVariant: keywordWithGlobal('font-variant'),
fontWeight: keywordWithGlobal('font-weight'),
listStyleType: keywordWithGlobal('list-style-type'),
listStylePosition: keywordWithGlobal('list-style-position'),
diff --git a/node_modules/clean-css/lib/optimizer/level-2/compactable.js b/node_modules/clean-css/lib/optimizer/level-2/compactable.js
index 9cf334d44..97e7e2aca 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/compactable.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/compactable.js
@@ -35,6 +35,141 @@ var override = require('../../utils/override');
// Puts the shorthand together from its components.
//
var compactable = {
+ 'animation': {
+ canOverride: canOverride.generic.components([
+ canOverride.generic.time,
+ canOverride.property.animationTimingFunction,
+ canOverride.generic.time,
+ canOverride.property.animationIterationCount,
+ canOverride.property.animationDirection,
+ canOverride.property.animationFillMode,
+ canOverride.property.animationPlayState,
+ canOverride.property.animationName
+ ]),
+ components: [
+ 'animation-duration',
+ 'animation-timing-function',
+ 'animation-delay',
+ 'animation-iteration-count',
+ 'animation-direction',
+ 'animation-fill-mode',
+ 'animation-play-state',
+ 'animation-name'
+ ],
+ breakUp: breakUp.multiplex(breakUp.animation),
+ defaultValue: 'none',
+ restore: restore.multiplex(restore.withoutDefaults),
+ shorthand: true,
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-delay': {
+ canOverride: canOverride.generic.time,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: '0s',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-direction': {
+ canOverride: canOverride.property.animationDirection,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'normal',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-duration': {
+ canOverride: canOverride.generic.time,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: '0s',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-fill-mode': {
+ canOverride: canOverride.property.animationFillMode,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'none',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-iteration-count': {
+ canOverride: canOverride.property.animationIterationCount,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: '1',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-name': {
+ canOverride: canOverride.property.animationName,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'none',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-play-state': {
+ canOverride: canOverride.property.animationPlayState,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'running',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-timing-function': {
+ canOverride: canOverride.property.animationTimingFunction,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'ease',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
'background': {
canOverride: canOverride.generic.components([
canOverride.generic.image,
@@ -67,7 +202,8 @@ var compactable = {
componentOf: [
'background'
],
- defaultValue: 'scroll'
+ defaultValue: 'scroll',
+ intoMultiplexMode: 'real'
},
'background-clip': {
canOverride: canOverride.property.backgroundClip,
@@ -75,6 +211,7 @@ var compactable = {
'background'
],
defaultValue: 'border-box',
+ intoMultiplexMode: 'real',
shortestValue: 'border-box'
},
'background-color': {
@@ -83,6 +220,7 @@ var compactable = {
'background'
],
defaultValue: 'transparent',
+ intoMultiplexMode: 'real', // otherwise real color will turn into default since color appears in last multiplex only
multiplexLastOnly: true,
nonMergeableValue: 'none',
shortestValue: 'red'
@@ -92,7 +230,8 @@ var compactable = {
componentOf: [
'background'
],
- defaultValue: 'none'
+ defaultValue: 'none',
+ intoMultiplexMode: 'default'
},
'background-origin': {
canOverride: canOverride.property.backgroundOrigin,
@@ -100,6 +239,7 @@ var compactable = {
'background'
],
defaultValue: 'padding-box',
+ intoMultiplexMode: 'real',
shortestValue: 'border-box'
},
'background-position': {
@@ -109,6 +249,7 @@ var compactable = {
],
defaultValue: ['0', '0'],
doubleValues: true,
+ intoMultiplexMode: 'real',
shortestValue: '0'
},
'background-repeat': {
@@ -117,7 +258,8 @@ var compactable = {
'background'
],
defaultValue: ['repeat'],
- doubleValues: true
+ doubleValues: true,
+ intoMultiplexMode: 'real'
},
'background-size': {
canOverride: canOverride.property.backgroundSize,
@@ -126,6 +268,7 @@ var compactable = {
],
defaultValue: ['auto'],
doubleValues: true,
+ intoMultiplexMode: 'real',
shortestValue: '0 0'
},
'bottom': {
@@ -216,6 +359,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-top-width',
shortestValue: '0'
},
'border-collapse': {
@@ -230,7 +374,9 @@ var compactable = {
canOverride.generic.color,
canOverride.generic.color
]),
- componentOf: ['border'],
+ componentOf: [
+ 'border'
+ ],
components: [
'border-top-color',
'border-right-color',
@@ -281,6 +427,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-right-width',
shortestValue: '0'
},
'border-radius': {
@@ -344,6 +491,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-left-width',
shortestValue: '0'
},
'border-style': {
@@ -428,6 +576,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-bottom-width',
shortestValue: '0'
},
'border-width': {
@@ -438,6 +587,9 @@ var compactable = {
canOverride.generic.unit,
canOverride.generic.unit
]),
+ componentOf: [
+ 'border'
+ ],
components: [
'border-top-width',
'border-right-width',
@@ -469,18 +621,53 @@ var compactable = {
canOverride: canOverride.property.float,
defaultValue: 'none'
},
+ 'font': {
+ breakUp: breakUp.font,
+ canOverride: canOverride.generic.components([
+ canOverride.property.fontStyle,
+ canOverride.property.fontVariant,
+ canOverride.property.fontWeight,
+ canOverride.property.fontStretch,
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.property.fontFamily
+ ]),
+ components: [
+ 'font-style',
+ 'font-variant',
+ 'font-weight',
+ 'font-stretch',
+ 'font-size',
+ 'line-height',
+ 'font-family'
+ ],
+ restore: restore.font,
+ shorthand: true
+ },
+ 'font-family': {
+ canOverride: canOverride.property.fontFamily,
+ defaultValue: 'user|agent|specific'
+ },
'font-size': {
canOverride: canOverride.generic.unit,
defaultValue: 'medium',
shortestValue: '0'
},
+ 'font-stretch': {
+ canOverride: canOverride.property.fontStretch,
+ defaultValue: 'normal'
+ },
'font-style': {
canOverride: canOverride.property.fontStyle,
defaultValue: 'normal'
},
+ 'font-variant': {
+ canOverride: canOverride.property.fontVariant,
+ defaultValue: 'normal'
+ },
'font-weight': {
canOverride: canOverride.property.fontWeight,
- defaultValue: '400',
+ defaultValue: 'normal',
shortestValue: '400'
},
'height': {
@@ -563,28 +750,32 @@ var compactable = {
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-top'
},
'margin-left': {
canOverride: canOverride.generic.unit,
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-right'
},
'margin-right': {
canOverride: canOverride.generic.unit,
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-left'
},
'margin-top': {
canOverride: canOverride.generic.unit,
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-bottom'
},
'outline': {
canOverride: canOverride.generic.components([
@@ -660,28 +851,32 @@ var compactable = {
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-top'
},
'padding-left': {
canOverride: canOverride.generic.unit,
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-right'
},
'padding-right': {
canOverride: canOverride.generic.unit,
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-left'
},
'padding-top': {
canOverride: canOverride.generic.unit,
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-bottom'
},
'position': {
canOverride: canOverride.property.position,
diff --git a/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js b/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
index 4a91a8331..29049302a 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
@@ -14,6 +14,19 @@ var PSEUDO_CLASSES_WITH_ARGUMENTS = [
':nth-of-type'
];
var RELATION_PATTERN = /[>\+~]/;
+var UNMIXABLE_PSEUDO_CLASSES = [
+ ':after',
+ ':before',
+ ':first-letter',
+ ':first-line',
+ ':lang'
+];
+var UNMIXABLE_PSEUDO_ELEMENTS = [
+ '::after',
+ '::before',
+ '::first-letter',
+ '::first-line'
+];
var Level = {
DOUBLE_QUOTE: 'double-quote',
@@ -21,7 +34,7 @@ var Level = {
ROOT: 'root'
};
-function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements) {
+function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
var singleSelectors = split(selector, Marker.COMMA);
var singleSelector;
var i, l;
@@ -31,7 +44,7 @@ function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements)
if (singleSelector.length === 0 ||
isDeepSelector(singleSelector) ||
- (singleSelector.indexOf(Marker.COLON) > -1 && !areMergeable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements))) {
+ (singleSelector.indexOf(Marker.COLON) > -1 && !areMergeable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging))) {
return false;
}
}
@@ -122,11 +135,11 @@ function extractPseudoFrom(selector) {
return list;
}
-function areMergeable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements) {
+function areMergeable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
return areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) &&
needArguments(matches) &&
(matches.length < 2 || !someIncorrectlyChained(selector, matches)) &&
- (matches.length < 2 || !someMixed(matches));
+ (matches.length < 2 || multiplePseudoMerging && allMixable(matches));
}
function areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) {
@@ -217,20 +230,30 @@ function someIncorrectlyChained(selector, matches) {
return false;
}
-function someMixed(matches) {
- var firstIsPseudoElement = DOUBLE_COLON_PATTERN.test(matches[0]);
+function allMixable(matches) {
+ var unmixableMatches = 0;
var match;
var i, l;
for (i = 0, l = matches.length; i < l; i++) {
match = matches[i];
- if (DOUBLE_COLON_PATTERN.test(match) != firstIsPseudoElement) {
- return true;
+ if (isPseudoElement(match)) {
+ unmixableMatches += UNMIXABLE_PSEUDO_ELEMENTS.indexOf(match) > -1 ? 1 : 0;
+ } else {
+ unmixableMatches += UNMIXABLE_PSEUDO_CLASSES.indexOf(match) > -1 ? 1 : 0;
+ }
+
+ if (unmixableMatches > 1) {
+ return false;
}
}
- return false;
+ return true;
+}
+
+function isPseudoElement(pseudo) {
+ return DOUBLE_COLON_PATTERN.test(pseudo);
}
module.exports = isMergeable;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js b/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
index 7c0537501..b148bacd7 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
@@ -19,7 +19,8 @@ function mergeAdjacent(tokens, context) {
var selectorsSortingMethod = options.level[OptimizationLevel.One].selectorsSortingMethod;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
- var mergeLimit = 8191;
+ var mergeLimit = options.compatibility.selectors.mergeLimit;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
for (var i = 0, l = tokens.length; i < l; i++) {
var token = tokens[i];
@@ -34,8 +35,8 @@ function mergeAdjacent(tokens, context) {
optimizeProperties(lastToken[2], true, true, context);
token[2] = [];
} else if (lastToken[0] == Token.RULE && serializeBody(token[2]) == serializeBody(lastToken[2]) &&
- isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
- isMergeable(serializeRules(lastToken[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
+ isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
+ isMergeable(serializeRules(lastToken[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
lastToken[1].length < mergeLimit) {
lastToken[1] = tidyRules(lastToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
lastToken[1] = lastToken.length > 1 ? sortSelectors(lastToken[1], selectorsSortingMethod) : lastToken[1];
diff --git a/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js b/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
index bdcf53ec0..82db950fe 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
@@ -42,6 +42,7 @@ function mergeNonAdjacentByBody(tokens, context) {
var selectorsSortingMethod = options.level[OptimizationLevel.One].selectorsSortingMethod;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var candidates = {};
for (var i = tokens.length - 1; i >= 0; i--) {
@@ -58,8 +59,8 @@ function mergeNonAdjacentByBody(tokens, context) {
var candidateBody = serializeBody(token[2]);
var oldToken = candidates[candidateBody];
if (oldToken &&
- isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
- isMergeable(serializeRules(oldToken[1]), mergeablePseudoClasses, mergeablePseudoElements)) {
+ isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
+ isMergeable(serializeRules(oldToken[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)) {
if (token[2].length > 0) {
token[1] = tidyRules(oldToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
diff --git a/node_modules/clean-css/lib/optimizer/level-2/optimize.js b/node_modules/clean-css/lib/optimizer/level-2/optimize.js
index 78cd44666..9be961d09 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/optimize.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/optimize.js
@@ -6,6 +6,7 @@ var reduceNonAdjacent = require('./reduce-non-adjacent');
var removeDuplicateFontAtRules = require('./remove-duplicate-font-at-rules');
var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
var removeDuplicates = require('./remove-duplicates');
+var removeUnusedAtRules = require('./remove-unused-at-rules');
var restructure = require('./restructure');
var optimizeProperties = require('./properties/optimize');
@@ -27,6 +28,9 @@ function removeEmpty(tokens) {
removeEmpty(token[2]);
isEmpty = token[2].length === 0;
break;
+ case Token.AT_RULE:
+ isEmpty = token[1].length === 0;
+ break;
case Token.AT_RULE_BLOCK:
isEmpty = token[2].length === 0;
}
@@ -109,6 +113,10 @@ function level2Optimize(tokens, context, withRestructuring) {
removeDuplicateMediaQueries(tokens, context);
}
+ if (levelOptions.removeUnusedAtRules) {
+ removeUnusedAtRules(tokens, context);
+ }
+
if (levelOptions.mergeMedia) {
reduced = mergeMediaQueries(tokens, context);
for (i = reduced.length - 1; i >= 0; i--) {
@@ -116,7 +124,9 @@ function level2Optimize(tokens, context, withRestructuring) {
}
}
- removeEmpty(tokens);
+ if (levelOptions.removeEmpty) {
+ removeEmpty(tokens);
+ }
return tokens;
}
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js b/node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js
new file mode 100644
index 000000000..ee7191ef6
--- /dev/null
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js
@@ -0,0 +1,11 @@
+var Marker = require('../../../tokenizer/marker');
+
+function isMergeableShorthand(shorthand) {
+ if (shorthand.name != 'font') {
+ return true;
+ }
+
+ return shorthand.value[0][1].indexOf(Marker.INTERNAL) == -1;
+}
+
+module.exports = isMergeableShorthand;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js b/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
index a75c4ed63..bcfeeb609 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
@@ -4,52 +4,410 @@ var populateComponents = require('./populate-components');
var compactable = require('../compactable');
var deepClone = require('../clone').deep;
+var restoreWithComponents = require('../restore-with-components');
+var restoreFromOptimizing = require('../../restore-from-optimizing');
var wrapSingle = require('../../wrap-for-optimizing').single;
+var serializeBody = require('../../../writer/one-time').body;
var Token = require('../../../tokenizer/token');
+function mergeIntoShorthands(properties, validator) {
+ var candidates = {};
+ var descriptor;
+ var componentOf;
+ var property;
+ var i, l;
+ var j, m;
+
+ // there is no shorthand property made up of less than 3 longhands
+ if (properties.length < 3) {
+ return;
+ }
+
+ for (i = 0, l = properties.length; i < l; i++) {
+ property = properties[i];
+ descriptor = compactable[property.name];
+
+ if (property.unused) {
+ continue;
+ }
+
+ if (property.hack) {
+ continue;
+ }
+
+ if (property.block) {
+ continue;
+ }
+
+ invalidateOrCompact(properties, i, candidates, validator);
+
+ if (descriptor && descriptor.componentOf) {
+ for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
+ componentOf = descriptor.componentOf[j];
+
+ candidates[componentOf] = candidates[componentOf] || {};
+ candidates[componentOf][property.name] = property;
+ }
+ }
+ }
+
+ invalidateOrCompact(properties, i, candidates, validator);
+}
+
+function invalidateOrCompact(properties, position, candidates, validator) {
+ var invalidatedBy = properties[position];
+ var shorthandName;
+ var shorthandDescriptor;
+ var candidateComponents;
+
+ for (shorthandName in candidates) {
+ if (undefined !== invalidatedBy && shorthandName == invalidatedBy.name) {
+ continue;
+ }
+
+ shorthandDescriptor = compactable[shorthandName];
+ candidateComponents = candidates[shorthandName];
+ if (invalidatedBy && invalidates(candidates, shorthandName, invalidatedBy)) {
+ delete candidates[shorthandName];
+ continue;
+ }
+
+ if (shorthandDescriptor.components.length > Object.keys(candidateComponents).length) {
+ continue;
+ }
+
+ if (mixedImportance(candidateComponents)) {
+ continue;
+ }
+
+ if (!overridable(candidateComponents, shorthandName, validator)) {
+ continue;
+ }
+
+ if (!mergeable(candidateComponents)) {
+ continue;
+ }
+
+ if (mixedInherit(candidateComponents)) {
+ replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator);
+ } else {
+ replaceWithShorthand(properties, candidateComponents, shorthandName, validator);
+ }
+ }
+}
+
+function invalidates(candidates, shorthandName, invalidatedBy) {
+ var shorthandDescriptor = compactable[shorthandName];
+ var invalidatedByDescriptor = compactable[invalidatedBy.name];
+ var componentName;
+
+ if ('overridesShorthands' in shorthandDescriptor && shorthandDescriptor.overridesShorthands.indexOf(invalidatedBy.name) > -1) {
+ return true;
+ }
+
+ if (invalidatedByDescriptor && 'componentOf' in invalidatedByDescriptor) {
+ for (componentName in candidates[shorthandName]) {
+ if (invalidatedByDescriptor.componentOf.indexOf(componentName) > -1) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
function mixedImportance(components) {
var important;
+ var componentName;
- for (var name in components) {
- if (undefined !== important && components[name].important != important)
+ for (componentName in components) {
+ if (undefined !== important && components[componentName].important != important) {
return true;
+ }
- important = components[name].important;
+ important = components[componentName].important;
}
return false;
}
+function overridable(components, shorthandName, validator) {
+ var descriptor = compactable[shorthandName];
+ var newValuePlaceholder = [
+ Token.PROPERTY,
+ [Token.PROPERTY_NAME, shorthandName],
+ [Token.PROPERTY_VALUE, descriptor.defaultValue]
+ ];
+ var newProperty = wrapSingle(newValuePlaceholder);
+ var component;
+ var mayOverride;
+ var i, l;
+
+ populateComponents([newProperty], validator, []);
+
+ for (i = 0, l = descriptor.components.length; i < l; i++) {
+ component = components[descriptor.components[i]];
+ mayOverride = compactable[component.name].canOverride;
+
+ if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function mergeable(components) {
+ var lastCount = null;
+ var currentCount;
+ var componentName;
+ var component;
+ var descriptor;
+ var values;
+
+ for (componentName in components) {
+ component = components[componentName];
+ descriptor = compactable[componentName];
+
+ if (!('restore' in descriptor)) {
+ continue;
+ }
+
+ restoreFromOptimizing([component.all[component.position]], restoreWithComponents);
+ values = descriptor.restore(component, compactable);
+
+ currentCount = values.length;
+
+ if (lastCount !== null && currentCount !== lastCount) {
+ return false;
+ }
+
+ lastCount = currentCount;
+ }
+
+ return true;
+}
+
+function mixedInherit(components) {
+ var componentName;
+ var lastValue = null;
+ var currentValue;
+
+ for (componentName in components) {
+ currentValue = hasInherit(components[componentName]);
+
+ if (lastValue !== null && lastValue !== currentValue) {
+ return true;
+ }
+
+ lastValue = currentValue;
+ }
+
+ return false;
+}
+
+function replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator) {
+ var viaLonghands = buildSequenceWithInheritLonghands(candidateComponents, shorthandName, validator);
+ var viaShorthand = buildSequenceWithInheritShorthand(candidateComponents, shorthandName, validator);
+ var longhandTokensSequence = viaLonghands[0];
+ var shorthandTokensSequence = viaShorthand[0];
+ var isLonghandsShorter = serializeBody(longhandTokensSequence).length < serializeBody(shorthandTokensSequence).length;
+ var newTokensSequence = isLonghandsShorter ? longhandTokensSequence : shorthandTokensSequence;
+ var newProperty = isLonghandsShorter ? viaLonghands[1] : viaShorthand[1];
+ var newComponents = isLonghandsShorter ? viaLonghands[2] : viaShorthand[2];
+ var all = candidateComponents[Object.keys(candidateComponents)[0]].all;
+ var componentName;
+ var oldComponent;
+ var newComponent;
+ var newToken;
+
+ newProperty.position = all.length;
+ newProperty.shorthand = true;
+ newProperty.dirty = true;
+ newProperty.all = all;
+ newProperty.all.push(newTokensSequence[0]);
+
+ properties.push(newProperty);
+
+ for (componentName in candidateComponents) {
+ oldComponent = candidateComponents[componentName];
+ oldComponent.unused = true;
+
+ if (oldComponent.name in newComponents) {
+ newComponent = newComponents[oldComponent.name];
+ newToken = findTokenIn(newTokensSequence, componentName);
+
+ newComponent.position = all.length;
+ newComponent.all = all;
+ newComponent.all.push(newToken);
+
+ properties.push(newComponent);
+ }
+ }
+}
+
+function buildSequenceWithInheritLonghands(components, shorthandName, validator) {
+ var tokensSequence = [];
+ var inheritComponents = {};
+ var nonInheritComponents = {};
+ var descriptor = compactable[shorthandName];
+ var shorthandToken = [
+ Token.PROPERTY,
+ [Token.PROPERTY_NAME, shorthandName],
+ [Token.PROPERTY_VALUE, descriptor.defaultValue]
+ ];
+ var newProperty = wrapSingle(shorthandToken);
+ var component;
+ var longhandToken;
+ var newComponent;
+ var nameMetadata;
+ var i, l;
+
+ populateComponents([newProperty], validator, []);
+
+ for (i = 0, l = descriptor.components.length; i < l; i++) {
+ component = components[descriptor.components[i]];
+
+ if (hasInherit(component)) {
+ longhandToken = component.all[component.position].slice(0, 2);
+ Array.prototype.push.apply(longhandToken, component.value);
+ tokensSequence.push(longhandToken);
+
+ newComponent = deepClone(component);
+ newComponent.value = inferComponentValue(components, newComponent.name);
+
+ newProperty.components[i] = newComponent;
+ inheritComponents[component.name] = deepClone(component);
+ } else {
+ newComponent = deepClone(component);
+ newComponent.all = component.all;
+ newProperty.components[i] = newComponent;
+
+ nonInheritComponents[component.name] = component;
+ }
+ }
+
+ nameMetadata = joinMetadata(nonInheritComponents, 1);
+ shorthandToken[1].push(nameMetadata);
+
+ restoreFromOptimizing([newProperty], restoreWithComponents);
+
+ shorthandToken = shorthandToken.slice(0, 2);
+ Array.prototype.push.apply(shorthandToken, newProperty.value);
+
+ tokensSequence.unshift(shorthandToken);
+
+ return [tokensSequence, newProperty, inheritComponents];
+}
+
+function inferComponentValue(components, propertyName) {
+ var descriptor = compactable[propertyName];
+
+ if ('oppositeTo' in descriptor) {
+ return components[descriptor.oppositeTo].value;
+ } else {
+ return [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
+ }
+}
+
function joinMetadata(components, at) {
var metadata = [];
var component;
var originalValue;
var componentMetadata;
- var name;
+ var componentName;
- for (name in components) {
- component = components[name];
+ for (componentName in components) {
+ component = components[componentName];
originalValue = component.all[component.position];
componentMetadata = originalValue[at][originalValue[at].length - 1];
Array.prototype.push.apply(metadata, componentMetadata);
}
- return metadata;
+ return metadata.sort(metadataSorter);
+}
+
+function metadataSorter(metadata1, metadata2) {
+ var line1 = metadata1[0];
+ var line2 = metadata2[0];
+ var column1 = metadata1[1];
+ var column2 = metadata2[1];
+
+ if (line1 < line2) {
+ return -1;
+ } else if (line1 === line2) {
+ return column1 < column2 ? -1 : 1;
+ } else {
+ return 1;
+ }
}
-function replaceWithShorthand(properties, candidateComponents, name, validator) {
- var descriptor = compactable[name];
+function buildSequenceWithInheritShorthand(components, shorthandName, validator) {
+ var tokensSequence = [];
+ var inheritComponents = {};
+ var nonInheritComponents = {};
+ var descriptor = compactable[shorthandName];
+ var shorthandToken = [
+ Token.PROPERTY,
+ [Token.PROPERTY_NAME, shorthandName],
+ [Token.PROPERTY_VALUE, 'inherit']
+ ];
+ var newProperty = wrapSingle(shorthandToken);
+ var component;
+ var longhandToken;
+ var nameMetadata;
+ var valueMetadata;
+ var i, l;
+
+ populateComponents([newProperty], validator, []);
+
+ for (i = 0, l = descriptor.components.length; i < l; i++) {
+ component = components[descriptor.components[i]];
+
+ if (hasInherit(component)) {
+ inheritComponents[component.name] = component;
+ } else {
+ longhandToken = component.all[component.position].slice(0, 2);
+ Array.prototype.push.apply(longhandToken, component.value);
+ tokensSequence.push(longhandToken);
+
+ nonInheritComponents[component.name] = deepClone(component);
+ }
+ }
+
+ nameMetadata = joinMetadata(inheritComponents, 1);
+ shorthandToken[1].push(nameMetadata);
+
+ valueMetadata = joinMetadata(inheritComponents, 2);
+ shorthandToken[2].push(valueMetadata);
+
+ tokensSequence.unshift(shorthandToken);
+
+ return [tokensSequence, newProperty, nonInheritComponents];
+}
+
+function findTokenIn(tokens, componentName) {
+ var i, l;
+
+ for (i = 0, l = tokens.length; i < l; i++) {
+ if (tokens[i][1][1] == componentName) {
+ return tokens[i];
+ }
+ }
+}
+
+function replaceWithShorthand(properties, candidateComponents, shorthandName, validator) {
+ var descriptor = compactable[shorthandName];
var nameMetadata;
var valueMetadata;
var newValuePlaceholder = [
Token.PROPERTY,
- [Token.PROPERTY_NAME, name],
+ [Token.PROPERTY_NAME, shorthandName],
[Token.PROPERTY_VALUE, descriptor.defaultValue]
];
- var mayOverride;
var all;
var newProperty = wrapSingle(newValuePlaceholder);
@@ -61,13 +419,6 @@ function replaceWithShorthand(properties, candidateComponents, name, validator)
for (var i = 0, l = descriptor.components.length; i < l; i++) {
var component = candidateComponents[descriptor.components[i]];
- if (hasInherit(component))
- return;
-
- mayOverride = compactable[component.name].canOverride;
- if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component))
- return;
-
newProperty.components[i] = deepClone(component);
newProperty.important = component.important;
@@ -91,67 +442,4 @@ function replaceWithShorthand(properties, candidateComponents, name, validator)
properties.push(newProperty);
}
-function invalidateOrCompact(properties, position, candidates, validator) {
- var property = properties[position];
-
- for (var name in candidates) {
- if (undefined !== property && name == property.name)
- continue;
-
- var descriptor = compactable[name];
- var candidateComponents = candidates[name];
- if (descriptor.components.length > Object.keys(candidateComponents).length) {
- delete candidates[name];
- continue;
- }
-
- if (mixedImportance(candidateComponents))
- continue;
-
- replaceWithShorthand(properties, candidateComponents, name, validator);
- }
-}
-
-function mergeIntoShorthands(properties, validator) {
- var candidates = {};
- var descriptor;
- var componentOf;
- var property;
- var i, l;
- var j, m;
-
- if (properties.length < 3)
- return;
-
- for (i = 0, l = properties.length; i < l; i++) {
- property = properties[i];
-
- if (property.unused)
- continue;
-
- if (property.hack)
- continue;
-
- if (property.block)
- continue;
-
- descriptor = compactable[property.name];
- if (!descriptor || !descriptor.componentOf)
- continue;
-
- if (property.shorthand) {
- invalidateOrCompact(properties, i, candidates, validator);
- } else {
- for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
- componentOf = descriptor.componentOf[j];
-
- candidates[componentOf] = candidates[componentOf] || {};
- candidates[componentOf][property.name] = property;
- }
- }
- }
-
- invalidateOrCompact(properties, i, candidates, validator);
-}
-
module.exports = mergeIntoShorthands;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js b/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
index 250b05fc4..5dc4bfb98 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
@@ -11,7 +11,8 @@ var restoreFromOptimizing = require('../../restore-from-optimizing');
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
function optimizeProperties(properties, withOverriding, withMerging, context) {
- var _properties = wrapForOptimizing(properties, false);
+ var levelOptions = context.options.level[OptimizationLevel.Two];
+ var _properties = wrapForOptimizing(properties, false, levelOptions.skipProperties);
var _property;
var i, l;
@@ -24,12 +25,12 @@ function optimizeProperties(properties, withOverriding, withMerging, context) {
}
}
- if (withOverriding && context.options.level[OptimizationLevel.Two].overrideProperties) {
- overrideProperties(_properties, withMerging, context.options.compatibility, context.validator);
+ if (withMerging && levelOptions.mergeIntoShorthands) {
+ mergeIntoShorthands(_properties, context.validator);
}
- if (withMerging && context.options.level[OptimizationLevel.Two].mergeIntoShorthands) {
- mergeIntoShorthands(_properties, context.validator);
+ if (withOverriding && levelOptions.overrideProperties) {
+ overrideProperties(_properties, withMerging, context.options.compatibility, context.validator);
}
restoreFromOptimizing(_properties, restoreWithComponents);
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js b/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
index 3c9d8d2af..3749720c9 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
@@ -2,6 +2,7 @@ var hasInherit = require('./has-inherit');
var everyValuesPair = require('./every-values-pair');
var findComponentIn = require('./find-component-in');
var isComponentOf = require('./is-component-of');
+var isMergeableShorthand = require('./is-mergeable-shorthand');
var overridesNonComponentShorthand = require('./overrides-non-component-shorthand');
var sameVendorPrefixesIn = require('./vendor-prefixes').same;
@@ -73,16 +74,44 @@ function overrideShorthand(property, by) {
function turnIntoMultiplex(property, size) {
property.multiplex = true;
- for (var i = 0, l = property.components.length; i < l; i++) {
- var component = property.components[i];
- if (component.multiplex)
- continue;
+ if (compactable[property.name].shorthand) {
+ turnShorthandValueIntoMultiplex(property, size);
+ } else {
+ turnLonghandValueIntoMultiplex(property, size);
+ }
+}
- var value = component.value.slice(0);
+function turnShorthandValueIntoMultiplex(property, size) {
+ var component;
+ var i, l;
- for (var j = 1; j < size; j++) {
- component.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
- Array.prototype.push.apply(component.value, value);
+ for (i = 0, l = property.components.length; i < l; i++) {
+ component = property.components[i];
+
+ if (!component.multiplex) {
+ turnLonghandValueIntoMultiplex(component, size);
+ }
+ }
+}
+
+function turnLonghandValueIntoMultiplex(property, size) {
+ var withRealValue = compactable[property.name].intoMultiplexMode == 'real';
+ var withValue = withRealValue ?
+ property.value.slice(0) :
+ compactable[property.name].defaultValue;
+ var i = multiplexSize(property);
+ var j;
+ var m = withValue.length;
+
+ for (; i < size; i++) {
+ property.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
+
+ if (Array.isArray(withValue)) {
+ for (j = 0; j < m; j++) {
+ property.value.push(withRealValue ? withValue[j] : [Token.PROPERTY_VALUE, withValue[j]]);
+ }
+ } else {
+ property.value.push(withRealValue ? withValue : [Token.PROPERTY_VALUE, withValue]);
}
}
}
@@ -124,8 +153,9 @@ function moreSameShorthands(properties, startAt, name) {
function overridingFunction(shorthand, validator) {
for (var i = 0, l = shorthand.components.length; i < l; i++) {
- if (anyValue(validator.isValidFunction, shorthand.components[i]))
+ if (!anyValue(validator.isUrl, shorthand.components[i]) && anyValue(validator.isFunction, shorthand.components[i])) {
return true;
+ }
}
return false;
@@ -271,8 +301,13 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (!sameVendorPrefixesIn([left], right.components))
continue;
- if (!anyValue(validator.isValidFunction, left) && overridingFunction(right, validator))
+ if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator))
+ continue;
+
+ if (!isMergeableShorthand(right)) {
+ left.unused = true;
continue;
+ }
component = findComponentIn(right, left);
mayOverride = compactable[left.name].canOverride;
@@ -289,7 +324,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
continue;
}
- if (!anyValue(validator.isValidFunction, left) && overridingFunction(right, validator)) {
+ if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) {
continue;
}
@@ -325,6 +360,9 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (overridingFunction(left, validator))
continue;
+ if (!isMergeableShorthand(left))
+ continue;
+
component = findComponentIn(left, right);
if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
var disabledBackgroundMerging =
@@ -367,6 +405,11 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
continue;
}
+ if (!isMergeableShorthand(right)) {
+ left.unused = true;
+ continue;
+ }
+
for (k = left.components.length - 1; k >= 0; k--) {
var leftComponent = left.components[k];
var rightComponent = right.components[k];
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js b/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js
index 6c77db50d..032169a24 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js
@@ -5,7 +5,7 @@ function understandable(validator, value1, value2, _position, isPaired) {
return false;
}
- if (isPaired && validator.isValidVariable(value1) !== validator.isValidVariable(value2)) {
+ if (isPaired && validator.isVariable(value1) !== validator.isVariable(value2)) {
return false;
}
diff --git a/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js b/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
index 3461bb268..6ce0902b9 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
@@ -13,6 +13,7 @@ function reduceNonAdjacent(tokens, context) {
var options = context.options;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var candidates = {};
var repeated = [];
@@ -27,7 +28,7 @@ function reduceNonAdjacent(tokens, context) {
var selectorAsString = serializeRules(token[1]);
var isComplexAndNotSpecial = token[1].length > 1 &&
- isMergeable(selectorAsString, mergeablePseudoClasses, mergeablePseudoElements);
+ isMergeable(selectorAsString, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging);
var wrappedSelectors = wrappedSelectorsFrom(token[1]);
var selectors = isComplexAndNotSpecial ?
[selectorAsString].concat(wrappedSelectors) :
@@ -88,6 +89,7 @@ function reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, con
function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var localContext = {};
function filterOut(idx) {
@@ -109,7 +111,7 @@ function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
var intoToken = tokens[intoPosition];
var reducedBodies = [];
- var selectors = isMergeable(complexSelector, mergeablePseudoClasses, mergeablePseudoElements) ?
+ var selectors = isMergeable(complexSelector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) ?
into[0].list :
[complexSelector];
diff --git a/node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js b/node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js
new file mode 100644
index 000000000..e60d5e7c2
--- /dev/null
+++ b/node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js
@@ -0,0 +1,232 @@
+var populateComponents = require('./properties/populate-components');
+
+var wrapForOptimizing = require('../wrap-for-optimizing').single;
+var restoreFromOptimizing = require('../restore-from-optimizing');
+
+var Token = require('../../tokenizer/token');
+
+var animationNameRegex = /^(\-moz\-|\-o\-|\-webkit\-)?animation-name$/;
+var animationRegex = /^(\-moz\-|\-o\-|\-webkit\-)?animation$/;
+var keyframeRegex = /^@(\-moz\-|\-o\-|\-webkit\-)?keyframes /;
+
+function removeUnusedAtRules(tokens, context) {
+ removeUnusedAtRule(tokens, matchCounterStyle, markCounterStylesAsUsed, context);
+ removeUnusedAtRule(tokens, matchFontFace, markFontFacesAsUsed, context);
+ removeUnusedAtRule(tokens, matchKeyframe, markKeyframesAsUsed, context);
+ removeUnusedAtRule(tokens, matchNamespace, markNamespacesAsUsed, context);
+}
+
+function removeUnusedAtRule(tokens, matchCallback, markCallback, context) {
+ var atRules = {};
+ var atRule;
+ var token;
+ var zeroAt;
+ var i, l;
+
+ for (i = 0, l = tokens.length; i < l; i++) {
+ matchCallback(tokens[i], atRules);
+ }
+
+ if (Object.keys(atRules).length === 0) {
+ return;
+ }
+
+ markUsedAtRules(tokens, markCallback, atRules, context);
+
+ for (atRule in atRules) {
+ token = atRules[atRule];
+ zeroAt = token[0] == Token.AT_RULE ? 1 : 2;
+ token[zeroAt] = [];
+ }
+}
+
+function markUsedAtRules(tokens, markCallback, atRules, context) {
+ var boundMarkCallback = markCallback(atRules);
+ var i, l;
+
+ for (i = 0, l = tokens.length; i < l; i++) {
+ switch (tokens[i][0]) {
+ case Token.RULE:
+ boundMarkCallback(tokens[i], context);
+ break;
+ case Token.NESTED_BLOCK:
+ markUsedAtRules(tokens[i][2], markCallback, atRules, context);
+ }
+ }
+}
+
+function matchCounterStyle(token, atRules) {
+ var match;
+
+ if (token[0] == Token.AT_RULE_BLOCK && token[1][0][1].indexOf('@counter-style') === 0) {
+ match = token[1][0][1].split(' ')[1];
+ atRules[match] = token;
+ }
+}
+
+function markCounterStylesAsUsed(atRules) {
+ return function (token, context) {
+ var property;
+ var wrappedProperty;
+ var i, l;
+
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (property[1][1] == 'list-style') {
+ wrappedProperty = wrapForOptimizing(property);
+ populateComponents([wrappedProperty], context.validator, context.warnings);
+
+ if (wrappedProperty.components[0].value[0][1] in atRules) {
+ delete atRules[property[2][1]];
+ }
+
+ restoreFromOptimizing([wrappedProperty]);
+ }
+
+ if (property[1][1] == 'list-style-type' && property[2][1] in atRules) {
+ delete atRules[property[2][1]];
+ }
+ }
+ };
+}
+
+function matchFontFace(token, atRules) {
+ var property;
+ var match;
+ var i, l;
+
+ if (token[0] == Token.AT_RULE_BLOCK && token[1][0][1] == '@font-face') {
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (property[1][1] == 'font-family') {
+ match = property[2][1].toLowerCase();
+ atRules[match] = token;
+ break;
+ }
+ }
+ }
+}
+
+function markFontFacesAsUsed(atRules) {
+ return function (token, context) {
+ var property;
+ var wrappedProperty;
+ var component;
+ var normalizedMatch;
+ var i, l;
+ var j, m;
+
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (property[1][1] == 'font') {
+ wrappedProperty = wrapForOptimizing(property);
+ populateComponents([wrappedProperty], context.validator, context.warnings);
+ component = wrappedProperty.components[6];
+
+ for (j = 0, m = component.value.length; j < m; j++) {
+ normalizedMatch = component.value[j][1].toLowerCase();
+
+ if (normalizedMatch in atRules) {
+ delete atRules[normalizedMatch];
+ }
+ }
+
+ restoreFromOptimizing([wrappedProperty]);
+ }
+
+ if (property[1][1] == 'font-family') {
+ for (j = 2, m = property.length; j < m; j++) {
+ normalizedMatch = property[j][1].toLowerCase();
+
+ if (normalizedMatch in atRules) {
+ delete atRules[normalizedMatch];
+ }
+ }
+ }
+ }
+ };
+}
+
+function matchKeyframe(token, atRules) {
+ var match;
+
+ if (token[0] == Token.NESTED_BLOCK && keyframeRegex.test(token[1][0][1])) {
+ match = token[1][0][1].split(' ')[1];
+ atRules[match] = token;
+ }
+}
+
+function markKeyframesAsUsed(atRules) {
+ return function (token, context) {
+ var property;
+ var wrappedProperty;
+ var component;
+ var i, l;
+ var j, m;
+
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (animationRegex.test(property[1][1])) {
+ wrappedProperty = wrapForOptimizing(property);
+ populateComponents([wrappedProperty], context.validator, context.warnings);
+ component = wrappedProperty.components[7];
+
+ for (j = 0, m = component.value.length; j < m; j++) {
+ if (component.value[j][1] in atRules) {
+ delete atRules[component.value[j][1]];
+ }
+ }
+
+ restoreFromOptimizing([wrappedProperty]);
+ }
+
+ if (animationNameRegex.test(property[1][1])) {
+ for (j = 2, m = property.length; j < m; j++) {
+ if (property[j][1] in atRules) {
+ delete atRules[property[j][1]];
+ }
+ }
+ }
+ }
+ };
+}
+
+function matchNamespace(token, atRules) {
+ var match;
+
+ if (token[0] == Token.AT_RULE && token[1].indexOf('@namespace') === 0) {
+ match = token[1].split(' ')[1];
+ atRules[match] = token;
+ }
+}
+
+function markNamespacesAsUsed(atRules) {
+ var namespaceRegex = new RegExp(Object.keys(atRules).join('\\\||') + '\\\|', 'g');
+
+ return function (token) {
+ var match;
+ var scope;
+ var normalizedMatch;
+ var i, l;
+ var j, m;
+
+ for (i = 0, l = token[1].length; i < l; i++) {
+ scope = token[1][i];
+ match = scope[1].match(namespaceRegex);
+
+ for (j = 0, m = match.length; j < m; j++) {
+ normalizedMatch = match[j].substring(0, match[j].length - 1);
+
+ if (normalizedMatch in atRules) {
+ delete atRules[normalizedMatch];
+ }
+ }
+ }
+ };
+}
+
+module.exports = removeUnusedAtRules;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/restore.js b/node_modules/clean-css/lib/optimizer/level-2/restore.js
index 149688c5b..13f12e496 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/restore.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/restore.js
@@ -135,6 +135,59 @@ function borderRadius(property, compactable) {
}
}
+function font(property, compactable) {
+ var components = property.components;
+ var restored = [];
+ var component;
+ var componentIndex = 0;
+ var fontFamilyIndex = 0;
+
+ if (property.value[0][1].indexOf(Marker.INTERNAL) === 0) {
+ property.value[0][1] = property.value[0][1].substring(Marker.INTERNAL.length);
+ return property.value;
+ }
+
+ // first four components are optional
+ while (componentIndex < 4) {
+ component = components[componentIndex];
+
+ if (component.value[0][1] != compactable[component.name].defaultValue) {
+ Array.prototype.push.apply(restored, component.value);
+ }
+
+ componentIndex++;
+ }
+
+ // then comes font-size
+ Array.prototype.push.apply(restored, components[componentIndex].value);
+ componentIndex++;
+
+ // then may come line-height
+ if (components[componentIndex].value[0][1] != compactable[components[componentIndex].name].defaultValue) {
+ Array.prototype.push.apply(restored, [[Token.PROPERTY_VALUE, Marker.FORWARD_SLASH]]);
+ Array.prototype.push.apply(restored, components[componentIndex].value);
+ }
+
+ componentIndex++;
+
+ // then comes font-family
+ while (components[componentIndex].value[fontFamilyIndex]) {
+ restored.push(components[componentIndex].value[fontFamilyIndex]);
+
+ if (components[componentIndex].value[fontFamilyIndex + 1]) {
+ restored.push([Token.PROPERTY_VALUE, Marker.COMMA]);
+ }
+
+ fontFamilyIndex++;
+ }
+
+ if (isInheritOnly(restored)) {
+ return [restored[0]];
+ }
+
+ return restored;
+}
+
function fourValues(property) {
var components = property.components;
var value1 = components[0].value[0];
@@ -227,6 +280,7 @@ function withoutDefaults(property, compactable) {
module.exports = {
background: background,
borderRadius: borderRadius,
+ font: font,
fourValues: fourValues,
multiplex: multiplex,
withoutDefaults: withoutDefaults
diff --git a/node_modules/clean-css/lib/optimizer/level-2/restructure.js b/node_modules/clean-css/lib/optimizer/level-2/restructure.js
index 2635415ae..90b8bfa65 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/restructure.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/restructure.js
@@ -25,7 +25,8 @@ function restructure(tokens, context) {
var options = context.options;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
- var mergeLimit = 8191;
+ var mergeLimit = options.compatibility.selectors.mergeLimit;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var specificityCache = context.cache.specificity;
var movableTokens = {};
var movedProperties = [];
@@ -86,7 +87,7 @@ function restructure(tokens, context) {
var mergeableTokens = [];
for (var i = sourceTokens.length - 1; i >= 0; i--) {
- if (!isMergeable(serializeRules(sourceTokens[i][1]), mergeablePseudoClasses, mergeablePseudoElements)) {
+ if (!isMergeable(serializeRules(sourceTokens[i][1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)) {
continue;
}
diff --git a/node_modules/clean-css/lib/optimizer/validator.js b/node_modules/clean-css/lib/optimizer/validator.js
index 35f041ea9..cfccd0f9d 100644
--- a/node_modules/clean-css/lib/optimizer/validator.js
+++ b/node_modules/clean-css/lib/optimizer/validator.js
@@ -1,44 +1,28 @@
-var Units = [
- '%',
- 'ch',
- 'cm',
- 'em',
- 'ex',
- 'in',
- 'mm',
- 'pc',
- 'pt',
- 'px',
- 'rem',
- 'vh',
- 'vm',
- 'vmax',
- 'vmin',
- 'vw'
-];
-var cssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + Units.join('|') + '|)|auto|inherit)';
-var cssCalcRegexStr = '(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)';
-var cssFunctionNoVendorRegexStr = '[A-Z]+(\\-|[A-Z]|[0-9])+\\(.*?\\)';
-var cssFunctionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(.*?\\)';
-var cssVariableRegexStr = 'var\\(\\-\\-[^\\)]+\\)';
-var cssFunctionAnyRegexStr = '(' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')';
-var cssUnitOrCalcRegexStr = '(' + cssUnitRegexStr + '|' + cssCalcRegexStr + ')';
-
-var cssFunctionNoVendorRegex = new RegExp('^' + cssFunctionNoVendorRegexStr + '$', 'i');
-var cssVariableRegex = new RegExp('^' + cssVariableRegexStr + '$', 'i');
-var cssFunctionAnyRegex = new RegExp('^' + cssFunctionAnyRegexStr + '$', 'i');
-var cssUnitRegex = new RegExp('^' + cssUnitRegexStr + '$', 'i');
-var cssUnitOrCalcRegex = new RegExp('^' + cssUnitOrCalcRegexStr + '$', 'i');
-
+var functionNoVendorRegexStr = '[A-Z]+(\\-|[A-Z]|[0-9])+\\(.*?\\)';
+var functionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(.*?\\)';
+var variableRegexStr = 'var\\(\\-\\-[^\\)]+\\)';
+var functionAnyRegexStr = '(' + variableRegexStr + '|' + functionNoVendorRegexStr + '|' + functionVendorRegexStr + ')';
+
+var animationTimingFunctionRegex = /^(cubic\-bezier|steps)\([^\)]+\)$/;
+var calcRegex = new RegExp('^(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)$', 'i');
+var functionAnyRegex = new RegExp('^' + functionAnyRegexStr + '$', 'i');
+var hslColorRegex = /^hsl\(\s*[\-\.\d]+\s*,\s*[\.\d]+%\s*,\s*[\.\d]+%\s*\)|hsla\(\s*[\-\.\d]+\s*,\s*[\.\d]+%\s*,\s*[\.\d]+%\s*,\s*[\.\d]+\s*\)$/;
+var identifierRegex = /^(\-[a-z0-9_][a-z0-9\-_]*|[a-z][a-z0-9\-_]*)$/i;
+var longHexColorRegex = /^#[0-9a-f]{6}$/i;
+var namedEntityRegex = /^[a-z]+$/i;
+var prefixRegex = /^-([a-z0-9]|-)*$/i;
+var rgbColorRegex = /^rgb\(\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*\)|rgba\(\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*,\s*[\.\d]+\s*\)$/;
+var shortHexColorRegex = /^#[0-9a-f]{3}$/i;
+var timeRegex = new RegExp('^(\\-?\\+?\\.?\\d+\\.?\\d*(s|ms))$');
var urlRegex = /^url\([\s\S]+\)$/i;
-
-var globalKeywords = [
- 'inherit',
- 'initial',
- 'unset'
-];
+var variableRegex = new RegExp('^' + variableRegexStr + '$', 'i');
var Keywords = {
+ '^': [
+ 'inherit',
+ 'initial',
+ 'unset'
+ ],
'*-style': [
'auto',
'dashed',
@@ -52,6 +36,37 @@ var Keywords = {
'ridge',
'solid'
],
+ 'animation-direction': [
+ 'alternate',
+ 'alternate-reverse',
+ 'normal',
+ 'reverse'
+ ],
+ 'animation-fill-mode': [
+ 'backwards',
+ 'both',
+ 'forwards',
+ 'none'
+ ],
+ 'animation-iteration-count': [
+ 'infinite'
+ ],
+ 'animation-name': [
+ 'none'
+ ],
+ 'animation-play-state': [
+ 'paused',
+ 'running'
+ ],
+ 'animation-timing-function': [
+ 'ease',
+ 'ease-in',
+ 'ease-in-out',
+ 'ease-out',
+ 'linear',
+ 'step-end',
+ 'step-start'
+ ],
'background-attachment': [
'fixed',
'inherit',
@@ -106,6 +121,9 @@ var Keywords = {
'none',
'right'
],
+ 'color': [
+ 'transparent'
+ ],
'cursor': [
'all-scroll',
'auto',
@@ -156,11 +174,46 @@ var Keywords = {
'left': [
'auto'
],
+ 'font': [
+ 'caption',
+ 'icon',
+ 'menu',
+ 'message-box',
+ 'small-caption',
+ 'status-bar',
+ 'unset'
+ ],
+ 'font-size': [
+ 'large',
+ 'larger',
+ 'medium',
+ 'small',
+ 'smaller',
+ 'x-large',
+ 'x-small',
+ 'xx-large',
+ 'xx-small'
+ ],
+ 'font-stretch': [
+ 'condensed',
+ 'expanded',
+ 'extra-condensed',
+ 'extra-expanded',
+ 'normal',
+ 'semi-condensed',
+ 'semi-expanded',
+ 'ultra-condensed',
+ 'ultra-expanded'
+ ],
'font-style': [
'italic',
'normal',
'oblique'
],
+ 'font-variant': [
+ 'normal',
+ 'small-caps'
+ ],
'font-weight': [
'100',
'200',
@@ -176,6 +229,9 @@ var Keywords = {
'lighter',
'normal'
],
+ 'line-height': [
+ 'normal'
+ ],
'list-style-position': [
'inside',
'outside'
@@ -262,163 +318,118 @@ var Keywords = {
]
};
-var VENDOR_PREFIX_PATTERN = /(^|\W)-\w+\-/;
-
-function areSameFunction(value1, value2) {
- if (!isValidFunction(value1) || !isValidFunction(value2)) {
- return false;
- }
-
- var function1Name = value1.substring(0, value1.indexOf('('));
- var function2Name = value2.substring(0, value2.indexOf('('));
-
- return function1Name === function2Name;
-}
-
-function hasNoVendorPrefix(value) {
- return VENDOR_PREFIX_PATTERN.test(value);
-}
-
-function isValidBackgroundAttachment(value) {
- return Keywords['background-attachment'].indexOf(value) > -1;
-}
-
-function isValidBackgroundClip(value) {
- return Keywords['background-clip'].indexOf(value) > -1;
-}
-
-function isValidBackgroundRepeat(value) {
- return Keywords['background-repeat'].indexOf(value) > -1;
-}
-
-function isValidBackgroundOrigin(value) {
- return Keywords['background-origin'].indexOf(value) > -1;
-}
-
-function isValidBackgroundPosition(value) {
- var parts;
- var i, l;
-
- if (value === 'inherit') {
- return true;
- }
-
- parts = value.split(' ');
- for (i = 0, l = parts.length; i < l; i++) {
- if (parts[i] === '') {
- continue;
- } else if (isValidBackgroundPositionPart(parts[i])) {
- continue;
- }
-
- return false;
- }
-
- return true;
-}
+var Units = [
+ '%',
+ 'ch',
+ 'cm',
+ 'em',
+ 'ex',
+ 'in',
+ 'mm',
+ 'pc',
+ 'pt',
+ 'px',
+ 'rem',
+ 'vh',
+ 'vm',
+ 'vmax',
+ 'vmin',
+ 'vw'
+];
-function isValidBackgroundPositionPart(value) {
- return Keywords['background-position'].indexOf(value) > -1 || cssUnitOrCalcRegex.test(value);
-}
+function isAnimationTimingFunction() {
+ var isTimingFunctionKeyword = isKeyword('animation-timing-function');
-function isValidBackgroundSizePart(value) {
- return Keywords['background-size'].indexOf(value) > -1 || cssUnitRegex.test(value);
+ return function (value) {
+ return isTimingFunctionKeyword(value) || animationTimingFunctionRegex.test(value);
+ };
}
-function isValidColor(value) {
- return isValidNamedColor(value) ||
- isValidColorValue(value);
+function isColor(value) {
+ return value != 'auto' &&
+ (
+ isKeyword('color')(value) ||
+ isHexColor(value) ||
+ isColorFunction(value) ||
+ isNamedEntity(value)
+ );
}
-function isValidColorValue(value) {
- return isValidHexColor(value) ||
- isValidRgbaColor(value) ||
- isValidHslaColor(value);
+function isColorFunction(value) {
+ return isRgbColor(value) || isHslColor(value);
}
-function isValidFunction(value) {
- return !urlRegex.test(value) && cssFunctionAnyRegex.test(value);
+function isDynamicUnit(value) {
+ return calcRegex.test(value);
}
-function isValidFunctionWithoutVendorPrefix(value) {
- return !urlRegex.test(value) && cssFunctionNoVendorRegex.test(value);
+function isFunction(value) {
+ return functionAnyRegex.test(value);
}
-function isValidGlobalValue(value) {
- return globalKeywords.indexOf(value) > -1;
+function isHexColor(value) {
+ return shortHexColorRegex.test(value) || longHexColorRegex.test(value);
}
-function isValidHexColor(value) {
- return (value.length === 4 || value.length === 7) && value[0] === '#';
+function isHslColor(value) {
+ return hslColorRegex.test(value);
}
-function isValidHslaColor(value) {
- return value.length > 0 && value.indexOf('hsla(') === 0 && value.indexOf(')') === value.length - 1;
+function isIdentifier(value) {
+ return identifierRegex.test(value);
}
-function isValidImage(value) {
- return value == 'none' || value == 'inherit' || isValidUrl(value);
+function isImage(value) {
+ return value == 'none' || value == 'inherit' || isUrl(value);
}
-function isValidKeywordValue(propertyName, value, includeGlobal) {
- return Keywords[propertyName].indexOf(value) > -1 || includeGlobal && isValidGlobalValue(value);
+function isKeyword(propertyName) {
+ return function(value) {
+ return Keywords[propertyName].indexOf(value) > -1;
+ };
}
-function isValidListStyleType(value) {
- return Keywords['list-style-type'].indexOf(value) > -1;
+function isNamedEntity(value) {
+ return namedEntityRegex.test(value);
}
-function isValidListStylePosition(value) {
- return Keywords['list-style-position'].indexOf(value) > -1;
+function isNumber(value) {
+ return value.length > 0 && ('' + parseFloat(value)) === value;
}
-function isValidNamedColor(value) {
- // We don't really check if it's a valid color value, but allow any letters in it
- return value !== 'auto' && (value === 'transparent' || value === 'inherit' || /^[a-zA-Z]+$/.test(value));
+function isRgbColor(value) {
+ return rgbColorRegex.test(value);
}
-function isValidRgbaColor(value) {
- return value.length > 0 && value.indexOf('rgba(') === 0 && value.indexOf(')') === value.length - 1;
+function isPrefixed(value) {
+ return prefixRegex.test(value);
}
-function isValidStyle(value) {
- return Keywords['*-style'].indexOf(value) > -1;
+function isPositiveNumber(value) {
+ return isNumber(value) &&
+ parseFloat(value) >= 0;
}
-function isValidTextShadow(compatibleCssUnitRegex, value) {
- return isValidUnitWithoutFunction(compatibleCssUnitRegex, value) ||
- isValidColor(value) ||
- isValidGlobalValue(value);
+function isVariable(value) {
+ return variableRegex.test(value);
}
-function isValidUnit(compatibleCssUnitAnyRegex, value) {
- return compatibleCssUnitAnyRegex.test(value);
+function isTime(value) {
+ return timeRegex.test(value);
}
-function isValidUnitWithoutFunction(compatibleCssUnitRegex, value) {
+function isUnit(compatibleCssUnitRegex, value) {
return compatibleCssUnitRegex.test(value);
}
-function isValidUrl(value) {
+function isUrl(value) {
return urlRegex.test(value);
}
-function isValidVariable(value) {
- return cssVariableRegex.test(value);
-}
-
-function isValidVendorPrefixedValue(value) {
- return /^-([A-Za-z0-9]|-)*$/gi.test(value);
-}
-
-function isValidWidth(compatibleCssUnitRegex, value) {
- return isValidUnit(compatibleCssUnitRegex, value) || Keywords.width.indexOf(value) > -1;
-}
-
-function isValidZIndex(value) {
+function isZIndex(value) {
return value == 'auto' ||
- isValidGlobalValue(value) ||
- value.length > 0 && value == ('' + parseInt(value));
+ isNumber(value) ||
+ isKeyword('^')(value);
}
function validator(compatibility) {
@@ -426,44 +437,50 @@ function validator(compatibility) {
return !(value in compatibility.units) || compatibility.units[value] === true;
});
- var compatibleCssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + validUnits.join('|') + '|)|auto|inherit)';
- var compatibleCssUnitRegex = new RegExp('^' + compatibleCssUnitRegexStr + '$', 'i');
- var compatibleCssUnitAnyRegex = new RegExp('^(none|' + Keywords.width.join('|') + '|' + compatibleCssUnitRegexStr + '|' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')$', 'i');
- var colorOpacity = compatibility.colors.opacity;
+ var compatibleCssUnitRegex = new RegExp('^(\\-?\\.?\\d+\\.?\\d*(' + validUnits.join('|') + '|)|auto|inherit)$', 'i');
return {
- areSameFunction: areSameFunction,
- colorOpacity: colorOpacity,
- hasNoVendorPrefix: hasNoVendorPrefix,
- isValidBackgroundAttachment: isValidBackgroundAttachment,
- isValidBackgroundClip: isValidBackgroundClip,
- isValidBackgroundOrigin: isValidBackgroundOrigin,
- isValidBackgroundPosition: isValidBackgroundPosition,
- isValidBackgroundPositionPart: isValidBackgroundPositionPart,
- isValidBackgroundRepeat: isValidBackgroundRepeat,
- isValidBackgroundSizePart: isValidBackgroundSizePart,
- isValidColor: isValidColor,
- isValidColorValue: isValidColorValue,
- isValidFunction: isValidFunction,
- isValidFunctionWithoutVendorPrefix: isValidFunctionWithoutVendorPrefix,
- isValidGlobalValue: isValidGlobalValue,
- isValidHexColor: isValidHexColor,
- isValidHslaColor: isValidHslaColor,
- isValidImage: isValidImage,
- isValidKeywordValue: isValidKeywordValue,
- isValidListStylePosition: isValidListStylePosition,
- isValidListStyleType: isValidListStyleType,
- isValidNamedColor: isValidNamedColor,
- isValidRgbaColor: isValidRgbaColor,
- isValidStyle: isValidStyle,
- isValidTextShadow: isValidTextShadow.bind(null, compatibleCssUnitRegex),
- isValidUnit: isValidUnit.bind(null, compatibleCssUnitAnyRegex),
- isValidUnitWithoutFunction: isValidUnitWithoutFunction.bind(null, compatibleCssUnitRegex),
- isValidUrl: isValidUrl,
- isValidVariable: isValidVariable,
- isValidVendorPrefixedValue: isValidVendorPrefixedValue,
- isValidWidth: isValidWidth.bind(null, compatibleCssUnitRegex),
- isValidZIndex: isValidZIndex
+ colorOpacity: compatibility.colors.opacity,
+ isAnimationDirectionKeyword: isKeyword('animation-direction'),
+ isAnimationFillModeKeyword: isKeyword('animation-fill-mode'),
+ isAnimationIterationCountKeyword: isKeyword('animation-iteration-count'),
+ isAnimationNameKeyword: isKeyword('animation-name'),
+ isAnimationPlayStateKeyword: isKeyword('animation-play-state'),
+ isAnimationTimingFunction: isAnimationTimingFunction(),
+ isBackgroundAttachmentKeyword: isKeyword('background-attachment'),
+ isBackgroundClipKeyword: isKeyword('background-clip'),
+ isBackgroundOriginKeyword: isKeyword('background-origin'),
+ isBackgroundPositionKeyword: isKeyword('background-position'),
+ isBackgroundRepeatKeyword: isKeyword('background-repeat'),
+ isBackgroundSizeKeyword: isKeyword('background-size'),
+ isColor: isColor,
+ isColorFunction: isColorFunction,
+ isDynamicUnit: isDynamicUnit,
+ isFontKeyword: isKeyword('font'),
+ isFontSizeKeyword: isKeyword('font-size'),
+ isFontStretchKeyword: isKeyword('font-stretch'),
+ isFontStyleKeyword: isKeyword('font-style'),
+ isFontVariantKeyword: isKeyword('font-variant'),
+ isFontWeightKeyword: isKeyword('font-weight'),
+ isFunction: isFunction,
+ isGlobal: isKeyword('^'),
+ isHslColor: isHslColor,
+ isIdentifier: isIdentifier,
+ isImage: isImage,
+ isKeyword: isKeyword,
+ isLineHeightKeyword: isKeyword('line-height'),
+ isListStylePositionKeyword: isKeyword('list-style-position'),
+ isListStyleTypeKeyword: isKeyword('list-style-type'),
+ isPrefixed: isPrefixed,
+ isPositiveNumber: isPositiveNumber,
+ isRgbColor: isRgbColor,
+ isStyleKeyword: isKeyword('*-style'),
+ isTime: isTime,
+ isUnit: isUnit.bind(null, compatibleCssUnitRegex),
+ isUrl: isUrl,
+ isVariable: isVariable,
+ isWidth: isKeyword('width'),
+ isZIndex: isZIndex
};
}
diff --git a/node_modules/clean-css/lib/optimizer/wrap-for-optimizing.js b/node_modules/clean-css/lib/optimizer/wrap-for-optimizing.js
index 0fbfdb056..c516fbc4a 100644
--- a/node_modules/clean-css/lib/optimizer/wrap-for-optimizing.js
+++ b/node_modules/clean-css/lib/optimizer/wrap-for-optimizing.js
@@ -17,7 +17,7 @@ var Match = {
VARIABLE_REFERENCE_PATTERN: /var\(--.+\)$/
};
-function wrapAll(properties, includeVariable) {
+function wrapAll(properties, includeVariable, skipProperties) {
var wrapped = [];
var single;
var property;
@@ -34,6 +34,10 @@ function wrapAll(properties, includeVariable) {
continue;
}
+ if (skipProperties && skipProperties.indexOf(property[1][1]) > -1) {
+ continue;
+ }
+
single = wrapSingle(property);
single.all = properties;
single.position = i;
diff --git a/node_modules/clean-css/lib/options/compatibility.js b/node_modules/clean-css/lib/options/compatibility.js
index ca881c627..8e6a119a8 100644
--- a/node_modules/clean-css/lib/options/compatibility.js
+++ b/node_modules/clean-css/lib/options/compatibility.js
@@ -56,7 +56,9 @@ var DEFAULTS = {
'::before',
'::first-letter',
'::first-line'
- ] // selectors with these pseudo-elements can be merged as these are universally supported
+ ], // selectors with these pseudo-elements can be merged as these are universally supported
+ mergeLimit: 8191, // number of rules that can be safely merged together
+ multiplePseudoMerging: true
},
units: {
ch: true,
diff --git a/node_modules/clean-css/lib/options/fetch.js b/node_modules/clean-css/lib/options/fetch.js
new file mode 100644
index 000000000..0aaad7866
--- /dev/null
+++ b/node_modules/clean-css/lib/options/fetch.js
@@ -0,0 +1,7 @@
+var loadRemoteResource = require('../reader/load-remote-resource');
+
+function fetchFrom(callback) {
+ return callback || loadRemoteResource;
+}
+
+module.exports = fetchFrom;
diff --git a/node_modules/clean-css/lib/options/inline.js b/node_modules/clean-css/lib/options/inline.js
index 4a6997075..54761f40a 100644
--- a/node_modules/clean-css/lib/options/inline.js
+++ b/node_modules/clean-css/lib/options/inline.js
@@ -3,6 +3,10 @@ function inlineOptionsFrom(rules) {
return rules;
}
+ if (rules === false) {
+ return ['none'];
+ }
+
return undefined === rules ?
['local'] :
rules.split(',');
diff --git a/node_modules/clean-css/lib/options/optimization-level.js b/node_modules/clean-css/lib/options/optimization-level.js
index d9828287b..0d3ad7303 100644
--- a/node_modules/clean-css/lib/options/optimization-level.js
+++ b/node_modules/clean-css/lib/options/optimization-level.js
@@ -17,9 +17,9 @@ DEFAULTS[OptimizationLevel.One] = {
optimizeBackground: true,
optimizeBorderRadius: true,
optimizeFilter: true,
- optimizeFont: true,
optimizeFontWeight: true,
optimizeOutline: true,
+ removeEmpty: true,
removeNegativePaddings: true,
removeQuotes: true,
removeWhitespace: true,
@@ -41,11 +41,14 @@ DEFAULTS[OptimizationLevel.Two] = {
mergeNonAdjacentRules: true,
mergeSemantically: false,
overrideProperties: true,
+ removeEmpty: true,
reduceNonAdjacentRules: true,
removeDuplicateFontRules: true,
removeDuplicateMediaBlocks: true,
removeDuplicateRules: true,
- restructureRules: false
+ removeUnusedAtRules: false,
+ restructureRules: false,
+ skipProperties: []
};
var ALL_KEYWORD_1 = '*';
@@ -55,6 +58,7 @@ var FALSE_KEYWORD_2 = 'off';
var TRUE_KEYWORD_1 = 'true';
var TRUE_KEYWORD_2 = 'on';
+var LIST_VALUE_SEPARATOR = ',';
var OPTION_SEPARATOR = ';';
var OPTION_VALUE_SEPARATOR = ':';
@@ -99,6 +103,10 @@ function optimizationLevelFrom(source) {
source[One].roundingPrecision = roundingPrecisionFrom(source[One].roundingPrecision);
}
+ if (Two in source && 'skipProperties' in source[Two] && typeof(source[Two].skipProperties) == 'string') {
+ source[Two].skipProperties = source[Two].skipProperties.split(LIST_VALUE_SEPARATOR);
+ }
+
if (Zero in source || One in source || Two in source) {
level[Zero] = override(level[Zero], source[Zero]);
}
diff --git a/node_modules/clean-css/lib/reader/apply-source-maps.js b/node_modules/clean-css/lib/reader/apply-source-maps.js
index d2f87250e..7c5a9282b 100644
--- a/node_modules/clean-css/lib/reader/apply-source-maps.js
+++ b/node_modules/clean-css/lib/reader/apply-source-maps.js
@@ -2,7 +2,6 @@ var fs = require('fs');
var path = require('path');
var isAllowedResource = require('./is-allowed-resource');
-var loadRemoteResource = require('./load-remote-resource');
var matchDataUri = require('./match-data-uri');
var rebaseLocalMap = require('./rebase-local-map');
var rebaseRemoteMap = require('./rebase-remote-map');
@@ -17,6 +16,7 @@ var MAP_MARKER_PATTERN = /^\/\*# sourceMappingURL=(\S+) \*\/$/;
function applySourceMaps(tokens, context, callback) {
var applyContext = {
callback: callback,
+ fetch: context.options.fetch,
index: 0,
inline: context.options.inline,
inlineRequest: context.options.inlineRequest,
@@ -151,7 +151,7 @@ function loadInputSourceMapFromRemoteUri(uri, applyContext, whenLoaded) {
return whenLoaded(null);
}
- loadRemoteResource(uri, applyContext.inlineRequest, applyContext.inlineTimeout, function (error, body) {
+ applyContext.fetch(uri, applyContext.inlineRequest, applyContext.inlineTimeout, function (error, body) {
if (error) {
applyContext.warnings.push('Missing source map at "' + uri + '" - ' + error);
return whenLoaded(null);
diff --git a/node_modules/clean-css/lib/reader/load-original-sources.js b/node_modules/clean-css/lib/reader/load-original-sources.js
index dbe2cad09..465035d6b 100644
--- a/node_modules/clean-css/lib/reader/load-original-sources.js
+++ b/node_modules/clean-css/lib/reader/load-original-sources.js
@@ -2,7 +2,6 @@ var fs = require('fs');
var path = require('path');
var isAllowedResource = require('./is-allowed-resource');
-var loadRemoteResource = require('./load-remote-resource');
var hasProtocol = require('../utils/has-protocol');
var isRemoteResource = require('../utils/is-remote-resource');
@@ -10,6 +9,7 @@ var isRemoteResource = require('../utils/is-remote-resource');
function loadOriginalSources(context, callback) {
var loadContext = {
callback: callback,
+ fetch: context.options.fetch,
index: 0,
inline: context.options.inline,
inlineRequest: context.options.inlineRequest,
@@ -99,7 +99,7 @@ function loadOriginalSourceFromRemoteUri(uri, loadContext, whenLoaded) {
return whenLoaded(null);
}
- loadRemoteResource(uri, loadContext.inlineRequest, loadContext.inlineTimeout, function (error, content) {
+ loadContext.fetch(uri, loadContext.inlineRequest, loadContext.inlineTimeout, function (error, content) {
if (error) {
loadContext.warnings.push('Missing original source at "' + uri + '" - ' + error);
}
diff --git a/node_modules/clean-css/lib/reader/read-sources.js b/node_modules/clean-css/lib/reader/read-sources.js
index e12e23514..c9173ed62 100644
--- a/node_modules/clean-css/lib/reader/read-sources.js
+++ b/node_modules/clean-css/lib/reader/read-sources.js
@@ -5,7 +5,6 @@ var applySourceMaps = require('./apply-source-maps');
var extractImportUrlAndMedia = require('./extract-import-url-and-media');
var isAllowedResource = require('./is-allowed-resource');
var loadOriginalSources = require('./load-original-sources');
-var loadRemoteResource = require('./load-remote-resource');
var normalizePath = require('./normalize-path');
var rebase = require('./rebase');
var rebaseLocalMap = require('./rebase-local-map');
@@ -50,27 +49,38 @@ function fromString(input, context, callback) {
}
function fromArray(input, context, callback) {
- var inputAsImports = input.reduce(function (accumulator, uri) {
- var normalizedUri = normalizeUri(uri);
+ var inputAsImports = input.reduce(function (accumulator, uriOrHash) {
+ if (typeof uriOrHash === 'string') {
+ return addStringSource(uriOrHash, accumulator);
+ } else {
+ return addHashSource(uriOrHash, context, accumulator);
+ }
- accumulator.push(restoreAsImport(normalizedUri));
- return accumulator;
}, []);
return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);
}
function fromHash(input, context, callback) {
+ var inputAsImports = addHashSource(input, context, []);
+ return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);
+}
+
+function addStringSource(input, imports) {
+ imports.push(restoreAsImport(normalizeUri(input)));
+ return imports;
+}
+
+function addHashSource(input, context, imports) {
var uri;
var normalizedUri;
var source;
- var inputAsImports = [];
for (uri in input) {
source = input[uri];
normalizedUri = normalizeUri(uri);
- inputAsImports.push(restoreAsImport(normalizedUri));
+ imports.push(restoreAsImport(normalizedUri));
context.sourcesContent[normalizedUri] = source.styles;
@@ -79,7 +89,7 @@ function fromHash(input, context, callback) {
}
}
- return fromStyles(inputAsImports.join(''), context, { inline: ['all'] }, callback);
+ return imports;
}
function normalizeUri(uri) {
@@ -152,6 +162,7 @@ function inline(tokens, externalContext, parentInlinerContext, callback) {
callback: callback,
errors: externalContext.errors,
externalContext: externalContext,
+ fetch: externalContext.options.fetch,
inlinedStylesheets: parentInlinerContext.inlinedStylesheets || externalContext.inlinedStylesheets,
inline: parentInlinerContext.inline,
inlineRequest: externalContext.options.inlineRequest,
@@ -267,7 +278,7 @@ function inlineRemoteStylesheet(uri, mediaQuery, metadata, inlinerContext) {
return isLoaded ?
whenLoaded(null, inlinerContext.externalContext.sourcesContent[uri]) :
- loadRemoteResource(uri, inlinerContext.inlineRequest, inlinerContext.inlineTimeout, whenLoaded);
+ inlinerContext.fetch(uri, inlinerContext.inlineRequest, inlinerContext.inlineTimeout, whenLoaded);
}
function inlineLocalStylesheet(uri, mediaQuery, metadata, inlinerContext) {
diff --git a/node_modules/clean-css/lib/reader/rebase.js b/node_modules/clean-css/lib/reader/rebase.js
index 4e0ff9751..181b319ad 100644
--- a/node_modules/clean-css/lib/reader/rebase.js
+++ b/node_modules/clean-css/lib/reader/rebase.js
@@ -91,7 +91,7 @@ function rebaseProperties(properties, validator, rebaseConfig) {
for (j = 2 /* 0 is Token.PROPERTY, 1 is name */, m = property.length; j < m; j++) {
value = property[j][1];
- if (validator.isValidUrl(value)) {
+ if (validator.isUrl(value)) {
property[j][1] = rewriteUrl(value, rebaseConfig);
}
}
diff --git a/node_modules/clean-css/lib/tokenizer/marker.js b/node_modules/clean-css/lib/tokenizer/marker.js
index c3f6805a7..767a5f0e8 100644
--- a/node_modules/clean-css/lib/tokenizer/marker.js
+++ b/node_modules/clean-css/lib/tokenizer/marker.js
@@ -10,6 +10,7 @@ var Marker = {
DOUBLE_QUOTE: '"',
EXCLAMATION: '!',
FORWARD_SLASH: '/',
+ INTERNAL: '-clean-css-',
NEW_LINE_NIX: '\n',
NEW_LINE_WIN: '\r',
OPEN_CURLY_BRACKET: '{',
diff --git a/node_modules/clean-css/lib/tokenizer/tokenize.js b/node_modules/clean-css/lib/tokenizer/tokenize.js
index 15fb584a0..7c071dd93 100644
--- a/node_modules/clean-css/lib/tokenizer/tokenize.js
+++ b/node_modules/clean-css/lib/tokenizer/tokenize.js
@@ -28,6 +28,7 @@ var BLOCK_RULES = [
'@supports'
];
+var REPEAT_PATTERN = /^\[\s*\d+\s*\]$/;
var RULE_WORD_SEPARATOR_PATTERN = /[\s\(]/;
var TAIL_BROKEN_VALUE_PATTERN = /[\s|\}]*$/;
@@ -377,6 +378,12 @@ function intoTokens(source, externalContext, internalContext, isNested) {
propertyToken.push([Token.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);
buffer = [];
+ } else if (character == Marker.CLOSE_SQUARE_BRACKET && propertyToken && propertyToken.length > 1 && buffer.length > 0 && isRepeatToken(buffer)) {
+ buffer.push(character);
+ serializedBuffer = buffer.join('').trim();
+ propertyToken[propertyToken.length - 1][1] += serializedBuffer;
+
+ buffer = [];
} else if ((isSpace || (isNewLineNix && !isNewLineWin)) && level == Level.RULE && seekingValue && propertyToken && buffer.length > 0) {
// space or *nix newline within property, e.g. a{margin:0 <--
serializedBuffer = buffer.join('').trim();
@@ -460,4 +467,8 @@ function tokenScopeFrom(tokenType) {
}
}
+function isRepeatToken(buffer) {
+ return REPEAT_PATTERN.test(buffer.join('') + Marker.CLOSE_SQUARE_BRACKET);
+}
+
module.exports = tokenize;
diff --git a/node_modules/clean-css/lib/writer/helpers.js b/node_modules/clean-css/lib/writer/helpers.js
index 0b8999e95..ab08633e8 100644
--- a/node_modules/clean-css/lib/writer/helpers.js
+++ b/node_modules/clean-css/lib/writer/helpers.js
@@ -85,7 +85,7 @@ function property(context, tokens, position, lastPropertyAt) {
switch (token[0]) {
case Token.AT_RULE:
store(context, token);
- store(context, position < lastPropertyAt ? semicolon(context, Breaks.AfterProperty, false) : emptyCharacter);
+ store(context, semicolon(context, Breaks.AfterProperty, false));
break;
case Token.COMMENT:
store(context, token);
diff --git a/node_modules/clean-css/package.json b/node_modules/clean-css/package.json
index f8a8db1f4..d612da4e3 100644
--- a/node_modules/clean-css/package.json
+++ b/node_modules/clean-css/package.json
@@ -1,6 +1,6 @@
{
"name": "clean-css",
- "version": "4.0.12",
+ "version": "4.1.3",
"author": "Jakub Pawlowicz <contact@jakubpawlowicz.com> (http://twitter.com/jakubpawlowicz)",
"description": "A well-tested CSS minifier",
"license": "MIT",
@@ -34,7 +34,7 @@
"source-map": "0.5.x"
},
"devDependencies": {
- "browserify": "13.x",
+ "browserify": "^14.0.0",
"http-proxy": "1.x",
"jshint": "2.x",
"nock": "9.x",