| /** |
| * Clean-css - https://github.com/jakubpawlowicz/clean-css |
| * Released under the terms of MIT license |
| * |
| * Copyright (C) 2017 JakubPawlowicz.com |
| */ |
| |
| var level0Optimize = require('./optimizer/level-0/optimize'); |
| var level1Optimize = require('./optimizer/level-1/optimize'); |
| var level2Optimize = require('./optimizer/level-2/optimize'); |
| var validator = require('./optimizer/validator'); |
| |
| var compatibilityFrom = require('./options/compatibility'); |
| var fetchFrom = require('./options/fetch'); |
| var formatFrom = require('./options/format').formatFrom; |
| var inlineFrom = require('./options/inline'); |
| var inlineRequestFrom = require('./options/inline-request'); |
| var inlineTimeoutFrom = require('./options/inline-timeout'); |
| var OptimizationLevel = require('./options/optimization-level').OptimizationLevel; |
| var optimizationLevelFrom = require('./options/optimization-level').optimizationLevelFrom; |
| var rebaseFrom = require('./options/rebase'); |
| var rebaseToFrom = require('./options/rebase-to'); |
| |
| var inputSourceMapTracker = require('./reader/input-source-map-tracker'); |
| var readSources = require('./reader/read-sources'); |
| |
| var serializeStyles = require('./writer/simple'); |
| var serializeStylesAndSourceMap = require('./writer/source-maps'); |
| |
| var CleanCSS = module.exports = function CleanCSS(options) { |
| options = options || {}; |
| |
| this.options = { |
| compatibility: compatibilityFrom(options.compatibility), |
| 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), |
| rebaseTo: rebaseToFrom(options.rebaseTo), |
| returnPromise: !!options.returnPromise, |
| sourceMap: !!options.sourceMap, |
| sourceMapInlineSources: !!options.sourceMapInlineSources |
| }; |
| }; |
| |
| |
| // for compatibility with optimize-css-assets-webpack-plugin |
| CleanCSS.process = function (input, opts) { |
| var cleanCss; |
| var optsTo = opts.to; |
| |
| delete opts.to; |
| cleanCss = new CleanCSS(Object.assign({ returnPromise: true, rebaseTo: optsTo }, opts)); |
| |
| return cleanCss.minify(input) |
| .then(function(output) { |
| return { css: output.styles }; |
| }); |
| }; |
| |
| |
| CleanCSS.prototype.minify = function (input, maybeSourceMap, maybeCallback) { |
| var options = this.options; |
| |
| if (options.returnPromise) { |
| return new Promise(function (resolve, reject) { |
| minify(input, options, maybeSourceMap, function (errors, output) { |
| return errors ? |
| reject(errors) : |
| resolve(output); |
| }); |
| }); |
| } else { |
| return minify(input, options, maybeSourceMap, maybeCallback); |
| } |
| }; |
| |
| function minify(input, options, maybeSourceMap, maybeCallback) { |
| var sourceMap = typeof maybeSourceMap != 'function' ? |
| maybeSourceMap : |
| null; |
| var callback = typeof maybeCallback == 'function' ? |
| maybeCallback : |
| (typeof maybeSourceMap == 'function' ? maybeSourceMap : null); |
| var context = { |
| stats: { |
| efficiency: 0, |
| minifiedSize: 0, |
| originalSize: 0, |
| startedAt: Date.now(), |
| timeSpent: 0 |
| }, |
| cache: { |
| specificity: {} |
| }, |
| errors: [], |
| inlinedStylesheets: [], |
| inputSourceMapTracker: inputSourceMapTracker(), |
| localOnly: !callback, |
| options: options, |
| source: null, |
| sourcesContent: {}, |
| validator: validator(options.compatibility), |
| warnings: [] |
| }; |
| |
| if (sourceMap) { |
| context.inputSourceMapTracker.track(undefined, sourceMap); |
| } |
| |
| return runner(context.localOnly)(function () { |
| return readSources(input, context, function (tokens) { |
| var serialize = context.options.sourceMap ? |
| serializeStylesAndSourceMap : |
| serializeStyles; |
| |
| var optimizedTokens = optimize(tokens, context); |
| var optimizedStyles = serialize(optimizedTokens, context); |
| var output = withMetadata(optimizedStyles, context); |
| |
| return callback ? |
| callback(context.errors.length > 0 ? context.errors : null, output) : |
| output; |
| }); |
| }); |
| } |
| |
| function runner(localOnly) { |
| // to always execute code asynchronously when a callback is given |
| // more at blog.izs.me/post/59142742143/designing-apis-for-asynchrony |
| return localOnly ? |
| function (callback) { return callback(); } : |
| process.nextTick; |
| } |
| |
| function optimize(tokens, context) { |
| var optimized; |
| |
| optimized = level0Optimize(tokens, context); |
| optimized = OptimizationLevel.One in context.options.level ? |
| level1Optimize(tokens, context) : |
| tokens; |
| optimized = OptimizationLevel.Two in context.options.level ? |
| level2Optimize(tokens, context, true) : |
| optimized; |
| |
| return optimized; |
| } |
| |
| function withMetadata(output, context) { |
| output.stats = calculateStatsFrom(output.styles, context); |
| output.errors = context.errors; |
| output.inlinedStylesheets = context.inlinedStylesheets; |
| output.warnings = context.warnings; |
| |
| return output; |
| } |
| |
| function calculateStatsFrom(styles, context) { |
| var finishedAt = Date.now(); |
| var timeSpent = finishedAt - context.stats.startedAt; |
| |
| delete context.stats.startedAt; |
| context.stats.timeSpent = timeSpent; |
| context.stats.efficiency = 1 - styles.length / context.stats.originalSize; |
| context.stats.minifiedSize = styles.length; |
| |
| return context.stats; |
| } |