1
0
mirror of https://github.com/S2-/minifyfromhtml.git synced 2025-08-02 20:00:05 +02:00

update node modules

This commit is contained in:
s2
2021-05-07 15:56:33 +02:00
parent d81e8e9fb8
commit 3ec373077c
550 changed files with 84712 additions and 15991 deletions

62
node_modules/clean-css/History.md generated vendored
View File

@@ -1,3 +1,63 @@
[5.1.2 / 2021-03-19](https://github.com/jakubpawlowicz/clean-css/compare/v5.1.1...v5.1.2)
==================
* Fixed issue [#996](https://github.com/jakubpawlowicz/clean-css/issues/996) - space removed from pseudo classes.
[5.1.1 / 2021-03-03](https://github.com/jakubpawlowicz/clean-css/compare/v5.1.0...v5.1.1)
==================
* Fixed issue [#1156](https://github.com/jakubpawlowicz/clean-css/issues/1156) - invalid hsl/hsla validation in level 2 optimizations.
[5.1.0 / 2021-02-18](https://github.com/jakubpawlowicz/clean-css/compare/5.0...v5.1.0)
==================
* Fixes stripping '%' from inside color functions.
* Improves tokenization speed by ~30%.
* Fixed issue [#1143](https://github.com/jakubpawlowicz/clean-css/issues/1143) - some missing level 1 value optimizations.
[5.0.1 / 2021-01-29](https://github.com/jakubpawlowicz/clean-css/compare/v5.0.0...v5.0.1)
==================
* Fixed issue [#1139](https://github.com/jakubpawlowicz/clean-css/issues/1139) - overriding & merging properties without `canOverride` set.
[5.0.0 / 2021-01-29](https://github.com/jakubpawlowicz/clean-css/compare/4.2...v5.0.0)
==================
* Adds a way process input files without bundling it into one big output file.
* Adds level 1 and level 2 optimization plugins.
* Disables URL rebasing by default.
* Disables URL unquoting by default.
* Drops support for Node.js 6 & 8 to support last 3 Node.js releases: 10, 12, and 14.
* Fixed issue [#889](https://github.com/jakubpawlowicz/clean-css/issues/889) - whitelisted level 1 optimizations.
* Fixed issue [#975](https://github.com/jakubpawlowicz/clean-css/issues/975) - incorrect block name optimization.
* Fixed issue [#1009](https://github.com/jakubpawlowicz/clean-css/issues/1009) - whitespace around comments.
* Fixed issue [#1021](https://github.com/jakubpawlowicz/clean-css/issues/1021) - allow one- and two-letter property names.
* Fixed issue [#1022](https://github.com/jakubpawlowicz/clean-css/issues/1022) - merging into shorthands new property positioning.
* Fixed issue [#1032](https://github.com/jakubpawlowicz/clean-css/issues/1032) - wrong order of merged shorthands with inherit.
* Fixed issue [#1043](https://github.com/jakubpawlowicz/clean-css/issues/1043) - `calc` fallback removed within other function.
* Fixed issue [#1045](https://github.com/jakubpawlowicz/clean-css/issues/1045) - non-standard protocol-less URL first slash removed.
* Fixed issue [#1050](https://github.com/jakubpawlowicz/clean-css/issues/1050) - correctly keeps default animation duration if delay is also set.
* Fixed issue [#1053](https://github.com/jakubpawlowicz/clean-css/issues/1053) - treats `calc()` as first class width value.
* Fixed issue [#1055](https://github.com/jakubpawlowicz/clean-css/issues/1055) - supports 4- and 8-character hex with alpha color notation.
* Fixed issue [#1057](https://github.com/jakubpawlowicz/clean-css/issues/1057) - level 2 optimizations and quoted font family name.
* Fixed issue [#1059](https://github.com/jakubpawlowicz/clean-css/issues/1059) - animation time units as CSS expressions.
* Fixed issue [#1060](https://github.com/jakubpawlowicz/clean-css/issues/1060) - variable removed when shorthand's only value.
* Fixed issue [#1062](https://github.com/jakubpawlowicz/clean-css/issues/1062) - wrong optimization of CSS pseudo-classes with selector list.
* Fixed issue [#1073](https://github.com/jakubpawlowicz/clean-css/issues/1073) - adds support for non-standard `rpx` units.
* Fixed issue [#1075](https://github.com/jakubpawlowicz/clean-css/issues/1075) - media merging and variables.
* Fixed issue [#1087](https://github.com/jakubpawlowicz/clean-css/issues/1087) - allow units with any case.
* Fixed issue [#1088](https://github.com/jakubpawlowicz/clean-css/issues/1088) - building source maps with source preserved via comments.
* Fixed issue [#1090](https://github.com/jakubpawlowicz/clean-css/issues/1090) - edge case in merging for `border` and `border-image`.
* Fixed issue [#1103](https://github.com/jakubpawlowicz/clean-css/issues/1103) - don't allow merging longhand into `unset` shorthand.
* Fixed issue [#1115](https://github.com/jakubpawlowicz/clean-css/issues/1115) - incorrect multiplex longhand into shorthand merging.
* Fixed issue [#1117](https://github.com/jakubpawlowicz/clean-css/issues/1117) - don't change zero values inside `min`, `max`, and `clamp` functions.
* Fixed issue [#1122](https://github.com/jakubpawlowicz/clean-css/issues/1122) - don't wrap data URI in single quotes.
* Fixed issue [#1125](https://github.com/jakubpawlowicz/clean-css/issues/1125) - quotes stripped from withing `@supports` clause.
* Fixed issue [#1128](https://github.com/jakubpawlowicz/clean-css/issues/1128) - take variables into account when reordering properties.
* Fixed issue [#1132](https://github.com/jakubpawlowicz/clean-css/issues/1132) - vendor-prefixed classes inside `:not()`.
* Reworks all level 1 optimizations to conform to plugin style.
[4.2.3 / 2020-01-28](https://github.com/jakubpawlowicz/clean-css/compare/v4.2.2...v4.2.3)
==================
@@ -16,7 +76,7 @@
* Fixes giving `breakWith` option via a string.
[4.2.0 / 2018-08-02](https://github.com/jakubpawlowicz/clean-css/compare/4.1...4.2.0)
[4.2.0 / 2018-08-02](https://github.com/jakubpawlowicz/clean-css/compare/4.1...v4.2.0)
==================
* Adds `process` method for compatibility with optimize-css-assets-webpack-plugin.

198
node_modules/clean-css/README.md generated vendored
View File

@@ -5,12 +5,11 @@
<br/>
</h1>
[![NPM version](https://img.shields.io/npm/v/clean-css.svg?style=flat)](https://www.npmjs.com/package/clean-css)
[![Linux Build Status](https://img.shields.io/travis/jakubpawlowicz/clean-css/master.svg?style=flat&label=Linux%20build)](https://travis-ci.org/jakubpawlowicz/clean-css)
[![Windows Build status](https://img.shields.io/appveyor/ci/jakubpawlowicz/clean-css/master.svg?style=flat&label=Windows%20build)](https://ci.appveyor.com/project/jakubpawlowicz/clean-css/branch/master)
[![npm version](https://img.shields.io/npm/v/clean-css.svg?style=flat)](https://www.npmjs.com/package/clean-css)
[![Build Status](https://img.shields.io/github/workflow/status/jakubpawlowicz/clean-css/Tests/master)](https://github.com/jakubpawlowicz/clean-css/actions?query=workflow%3ATests+branch%3Amaster)
[![PPC Linux Build Status](https://img.shields.io/travis/jakubpawlowicz/clean-css/master.svg?style=flat&label=PPC%20Linux%20build)](https://travis-ci.org/jakubpawlowicz/clean-css)
[![Dependency Status](https://img.shields.io/david/jakubpawlowicz/clean-css.svg?style=flat)](https://david-dm.org/jakubpawlowicz/clean-css)
[![NPM Downloads](https://img.shields.io/npm/dm/clean-css.svg)](https://npmcharts.com/compare/clean-css?minimal=true)
[![Twitter](https://img.shields.io/badge/Twitter-@cleancss-blue.svg)](https://twitter.com/cleancss)
[![npm Downloads](https://img.shields.io/npm/dm/clean-css.svg)](https://npmcharts.com/compare/clean-css?minimal=true)
clean-css is a fast and efficient CSS optimizer for [Node.js](http://nodejs.org/) platform and [any modern browser](https://jakubpawlowicz.github.io/clean-css).
@@ -21,9 +20,10 @@ According to [tests](http://goalsmashers.github.io/css-minification-benchmark/)
- [Node.js version support](#nodejs-version-support)
- [Install](#install)
- [Use](#use)
* [Important: 4.0 breaking changes](#important-40-breaking-changes)
* [What's new in version 4.1](#whats-new-in-version-41)
* [What's new in version 5.0](#whats-new-in-version-50)
* [What's new in version 4.2](#whats-new-in-version-42)
* [What's new in version 4.1](#whats-new-in-version-41)
* [Important: 4.0 breaking changes](#important-40-breaking-changes)
* [Constructor options](#constructor-options)
* [Compatibility modes](#compatibility-modes)
* [Fetch option](#fetch-option)
@@ -33,11 +33,13 @@ According to [tests](http://goalsmashers.github.io/css-minification-benchmark/)
+ [Level 0 optimizations](#level-0-optimizations)
+ [Level 1 optimizations](#level-1-optimizations)
+ [Level 2 optimizations](#level-2-optimizations)
* [Plugins](#plugins)
* [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 multiple files without concatenating them into one output file?](#how-to-process-multiple-files-without-concatenating-them-into-one-output-file)
* [How to process remote `@import`s correctly?](#how-to-process-remote-imports-correctly)
* [How to apply arbitrary transformations to CSS properties?](#how-to-apply-arbitrary-transformations-to-css-properties)
* [How to specify a custom rounding precision?](#how-to-specify-a-custom-rounding-precision)
@@ -56,7 +58,7 @@ According to [tests](http://goalsmashers.github.io/css-minification-benchmark/)
# Node.js version support
clean-css requires Node.js 4.0+ (tested on Linux, OS X, and Windows)
clean-css requires Node.js 6.0+ (tested on Linux, OS X, and Windows)
# Install
@@ -73,6 +75,49 @@ var options = { /* options */ };
var output = new CleanCSS(options).minify(input);
```
## What's new in version 5.0
clean-css 5.0 will introduce some breaking changes:
* Node.js 6.x and 8.x are officially no longer supported;
* `transform` callback in level-1 optimizations is removed in favor of new [plugins](#plugins) interface;
* changes default Internet Explorer compatibility from 10+ to >11, to revert the old default use `{ compatibility: 'ie10' }` flag;
* changes default `rebase` option from `true` to `false` so URLs are not rebased by default. Please note that if you set `rebaseTo` option it still counts as setting `rebase: true` to preserve some of the backward compatibility.
And on the new features side of things:
* format options now accepts numerical values for all breaks, which will allow you to have more control over output formatting, e.g. `format: {breaks: {afterComment: 2}}` means clean-css will add two line breaks after each comment
* a new `batch` option (defaults to `false`) is added, when set to `true` it will process all inputs, given either as an array or a hash, without concatenating them.
## What's new in version 4.2
clean-css 4.2 introduces the following changes / features:
* Adds `process` method for compatibility with optimize-css-assets-webpack-plugin;
* new `transition` property optimizer;
* preserves any CSS content between `/* clean-css ignore:start */` and `/* clean-css ignore:end */` comments;
* allows filtering based on selector in `transform` callback, see [example](#how-to-apply-arbitrary-transformations-to-css-properties);
* adds configurable line breaks via `format: { breakWith: 'lf' }` option.
## 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.
## Important: 4.0 breaking changes
clean-css 4.0 introduces some breaking changes:
@@ -95,35 +140,6 @@ 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.
## What's new in version 4.2
clean-css 4.2 introduces the following changes / features:
* Adds `process` method for compatibility with optimize-css-assets-webpack-plugin;
* new `transition` property optimizer;
* preserves any CSS content between `/* clean-css ignore:start */` and `/* clean-css ignore:end */` comments;
* allows filtering based on selector in `transform` callback, see [example](#how-to-apply-arbitrary-transformations-to-css-properties);
* adds configurable line breaks via `format: { breakWith: 'lf' }` option.
## Constructor options
clean-css constructor accepts a hash as a parameter with the following options available:
@@ -135,7 +151,7 @@ clean-css constructor accepts a hash as a parameter with the following options a
* `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);
* `inlineTimeout` - controls number of milliseconds after which inlining a remote `@import` fails; defaults to 5000;
* `level` - controls optimization level used; defaults to `1`; see [optimization levels](#optimization-levels) for examples;
* `rebase` - controls URL rebasing; defaults to `true`;
* `rebase` - controls URL rebasing; defaults to `false`;
* `rebaseTo` - controls a directory to which all URLs are rebased, most likely the directory under which the output file will live; defaults to the current directory;
* `returnPromise` - controls whether `minify` method returns a Promise object or not; defaults to `false`; see [promise interface](#promise-interface) for examples;
* `sourceMap` - controls whether an output source map is built; defaults to `false`;
@@ -156,6 +172,7 @@ Each of these modes is an alias to a [fine grained configuration](https://github
new CleanCSS({
compatibility: {
colors: {
hexAlpha: false, // controls 4- and 8-character hex color support
opacity: true // controls `rgba()` / `hsla()` color support
},
properties: {
@@ -170,7 +187,7 @@ new CleanCSS({
merging: true, // controls property merging based on understandability
shorterLengthUnits: false, // controls shortening pixel units into `pc`, `pt`, or `in` units
spaceAfterClosingBrace: true, // controls keeping space after closing brace - `url() no-repeat` into `url()no-repeat`
urlQuotes: false, // controls keeping quoting inside `url()`
urlQuotes: true, // controls keeping quoting inside `url()`
zeroUnits: true // controls removal of units `0` value
},
selectors: {
@@ -273,11 +290,34 @@ new CleanCSS({
beforeBlockBegins: false, // controls if a space comes before a block begins; e.g. `.block {`; defaults to `false`
beforeValue: false // controls if a space comes before a value; e.g. `width: 1rem`; defaults to `false`
},
wrapAt: false // controls maximum line length; defaults to `false`
wrapAt: false, // controls maximum line length; defaults to `false`
semicolonAfterLastProperty: false // controls removing trailing semicolons in rule; defaults to `false` - means remove
}
})
```
Also since clean-css 5.0 you can use numerical values for all line breaks, which will repeat a line break that many times, e.g:
```js
new CleanCSS({
format: {
breaks: {
afterAtRule: 2,
afterBlockBegins: 1, // 1 is synonymous with `true`
afterBlockEnds: 2,
afterComment: 1,
afterProperty: 1,
afterRuleBegins: 1,
afterRuleEnds: 1,
beforeBlockEnds: 1,
betweenSelectors: 0 // 0 is synonymous with `false`
}
}
})
```
which will add nicer spacing between at rules and blocks.
## Inlining options
`inline` option whitelists which `@import` rules will be processed, e.g.
@@ -368,9 +408,7 @@ new CleanCSS({
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`
tidySelectors: true, // controls selectors optimizing; defaults to `true`,
semicolonAfterLastProperty: false, // controls removing trailing semicolons in rule; defaults to `false` - means remove
transform: function () {} // defines a callback for fine-grained property optimization; defaults to no-op
tidySelectors: true, // controls selectors optimizing; defaults to `true`
}
}
});
@@ -433,6 +471,31 @@ new CleanCSS({
});
```
## Plugins
In clean-css version 5 and above you can define plugins which run alongside level 1 and level 2 optimizations, e.g.
```js
var myPlugin = {
level1: {
property: function removeRepeatedBackgroundRepeat(_rule, property, _options) {
// So `background-repeat:no-repeat no-repeat` becomes `background-repeat:no-repeat`
if (property.name == 'background-repeat' && property.value.length == 2 && property.value[0][1] == property.value[1][1]) {
property.value.pop();
property.dirty = true;
}
}
}
}
new CleanCSS({plugins: [myPlugin]})
```
Search `test\module-test.js` for `plugins` or check out `lib/optimizer/level-1/property-optimizers` and `lib/optimizer/level-1/value-optimizers` for more examples.
__Important__: To rewrite your old `transform` as a plugin, check out [this commit](https://github.com/jakubpawlowicz/clean-css/commit/b6ddc523267fc42cf0f6bd1626a79cad97319e17#diff-a71ef45f934725cdb25860dc0b606bcd59e3acee9788cd6df4f9d05339e8a153).
## Minify method
Once configured clean-css provides a `minify` method to optimize a given CSS, e.g.
@@ -515,6 +578,16 @@ Passing an array of hashes allows you to explicitly specify the order in which t
Important note - any `@import` rules already present in the hash will be resolved in memory.
## How to process multiple files without concatenating them into one output file?
Since clean-css 5.0 you can, when passing an array of paths, hash, or array of hashes (see above), ask clean-css not to join styles into one output, but instead return stylesheets optimized one by one, e.g.
```js
var output = new CleanCSS({ batch: true }).minify(['path/to/file/one', 'path/to/file/two']);
var outputOfFile1 = output['path/to/file/one'].styles // all other fields, like errors, warnings, or stats are there too
var outputOfFile2 = output['path/to/file/two'].styles
```
## How to process remote `@import`s correctly?
In order to inline remote `@import` statements you need to provide a callback to minify method as fetching remote assets is an asynchronous operation, e.g.:
@@ -530,26 +603,7 @@ If you don't provide a callback, then remote `@import`s will be left as is.
## How to apply arbitrary transformations to CSS properties?
If clean-css doesn't perform a particular property optimization, you can use `transform` callback to apply it:
```js
var source = '.block{background-image:url(/path/to/image.png)}';
var output = new CleanCSS({
level: {
1: {
transform: function (propertyName, propertyValue, selector /* `selector` available since 4.2.0-pre */) {
if (propertyName == 'background-image' && propertyValue.indexOf('/path/to') > -1) {
return propertyValue.replace('/path/to', '../valid/path/to');
}
}
}
}
}).minify(source);
console.log(output.styles); # => .block{background-image:url(../valid/path/to/image.png)}
```
Note: returning `false` from `transform` callback will drop a property.
Please see [plugins](#plugins).
## How to specify a custom rounding precision?
@@ -567,9 +621,25 @@ new CleanCSS({
which sets all units rounding precision to 3 digits except `px` unit precision of 5 digits.
## How to optimize a stylesheet with custom `rpx` units?
Since `rpx` is a non standard unit (see [#1074](https://github.com/jakubpawlowicz/clean-css/issues/1074)), it will be dropped by default as an invalid value.
However you can treat `rpx` units as regular ones:
```js
new CleanCSS({
compatibility: {
customUnits: {
rpx: true
}
}
}).minify(source)
```
## How to keep a CSS fragment intact?
Note: available in the current master, to be released in 4.2.0.
Note: available since 4.2.0.
Wrap the CSS fragment in special comments which instruct clean-css to preserve it, e.g.

80
node_modules/clean-css/lib/clean.js generated vendored
View File

@@ -18,6 +18,7 @@ var inlineRequestFrom = require('./options/inline-request');
var inlineTimeoutFrom = require('./options/inline-timeout');
var OptimizationLevel = require('./options/optimization-level').OptimizationLevel;
var optimizationLevelFrom = require('./options/optimization-level').optimizationLevelFrom;
var pluginsFrom = require('./options/plugins');
var rebaseFrom = require('./options/rebase');
var rebaseToFrom = require('./options/rebase-to');
@@ -31,14 +32,17 @@ var CleanCSS = module.exports = function CleanCSS(options) {
options = options || {};
this.options = {
batch: !!options.batch,
compatibility: compatibilityFrom(options.compatibility),
explicitRebaseTo: 'rebaseTo' in options,
fetch: fetchFrom(options.fetch),
format: formatFrom(options.format),
inline: inlineFrom(options.inline),
inlineRequest: inlineRequestFrom(options.inlineRequest),
inlineTimeout: inlineTimeoutFrom(options.inlineTimeout),
level: optimizationLevelFrom(options.level),
rebase: rebaseFrom(options.rebase),
plugins: pluginsFrom(options.plugins),
rebase: rebaseFrom(options.rebase, options.rebaseTo),
rebaseTo: rebaseToFrom(options.rebaseTo),
returnPromise: !!options.returnPromise,
sourceMap: !!options.sourceMap,
@@ -67,17 +71,78 @@ CleanCSS.prototype.minify = function (input, maybeSourceMap, maybeCallback) {
if (options.returnPromise) {
return new Promise(function (resolve, reject) {
minify(input, options, maybeSourceMap, function (errors, output) {
minifyAll(input, options, maybeSourceMap, function (errors, output) {
return errors ?
reject(errors) :
resolve(output);
});
});
} else {
return minify(input, options, maybeSourceMap, maybeCallback);
return minifyAll(input, options, maybeSourceMap, maybeCallback);
}
};
function minifyAll(input, options, maybeSourceMap, maybeCallback) {
if (options.batch && Array.isArray(input)) {
return minifyInBatchesFromArray(input, options, maybeSourceMap, maybeCallback);
} else if (options.batch && (typeof input == 'object')) {
return minifyInBatchesFromHash(input, options, maybeSourceMap, maybeCallback);
} else {
return minify(input, options, maybeSourceMap, maybeCallback);
}
}
function minifyInBatchesFromArray(input, options, maybeSourceMap, maybeCallback) {
var callback = typeof maybeCallback == 'function' ?
maybeCallback :
(typeof maybeSourceMap == 'function' ? maybeSourceMap : null);
var errors = [];
var outputAsHash = {};
var inputValue;
var i, l;
function whenHashBatchDone(innerErrors, output) {
outputAsHash = Object.assign(outputAsHash, output);
errors.concat(innerErrors);
}
for (i = 0, l = input.length; i < l; i++) {
if (typeof input[i] == 'object') {
minifyInBatchesFromHash(input[i], options, whenHashBatchDone);
} else {
inputValue = input[i];
outputAsHash[inputValue] = minify([inputValue], options);
errors.concat(outputAsHash[inputValue].errors);
}
}
return callback ?
callback(errors.length > 0 ? errors : null, outputAsHash) :
outputAsHash;
}
function minifyInBatchesFromHash(input, options, maybeSourceMap, maybeCallback) {
var callback = typeof maybeCallback == 'function' ?
maybeCallback :
(typeof maybeSourceMap == 'function' ? maybeSourceMap : null);
var errors = [];
var outputAsHash = {};
var inputKey;
var inputValue;
for (inputKey in input) {
inputValue = input[inputKey];
outputAsHash[inputKey] = minify(inputValue.styles, options, inputValue.sourceMap);
errors.concat(outputAsHash[inputKey].errors);
}
return callback ?
callback(errors.length > 0 ? errors : null, outputAsHash) :
outputAsHash;
}
function minify(input, options, maybeSourceMap, maybeCallback) {
var sourceMap = typeof maybeSourceMap != 'function' ?
maybeSourceMap :
@@ -106,11 +171,20 @@ function minify(input, options, maybeSourceMap, maybeCallback) {
validator: validator(options.compatibility),
warnings: []
};
var implicitRebaseToWarning;
if (sourceMap) {
context.inputSourceMapTracker.track(undefined, sourceMap);
}
if (options.rebase && !options.explicitRebaseTo) {
implicitRebaseToWarning =
'You have set `rebase: true` without giving `rebaseTo` option, which, in this case, defaults to the current working directory. ' +
'You are then warned this can lead to unexpected URL rebasing (aka here be dragons)! ' +
'If you are OK with the clean-css output, then you can get rid of this warning by giving clean-css a `rebaseTo: process.cwd()` option.';
context.warnings.push(implicitRebaseToWarning);
}
return runner(context.localOnly)(function () {
return readSources(input, context, function (tokens) {
var serialize = context.options.sourceMap ?

View File

@@ -1,6 +1,6 @@
var wrapSingle = require('../wrap-for-optimizing').single;
var wrapSingle = require('./wrap-for-optimizing').single;
var Token = require('../../tokenizer/token');
var Token = require('../tokenizer/token');
function deep(property) {
var cloned = shallow(property);

View File

@@ -1,4 +1,4 @@
var InvalidPropertyError = require('./invalid-property-error');
var InvalidPropertyError = require('../invalid-property-error');
var wrapSingle = require('../wrap-for-optimizing').single;
@@ -31,8 +31,8 @@ function _styleFilter(validator) {
};
}
function _wrapDefault(name, property, compactable) {
var descriptor = compactable[name];
function _wrapDefault(name, property, configuration) {
var descriptor = configuration[name];
if (descriptor.doubleValues && descriptor.defaultValue.length == 2) {
return wrapSingle([
Token.PROPERTY,
@@ -58,21 +58,21 @@ function _wrapDefault(name, property, compactable) {
function _widthFilter(validator) {
return function (value) {
return value[1] != 'inherit' &&
(validator.isWidth(value[1]) || validator.isUnit(value[1]) && !validator.isDynamicUnit(value[1])) &&
(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);
function animation(property, configuration, validator) {
var duration = _wrapDefault(property.name + '-duration', property, configuration);
var timing = _wrapDefault(property.name + '-timing-function', property, configuration);
var delay = _wrapDefault(property.name + '-delay', property, configuration);
var iteration = _wrapDefault(property.name + '-iteration-count', property, configuration);
var direction = _wrapDefault(property.name + '-direction', property, configuration);
var fill = _wrapDefault(property.name + '-fill-mode', property, configuration);
var play = _wrapDefault(property.name + '-play-state', property, configuration);
var name = _wrapDefault(property.name + '-name', property, configuration);
var components = [duration, timing, delay, iteration, direction, fill, play, name];
var values = property.value;
var value;
@@ -131,15 +131,15 @@ function animation(property, compactable, validator) {
return components;
}
function background(property, compactable, validator) {
var image = _wrapDefault('background-image', property, compactable);
var position = _wrapDefault('background-position', property, compactable);
var size = _wrapDefault('background-size', property, compactable);
var repeat = _wrapDefault('background-repeat', property, compactable);
var attachment = _wrapDefault('background-attachment', property, compactable);
var origin = _wrapDefault('background-origin', property, compactable);
var clip = _wrapDefault('background-clip', property, compactable);
var color = _wrapDefault('background-color', property, compactable);
function background(property, configuration, validator) {
var image = _wrapDefault('background-image', property, configuration);
var position = _wrapDefault('background-position', property, configuration);
var size = _wrapDefault('background-size', property, configuration);
var repeat = _wrapDefault('background-repeat', property, configuration);
var attachment = _wrapDefault('background-attachment', property, configuration);
var origin = _wrapDefault('background-origin', property, configuration);
var clip = _wrapDefault('background-clip', property, configuration);
var color = _wrapDefault('background-color', property, configuration);
var components = [image, position, size, repeat, attachment, origin, clip, color];
var values = property.value;
@@ -207,7 +207,7 @@ 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.isColor(value[1]) || validator.isPrefixed(value[1]))) {
} else if ((color.value[0][1] == configuration[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isColor(value[1]) || validator.isPrefixed(value[1]))) {
color.value = [value];
anyValueSet = true;
} else if (validator.isUrl(value[1]) || validator.isFunction(value[1])) {
@@ -226,7 +226,7 @@ function background(property, compactable, validator) {
return components;
}
function borderRadius(property, compactable) {
function borderRadius(property, configuration) {
var values = property.value;
var splitAt = -1;
@@ -241,17 +241,17 @@ function borderRadius(property, compactable) {
throw new InvalidPropertyError('Invalid border-radius value at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
}
var target = _wrapDefault(property.name, property, compactable);
var target = _wrapDefault(property.name, property, configuration);
target.value = splitAt > -1 ?
values.slice(0, splitAt) :
values.slice(0);
target.components = fourValues(target, compactable);
target.components = fourValues(target, configuration);
var remainder = _wrapDefault(property.name, property, compactable);
var remainder = _wrapDefault(property.name, property, configuration);
remainder.value = splitAt > -1 ?
values.slice(splitAt + 1) :
values.slice(0);
remainder.components = fourValues(remainder, compactable);
remainder.components = fourValues(remainder, configuration);
for (var j = 0; j < 4; j++) {
target.components[j].multiplex = true;
@@ -261,14 +261,14 @@ 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);
function font(property, configuration, validator) {
var style = _wrapDefault('font-style', property, configuration);
var variant = _wrapDefault('font-variant', property, configuration);
var weight = _wrapDefault('font-weight', property, configuration);
var stretch = _wrapDefault('font-stretch', property, configuration);
var size = _wrapDefault('font-size', property, configuration);
var height = _wrapDefault('line-height', property, configuration);
var family = _wrapDefault('font-family', property, configuration);
var components = [style, variant, weight, stretch, size, height, family];
var values = property.value;
var fuzzyMatched = 4; // style, variant, weight, and stretch
@@ -403,7 +403,7 @@ function _anyIsFontFamily(values, validator) {
for (i = 0, l = values.length; i < l; i++) {
value = values[i];
if (validator.isIdentifier(value[1])) {
if (validator.isIdentifier(value[1]) || validator.isQuotedText(value[1])) {
return true;
}
}
@@ -411,8 +411,8 @@ function _anyIsFontFamily(values, validator) {
return false;
}
function fourValues(property, compactable) {
var componentNames = compactable[property.name].components;
function fourValues(property, configuration) {
var componentNames = configuration[property.name].components;
var components = [];
var value = property.value;
@@ -439,7 +439,7 @@ function fourValues(property, compactable) {
}
function multiplex(splitWith) {
return function (property, compactable, validator) {
return function (property, configuration, validator) {
var splitsAt = [];
var values = property.value;
var i, j, l, m;
@@ -451,7 +451,7 @@ function multiplex(splitWith) {
}
if (splitsAt.length === 0)
return splitWith(property, compactable, validator);
return splitWith(property, configuration, validator);
var splitComponents = [];
@@ -460,10 +460,10 @@ function multiplex(splitWith) {
var from = i === 0 ? 0 : splitsAt[i - 1] + 1;
var to = i < l ? splitsAt[i] : values.length;
var _property = _wrapDefault(property.name, property, compactable);
var _property = _wrapDefault(property.name, property, configuration);
_property.value = values.slice(from, to);
splitComponents.push(splitWith(_property, compactable, validator));
splitComponents.push(splitWith(_property, configuration, validator));
}
var components = splitComponents[0];
@@ -482,10 +482,10 @@ function multiplex(splitWith) {
};
}
function listStyle(property, compactable, validator) {
var type = _wrapDefault('list-style-type', property, compactable);
var position = _wrapDefault('list-style-position', property, compactable);
var image = _wrapDefault('list-style-image', property, compactable);
function listStyle(property, configuration, validator) {
var type = _wrapDefault('list-style-type', property, configuration);
var position = _wrapDefault('list-style-position', property, configuration);
var image = _wrapDefault('list-style-image', property, configuration);
var components = [type, position, image];
if (property.value.length == 1 && property.value[0][1] == 'inherit') {
@@ -523,11 +523,11 @@ function listStyle(property, compactable, validator) {
return components;
}
function transition(property, compactable, validator) {
var prop = _wrapDefault(property.name + '-property', property, compactable);
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);
function transition(property, configuration, validator) {
var prop = _wrapDefault(property.name + '-property', property, configuration);
var duration = _wrapDefault(property.name + '-duration', property, configuration);
var timing = _wrapDefault(property.name + '-timing-function', property, configuration);
var delay = _wrapDefault(property.name + '-delay', property, configuration);
var components = [prop, duration, timing, delay];
var values = property.value;
var value;
@@ -570,12 +570,12 @@ function transition(property, compactable, validator) {
return components;
}
function widthStyleColor(property, compactable, validator) {
var descriptor = compactable[property.name];
function widthStyleColor(property, configuration, validator) {
var descriptor = configuration[property.name];
var components = [
_wrapDefault(descriptor.components[0], property, compactable),
_wrapDefault(descriptor.components[1], property, compactable),
_wrapDefault(descriptor.components[2], property, compactable)
_wrapDefault(descriptor.components[0], property, configuration),
_wrapDefault(descriptor.components[1], property, configuration),
_wrapDefault(descriptor.components[2], property, configuration)
];
var color, style, width;

View File

@@ -28,7 +28,14 @@ function areSameFunction(validator, value1, value2) {
var function1Name = value1.substring(0, value1.indexOf('('));
var function2Name = value2.substring(0, value2.indexOf('('));
return function1Name === function2Name;
var function1Value = value1.substring(function1Name.length + 1, value1.length - 1);
var function2Value = value2.substring(function2Name.length + 1, value2.length - 1);
if (validator.isFunction(function1Value) || validator.isFunction(function2Value)) {
return function1Name === function2Name && areSameFunction(validator, function1Value, function2Value);
} else {
return function1Name === function2Name;
}
}
function backgroundPosition(validator, value1, value2) {
@@ -64,6 +71,8 @@ function color(validator, value1, value2) {
return false;
} else if (!validator.colorOpacity && (validator.isRgbColor(value2) || validator.isHslColor(value2))) {
return false;
} else if (!validator.colorHexAlpha && (validator.isHexAlphaColor(value1) || validator.isHexAlphaColor(value2))) {
return false;
} else if (validator.isColor(value1) && validator.isColor(value2)) {
return true;
}

View File

@@ -1,4 +1,4 @@
var sameVendorPrefixes = require('./vendor-prefixes').same;
var sameVendorPrefixes = require('../../vendor-prefixes').same;
function understandable(validator, value1, value2, _position, isPaired) {
if (!sameVendorPrefixes(value1, value2)) {

View File

@@ -1,4 +1,4 @@
var shallowClone = require('./clone').shallow;
var shallowClone = require('../clone').shallow;
var Token = require('../../tokenizer/token');
var Marker = require('../../tokenizer/marker');
@@ -14,7 +14,7 @@ function isInheritOnly(values) {
return true;
}
function background(property, compactable, lastInMultiplex) {
function background(property, configuration, lastInMultiplex) {
var components = property.components;
var restored = [];
var needsOne, needsBoth;
@@ -24,7 +24,7 @@ function background(property, compactable, lastInMultiplex) {
}
function isDefaultValue(component) {
var descriptor = compactable[component.name];
var descriptor = configuration[component.name];
if (descriptor.doubleValues && descriptor.defaultValue.length == 1) {
return component.value[0][1] == descriptor.defaultValue[0] && (component.value[1] ? component.value[1][1] == descriptor.defaultValue[0] : true);
@@ -79,7 +79,7 @@ function background(property, compactable, lastInMultiplex) {
i--;
} else {
if (isDefault || compactable[component.name].multiplexLastOnly && !lastInMultiplex)
if (isDefault || configuration[component.name].multiplexLastOnly && !lastInMultiplex)
continue;
restoreValue(component);
@@ -90,7 +90,7 @@ function background(property, compactable, lastInMultiplex) {
restored.push(property.value[0]);
if (restored.length === 0)
restored.push([Token.PROPERTY_VALUE, compactable[property.name].defaultValue]);
restored.push([Token.PROPERTY_VALUE, configuration[property.name].defaultValue]);
if (isInheritOnly(restored))
return [restored[0]];
@@ -98,7 +98,7 @@ function background(property, compactable, lastInMultiplex) {
return restored;
}
function borderRadius(property, compactable) {
function borderRadius(property, configuration) {
if (property.multiplex) {
var horizontal = shallowClone(property);
var vertical = shallowClone(property);
@@ -118,8 +118,8 @@ function borderRadius(property, compactable) {
vertical.components.push(verticalComponent);
}
var horizontalValues = fourValues(horizontal, compactable);
var verticalValues = fourValues(vertical, compactable);
var horizontalValues = fourValues(horizontal, configuration);
var verticalValues = fourValues(vertical, configuration);
if (horizontalValues.length == verticalValues.length &&
horizontalValues[0][1] == verticalValues[0][1] &&
@@ -131,11 +131,11 @@ function borderRadius(property, compactable) {
return horizontalValues.concat([[Token.PROPERTY_VALUE, Marker.FORWARD_SLASH]]).concat(verticalValues);
}
} else {
return fourValues(property, compactable);
return fourValues(property, configuration);
}
}
function font(property, compactable) {
function font(property, configuration) {
var components = property.components;
var restored = [];
var component;
@@ -151,7 +151,7 @@ function font(property, compactable) {
while (componentIndex < 4) {
component = components[componentIndex];
if (component.value[0][1] != compactable[component.name].defaultValue) {
if (component.value[0][1] != configuration[component.name].defaultValue) {
Array.prototype.push.apply(restored, component.value);
}
@@ -163,7 +163,7 @@ function font(property, compactable) {
componentIndex++;
// then may come line-height
if (components[componentIndex].value[0][1] != compactable[components[componentIndex].name].defaultValue) {
if (components[componentIndex].value[0][1] != configuration[components[componentIndex].name].defaultValue) {
Array.prototype.push.apply(restored, [[Token.PROPERTY_VALUE, Marker.FORWARD_SLASH]]);
Array.prototype.push.apply(restored, components[componentIndex].value);
}
@@ -207,9 +207,9 @@ function fourValues(property) {
}
function multiplex(restoreWith) {
return function (property, compactable) {
return function (property, configuration) {
if (!property.multiplex)
return restoreWith(property, compactable, true);
return restoreWith(property, configuration, true);
var multiplexSize = 0;
var restored = [];
@@ -245,7 +245,7 @@ function multiplex(restoreWith) {
// No we can restore shorthand value
var lastInMultiplex = i == multiplexSize;
var _restored = restoreWith(_property, compactable, lastInMultiplex);
var _restored = restoreWith(_property, configuration, lastInMultiplex);
Array.prototype.push.apply(restored, _restored);
if (i < multiplexSize)
@@ -256,21 +256,21 @@ function multiplex(restoreWith) {
};
}
function withoutDefaults(property, compactable) {
function withoutDefaults(property, configuration) {
var components = property.components;
var restored = [];
for (var i = components.length - 1; i >= 0; i--) {
var component = components[i];
var descriptor = compactable[component.name];
var descriptor = configuration[component.name];
if (component.value[0][1] != descriptor.defaultValue || ('keepUnlessDefault' in descriptor) && !isDefault(components, compactable, descriptor.keepUnlessDefault)) {
if (component.value[0][1] != descriptor.defaultValue || ('keepUnlessDefault' in descriptor) && !isDefault(components, configuration, descriptor.keepUnlessDefault)) {
restored.unshift(component.value[0]);
}
}
if (restored.length === 0)
restored.push([Token.PROPERTY_VALUE, compactable[property.name].defaultValue]);
restored.push([Token.PROPERTY_VALUE, configuration[property.name].defaultValue]);
if (isInheritOnly(restored))
return [restored[0]];
@@ -278,14 +278,14 @@ function withoutDefaults(property, compactable) {
return restored;
}
function isDefault(components, compactable, propertyName) {
function isDefault(components, configuration, propertyName) {
var component;
var i, l;
for (i = 0, l = components.length; i < l; i++) {
component = components[i];
if (component.name == propertyName && component.value[0][1] == compactable[propertyName].defaultValue) {
if (component.name == propertyName && component.value[0][1] == configuration[propertyName].defaultValue) {
return true;
}
}

View File

@@ -1,6 +1,3 @@
var shortenHex = require('./shorten-hex');
var shortenHsl = require('./shorten-hsl');
var shortenRgb = require('./shorten-rgb');
var sortSelectors = require('./sort-selectors');
var tidyRules = require('./tidy-rules');
var tidyBlock = require('./tidy-block');
@@ -11,399 +8,85 @@ var removeUnused = require('../remove-unused');
var restoreFromOptimizing = require('../restore-from-optimizing');
var wrapForOptimizing = require('../wrap-for-optimizing').all;
var configuration = require('../configuration');
var optimizers = require('./value-optimizers');
var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
var Token = require('../../tokenizer/token');
var Marker = require('../../tokenizer/marker');
var formatPosition = require('../../utils/format-position');
var split = require('../../utils/split');
var serializeRules = require('../../writer/one-time').rules;
var IgnoreProperty = 'ignore-property';
var CHARSET_TOKEN = '@charset';
var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');
var DEFAULT_ROUNDING_PRECISION = require('../../options/rounding-precision').DEFAULT;
var WHOLE_PIXEL_VALUE = /(?:^|\s|\()(-?\d+)px/;
var TIME_VALUE = /^(\-?[\d\.]+)(m?s)$/;
var HEX_VALUE_PATTERN = /[0-9a-f]/i;
var PROPERTY_NAME_PATTERN = /^(?:\-chrome\-|\-[\w\-]+\w|\w[\w\-]+\w|\-\-\S+)$/;
var PROPERTY_NAME_PATTERN = /^(?:\-chrome\-|\-[\w\-]+\w|\w[\w\-]+\w|\w{1,}|\-\-\S+)$/;
var IMPORT_PREFIX_PATTERN = /^@import/i;
var QUOTED_PATTERN = /^('.*'|".*")$/;
var QUOTED_BUT_SAFE_PATTERN = /^['"][a-zA-Z][a-zA-Z\d\-_]+['"]$/;
var URL_PREFIX_PATTERN = /^url\(/i;
var LOCAL_PREFIX_PATTERN = /^local\(/i;
var VARIABLE_NAME_PATTERN = /^--\S+$/;
function isLocal(value){
return LOCAL_PREFIX_PATTERN.test(value);
}
function isNegative(value) {
return value && value[1][0] == '-' && parseFloat(value[1]) < 0;
}
function isQuoted(value) {
return QUOTED_PATTERN.test(value);
}
function isUrl(value) {
function startsAsUrl(value) {
return URL_PREFIX_PATTERN.test(value);
}
function normalizeUrl(value) {
return value
.replace(URL_PREFIX_PATTERN, 'url(')
.replace(/\\?\n|\\?\r\n/g, '');
function isImport(token) {
return IMPORT_PREFIX_PATTERN.test(token[1]);
}
function optimizeBackground(property) {
var values = property.value;
function isLegacyFilter(property) {
var value;
if (values.length == 1 && values[0][1] == 'none') {
values[0][1] = '0 0';
}
if (property.name == 'filter' || property.name == '-ms-filter') {
value = property.value[0][1];
if (values.length == 1 && values[0][1] == 'transparent') {
values[0][1] = '0 0';
}
}
function optimizeBorderRadius(property) {
var values = property.value;
var spliceAt;
if (values.length == 3 && values[1][1] == '/' && values[0][1] == values[2][1]) {
spliceAt = 1;
} else if (values.length == 5 && values[2][1] == '/' && values[0][1] == values[3][1] && values[1][1] == values[4][1]) {
spliceAt = 2;
} else if (values.length == 7 && values[3][1] == '/' && values[0][1] == values[4][1] && values[1][1] == values[5][1] && values[2][1] == values[6][1]) {
spliceAt = 3;
} else if (values.length == 9 && values[4][1] == '/' && values[0][1] == values[5][1] && values[1][1] == values[6][1] && values[2][1] == values[7][1] && values[3][1] == values[8][1]) {
spliceAt = 4;
}
if (spliceAt) {
property.value.splice(spliceAt);
property.dirty = true;
}
}
/**
* @param {string} name
* @param {string} value
* @param {Object} compatibility
* @return {string}
*/
function optimizeColors(name, value, compatibility) {
if (!value.match(/#|rgb|hsl/gi)) {
return shortenHex(value);
}
value = value
.replace(/(rgb|hsl)a?\((\-?\d+),(\-?\d+\%?),(\-?\d+\%?),(0*[1-9]+[0-9]*(\.?\d*)?)\)/gi, function (match, colorFn, p1, p2, p3, alpha) {
return (parseInt(alpha, 10) >= 1 ? colorFn + '(' + [p1,p2,p3].join(',') + ')' : match);
})
.replace(/rgb\((\-?\d+),(\-?\d+),(\-?\d+)\)/gi, function (match, red, green, blue) {
return shortenRgb(red, green, blue);
})
.replace(/hsl\((-?\d+),(-?\d+)%?,(-?\d+)%?\)/gi, function (match, hue, saturation, lightness) {
return shortenHsl(hue, saturation, lightness);
})
.replace(/(^|[^='"])#([0-9a-f]{6})/gi, function (match, prefix, color, at, inputValue) {
var suffix = inputValue[at + match.length];
if (suffix && HEX_VALUE_PATTERN.test(suffix)) {
return match;
} else if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) {
return (prefix + '#' + color[0] + color[2] + color[4]).toLowerCase();
} else {
return (prefix + '#' + color).toLowerCase();
}
})
.replace(/(^|[^='"])#([0-9a-f]{3})/gi, function (match, prefix, color) {
return prefix + '#' + color.toLowerCase();
})
.replace(/(rgb|rgba|hsl|hsla)\(([^\)]+)\)/gi, function (match, colorFunction, colorDef) {
var tokens = colorDef.split(',');
var colorFnLowercase = colorFunction && colorFunction.toLowerCase();
var applies = (colorFnLowercase == 'hsl' && tokens.length == 3) ||
(colorFnLowercase == 'hsla' && tokens.length == 4) ||
(colorFnLowercase == 'rgb' && tokens.length === 3 && colorDef.indexOf('%') > 0) ||
(colorFnLowercase == 'rgba' && tokens.length == 4 && colorDef.indexOf('%') > 0);
if (!applies) {
return match;
}
if (tokens[1].indexOf('%') == -1) {
tokens[1] += '%';
}
if (tokens[2].indexOf('%') == -1) {
tokens[2] += '%';
}
return colorFunction + '(' + tokens.join(',') + ')';
});
if (compatibility.colors.opacity && name.indexOf('background') == -1) {
value = value.replace(/(?:rgba|hsla)\(0,0%?,0%?,0\)/g, function (match) {
if (split(value, ',').pop().indexOf('gradient(') > -1) {
return match;
}
return 'transparent';
});
}
return shortenHex(value);
}
function optimizeFilter(property) {
if (property.value.length == 1) {
property.value[0][1] = property.value[0][1].replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\W)/, function (match, filter, suffix) {
return filter.toLowerCase() + suffix;
});
}
property.value[0][1] = property.value[0][1]
.replace(/,(\S)/g, ', $1')
.replace(/ ?= ?/g, '=');
}
function optimizeFontWeight(property, atIndex) {
var value = property.value[atIndex][1];
if (value == 'normal') {
value = '400';
} else if (value == 'bold') {
value = '700';
}
property.value[atIndex][1] = value;
}
function optimizeMultipleZeros(property) {
var values = property.value;
var spliceAt;
if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
if (property.name.indexOf('box-shadow') > -1) {
spliceAt = 2;
} else {
spliceAt = 1;
}
}
if (spliceAt) {
property.value.splice(spliceAt);
property.dirty = true;
}
}
function optimizeOutline(property) {
var values = property.value;
if (values.length == 1 && values[0][1] == 'none') {
values[0][1] = '0';
}
}
function optimizePixelLengths(_, value, compatibility) {
if (!WHOLE_PIXEL_VALUE.test(value)) {
return value;
}
return value.replace(WHOLE_PIXEL_VALUE, function (match, val) {
var newValue;
var intVal = parseInt(val);
if (intVal === 0) {
return match;
}
if (compatibility.properties.shorterLengthUnits && compatibility.units.pt && intVal * 3 % 4 === 0) {
newValue = intVal * 3 / 4 + 'pt';
}
if (compatibility.properties.shorterLengthUnits && compatibility.units.pc && intVal % 16 === 0) {
newValue = intVal / 16 + 'pc';
}
if (compatibility.properties.shorterLengthUnits && compatibility.units.in && intVal % 96 === 0) {
newValue = intVal / 96 + 'in';
}
if (newValue) {
newValue = match.substring(0, match.indexOf(val)) + newValue;
}
return newValue && newValue.length < match.length ? newValue : match;
});
}
function optimizePrecision(_, value, precisionOptions) {
if (!precisionOptions.enabled || value.indexOf('.') === -1) {
return value;
}
return value
.replace(precisionOptions.decimalPointMatcher, '$1$2$3')
.replace(precisionOptions.zeroMatcher, function (match, integerPart, fractionPart, unit) {
var multiplier = precisionOptions.units[unit].multiplier;
var parsedInteger = parseInt(integerPart);
var integer = isNaN(parsedInteger) ? 0 : parsedInteger;
var fraction = parseFloat(fractionPart);
return Math.round((integer + fraction) * multiplier) / multiplier + unit;
});
}
function optimizeTimeUnits(_, value) {
if (!TIME_VALUE.test(value))
return value;
return value.replace(TIME_VALUE, function (match, val, unit) {
var newValue;
if (unit == 'ms') {
newValue = parseInt(val) / 1000 + 's';
} else if (unit == 's') {
newValue = parseFloat(val) * 1000 + 'ms';
}
return newValue.length < match.length ? newValue : match;
});
}
function optimizeUnits(name, value, unitsRegexp) {
if (/^(?:\-moz\-calc|\-webkit\-calc|calc|rgb|hsl|rgba|hsla)\(/.test(value)) {
return value;
}
if (name == 'flex' || name == '-ms-flex' || name == '-webkit-flex' || name == 'flex-basis' || name == '-webkit-flex-basis') {
return value;
}
if (value.indexOf('%') > 0 && (name == 'height' || name == 'max-height' || name == 'width' || name == 'max-width')) {
return value;
}
return value
.replace(unitsRegexp, '$1' + '0' + '$2')
.replace(unitsRegexp, '$1' + '0' + '$2');
}
function optimizeWhitespace(name, value) {
if (name.indexOf('filter') > -1 || value.indexOf(' ') == -1 || value.indexOf('expression') === 0) {
return value;
}
if (value.indexOf(Marker.SINGLE_QUOTE) > -1 || value.indexOf(Marker.DOUBLE_QUOTE) > -1) {
return value;
}
value = value.replace(/\s+/g, ' ');
if (value.indexOf('calc') > -1) {
value = value.replace(/\) ?\/ ?/g, ')/ ');
}
return value
.replace(/(\(;?)\s+/g, '$1')
.replace(/\s+(;?\))/g, '$1')
.replace(/, /g, ',');
}
function optimizeZeroDegUnit(_, value) {
if (value.indexOf('0deg') == -1) {
return value;
}
return value.replace(/\(0deg\)/g, '(0)');
}
function optimizeZeroUnits(name, value) {
if (value.indexOf('0') == -1) {
return value;
}
if (value.indexOf('-') > -1) {
value = value
.replace(/([^\w\d\-]|^)\-0([^\.]|$)/g, '$10$2')
.replace(/([^\w\d\-]|^)\-0([^\.]|$)/g, '$10$2');
}
return value
.replace(/(^|\s)0+([1-9])/g, '$1$2')
.replace(/(^|\D)\.0+(\D|$)/g, '$10$2')
.replace(/(^|\D)\.0+(\D|$)/g, '$10$2')
.replace(/\.([1-9]*)0+(\D|$)/g, function (match, nonZeroPart, suffix) {
return (nonZeroPart.length > 0 ? '.' : '') + nonZeroPart + suffix;
})
.replace(/(^|\D)0\.(\d)/g, '$1.$2');
}
function removeQuotes(name, value) {
if (name == 'content' || name.indexOf('font-variation-settings') > -1 || name.indexOf('font-feature-settings') > -1 || name == 'grid' || name.indexOf('grid-') > -1) {
return value;
}
return QUOTED_BUT_SAFE_PATTERN.test(value) ?
value.substring(1, value.length - 1) :
value;
}
function removeUrlQuotes(value) {
return /^url\(['"].+['"]\)$/.test(value) && !/^url\(['"].*[\*\s\(\)'"].*['"]\)$/.test(value) && !/^url\(['"]data:[^;]+;charset/.test(value) ?
value.replace(/["']/g, '') :
value;
}
function transformValue(propertyName, propertyValue, rule, transformCallback) {
var selector = serializeRules(rule);
var transformedValue = transformCallback(propertyName, propertyValue, selector);
if (transformedValue === undefined) {
return propertyValue;
} else if (transformedValue === false) {
return IgnoreProperty;
return value.indexOf('progid') > -1 ||
value.indexOf('alpha') === 0 ||
value.indexOf('chroma') === 0;
} else {
return transformedValue;
return false;
}
}
//
function noop() {}
function optimizeBody(rule, properties, context) {
var options = context.options;
var levelOptions = options.level[OptimizationLevel.One];
var valueOptimizers;
var property, name, type, value;
var valueIsUrl;
var propertyToken;
var _properties = wrapForOptimizing(properties, true);
var propertyOptimizer;
var serializedRule = serializeRules(rule);
var _properties = wrapForOptimizing(properties);
var pluginValueOptimizers = context.options.plugins.level1Value;
var pluginPropertyOptimizers = context.options.plugins.level1Property;
var i, l;
propertyLoop:
for (var i = 0, l = _properties.length; i < l; i++) {
for (i = 0, l = _properties.length; i < l; i++) {
var j, k, m, n;
property = _properties[i];
name = property.name;
propertyOptimizer = configuration[name] && configuration[name].propertyOptimizer || noop;
valueOptimizers = configuration[name] && configuration[name].valueOptimizers || [optimizers.whiteSpace];
if (!PROPERTY_NAME_PATTERN.test(name)) {
propertyToken = property.all[property.position];
context.warnings.push('Invalid property name \'' + name + '\' at ' + formatPosition(propertyToken[1][2][0]) + '. Ignoring.');
property.unused = true;
continue;
}
if (property.value.length === 0) {
propertyToken = property.all[property.position];
context.warnings.push('Empty property \'' + name + '\' at ' + formatPosition(propertyToken[1][2][0]) + '. Ignoring.');
property.unused = true;
continue;
}
if (property.hack && (
@@ -411,17 +94,11 @@ function optimizeBody(rule, properties, context) {
property.hack[0] == Hack.BACKSLASH && !options.compatibility.properties.ieSuffixHack ||
property.hack[0] == Hack.BANG && !options.compatibility.properties.ieBangHack)) {
property.unused = true;
}
if (levelOptions.removeNegativePaddings && name.indexOf('padding') === 0 && (isNegative(property.value[0]) || isNegative(property.value[1]) || isNegative(property.value[2]) || isNegative(property.value[3]))) {
property.unused = true;
continue;
}
if (!options.compatibility.properties.ieFilters && isLegacyFilter(property)) {
property.unused = true;
}
if (property.unused) {
continue;
}
@@ -434,10 +111,10 @@ function optimizeBody(rule, properties, context) {
continue;
}
for (var j = 0, m = property.value.length; j < m; j++) {
valuesLoop:
for (j = 0, m = property.value.length; j < m; j++) {
type = property.value[j][0];
value = property.value[j][1];
valueIsUrl = isUrl(value);
if (type == Token.PROPERTY_BLOCK) {
property.unused = true;
@@ -445,70 +122,27 @@ function optimizeBody(rule, properties, context) {
break;
}
if (valueIsUrl && !context.validator.isUrl(value)) {
if (startsAsUrl(value) && !context.validator.isUrl(value)) {
property.unused = true;
context.warnings.push('Broken URL \'' + value + '\' at ' + formatPosition(property.value[j][2][0]) + '. Ignoring.');
break;
}
if (valueIsUrl) {
value = levelOptions.normalizeUrls ?
normalizeUrl(value) :
value;
value = !options.compatibility.properties.urlQuotes ?
removeUrlQuotes(value) :
value;
} else if (isQuoted(value) || isLocal(value)) {
value = levelOptions.removeQuotes ?
removeQuotes(name, value) :
value;
} else {
value = levelOptions.removeWhitespace ?
optimizeWhitespace(name, value) :
value;
value = optimizePrecision(name, value, options.precision);
value = optimizePixelLengths(name, value, options.compatibility);
value = levelOptions.replaceTimeUnits ?
optimizeTimeUnits(name, value) :
value;
value = levelOptions.replaceZeroUnits ?
optimizeZeroUnits(name, value) :
value;
if (options.compatibility.properties.zeroUnits) {
value = optimizeZeroDegUnit(name, value);
value = optimizeUnits(name, value, options.unitsRegexp);
}
if (options.compatibility.properties.colors) {
value = optimizeColors(name, value, options.compatibility);
}
for (k = 0, n = valueOptimizers.length; k < n; k++) {
value = valueOptimizers[k](name, value, options);
}
value = transformValue(name, value, rule, levelOptions.transform);
if (value === IgnoreProperty) {
property.unused = true;
continue propertyLoop;
for (k = 0, n = pluginValueOptimizers.length; k < n; k++) {
value = pluginValueOptimizers[k](name, value, options);
}
property.value[j][1] = value;
}
if (levelOptions.replaceMultipleZeros) {
optimizeMultipleZeros(property);
}
propertyOptimizer(serializedRule, property, options);
if (name == 'background' && levelOptions.optimizeBackground) {
optimizeBackground(property);
} else if (name.indexOf('border') === 0 && name.indexOf('radius') > 0 && levelOptions.optimizeBorderRadius) {
optimizeBorderRadius(property);
} else if (name == 'filter'&& levelOptions.optimizeFilter && options.compatibility.properties.ieFilters) {
optimizeFilter(property);
} else if (name == 'font-weight' && levelOptions.optimizeFontWeight) {
optimizeFontWeight(property, 0);
} else if (name == 'outline' && levelOptions.optimizeOutline) {
optimizeOutline(property);
for (j = 0, m = pluginPropertyOptimizers.length; j < m; j++) {
pluginPropertyOptimizers[j](serializedRule, property, options);
}
}
@@ -613,24 +247,6 @@ function buildPrecisionOptions(roundingPrecision) {
return precisionOptions;
}
function isImport(token) {
return IMPORT_PREFIX_PATTERN.test(token[1]);
}
function isLegacyFilter(property) {
var value;
if (property.name == 'filter' || property.name == '-ms-filter') {
value = property.value[0][1];
return value.indexOf('progid') > -1 ||
value.indexOf('alpha') === 0 ||
value.indexOf('chroma') === 0;
} else {
return false;
}
}
function level1Optimize(tokens, context) {
var options = context.options;
var levelOptions = options.level[OptimizationLevel.One];

View File

@@ -0,0 +1,10 @@
module.exports = {
background: require('./property-optimizers/background').level1.property,
boxShadow: require('./property-optimizers/box-shadow').level1.property,
borderRadius: require('./property-optimizers/border-radius').level1.property,
filter: require('./property-optimizers/filter').level1.property,
fontWeight: require('./property-optimizers/font-weight').level1.property,
margin: require('./property-optimizers/margin').level1.property,
outline: require('./property-optimizers/outline').level1.property,
padding: require('./property-optimizers/padding').level1.property
};

View File

@@ -0,0 +1,23 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var plugin = {
level1: {
property: function background(_rule, property, options) {
var values = property.value;
if (!options.level[OptimizationLevel.One].optimizeBackground) {
return;
}
if (values.length == 1 && values[0][1] == 'none') {
values[0][1] = '0 0';
}
if (values.length == 1 && values[0][1] == 'transparent') {
values[0][1] = '0 0';
}
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,29 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var plugin = {
level1: {
property: function borderRadius(_rule, property, options) {
var values = property.value;
if (!options.level[OptimizationLevel.One].optimizeBorderRadius) {
return;
}
if (values.length == 3 && values[1][1] == '/' && values[0][1] == values[2][1]) {
property.value.splice(1);
property.dirty = true;
} else if (values.length == 5 && values[2][1] == '/' && values[0][1] == values[3][1] && values[1][1] == values[4][1]) {
property.value.splice(2);
property.dirty = true;
} else if (values.length == 7 && values[3][1] == '/' && values[0][1] == values[4][1] && values[1][1] == values[5][1] && values[2][1] == values[6][1]) {
property.value.splice(3);
property.dirty = true;
} else if (values.length == 9 && values[4][1] == '/' && values[0][1] == values[5][1] && values[1][1] == values[6][1] && values[2][1] == values[7][1] && values[3][1] == values[8][1]) {
property.value.splice(4);
property.dirty = true;
}
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,15 @@
var plugin = {
level1: {
property: function boxShadow(_rule, property) {
var values = property.value;
// remove multiple zeros
if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
property.value.splice(2);
property.dirty = true;
}
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,31 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var ALPHA_OR_CHROMA_FILTER_PATTERN = /progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\W)/;
var NO_SPACE_AFTER_COMMA_PATTERN = /,(\S)/g;
var WHITESPACE_AROUND_EQUALS_PATTERN = / ?= ?/g;
var plugin = {
level1: {
property: function filter(_rule, property, options) {
if (!options.compatibility.properties.ieFilters) {
return;
}
if (!options.level[OptimizationLevel.One].optimizeFilter) {
return;
}
if (property.value.length == 1) {
property.value[0][1] = property.value[0][1].replace(ALPHA_OR_CHROMA_FILTER_PATTERN, function (match, filter, suffix) {
return filter.toLowerCase() + suffix;
});
}
property.value[0][1] = property.value[0][1]
.replace(NO_SPACE_AFTER_COMMA_PATTERN, ', $1')
.replace(WHITESPACE_AROUND_EQUALS_PATTERN, '=');
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,23 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var plugin = {
level1: {
property: function fontWeight(_rule, property, options) {
var value = property.value[0][1];
if (!options.level[OptimizationLevel.One].optimizeFontWeight) {
return;
}
if (value == 'normal') {
value = '400';
} else if (value == 'bold') {
value = '700';
}
property.value[0][1] = value;
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,21 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var plugin = {
level1: {
property: function margin(_rule, property, options) {
var values = property.value;
if (!options.level[OptimizationLevel.One].replaceMultipleZeros) {
return;
}
// remove multiple zeros
if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
property.value.splice(1);
property.dirty = true;
}
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,19 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var plugin = {
level1: {
property: function outline(_rule, property, options) {
var values = property.value;
if (!options.level[OptimizationLevel.One].optimizeOutline) {
return;
}
if (values.length == 1 && values[0][1] == 'none') {
values[0][1] = '0';
}
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,26 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
function isNegative(value) {
return value && value[1][0] == '-' && parseFloat(value[1]) < 0;
}
var plugin = {
level1: {
property: function padding(_rule, property, options) {
var values = property.value;
// remove multiple zeros
if (values.length == 4 && values[0][1] === '0' && values[1][1] === '0' && values[2][1] === '0' && values[3][1] === '0') {
property.value.splice(1);
property.dirty = true;
}
// remove negative paddings
if (options.level[OptimizationLevel.One].removeNegativePaddings && (isNegative(property.value[0]) || isNegative(property.value[1]) || isNegative(property.value[2]) || isNegative(property.value[3]))) {
property.unused = true;
}
}
}
};
module.exports = plugin;

View File

@@ -1,20 +1,31 @@
var SUPPORTED_COMPACT_BLOCK_MATCHER = /^@media\W/;
var SUPPORTED_QUOTE_REMOVAL_MATCHER = /^@(?:keyframes|-moz-keyframes|-o-keyframes|-webkit-keyframes)\W/;
function tidyBlock(values, spaceAfterClosingBrace) {
var withoutSpaceAfterClosingBrace;
var withoutQuotes;
var i;
for (i = values.length - 1; i >= 0; i--) {
withoutSpaceAfterClosingBrace = !spaceAfterClosingBrace && SUPPORTED_COMPACT_BLOCK_MATCHER.test(values[i][1]);
withoutQuotes = SUPPORTED_QUOTE_REMOVAL_MATCHER.test(values[i][1]);
values[i][1] = values[i][1]
.replace(/\n|\r\n/g, ' ')
.replace(/\s+/g, ' ')
.replace(/(,|:|\() /g, '$1')
.replace(/ \)/g, ')')
.replace(/'([a-zA-Z][a-zA-Z\d\-_]+)'/, '$1')
.replace(/"([a-zA-Z][a-zA-Z\d\-_]+)"/, '$1')
.replace(withoutSpaceAfterClosingBrace ? /\) /g : null, ')');
.replace(/ \)/g, ')');
if (withoutQuotes) {
values[i][1] = values[i][1]
.replace(/'([a-zA-Z][a-zA-Z\d\-_]+)'/, '$1')
.replace(/"([a-zA-Z][a-zA-Z\d\-_]+)"/, '$1');
}
if (withoutSpaceAfterClosingBrace) {
values[i][1] = values[i][1]
.replace(/\) /g, ')');
}
}
return values;

View File

@@ -16,6 +16,18 @@ var ASTERISK_PLUS_HTML_HACK = '*+html ';
var ASTERISK_FIRST_CHILD_PLUS_HTML_HACK = '*:first-child+html ';
var LESS_THAN = '<';
var PSEUDO_CLASSES_WITH_SELECTORS = [
':current',
':future',
':has',
':host',
':host-context',
':is',
':not',
':past',
':where'
];
function hasInvalidCharacters(value) {
var isEscaped;
var isInvalid = false;
@@ -57,7 +69,9 @@ function removeWhitespace(value, format) {
var isAttribute;
var isRelation;
var isWhitespace;
var isSpaceAwarePseudoClass;
var roundBracketLevel = 0;
var wasComma = false;
var wasRelation = false;
var wasWhitespace = false;
var withCaseAttribute = CASE_ATTRIBUTE_PATTERN.test(value);
@@ -72,6 +86,9 @@ function removeWhitespace(value, format) {
isQuoted = isSingleQuoted || isDoubleQuoted;
isRelation = !isAttribute && !isEscaped && roundBracketLevel === 0 && RELATION_PATTERN.test(character);
isWhitespace = WHITESPACE_PATTERN.test(character);
isSpaceAwarePseudoClass = roundBracketLevel == 1 && character == Marker.CLOSE_ROUND_BRACKET ?
false :
isSpaceAwarePseudoClass || (roundBracketLevel === 0 && character == Marker.COLON && isPseudoClassWithSelectors(value, i));
if (wasEscaped && isQuoted && isNewLineWin) {
// swallow escaped new windows lines in comments
@@ -111,6 +128,10 @@ function removeWhitespace(value, format) {
} else if (!isWhitespace && wasRelation && spaceAroundRelation) {
stripped.push(Marker.SPACE);
stripped.push(character);
} else if (isWhitespace && !wasWhitespace && wasComma && roundBracketLevel > 0 && isSpaceAwarePseudoClass) {
// skip space
} else if (isWhitespace && !wasWhitespace && roundBracketLevel > 0 && isSpaceAwarePseudoClass) {
stripped.push(character);
} else if (isWhitespace && (isAttribute || roundBracketLevel > 0) && !isQuoted) {
// skip space
} else if (isWhitespace && wasWhitespace && !isQuoted) {
@@ -133,6 +154,7 @@ function removeWhitespace(value, format) {
isEscaped = character == Marker.BACK_SLASH;
wasRelation = isRelation;
wasWhitespace = isWhitespace;
wasComma = character == Marker.COMMA;
}
return withCaseAttribute ?
@@ -140,6 +162,12 @@ function removeWhitespace(value, format) {
stripped.join('');
}
function isPseudoClassWithSelectors(value, colonPosition) {
var pseudoClass = value.substring(colonPosition, value.indexOf(Marker.OPEN_ROUND_BRACKET, colonPosition));
return PSEUDO_CLASSES_WITH_SELECTORS.indexOf(pseudoClass) > -1;
}
function removeQuotes(value) {
if (value.indexOf('\'') == -1 && value.indexOf('"') == -1) {
return value;

View File

@@ -0,0 +1,14 @@
module.exports = {
color: require('./value-optimizers/color').level1.value,
degrees: require('./value-optimizers/degrees').level1.value,
fraction: require('./value-optimizers/fraction').level1.value,
precision: require('./value-optimizers/precision').level1.value,
textQuotes: require('./value-optimizers/text-quotes').level1.value,
time: require('./value-optimizers/time').level1.value,
unit: require('./value-optimizers/unit').level1.value,
urlPrefix: require('./value-optimizers/url-prefix').level1.value,
urlQuotes: require('./value-optimizers/url-quotes').level1.value,
urlWhiteSpace: require('./value-optimizers/url-whitespace').level1.value,
whiteSpace: require('./value-optimizers/whitespace').level1.value,
zero: require('./value-optimizers/zero').level1.value
};

View File

@@ -0,0 +1,90 @@
var shortenHex = require('./color/shorten-hex');
var shortenHsl = require('./color/shorten-hsl');
var shortenRgb = require('./color/shorten-rgb');
var split = require('../../../utils/split');
var ANY_COLOR_FUNCTION_PATTERN = /(rgb|rgba|hsl|hsla)\(([^\(\)]+)\)/gi;
var COLOR_PREFIX_PATTERN = /#|rgb|hsl/gi;
var HEX_LONG_PATTERN = /(^|[^='"])#([0-9a-f]{6})/gi;
var HEX_SHORT_PATTERN = /(^|[^='"])#([0-9a-f]{3})/gi;
var HEX_VALUE_PATTERN = /[0-9a-f]/i;
var HSL_PATTERN = /hsl\((-?\d+),(-?\d+)%?,(-?\d+)%?\)/gi;
var RGBA_HSLA_PATTERN = /(rgb|hsl)a?\((\-?\d+),(\-?\d+\%?),(\-?\d+\%?),(0*[1-9]+[0-9]*(\.?\d*)?)\)/gi;
var RGB_PATTERN = /rgb\((\-?\d+),(\-?\d+),(\-?\d+)\)/gi;
var TRANSPARENT_FUNCTION_PATTERN = /(?:rgba|hsla)\(0,0%?,0%?,0\)/g;
var plugin = {
level1: {
value: function color(name, value, options) {
if (!options.compatibility.properties.colors) {
return value;
}
if (!value.match(COLOR_PREFIX_PATTERN)) {
return shortenHex(value);
}
value = value
.replace(RGBA_HSLA_PATTERN, function (match, colorFn, p1, p2, p3, alpha) {
return (parseInt(alpha, 10) >= 1 ? colorFn + '(' + [p1,p2,p3].join(',') + ')' : match);
})
.replace(RGB_PATTERN, function (match, red, green, blue) {
return shortenRgb(red, green, blue);
})
.replace(HSL_PATTERN, function (match, hue, saturation, lightness) {
return shortenHsl(hue, saturation, lightness);
})
.replace(HEX_LONG_PATTERN, function (match, prefix, color, at, inputValue) {
var suffix = inputValue[at + match.length];
if (suffix && HEX_VALUE_PATTERN.test(suffix)) {
return match;
} else if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) {
return (prefix + '#' + color[0] + color[2] + color[4]).toLowerCase();
} else {
return (prefix + '#' + color).toLowerCase();
}
})
.replace(HEX_SHORT_PATTERN, function (match, prefix, color) {
return prefix + '#' + color.toLowerCase();
})
.replace(ANY_COLOR_FUNCTION_PATTERN, function (match, colorFunction, colorDef) {
var tokens = colorDef.split(',');
var colorFnLowercase = colorFunction && colorFunction.toLowerCase();
var applies = (colorFnLowercase == 'hsl' && tokens.length == 3) ||
(colorFnLowercase == 'hsla' && tokens.length == 4) ||
(colorFnLowercase == 'rgb' && tokens.length === 3 && colorDef.indexOf('%') > 0) ||
(colorFnLowercase == 'rgba' && tokens.length == 4 && colorDef.indexOf('%') > 0);
if (!applies) {
return match;
}
if (tokens[1].indexOf('%') == -1) {
tokens[1] += '%';
}
if (tokens[2].indexOf('%') == -1) {
tokens[2] += '%';
}
return colorFunction + '(' + tokens.join(',') + ')';
});
if (options.compatibility.colors.opacity && name.indexOf('background') == -1) {
value = value.replace(TRANSPARENT_FUNCTION_PATTERN, function (match) {
if (split(value, ',').pop().indexOf('gradient(') > -1) {
return match;
}
return 'transparent';
});
}
return shortenHex(value);
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,19 @@
var ZERO_DEG_PATTERN = /\(0deg\)/g;
var plugin = {
level1: {
value: function degrees(_name, value, options) {
if (!options.compatibility.properties.zeroUnits) {
return value;
}
if (value.indexOf('0deg') == -1) {
return value;
}
return value.replace(ZERO_DEG_PATTERN, '(0)');
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,43 @@
var startsAsUrl = require('./starts-as-url');
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var DOT_ZERO_PATTERN = /(^|\D)\.0+(\D|$)/g;
var FRACTION_PATTERN = /\.([1-9]*)0+(\D|$)/g;
var LEADING_ZERO_FRACTION_PATTERN = /(^|\D)0\.(\d)/g;
var MINUS_ZERO_FRACTION_PATTERN = /([^\w\d\-]|^)\-0([^\.]|$)/g;
var ZERO_PREFIXED_UNIT_PATTERN = /(^|\s)0+([1-9])/g;
var plugin = {
level1: {
value: function fraction(name, value, options) {
if (!options.level[OptimizationLevel.One].replaceZeroUnits) {
return value;
}
if (startsAsUrl(value)) {
return value;
}
if (value.indexOf('0') == -1) {
return value;
}
if (value.indexOf('-') > -1) {
value = value
.replace(MINUS_ZERO_FRACTION_PATTERN, '$10$2')
.replace(MINUS_ZERO_FRACTION_PATTERN, '$10$2');
}
return value
.replace(ZERO_PREFIXED_UNIT_PATTERN, '$1$2')
.replace(DOT_ZERO_PATTERN, '$10$2')
.replace(FRACTION_PATTERN, function (match, nonZeroPart, suffix) {
return (nonZeroPart.length > 0 ? '.' : '') + nonZeroPart + suffix;
})
.replace(LEADING_ZERO_FRACTION_PATTERN, '$1.$2');
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,22 @@
var plugin = {
level1: {
value: function precision(_name, value, options) {
if (!options.precision.enabled || value.indexOf('.') === -1) {
return value;
}
return value
.replace(options.precision.decimalPointMatcher, '$1$2$3')
.replace(options.precision.zeroMatcher, function (match, integerPart, fractionPart, unit) {
var multiplier = options.precision.units[unit].multiplier;
var parsedInteger = parseInt(integerPart);
var integer = isNaN(parsedInteger) ? 0 : parsedInteger;
var fraction = parseFloat(fractionPart);
return Math.round((integer + fraction) * multiplier) / multiplier + unit;
});
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,7 @@
var URL_PREFIX_PATTERN = /^url\(/i;
function startsAsUrl(value) {
return URL_PREFIX_PATTERN.test(value);
}
module.exports = startsAsUrl;

View File

@@ -0,0 +1,25 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var LOCAL_PREFIX_PATTERN = /^local\(/i;
var QUOTED_PATTERN = /^('.*'|".*")$/;
var QUOTED_BUT_SAFE_PATTERN = /^['"][a-zA-Z][a-zA-Z\d\-_]+['"]$/;
var plugin = {
level1: {
value: function textQuotes(_name, value, options) {
if (!options.level[OptimizationLevel.One].removeQuotes) {
return value;
}
if (!QUOTED_PATTERN.test(value) && !LOCAL_PREFIX_PATTERN.test(value)) {
return value;
}
return QUOTED_BUT_SAFE_PATTERN.test(value) ?
value.substring(1, value.length - 1) :
value;
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,31 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var TIME_VALUE = /^(\-?[\d\.]+)(m?s)$/;
var plugin = {
level1: {
value: function time(name, value, options) {
if (!options.level[OptimizationLevel.One].replaceTimeUnits) {
return value;
}
if (!TIME_VALUE.test(value)) {
return value;
}
return value.replace(TIME_VALUE, function (match, val, unit) {
var newValue;
if (unit == 'ms') {
newValue = parseInt(val) / 1000 + 's';
} else if (unit == 's') {
newValue = parseFloat(val) * 1000 + 'ms';
}
return newValue.length < match.length ? newValue : match;
});
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,40 @@
var WHOLE_PIXEL_VALUE = /(?:^|\s|\()(-?\d+)px/;
var plugin = {
level1: {
value: function unit(_name, value, options) {
if (!WHOLE_PIXEL_VALUE.test(value)) {
return value;
}
return value.replace(WHOLE_PIXEL_VALUE, function (match, val) {
var newValue;
var intVal = parseInt(val);
if (intVal === 0) {
return match;
}
if (options.compatibility.properties.shorterLengthUnits && options.compatibility.units.pt && intVal * 3 % 4 === 0) {
newValue = intVal * 3 / 4 + 'pt';
}
if (options.compatibility.properties.shorterLengthUnits && options.compatibility.units.pc && intVal % 16 === 0) {
newValue = intVal / 16 + 'pc';
}
if (options.compatibility.properties.shorterLengthUnits && options.compatibility.units.in && intVal % 96 === 0) {
newValue = intVal / 96 + 'in';
}
if (newValue) {
newValue = match.substring(0, match.indexOf(val)) + newValue;
}
return newValue && newValue.length < match.length ? newValue : match;
});
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,23 @@
var startsAsUrl = require('./starts-as-url');
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var URL_PREFIX_PATTERN = /^url\(/i;
var plugin = {
level1: {
value: function urlPrefix(_name, value, options) {
if (!options.level[OptimizationLevel.One].normalizeUrls) {
return value;
}
if (!startsAsUrl(value)) {
return value;
}
return value.replace(URL_PREFIX_PATTERN, 'url(');
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,20 @@
var QUOTED_URL_PATTERN = /^url\(['"].+['"]\)$/;
var QUOTED_URL_WITH_WHITESPACE_PATTERN = /^url\(['"].*[\*\s\(\)'"].*['"]\)$/;
var QUOTES_PATTERN = /["']/g;
var URL_DATA_PATTERN = /^url\(['"]data:[^;]+;charset/;
var plugin = {
level1: {
value: function urlQuotes(_name, value, options) {
if (options.compatibility.properties.urlQuotes) {
return value;
}
return QUOTED_URL_PATTERN.test(value) && !QUOTED_URL_WITH_WHITESPACE_PATTERN.test(value) && !URL_DATA_PATTERN.test(value) ?
value.replace(QUOTES_PATTERN, '') :
value;
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,17 @@
var startsAsUrl = require('./starts-as-url');
var WHITESPACE_PATTERN = /\\?\n|\\?\r\n/g;
var plugin = {
level1: {
value: function urlWhitespace(_name, value) {
if (!startsAsUrl(value)) {
return value;
}
return value.replace(WHITESPACE_PATTERN, '');
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,40 @@
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var Marker = require('../../../tokenizer/marker');
var CALC_DIVISION_WHITESPACE_PATTERN = /\) ?\/ ?/g;
var COMMA_AND_SPACE_PATTERN = /, /g;
var MULTI_WHITESPACE_PATTERN = /\s+/g;
var FUNCTION_CLOSING_BRACE_WHITESPACE_PATTERN = /\s+(;?\))/g;
var FUNCTION_OPENING_BRACE_WHITESPACE_PATTERN = /(\(;?)\s+/g;
var plugin = {
level1: {
value: function whitespace(name, value, options) {
if (!options.level[OptimizationLevel.One].removeWhitespace) {
return value;
}
if (value.indexOf(' ') == -1 || value.indexOf('expression') === 0) {
return value;
}
if (value.indexOf(Marker.SINGLE_QUOTE) > -1 || value.indexOf(Marker.DOUBLE_QUOTE) > -1) {
return value;
}
value = value.replace(MULTI_WHITESPACE_PATTERN, ' ');
if (value.indexOf('calc') > -1) {
value = value.replace(CALC_DIVISION_WHITESPACE_PATTERN, ')/ ');
}
return value
.replace(FUNCTION_OPENING_BRACE_WHITESPACE_PATTERN, '$1')
.replace(FUNCTION_CLOSING_BRACE_WHITESPACE_PATTERN, '$1')
.replace(COMMA_AND_SPACE_PATTERN, ',');
}
}
};
module.exports = plugin;

View File

@@ -0,0 +1,25 @@
var FUNCTION_PATTERN = /^(?:\-moz\-calc|\-webkit\-calc|calc|rgb|hsl|rgba|hsla|min|max|clamp)\(/;
var plugin = {
level1: {
value: function zero(name, value, options) {
if (!options.compatibility.properties.zeroUnits) {
return value;
}
if (FUNCTION_PATTERN.test(value)) {
return value;
}
if (value.indexOf('%') > 0 && (name == 'height' || name == 'max-height' || name == 'width' || name == 'max-width')) {
return value;
}
return value
.replace(options.unitsRegexp, '$1' + '0' + '$2')
.replace(options.unitsRegexp, '$1' + '0' + '$2');
}
}
};
module.exports = plugin;

View File

@@ -27,9 +27,6 @@ function extractProperties(token) {
if (name.length === 0)
continue;
if (name.indexOf('--') === 0)
continue;
value = serializeValue(property, i);
properties.push([

View File

@@ -3,6 +3,8 @@ var split = require('../../utils/split');
var DEEP_SELECTOR_PATTERN = /\/deep\//;
var DOUBLE_COLON_PATTERN = /^::/;
var VENDOR_PREFIXED_PATTERN = /:(-moz-|-ms-|-o-|-webkit-)/;
var NOT_PSEUDO = ':not';
var PSEUDO_CLASSES_WITH_ARGUMENTS = [
':dir',
@@ -44,6 +46,7 @@ function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements,
if (singleSelector.length === 0 ||
isDeepSelector(singleSelector) ||
isVendorPrefixed(singleSelector) ||
(singleSelector.indexOf(Marker.COLON) > -1 && !areMergeable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging))) {
return false;
}
@@ -56,6 +59,10 @@ function isDeepSelector(selector) {
return DEEP_SELECTOR_PATTERN.test(selector);
}
function isVendorPrefixed(selector) {
return VENDOR_PREFIXED_PATTERN.test(selector);
}
function extractPseudoFrom(selector) {
var list = [];
var character;

View File

@@ -70,6 +70,7 @@ function recursivelyOptimizeProperties(tokens, context) {
function level2Optimize(tokens, context, withRestructuring) {
var levelOptions = context.options.level[OptimizationLevel.Two];
var level2Plugins = context.options.plugins.level2Block;
var reduced;
var i;
@@ -124,6 +125,10 @@ function level2Optimize(tokens, context, withRestructuring) {
}
}
for (i = 0; i < level2Plugins.length; i++) {
level2Plugins[i](tokens);
}
if (levelOptions.removeEmpty) {
removeEmpty(tokens);
}

View File

@@ -1,4 +1,4 @@
var compactable = require('../compactable');
var configuration = require('../../configuration');
function findComponentIn(shorthand, longhand) {
var comparator = nameComparator(longhand);
@@ -21,7 +21,7 @@ function findInSubComponents(shorthand, comparator) {
var longhandMatch;
var i, l;
if (!compactable[shorthand.name].shorthandComponents) {
if (!configuration[shorthand.name].shorthandComponents) {
return;
}

View File

@@ -0,0 +1,14 @@
function hasSameValues(property) {
var firstValue = property.value[0][1];
var i, l;
for (i = 1, l = property.value.length; i < l; i++) {
if (property.value[i][1] != firstValue) {
return false;
}
}
return true;
}
module.exports = hasSameValues;

View File

@@ -0,0 +1,10 @@
function hasUnset(property) {
for (var i = property.value.length - 1; i >= 0; i--) {
if (property.value[i][1] == 'unset')
return true;
}
return false;
}
module.exports = hasUnset;

View File

@@ -1,12 +1,12 @@
var compactable = require('../compactable');
var configuration = require('../../configuration');
function isComponentOf(property1, property2, shallow) {
return isDirectComponentOf(property1, property2) ||
!shallow && !!compactable[property1.name].shorthandComponents && isSubComponentOf(property1, property2);
!shallow && !!configuration[property1.name].shorthandComponents && isSubComponentOf(property1, property2);
}
function isDirectComponentOf(property1, property2) {
var descriptor = compactable[property1.name];
var descriptor = configuration[property1.name];
return 'components' in descriptor && descriptor.components.indexOf(property2.name) > -1;
}

View File

@@ -1,9 +1,10 @@
var everyValuesPair = require('./every-values-pair');
var hasInherit = require('./has-inherit');
var hasSameValues = require('./has-same-values');
var populateComponents = require('./populate-components');
var compactable = require('../compactable');
var deepClone = require('../clone').deep;
var configuration = require('../../configuration');
var deepClone = require('../../clone').deep;
var restoreWithComponents = require('../restore-with-components');
var restoreFromOptimizing = require('../../restore-from-optimizing');
@@ -27,7 +28,11 @@ function mergeIntoShorthands(properties, validator) {
for (i = 0, l = properties.length; i < l; i++) {
property = properties[i];
descriptor = compactable[property.name];
descriptor = configuration[property.name];
if (property.dynamic) {
continue;
}
if (property.unused) {
continue;
@@ -41,6 +46,10 @@ function mergeIntoShorthands(properties, validator) {
continue;
}
if (descriptor && descriptor.singleTypeComponents && !hasSameValues(property)) {
continue;
}
invalidateOrCompact(properties, i, candidates, validator);
if (descriptor && descriptor.componentOf) {
@@ -61,13 +70,15 @@ function invalidateOrCompact(properties, position, candidates, validator) {
var shorthandName;
var shorthandDescriptor;
var candidateComponents;
var replacedCandidates = [];
var i;
for (shorthandName in candidates) {
if (undefined !== invalidatedBy && shorthandName == invalidatedBy.name) {
continue;
}
shorthandDescriptor = compactable[shorthandName];
shorthandDescriptor = configuration[shorthandName];
candidateComponents = candidates[shorthandName];
if (invalidatedBy && invalidates(candidates, shorthandName, invalidatedBy)) {
delete candidates[shorthandName];
@@ -95,12 +106,18 @@ function invalidateOrCompact(properties, position, candidates, validator) {
} else {
replaceWithShorthand(properties, candidateComponents, shorthandName, validator);
}
replacedCandidates.push(shorthandName);
}
for (i = replacedCandidates.length - 1; i >= 0; i--) {
delete candidates[replacedCandidates[i]];
}
}
function invalidates(candidates, shorthandName, invalidatedBy) {
var shorthandDescriptor = compactable[shorthandName];
var invalidatedByDescriptor = compactable[invalidatedBy.name];
var shorthandDescriptor = configuration[shorthandName];
var invalidatedByDescriptor = configuration[invalidatedBy.name];
var componentName;
if ('overridesShorthands' in shorthandDescriptor && shorthandDescriptor.overridesShorthands.indexOf(invalidatedBy.name) > -1) {
@@ -134,7 +151,7 @@ function mixedImportance(components) {
}
function overridable(components, shorthandName, validator) {
var descriptor = compactable[shorthandName];
var descriptor = configuration[shorthandName];
var newValuePlaceholder = [
Token.PROPERTY,
[Token.PROPERTY_NAME, shorthandName],
@@ -149,7 +166,7 @@ function overridable(components, shorthandName, validator) {
for (i = 0, l = descriptor.components.length; i < l; i++) {
component = components[descriptor.components[i]];
mayOverride = compactable[component.name].canOverride;
mayOverride = configuration[component.name].canOverride || sameValue;
if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component)) {
return false;
@@ -159,6 +176,10 @@ function overridable(components, shorthandName, validator) {
return true;
}
function sameValue(_validator, value1, value2) {
return value1 === value2;
}
function mergeable(components) {
var lastCount = null;
var currentCount;
@@ -169,14 +190,14 @@ function mergeable(components) {
for (componentName in components) {
component = components[componentName];
descriptor = compactable[componentName];
descriptor = configuration[componentName];
if (!('restore' in descriptor)) {
continue;
}
restoreFromOptimizing([component.all[component.position]], restoreWithComponents);
values = descriptor.restore(component, compactable);
values = descriptor.restore(component, configuration);
currentCount = values.length;
@@ -217,24 +238,30 @@ function replaceWithInheritBestFit(properties, candidateComponents, shorthandNam
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 lastComponent = candidateComponents[Object.keys(candidateComponents).pop()];
var all = lastComponent.all;
var insertAt = lastComponent.position;
var componentName;
var oldComponent;
var newComponent;
var newToken;
newProperty.position = all.length;
newProperty.position = insertAt;
newProperty.shorthand = true;
newProperty.important = lastComponent.important;
newProperty.multiplex = false;
newProperty.dirty = true;
newProperty.all = all;
newProperty.all.push(newTokensSequence[0]);
newProperty.all[insertAt] = newTokensSequence[0];
properties.push(newProperty);
properties.splice(insertAt, 1, newProperty);
for (componentName in candidateComponents) {
oldComponent = candidateComponents[componentName];
oldComponent.unused = true;
newProperty.multiplex = newProperty.multiplex || oldComponent.multiplex;
if (oldComponent.name in newComponents) {
newComponent = newComponents[oldComponent.name];
newToken = findTokenIn(newTokensSequence, componentName);
@@ -252,7 +279,7 @@ function buildSequenceWithInheritLonghands(components, shorthandName, validator)
var tokensSequence = [];
var inheritComponents = {};
var nonInheritComponents = {};
var descriptor = compactable[shorthandName];
var descriptor = configuration[shorthandName];
var shorthandToken = [
Token.PROPERTY,
[Token.PROPERTY_NAME, shorthandName],
@@ -289,6 +316,8 @@ function buildSequenceWithInheritLonghands(components, shorthandName, validator)
}
}
newProperty.important = components[Object.keys(components).pop()].important;
nameMetadata = joinMetadata(nonInheritComponents, 1);
shorthandToken[1].push(nameMetadata);
@@ -303,7 +332,7 @@ function buildSequenceWithInheritLonghands(components, shorthandName, validator)
}
function inferComponentValue(components, propertyName) {
var descriptor = compactable[propertyName];
var descriptor = configuration[propertyName];
if ('oppositeTo' in descriptor) {
return components[descriptor.oppositeTo].value;
@@ -349,7 +378,7 @@ function buildSequenceWithInheritShorthand(components, shorthandName, validator)
var tokensSequence = [];
var inheritComponents = {};
var nonInheritComponents = {};
var descriptor = compactable[shorthandName];
var descriptor = configuration[shorthandName];
var shorthandToken = [
Token.PROPERTY,
[Token.PROPERTY_NAME, shorthandName],
@@ -400,7 +429,7 @@ function findTokenIn(tokens, componentName) {
}
function replaceWithShorthand(properties, candidateComponents, shorthandName, validator) {
var descriptor = compactable[shorthandName];
var descriptor = configuration[shorthandName];
var nameMetadata;
var valueMetadata;
var newValuePlaceholder = [
@@ -409,10 +438,12 @@ function replaceWithShorthand(properties, candidateComponents, shorthandName, va
[Token.PROPERTY_VALUE, descriptor.defaultValue]
];
var all;
var insertAt = inferInsertAtFrom(properties, candidateComponents, shorthandName);
var newProperty = wrapSingle(newValuePlaceholder);
newProperty.shorthand = true;
newProperty.dirty = true;
newProperty.multiplex = false;
populateComponents([newProperty], validator, []);
@@ -421,6 +452,7 @@ function replaceWithShorthand(properties, candidateComponents, shorthandName, va
newProperty.components[i] = deepClone(component);
newProperty.important = component.important;
newProperty.multiplex = newProperty.multiplex || component.multiplex;
all = component.all;
}
@@ -435,11 +467,33 @@ function replaceWithShorthand(properties, candidateComponents, shorthandName, va
valueMetadata = joinMetadata(candidateComponents, 2);
newValuePlaceholder[2].push(valueMetadata);
newProperty.position = all.length;
newProperty.position = insertAt;
newProperty.all = all;
newProperty.all.push(newValuePlaceholder);
newProperty.all[insertAt] = newValuePlaceholder;
properties.push(newProperty);
properties.splice(insertAt, 1, newProperty);
}
function inferInsertAtFrom(properties, candidateComponents, shorthandName) {
var candidateComponentNames = Object.keys(candidateComponents);
var firstCandidatePosition = candidateComponents[candidateComponentNames[0]].position;
var lastCandidatePosition = candidateComponents[candidateComponentNames[candidateComponentNames.length - 1]].position;
if (shorthandName == 'border' && traversesVia(properties.slice(firstCandidatePosition, lastCandidatePosition), 'border-image')) {
return firstCandidatePosition;
} else {
return lastCandidatePosition;
}
}
function traversesVia(properties, propertyName) {
for (var i = properties.length - 1; i >= 0; i--) {
if (properties[i].name == propertyName) {
return true;
}
}
return false;
}
module.exports = mergeIntoShorthands;

View File

@@ -12,7 +12,7 @@ var OptimizationLevel = require('../../../options/optimization-level').Optimizat
function optimizeProperties(properties, withOverriding, withMerging, context) {
var levelOptions = context.options.level[OptimizationLevel.Two];
var _properties = wrapForOptimizing(properties, false, levelOptions.skipProperties);
var _properties = wrapForOptimizing(properties, levelOptions.skipProperties);
var _property;
var i, l;

View File

@@ -1,15 +1,16 @@
var hasInherit = require('./has-inherit');
var hasUnset = require('./has-unset');
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;
var sameVendorPrefixesIn = require('./../../vendor-prefixes').same;
var compactable = require('../compactable');
var deepClone = require('../clone').deep;
var configuration = require('../../configuration');
var deepClone = require('../../clone').deep;
var restoreWithComponents = require('../restore-with-components');
var shallowClone = require('../clone').shallow;
var shallowClone = require('../../clone').shallow;
var restoreFromOptimizing = require('../../restore-from-optimizing');
@@ -18,11 +19,15 @@ var Marker = require('../../../tokenizer/marker');
var serializeProperty = require('../../../writer/one-time').property;
function sameValue(_validator, value1, value2) {
return value1 === value2;
}
function wouldBreakCompatibility(property, validator) {
for (var i = 0; i < property.components.length; i++) {
var component = property.components[i];
var descriptor = compactable[component.name];
var canOverride = descriptor && descriptor.canOverride || canOverride.sameValue;
var descriptor = configuration[component.name];
var canOverride = descriptor && descriptor.canOverride || sameValue;
var _component = shallowClone(component);
_component.value = [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
@@ -73,7 +78,7 @@ function overrideShorthand(property, by) {
function turnIntoMultiplex(property, size) {
property.multiplex = true;
if (compactable[property.name].shorthand) {
if (configuration[property.name].shorthand) {
turnShorthandValueIntoMultiplex(property, size);
} else {
turnLonghandValueIntoMultiplex(property, size);
@@ -94,7 +99,7 @@ function turnShorthandValueIntoMultiplex(property, size) {
}
function turnLonghandValueIntoMultiplex(property, size) {
var descriptor = compactable[property.name];
var descriptor = configuration[property.name];
var withRealValue = descriptor.intoMultiplexMode == 'real';
var withValue = descriptor.intoMultiplexMode == 'real' ?
property.value.slice(0) :
@@ -206,7 +211,7 @@ function wouldResultInLongerValue(left, right) {
}
function isCompactable(property) {
return property.name in compactable;
return property.name in configuration;
}
function noneOverrideHack(left, right) {
@@ -263,7 +268,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (right.block)
continue;
mayOverride = compactable[right.name].canOverride;
mayOverride = configuration[right.name].canOverride || sameValue;
traverseLoop:
for (j = i - 1; j >= 0; j--) {
@@ -275,6 +280,9 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (left.block)
continue;
if (left.dynamic || right.dynamic)
continue;
if (left.unused || right.unused)
continue;
@@ -310,7 +318,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
}
component = findComponentIn(right, left);
mayOverride = compactable[left.name].canOverride;
mayOverride = configuration[left.name].canOverride || sameValue;
if (everyValuesPair(mayOverride.bind(null, validator), left, component)) {
left.unused = true;
}
@@ -335,7 +343,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
for (k = overriddenComponents.length - 1; k >= 0; k--) {
overriddenComponent = overriddenComponents[k];
overridingComponent = findComponentIn(right, overriddenComponent);
mayOverride = compactable[overriddenComponent.name].canOverride;
mayOverride = configuration[overriddenComponent.name].canOverride || sameValue;
if (!everyValuesPair(mayOverride.bind(null, validator), left, overridingComponent)) {
continue traverseLoop;
@@ -363,13 +371,16 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (!isMergeableShorthand(left))
continue;
if (hasUnset(left) || hasUnset(right))
continue;
component = findComponentIn(left, right);
if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
var disabledBackgroundMerging =
!compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1 ||
!compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1 ||
!compatibility.properties.backgroundSizeMerging && component.name.indexOf('background-size') > -1;
var nonMergeableValue = compactable[right.name].nonMergeableValue === right.value[0][1];
var nonMergeableValue = configuration[right.name].nonMergeableValue === right.value[0][1];
if (disabledBackgroundMerging || nonMergeableValue)
continue;
@@ -414,7 +425,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
var leftComponent = left.components[k];
var rightComponent = right.components[k];
mayOverride = compactable[leftComponent.name].canOverride;
mayOverride = configuration[leftComponent.name].canOverride || sameValue;
if (!everyValuesPair(mayOverride.bind(null, validator), leftComponent, rightComponent))
continue propertyLoop;
}
@@ -428,7 +439,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
continue;
component = findComponentIn(left, right);
mayOverride = compactable[right.name].canOverride;
mayOverride = configuration[right.name].canOverride || sameValue;
if (!everyValuesPair(mayOverride.bind(null, validator), component, right))
continue;
@@ -437,7 +448,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
continue;
}
var rightRestored = compactable[right.name].restore(right, compactable);
var rightRestored = configuration[right.name].restore(right, configuration);
if (rightRestored.length > 1)
continue;
@@ -452,12 +463,12 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
for (k = right.components.length - 1; k >= 0 && overridable; k--) {
overriddenComponent = left.components[k];
overridingComponent = right.components[k];
mayOverride = compactable[overridingComponent.name].canOverride;
mayOverride = configuration[overridingComponent.name].canOverride || sameValue;
overridable = overridable && everyValuesPair(mayOverride.bind(null, validator), overriddenComponent, overridingComponent);
}
} else {
mayOverride = compactable[right.name].canOverride;
mayOverride = configuration[right.name].canOverride || sameValue;
overridable = everyValuesPair(mayOverride.bind(null, validator), left, right);
}

View File

@@ -1,9 +1,9 @@
var compactable = require('../compactable');
var configuration = require('../../configuration');
function overridesNonComponentShorthand(property1, property2) {
return property1.name in compactable &&
'overridesShorthands' in compactable[property1.name] &&
compactable[property1.name].overridesShorthands.indexOf(property2.name) > -1;
return property1.name in configuration &&
'overridesShorthands' in configuration[property1.name] &&
configuration[property1.name].overridesShorthands.indexOf(property2.name) > -1;
}
module.exports = overridesNonComponentShorthand;

View File

@@ -1,5 +1,5 @@
var compactable = require('../compactable');
var InvalidPropertyError = require('../invalid-property-error');
var configuration = require('../../configuration');
var InvalidPropertyError = require('../../invalid-property-error');
function populateComponents(properties, validator, warnings) {
var component;
@@ -7,19 +7,24 @@ function populateComponents(properties, validator, warnings) {
for (var i = properties.length - 1; i >= 0; i--) {
var property = properties[i];
var descriptor = compactable[property.name];
var descriptor = configuration[property.name];
if (!property.dynamic && descriptor && descriptor.shorthand) {
if (onlyValueIsVariable(property, validator) || moreThanOneValueIsVariable(property, validator)) {
property.optimizable = false;
continue;
}
if (descriptor && descriptor.shorthand) {
property.shorthand = true;
property.dirty = true;
try {
property.components = descriptor.breakUp(property, compactable, validator);
property.components = descriptor.breakUp(property, configuration, validator);
if (descriptor.shorthandComponents) {
for (j = 0, m = property.components.length; j < m; j++) {
component = property.components[j];
component.components = compactable[component.name].breakUp(component, compactable, validator);
component.components = configuration[component.name].breakUp(component, configuration, validator);
}
}
} catch (e) {
@@ -39,4 +44,12 @@ function populateComponents(properties, validator, warnings) {
}
}
function onlyValueIsVariable(property, validator) {
return property.value.length == 1 && validator.isVariable(property.value[0][1]);
}
function moreThanOneValueIsVariable(property, validator) {
return property.value.length > 1 && property.value.filter(function (value) { return validator.isVariable(value[1]); }).length > 1;
}
module.exports = populateComponents;

View File

@@ -1,10 +1,10 @@
var compactable = require('./compactable');
var configuration = require('../configuration');
function restoreWithComponents(property) {
var descriptor = compactable[property.name];
var descriptor = configuration[property.name];
if (descriptor && descriptor.shorthand) {
return descriptor.restore(property, compactable);
return descriptor.restore(property, configuration);
} else {
return property.value;
}

View File

@@ -17,6 +17,15 @@ function restoreFromOptimizing(properties, restoreCallback) {
for (i = properties.length - 1; i >= 0; i--) {
property = properties[i];
if (property.dynamic && property.important) {
restoreImportant(property);
continue;
}
if (property.dynamic) {
continue;
}
if (property.unused) {
continue;
}
@@ -25,7 +34,7 @@ function restoreFromOptimizing(properties, restoreCallback) {
continue;
}
if (restoreCallback) {
if (property.optimizable && restoreCallback) {
restored = restoreCallback(property);
property.value = restored;
} else {

View File

@@ -6,11 +6,14 @@ var functionAnyRegexStr = '(' + variableRegexStr + '|' + functionNoVendorRegexSt
var calcRegex = new RegExp('^(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)$', 'i');
var decimalRegex = /[0-9]/;
var functionAnyRegex = new RegExp('^' + functionAnyRegexStr + '$', 'i');
var hslColorRegex = /^hsl\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\.?\d+%\s{0,31},\s{0,31}\.?\d+%\s{0,31}\)|hsla\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\.?\d+%\s{0,31},\s{0,31}\.?\d+%\s{0,31},\s{0,31}\.?\d+\s{0,31}\)$/i;
var identifierRegex = /^(\-[a-z0-9_][a-z0-9\-_]*|[a-z][a-z0-9\-_]*)$/i;
var hexAlphaColorRegex = /^#(?:[0-9a-f]{4}|[0-9a-f]{8})$/i;
var hslColorRegex = /^hsl\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31}\)|hsla\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31},\s{0,31}\d*\.?\d+%\s{0,31},\s{0,31}\.?\d+\s{0,31}\)$/;
var identifierRegex = /^(\-[a-z0-9_][a-z0-9\-_]*|[a-z_][a-z0-9\-_]*)$/i;
var namedEntityRegex = /^[a-z]+$/i;
var prefixRegex = /^-([a-z0-9]|-)*$/i;
var quotedTextRegex = /^("[^"]*"|'[^']*')$/i;
var rgbColorRegex = /^rgb\(\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31}\)|rgba\(\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\.\d]+\s{0,31}\)$/i;
var timeUnitPattern = /\d+(s|ms)/;
var timingFunctionRegex = /^(cubic\-bezier|steps)\([^\)]+\)$/;
var validTimeUnits = ['ms', 's'];
var urlRegex = /^url\([\s\S]+\)$/i;
@@ -250,7 +253,7 @@ var Keywords = {
'decimal',
'decimal-leading-zero',
'disc',
'decimal|disc', // this is the default value of list-style-type, see comment in compactable.js
'decimal|disc', // this is the default value of list-style-type, see comment in configuration.js
'georgian',
'lower-alpha',
'lower-greek',
@@ -281,7 +284,7 @@ var Keywords = {
'center',
'justify',
'left',
'left|right', // this is the default value of list-style-type, see comment in compactable.js
'left|right', // this is the default value of list-style-type, see comment in configuration.js
'right'
],
'text-decoration': [
@@ -375,10 +378,18 @@ function isHslColor(value) {
return hslColorRegex.test(value);
}
function isHexAlphaColor(value) {
return hexAlphaColorRegex.test(value);
}
function isIdentifier(value) {
return identifierRegex.test(value);
}
function isQuotedText(value) {
return quotedTextRegex.test(value);
}
function isImage(value) {
return value == 'none' || value == 'inherit' || isUrl(value);
}
@@ -418,7 +429,12 @@ function isTime(value) {
var numberUpTo = scanForNumber(value);
return numberUpTo == value.length && parseInt(value) === 0 ||
numberUpTo > -1 && validTimeUnits.indexOf(value.slice(numberUpTo + 1)) > -1;
numberUpTo > -1 && validTimeUnits.indexOf(value.slice(numberUpTo + 1)) > -1 ||
isCalculatedTime(value);
}
function isCalculatedTime(value) {
return isFunction(value) && timeUnitPattern.test(value);
}
function isTimingFunction() {
@@ -433,7 +449,7 @@ function isUnit(validUnits, value) {
var numberUpTo = scanForNumber(value);
return numberUpTo == value.length && parseInt(value) === 0 ||
numberUpTo > -1 && validUnits.indexOf(value.slice(numberUpTo + 1)) > -1 ||
numberUpTo > -1 && validUnits.indexOf(value.slice(numberUpTo + 1).toLowerCase()) > -1 ||
value == 'auto' ||
value == 'inherit';
}
@@ -480,8 +496,13 @@ function validator(compatibility) {
return !(value in compatibility.units) || compatibility.units[value] === true;
});
if (compatibility.customUnits.rpx) {
validUnits.push('rpx');
}
return {
colorOpacity: compatibility.colors.opacity,
colorHexAlpha: compatibility.colors.hexAlpha,
isAnimationDirectionKeyword: isKeyword('animation-direction'),
isAnimationFillModeKeyword: isKeyword('animation-fill-mode'),
isAnimationIterationCountKeyword: isKeyword('animation-iteration-count'),
@@ -505,6 +526,7 @@ function validator(compatibility) {
isFontWeightKeyword: isKeyword('font-weight'),
isFunction: isFunction,
isGlobal: isKeyword('^'),
isHexAlphaColor: isHexAlphaColor,
isHslColor: isHslColor,
isIdentifier: isIdentifier,
isImage: isImage,
@@ -515,6 +537,7 @@ function validator(compatibility) {
isNumber: isNumber,
isPrefixed: isPrefixed,
isPositiveNumber: isPositiveNumber,
isQuotedText: isQuotedText,
isRgbColor: isRgbColor,
isStyleKeyword: isKeyword('*-style'),
isTime: isTime,

View File

@@ -17,7 +17,7 @@ var Match = {
VARIABLE_REFERENCE_PATTERN: /var\(--.+\)$/
};
function wrapAll(properties, includeVariable, skipProperties) {
function wrapAll(properties, skipProperties) {
var wrapped = [];
var single;
var property;
@@ -30,10 +30,6 @@ function wrapAll(properties, includeVariable, skipProperties) {
continue;
}
if (!includeVariable && someVariableReferences(property)) {
continue;
}
if (skipProperties && skipProperties.indexOf(property[1][1]) > -1) {
continue;
}
@@ -174,10 +170,12 @@ function wrapSingle(property) {
block: property[2] && property[2][0] == Token.PROPERTY_BLOCK,
components: [],
dirty: false,
dynamic: someVariableReferences(property),
hack: whichHack,
important: importantProperty,
name: property[1][1],
multiplex: property.length > 3 ? isMultiplex(property) : false,
optimizable: true,
position: 0,
shorthand: false,
unused: false,

View File

@@ -1,8 +1,12 @@
var DEFAULTS = {
'*': {
colors: {
hexAlpha: false, // 4- and 8-character hex notation
opacity: true // rgba / hsla
},
customUnits: {
rpx: false
},
properties: {
backgroundClipMerging: true, // background-clip to shorthand
backgroundOriginMerging: true, // background-origin to shorthand
@@ -11,11 +15,11 @@ var DEFAULTS = {
ieBangHack: false, // !ie suffix hacks on IE<8
ieFilters: false, // whether to preserve `filter` and `-ms-filter` properties
iePrefixHack: false, // underscore / asterisk prefix hacks on IE
ieSuffixHack: false, // \9 suffix hacks on IE6-9
ieSuffixHack: false, // \9 suffix hacks on IE6-9, \0 suffix hack on IE6-11
merging: true, // merging properties into one
shorterLengthUnits: false, // optimize pixel units into `pt`, `pc` or `in` units
spaceAfterClosingBrace: true, // 'url() no-repeat' to 'url()no-repeat'
urlQuotes: false, // whether to wrap content of `url()` into quotes or not
urlQuotes: true, // whether to wrap content of `url()` into quotes or not
zeroUnits: true // 0[unit] -> 0
},
selectors: {
@@ -75,9 +79,17 @@ var DEFAULTS = {
}
};
DEFAULTS.ie11 = DEFAULTS['*'];
DEFAULTS.ie11 = merge(DEFAULTS['*'], {
properties: {
ieSuffixHack: true
}
});
DEFAULTS.ie10 = DEFAULTS['*'];
DEFAULTS.ie10 = merge(DEFAULTS['*'], {
properties: {
ieSuffixHack: true
}
});
DEFAULTS.ie9 = merge(DEFAULTS['*'], {
properties: {

View File

@@ -98,36 +98,36 @@ function formatFrom(source) {
}
if (typeof source == 'object') {
return override(DEFAULTS, source);
}
if (typeof source == 'object') {
return override(DEFAULTS, source);
return remapBreaks(override(DEFAULTS, source));
}
if (typeof source == 'string' && source == BEAUTIFY_ALIAS) {
return override(DEFAULTS, {
breaks: breaks(true),
indentBy: 2,
spaces: spaces(true)
});
return remapBreaks(
override(DEFAULTS, {
breaks: breaks(true),
indentBy: 2,
spaces: spaces(true)
})
);
}
if (typeof source == 'string' && source == KEEP_BREAKS_ALIAS) {
return override(DEFAULTS, {
breaks: {
afterAtRule: true,
afterBlockBegins: true,
afterBlockEnds: true,
afterComment: true,
afterRuleEnds: true,
beforeBlockEnds: true
}
});
return remapBreaks(
override(DEFAULTS, {
breaks: {
afterAtRule: true,
afterBlockBegins: true,
afterBlockEnds: true,
afterComment: true,
afterRuleEnds: true,
beforeBlockEnds: true
}
})
);
}
if (typeof source == 'string') {
return override(DEFAULTS, toHash(source));
return remapBreaks(override(DEFAULTS, toHash(source)));
}
return DEFAULTS;
@@ -209,6 +209,23 @@ function mapIndentWith(value) {
}
}
function remapBreaks(source) {
for (var key in Breaks) {
var breakName = Breaks[key];
var breakValue = source.breaks[breakName];
if (breakValue === true) {
source.breaks[breakName] = source.breakWith;
} else if (breakValue === false) {
source.breaks[breakName] = '';
} else {
source.breaks[breakName] = source.breakWith.repeat(parseInt(breakValue));
}
}
return source;
}
module.exports = {
Breaks: Breaks,
Spaces: Spaces,

View File

@@ -31,8 +31,7 @@ DEFAULTS[OptimizationLevel.One] = {
specialComments: 'all',
tidyAtRules: true,
tidyBlockScopes: true,
tidySelectors: true,
transform: noop
tidySelectors: true
};
DEFAULTS[OptimizationLevel.Two] = {
mergeAdjacentRules: true,
@@ -62,15 +61,12 @@ var LIST_VALUE_SEPARATOR = ',';
var OPTION_SEPARATOR = ';';
var OPTION_VALUE_SEPARATOR = ':';
function noop() {}
function optimizationLevelFrom(source) {
var level = override(DEFAULTS, {});
var Zero = OptimizationLevel.Zero;
var One = OptimizationLevel.One;
var Two = OptimizationLevel.Two;
if (undefined === source) {
delete level[Two];
return level;

25
node_modules/clean-css/lib/options/plugins.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
function pluginsFrom(plugins) {
var flatPlugins = {
level1Value: [],
level1Property: [],
level2Block: []
};
plugins = plugins || [];
flatPlugins.level1Value = plugins
.map(function (plugin) { return plugin.level1 && plugin.level1.value; })
.filter(function (plugin) { return plugin != null; });
flatPlugins.level1Property = plugins
.map(function (plugin) { return plugin.level1 && plugin.level1.property; })
.filter(function (plugin) { return plugin != null; });
flatPlugins.level2Block = plugins
.map(function (plugin) { return plugin.level2 && plugin.level2.block; })
.filter(function (plugin) { return plugin != null; });
return flatPlugins;
}
module.exports = pluginsFrom;

View File

@@ -1,5 +1,11 @@
function rebaseFrom(rebaseOption) {
return undefined === rebaseOption ? true : !!rebaseOption;
function rebaseFrom(rebaseOption, rebaseToOption) {
if (undefined !== rebaseToOption) {
return true;
} else if (undefined === rebaseOption) {
return false;
} else {
return !!rebaseOption;
}
}
module.exports = rebaseFrom;

View File

@@ -65,7 +65,7 @@ function findTokenSource(token) {
var scope;
var metadata;
if (token[0] == Token.AT_RULE || token[0] == Token.COMMENT) {
if (token[0] == Token.AT_RULE || token[0] == Token.COMMENT || token[0] == Token.RAW) {
metadata = token[2][0];
} else {
scope = token[1][0];
@@ -130,7 +130,7 @@ function extractInputSourceMapFromDataUri(uri) {
var encoding = dataUriMatch[3] ? dataUriMatch[3].split(';')[1] : 'utf8';
var data = encoding == 'utf8' ? global.unescape(dataUriMatch[4]) : dataUriMatch[4];
var buffer = new Buffer(data, encoding);
var buffer = Buffer.from(data, encoding);
buffer.charset = charset;
return JSON.parse(buffer.toString());

View File

@@ -1,11 +1,14 @@
var path = require('path');
var url = require('url');
var isDataUriResource = require('../utils/is-data-uri-resource');
var DOUBLE_QUOTE = '"';
var SINGLE_QUOTE = '\'';
var URL_PREFIX = 'url(';
var URL_SUFFIX = ')';
var PROTOCOL_LESS_PREFIX_PATTERN = /^[^\w\d]*\/\//;
var QUOTE_PREFIX_PATTERN = /^["']/;
var QUOTE_SUFFIX_PATTERN = /["']$/;
var ROUND_BRACKETS_PATTERN = /[\(\)]/;
@@ -24,14 +27,10 @@ function rebase(uri, rebaseConfig) {
return uri;
}
if (isRemote(uri) || isSVGMarker(uri) || isInternal(uri)) {
if (isRemote(uri) || isSVGMarker(uri) || isInternal(uri) || isDataUriResource(uri)) {
return uri;
}
if (isData(uri)) {
return '\'' + uri + '\'';
}
if (isRemote(rebaseConfig.toBase)) {
return url.resolve(rebaseConfig.toBase, uri);
}
@@ -54,11 +53,7 @@ function isInternal(uri) {
}
function isRemote(uri) {
return /^[^:]+?:\/\//.test(uri) || uri.indexOf('//') === 0;
}
function isData(uri) {
return uri.indexOf('data:') === 0;
return /^[^:]+?:\/\//.test(uri) || PROTOCOL_LESS_PREFIX_PATTERN.test(uri);
}
function absolute(uri, rebaseConfig) {

View File

@@ -90,6 +90,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
var levels = [];
var buffer = [];
var buffers = [];
var isBufferEmpty = true;
var serializedBuffer;
var serializedBufferPart;
var roundBracketLevel = 0;
@@ -105,6 +106,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
var isCommentEndMarker;
var isEscaped;
var wasEscaped = false;
var characterWithNoSpecialMeaning;
var isRaw = false;
var seekingValue = false;
var seekingPropertyBlockClosing = false;
@@ -122,26 +124,40 @@ function intoTokens(source, externalContext, internalContext, isNested) {
isCommentStart = !wasCommentEnd && level != Level.COMMENT && !isQuoted && character == Marker.ASTERISK && source[position.index - 1] == Marker.FORWARD_SLASH;
isCommentEndMarker = !wasCommentStart && !isQuoted && character == Marker.FORWARD_SLASH && source[position.index - 1] == Marker.ASTERISK;
isCommentEnd = level == Level.COMMENT && isCommentEndMarker;
characterWithNoSpecialMeaning = !isSpace && !isCarriageReturn && (character >= 'A' && character <= 'Z' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '-');
roundBracketLevel = Math.max(roundBracketLevel, 0);
metadata = buffer.length === 0 ?
metadata = isBufferEmpty ?
[position.line, position.column, position.source] :
metadata;
if (isEscaped) {
// previous character was a backslash
buffer.push(character);
isBufferEmpty = false;
} else if (characterWithNoSpecialMeaning) {
// it's just an alphanumeric character or a hyphen (part of any rule or property name) so let's end it quickly
buffer.push(character);
isBufferEmpty = false;
} else if ((isSpace || isNewLineNix && !isNewLineWin) && (isQuoted || level == Level.COMMENT)) {
buffer.push(character);
isBufferEmpty = false;
} else if ((isSpace || isNewLineNix && !isNewLineWin) && isBufferEmpty) {
// noop
} else if (!isCommentEnd && level == Level.COMMENT) {
buffer.push(character);
isBufferEmpty = false;
} else if (!isCommentStart && !isCommentEnd && isRaw) {
buffer.push(character);
isBufferEmpty = false;
} else if (isCommentStart && (level == Level.BLOCK || level == Level.RULE) && buffer.length > 1) {
// comment start within block preceded by some content, e.g. div/*<--
metadatas.push(metadata);
buffer.push(character);
buffers.push(buffer.slice(0, buffer.length - 2));
buffers.push(buffer.slice(0, -2));
isBufferEmpty = false;
buffer = buffer.slice(buffer.length - 2);
buffer = buffer.slice(-2);
metadata = [position.line, position.column - 1, position.source];
levels.push(level);
@@ -151,6 +167,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
levels.push(level);
level = Level.COMMENT;
buffer.push(character);
isBufferEmpty = false;
} else if (isCommentEnd && isIgnoreStartComment(buffer)) {
// ignore:start comment end, e.g. /* clean-css ignore:start */<--
serializedBuffer = buffer.join('').trim() + character;
@@ -160,6 +177,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
isRaw = true;
metadata = metadatas.pop() || null;
buffer = buffers.pop() || [];
isBufferEmpty = buffer.length === 0;
} else if (isCommentEnd && isIgnoreEndComment(buffer)) {
// ignore:start comment end, e.g. /* clean-css ignore:end */<--
serializedBuffer = buffer.join('') + character;
@@ -178,6 +196,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
metadata = metadatas.pop() || null;
buffer = buffers.pop() || [];
isBufferEmpty = buffer.length === 0;
} else if (isCommentEnd) {
// comment end, e.g. /* comment */<--
serializedBuffer = buffer.join('').trim() + character;
@@ -187,38 +206,47 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
metadata = metadatas.pop() || null;
buffer = buffers.pop() || [];
isBufferEmpty = buffer.length === 0;
} else if (isCommentEndMarker && source[position.index + 1] != Marker.ASTERISK) {
externalContext.warnings.push('Unexpected \'*/\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.SINGLE_QUOTE && !isQuoted) {
// single quotation start, e.g. a[href^='https<--
levels.push(level);
level = Level.SINGLE_QUOTE;
buffer.push(character);
isBufferEmpty = false;
} else if (character == Marker.SINGLE_QUOTE && level == Level.SINGLE_QUOTE) {
// single quotation end, e.g. a[href^='https'<--
level = levels.pop();
buffer.push(character);
isBufferEmpty = false;
} else if (character == Marker.DOUBLE_QUOTE && !isQuoted) {
// double quotation start, e.g. a[href^="<--
levels.push(level);
level = Level.DOUBLE_QUOTE;
buffer.push(character);
isBufferEmpty = false;
} else if (character == Marker.DOUBLE_QUOTE && level == Level.DOUBLE_QUOTE) {
// double quotation end, e.g. a[href^="https"<--
level = levels.pop();
buffer.push(character);
isBufferEmpty = false;
} else if (!isCommentStart && !isCommentEnd && character != Marker.CLOSE_ROUND_BRACKET && character != Marker.OPEN_ROUND_BRACKET && level != Level.COMMENT && !isQuoted && roundBracketLevel > 0) {
// character inside any function, e.g. hsla(.<--
buffer.push(character);
isBufferEmpty = false;
} else if (character == Marker.OPEN_ROUND_BRACKET && !isQuoted && level != Level.COMMENT && !seekingValue) {
// round open bracket, e.g. @import url(<--
buffer.push(character);
isBufferEmpty = false;
roundBracketLevel++;
} else if (character == Marker.CLOSE_ROUND_BRACKET && !isQuoted && level != Level.COMMENT && !seekingValue) {
// round open bracket, e.g. @import url(test.css)<--
buffer.push(character);
isBufferEmpty = false;
roundBracketLevel--;
} else if (character == Marker.SEMICOLON && level == Level.BLOCK && buffer[0] == Marker.AT) {
@@ -227,16 +255,19 @@ function intoTokens(source, externalContext, internalContext, isNested) {
allTokens.push([Token.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.COMMA && level == Level.BLOCK && ruleToken) {
// comma separator at block level, e.g. a,div,<--
serializedBuffer = buffer.join('').trim();
ruleToken[1].push([tokenScopeFrom(ruleToken[0]), serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext, ruleToken[1].length)]]);
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.COMMA && level == Level.BLOCK && tokenTypeFrom(buffer) == Token.AT_RULE) {
// comma separator at block level, e.g. @import url(...) screen,<--
// keep iterating as end semicolon will create the token
buffer.push(character);
isBufferEmpty = false;
} else if (character == Marker.COMMA && level == Level.BLOCK) {
// comma separator at block level, e.g. a,<--
ruleToken = [tokenTypeFrom(buffer), [], []];
@@ -244,6 +275,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
ruleToken[1].push([tokenScopeFrom(ruleToken[0]), serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext, 0)]]);
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.OPEN_CURLY_BRACKET && level == Level.BLOCK && ruleToken && ruleToken[0] == Token.NESTED_BLOCK) {
// open brace opening at-rule at block level, e.g. @media{<--
serializedBuffer = buffer.join('').trim();
@@ -254,6 +286,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
position.column++;
position.index++;
buffer = [];
isBufferEmpty = true;
ruleToken[2] = intoTokens(source, externalContext, internalContext, true);
ruleToken = null;
@@ -268,6 +301,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
position.column++;
position.index++;
buffer = [];
isBufferEmpty = true;
ruleToken[2] = intoTokens(source, externalContext, internalContext, true);
ruleToken = null;
@@ -282,6 +316,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
levels.push(level);
level = Level.RULE;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.OPEN_CURLY_BRACKET && level == Level.RULE && seekingValue) {
// open brace opening rule at rule level, e.g. div{--variable:{<--
ruleTokens.push(ruleToken);
@@ -304,6 +339,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
levels.push(level);
level = Level.RULE;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.COLON && level == Level.RULE && !seekingValue) {
// colon at rule level, e.g. a{color:<--
serializedBuffer = buffer.join('').trim();
@@ -312,13 +348,15 @@ function intoTokens(source, externalContext, internalContext, isNested) {
seekingValue = true;
buffer = [];
} else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && ruleTokens.length > 0 && buffer.length > 0 && buffer[0] == Marker.AT) {
isBufferEmpty = true;
} else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && ruleTokens.length > 0 && !isBufferEmpty && buffer[0] == Marker.AT) {
// semicolon at rule level for at-rule, e.g. a{--color:{@apply(--other-color);<--
serializedBuffer = buffer.join('').trim();
ruleToken[1].push([Token.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
buffer = [];
} else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && buffer.length > 0) {
isBufferEmpty = true;
} else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && !isBufferEmpty) {
// semicolon at rule level, e.g. a{color:red;<--
serializedBuffer = buffer.join('').trim();
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
@@ -326,25 +364,28 @@ function intoTokens(source, externalContext, internalContext, isNested) {
propertyToken = null;
seekingValue = false;
buffer = [];
} else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && buffer.length === 0) {
isBufferEmpty = true;
} else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && isBufferEmpty) {
// semicolon after bracketed value at rule level, e.g. a{color:rgb(...);<--
propertyToken = null;
seekingValue = false;
} else if (character == Marker.SEMICOLON && level == Level.RULE && buffer.length > 0 && buffer[0] == Marker.AT) {
} else if (character == Marker.SEMICOLON && level == Level.RULE && !isBufferEmpty && buffer[0] == Marker.AT) {
// semicolon for at-rule at rule level, e.g. a{@apply(--variable);<--
serializedBuffer = buffer.join('');
newTokens.push([Token.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
seekingValue = false;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.SEMICOLON && level == Level.RULE && seekingPropertyBlockClosing) {
// close brace after a property block at rule level, e.g. a{--custom:{color:red;};<--
seekingPropertyBlockClosing = false;
buffer = [];
} else if (character == Marker.SEMICOLON && level == Level.RULE && buffer.length === 0) {
isBufferEmpty = true;
} else if (character == Marker.SEMICOLON && level == Level.RULE && isBufferEmpty) {
// stray semicolon at rule level, e.g. a{;<--
// noop
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && seekingValue && buffer.length > 0 && ruleTokens.length > 0) {
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && seekingValue && !isBufferEmpty && ruleTokens.length > 0) {
// close brace at rule level, e.g. a{--color:{color:red}<--
serializedBuffer = buffer.join('');
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
@@ -355,7 +396,8 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
seekingValue = false;
buffer = [];
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && buffer.length > 0 && buffer[0] == Marker.AT && ruleTokens.length > 0) {
isBufferEmpty = true;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && !isBufferEmpty && buffer[0] == Marker.AT && ruleTokens.length > 0) {
// close brace at rule level for at-rule, e.g. a{--color:{@apply(--other-color)}<--
serializedBuffer = buffer.join('');
ruleToken[1].push([Token.AT_RULE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
@@ -366,6 +408,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
seekingValue = false;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && ruleTokens.length > 0) {
// close brace at rule level after space, e.g. a{--color:{color:red }<--
propertyToken = null;
@@ -374,7 +417,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
seekingValue = false;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && buffer.length > 0) {
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && propertyToken && !isBufferEmpty) {
// close brace at rule level, e.g. a{color:red}<--
serializedBuffer = buffer.join('');
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
@@ -385,7 +428,8 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
seekingValue = false;
buffer = [];
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && buffer.length > 0 && buffer[0] == Marker.AT) {
isBufferEmpty = true;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && !isBufferEmpty && buffer[0] == Marker.AT) {
// close brace after at-rule at rule level, e.g. a{@apply(--variable)}<--
propertyToken = null;
ruleToken = null;
@@ -396,6 +440,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
level = levels.pop();
seekingValue = false;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE && levels[levels.length - 1] == Level.RULE) {
// close brace after a property block at rule level, e.g. a{--custom:{color:red;}<--
propertyToken = null;
@@ -406,6 +451,7 @@ function intoTokens(source, externalContext, internalContext, isNested) {
seekingValue = false;
seekingPropertyBlockClosing = true;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE) {
// close brace after a rule, e.g. a{color:red;}<--
propertyToken = null;
@@ -418,76 +464,91 @@ function intoTokens(source, externalContext, internalContext, isNested) {
// stray close brace at block level, e.g. a{color:red}color:blue}<--
externalContext.warnings.push('Unexpected \'}\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
buffer.push(character);
isBufferEmpty = false;
} else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.BLOCK) {
// close brace at block level, e.g. @media screen {...}<--
break;
} else if (character == Marker.OPEN_ROUND_BRACKET && level == Level.RULE && seekingValue) {
// round open bracket, e.g. a{color:hsla(<--
buffer.push(character);
isBufferEmpty = false;
roundBracketLevel++;
} else if (character == Marker.CLOSE_ROUND_BRACKET && level == Level.RULE && seekingValue && roundBracketLevel == 1) {
// round close bracket, e.g. a{color:hsla(0,0%,0%)<--
buffer.push(character);
isBufferEmpty = false;
serializedBuffer = buffer.join('').trim();
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
roundBracketLevel--;
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.CLOSE_ROUND_BRACKET && level == Level.RULE && seekingValue) {
// round close bracket within other brackets, e.g. a{width:calc((10rem / 2)<--
buffer.push(character);
isBufferEmpty = false;
roundBracketLevel--;
} else if (character == Marker.FORWARD_SLASH && source[position.index + 1] != Marker.ASTERISK && level == Level.RULE && seekingValue && buffer.length > 0) {
} else if (character == Marker.FORWARD_SLASH && source[position.index + 1] != Marker.ASTERISK && level == Level.RULE && seekingValue && !isBufferEmpty) {
// forward slash within a property, e.g. a{background:url(image.png) 0 0/<--
serializedBuffer = buffer.join('').trim();
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
propertyToken.push([Token.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.FORWARD_SLASH && source[position.index + 1] != Marker.ASTERISK && level == Level.RULE && seekingValue) {
// forward slash within a property after space, e.g. a{background:url(image.png) 0 0 /<--
propertyToken.push([Token.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);
buffer = [];
} else if (character == Marker.COMMA && level == Level.RULE && seekingValue && buffer.length > 0) {
isBufferEmpty = true;
} else if (character == Marker.COMMA && level == Level.RULE && seekingValue && !isBufferEmpty) {
// comma within a property, e.g. a{background:url(image.png),<--
serializedBuffer = buffer.join('').trim();
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
propertyToken.push([Token.PROPERTY_VALUE, character, [[position.line, position.column, position.source]]]);
buffer = [];
isBufferEmpty = true;
} else if (character == Marker.COMMA && level == Level.RULE && seekingValue) {
// comma within a property after space, e.g. a{background:url(image.png) ,<--
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)) {
isBufferEmpty = true;
} else if (character == Marker.CLOSE_SQUARE_BRACKET && propertyToken && propertyToken.length > 1 && !isBufferEmpty && 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) {
isBufferEmpty = true;
} else if ((isSpace || (isNewLineNix && !isNewLineWin)) && level == Level.RULE && seekingValue && propertyToken && !isBufferEmpty) {
// space or *nix newline within property, e.g. a{margin:0 <--
serializedBuffer = buffer.join('').trim();
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
buffer = [];
isBufferEmpty = true;
} else if (isNewLineWin && level == Level.RULE && seekingValue && propertyToken && buffer.length > 1) {
// win newline within property, e.g. a{margin:0\r\n<--
serializedBuffer = buffer.join('').trim();
propertyToken.push([Token.PROPERTY_VALUE, serializedBuffer, [originalMetadata(metadata, serializedBuffer, externalContext)]]);
buffer = [];
isBufferEmpty = true;
} else if (isNewLineWin && level == Level.RULE && seekingValue) {
// win newline
buffer = [];
} else if (buffer.length == 1 && isNewLineWin) {
isBufferEmpty = true;
} else if (isNewLineWin && buffer.length == 1) {
// ignore windows newline which is composed of two characters
buffer.pop();
} else if (buffer.length > 0 || !isSpace && !isNewLineNix && !isNewLineWin && !isCarriageReturn) {
isBufferEmpty = buffer.length === 0;
} else if (!isBufferEmpty || !isSpace && !isNewLineNix && !isNewLineWin && !isCarriageReturn) {
// any character
buffer.push(character);
isBufferEmpty = false;
}
wasEscaped = isEscaped;

View File

@@ -109,6 +109,7 @@ function property(context, tokens, position, lastPropertyAt) {
break;
case Token.COMMENT:
store(context, token);
store(context, breakFor(context, Breaks.AfterComment) + context.indentWith);
break;
case Token.PROPERTY:
store(context, token[1]);
@@ -142,8 +143,8 @@ function value(context, token) {
}
}
function allowsBreak(context, where) {
return context.format && context.format.breaks[where];
function breakFor(context, where) {
return context.format ? context.format.breaks[where] : emptyCharacter;
}
function allowsSpace(context, where) {
@@ -156,7 +157,7 @@ function openBrace(context, where, needsPrefixSpace) {
context.indentWith = context.format.indentWith.repeat(context.indentBy);
return (needsPrefixSpace && allowsSpace(context, Spaces.BeforeBlockBegins) ? Marker.SPACE : emptyCharacter) +
Marker.OPEN_CURLY_BRACKET +
(allowsBreak(context, where) ? context.format.breakWith : emptyCharacter) +
breakFor(context, where) +
context.indentWith;
} else {
return Marker.OPEN_CURLY_BRACKET;
@@ -167,10 +168,10 @@ function closeBrace(context, where, beforeBlockEnd, isLast) {
if (context.format) {
context.indentBy -= context.format.indentBy;
context.indentWith = context.format.indentWith.repeat(context.indentBy);
return (allowsBreak(context, Breaks.AfterProperty) || beforeBlockEnd && allowsBreak(context, Breaks.BeforeBlockEnds) ? context.format.breakWith : emptyCharacter) +
return (beforeBlockEnd ? breakFor(context, Breaks.BeforeBlockEnds) : breakFor(context, Breaks.AfterProperty)) +
context.indentWith +
Marker.CLOSE_CURLY_BRACKET +
(isLast ? emptyCharacter : (allowsBreak(context, where) ? context.format.breakWith : emptyCharacter) + context.indentWith);
(isLast ? emptyCharacter : breakFor(context, where) + context.indentWith);
} else {
return Marker.CLOSE_CURLY_BRACKET;
}
@@ -184,13 +185,13 @@ function colon(context) {
function semicolon(context, where, isLast) {
return context.format ?
Marker.SEMICOLON + (isLast || !allowsBreak(context, where) ? emptyCharacter : context.format.breakWith + context.indentWith) :
Marker.SEMICOLON + (isLast ? emptyCharacter : (breakFor(context, where) + context.indentWith)) :
Marker.SEMICOLON;
}
function comma(context) {
return context.format ?
Marker.COMMA + (allowsBreak(context, Breaks.BetweenSelectors) ? context.format.breakWith : emptyCharacter) + context.indentWith :
Marker.COMMA + breakFor(context, Breaks.BetweenSelectors) + context.indentWith :
Marker.COMMA;
}
@@ -223,7 +224,7 @@ function all(context, tokens) {
break;
case Token.COMMENT:
store(context, token);
store(context, allowsBreak(context, Breaks.AfterComment) ? context.format.breakWith : emptyCharacter);
store(context, breakFor(context, Breaks.AfterComment) + context.indentWith);
break;
case Token.RAW:
store(context, token);

36
node_modules/clean-css/package.json generated vendored
View File

@@ -1,55 +1,53 @@
{
"_args": [
[
"clean-css@4.2.3",
"D:\\Projects\\minifyfromhtml"
]
],
"_from": "clean-css@4.2.3",
"_id": "clean-css@4.2.3",
"_from": "clean-css@5.1.2",
"_id": "clean-css@5.1.2",
"_inBundle": false,
"_integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
"_integrity": "sha512-QcaGg9OuMo+0Ds933yLOY+gHPWbxhxqF0HDexmToPf8pczvmvZGYzd+QqWp9/mkucAOKViI+dSFOqoZIvXbeBw==",
"_location": "/clean-css",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "clean-css@4.2.3",
"raw": "clean-css@5.1.2",
"name": "clean-css",
"escapedName": "clean-css",
"rawSpec": "4.2.3",
"rawSpec": "5.1.2",
"saveSpec": null,
"fetchSpec": "4.2.3"
"fetchSpec": "5.1.2"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
"_spec": "4.2.3",
"_resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.2.tgz",
"_shasum": "6ea0da7286b4ddc2469a1b776e2461a5007eed54",
"_spec": "clean-css@5.1.2",
"_where": "D:\\Projects\\minifyfromhtml",
"author": {
"name": "Jakub Pawlowicz",
"email": "contact@jakubpawlowicz.com",
"url": "http://twitter.com/jakubpawlowicz"
"url": "https://jakubpawlowicz.com"
},
"bugs": {
"url": "https://github.com/jakubpawlowicz/clean-css/issues"
},
"bundleDependencies": false,
"dependencies": {
"source-map": "~0.6.0"
},
"deprecated": false,
"description": "A well-tested CSS minifier",
"devDependencies": {
"browserify": "^14.0.0",
"browserify": "^17.0.0",
"http-proxy": "1.x",
"jshint": "2.x",
"nock": "9.x",
"nock": "^13.0.0",
"server-destroy": "1.x",
"uglify-js": ">=2.6.1",
"vows": "0.8.x"
},
"engines": {
"node": ">= 4.0"
"node": ">= 10.0"
},
"files": [
"lib",
@@ -76,5 +74,5 @@
"prepublish": "npm run check",
"test": "vows"
},
"version": "4.2.3"
"version": "5.1.2"
}