1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | var level0Optimize = require('./optimizer/level-0/optimize');
|
9 | var level1Optimize = require('./optimizer/level-1/optimize');
|
10 | var level2Optimize = require('./optimizer/level-2/optimize');
|
11 | var validator = require('./optimizer/validator');
|
12 |
|
13 | var compatibilityFrom = require('./options/compatibility');
|
14 | var fetchFrom = require('./options/fetch');
|
15 | var formatFrom = require('./options/format').formatFrom;
|
16 | var inlineFrom = require('./options/inline');
|
17 | var inlineRequestFrom = require('./options/inline-request');
|
18 | var inlineTimeoutFrom = require('./options/inline-timeout');
|
19 | var OptimizationLevel = require('./options/optimization-level').OptimizationLevel;
|
20 | var optimizationLevelFrom = require('./options/optimization-level').optimizationLevelFrom;
|
21 | var rebaseFrom = require('./options/rebase');
|
22 | var rebaseToFrom = require('./options/rebase-to');
|
23 |
|
24 | var inputSourceMapTracker = require('./reader/input-source-map-tracker');
|
25 | var readSources = require('./reader/read-sources');
|
26 |
|
27 | var serializeStyles = require('./writer/simple');
|
28 | var serializeStylesAndSourceMap = require('./writer/source-maps');
|
29 |
|
30 | var CleanCSS = module.exports = function CleanCSS(options) {
|
31 | options = options || {};
|
32 |
|
33 | this.options = {
|
34 | compatibility: compatibilityFrom(options.compatibility),
|
35 | fetch: fetchFrom(options.fetch),
|
36 | format: formatFrom(options.format),
|
37 | inline: inlineFrom(options.inline),
|
38 | inlineRequest: inlineRequestFrom(options.inlineRequest),
|
39 | inlineTimeout: inlineTimeoutFrom(options.inlineTimeout),
|
40 | level: optimizationLevelFrom(options.level),
|
41 | rebase: rebaseFrom(options.rebase),
|
42 | rebaseTo: rebaseToFrom(options.rebaseTo),
|
43 | returnPromise: !!options.returnPromise,
|
44 | sourceMap: !!options.sourceMap,
|
45 | sourceMapInlineSources: !!options.sourceMapInlineSources
|
46 | };
|
47 | };
|
48 |
|
49 | CleanCSS.prototype.minify = function (input, maybeSourceMap, maybeCallback) {
|
50 | var options = this.options;
|
51 |
|
52 | if (options.returnPromise) {
|
53 | return new Promise(function (resolve, reject) {
|
54 | minify(input, options, maybeSourceMap, function (errors, output) {
|
55 | return errors ?
|
56 | reject(errors) :
|
57 | resolve(output);
|
58 | });
|
59 | });
|
60 | } else {
|
61 | return minify(input, options, maybeSourceMap, maybeCallback);
|
62 | }
|
63 | };
|
64 |
|
65 | function minify(input, options, maybeSourceMap, maybeCallback) {
|
66 | var sourceMap = typeof maybeSourceMap != 'function' ?
|
67 | maybeSourceMap :
|
68 | null;
|
69 | var callback = typeof maybeCallback == 'function' ?
|
70 | maybeCallback :
|
71 | (typeof maybeSourceMap == 'function' ? maybeSourceMap : null);
|
72 | var context = {
|
73 | stats: {
|
74 | efficiency: 0,
|
75 | minifiedSize: 0,
|
76 | originalSize: 0,
|
77 | startedAt: Date.now(),
|
78 | timeSpent: 0
|
79 | },
|
80 | cache: {
|
81 | specificity: {}
|
82 | },
|
83 | errors: [],
|
84 | inlinedStylesheets: [],
|
85 | inputSourceMapTracker: inputSourceMapTracker(),
|
86 | localOnly: !callback,
|
87 | options: options,
|
88 | source: null,
|
89 | sourcesContent: {},
|
90 | validator: validator(options.compatibility),
|
91 | warnings: []
|
92 | };
|
93 |
|
94 | if (sourceMap) {
|
95 | context.inputSourceMapTracker.track(undefined, sourceMap);
|
96 | }
|
97 |
|
98 | return runner(context.localOnly)(function () {
|
99 | return readSources(input, context, function (tokens) {
|
100 | var serialize = context.options.sourceMap ?
|
101 | serializeStylesAndSourceMap :
|
102 | serializeStyles;
|
103 |
|
104 | var optimizedTokens = optimize(tokens, context);
|
105 | var optimizedStyles = serialize(optimizedTokens, context);
|
106 | var output = withMetadata(optimizedStyles, context);
|
107 |
|
108 | return callback ?
|
109 | callback(context.errors.length > 0 ? context.errors : null, output) :
|
110 | output;
|
111 | });
|
112 | });
|
113 | }
|
114 |
|
115 | function runner(localOnly) {
|
116 |
|
117 |
|
118 | return localOnly ?
|
119 | function (callback) { return callback(); } :
|
120 | process.nextTick;
|
121 | }
|
122 |
|
123 | function optimize(tokens, context) {
|
124 | var optimized;
|
125 |
|
126 | optimized = level0Optimize(tokens, context);
|
127 | optimized = OptimizationLevel.One in context.options.level ?
|
128 | level1Optimize(tokens, context) :
|
129 | tokens;
|
130 | optimized = OptimizationLevel.Two in context.options.level ?
|
131 | level2Optimize(tokens, context, true) :
|
132 | optimized;
|
133 |
|
134 | return optimized;
|
135 | }
|
136 |
|
137 | function withMetadata(output, context) {
|
138 | output.stats = calculateStatsFrom(output.styles, context);
|
139 | output.errors = context.errors;
|
140 | output.inlinedStylesheets = context.inlinedStylesheets;
|
141 | output.warnings = context.warnings;
|
142 |
|
143 | return output;
|
144 | }
|
145 |
|
146 | function calculateStatsFrom(styles, context) {
|
147 | var finishedAt = Date.now();
|
148 | var timeSpent = finishedAt - context.stats.startedAt;
|
149 |
|
150 | delete context.stats.startedAt;
|
151 | context.stats.timeSpent = timeSpent;
|
152 | context.stats.efficiency = 1 - styles.length / context.stats.originalSize;
|
153 | context.stats.minifiedSize = styles.length;
|
154 |
|
155 | return context.stats;
|
156 | }
|