/** * 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; }