* Both relative and absolute paths are supported - see test/module-test.js.
* Fixed issue [#363](https://github.com/GoalSmashers/clean-css/issues/363) - `rem` units overriding `px`.
* Fixed issue [#373](https://github.com/GoalSmashers/clean-css/issues/373) - proper background shorthand merging.
* Fixed issue [#395](https://github.com/GoalSmashers/clean-css/issues/395) - unescaped brackets in data URIs.
+* Fixed issue [#400](https://github.com/GoalSmashers/clean-css/issues/400) - API to accept an array of filenames.
* Fixed issue [#403](https://github.com/GoalSmashers/clean-css/issues/403) - tracking input files in source maps.
* Fixed issue [#404](https://github.com/GoalSmashers/clean-css/issues/404) - no state sharing in API.
* Refixed issue [#304](https://github.com/GoalSmashers/clean-css/issues/304) - background position merging.
new CleanCSS({ sourceMap: true, target: pathToOutputDirectory }).minify(source, function (minified) {
// access minified.sourceMap for SourceMapGenerator object
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
- // see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L132 on how it's used in clean-css' CLI
+ // see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
});
```
new CleanCSS({ sourceMap: inputSourceMapAsString, target: pathToOutputDirectory }).minify(source, function (minified) {
// access minified.sourceMap to access SourceMapGenerator object
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
- // see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L132 on how it's used in clean-css' CLI
+ // see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
});
```
target: commands.output
};
-if (commands.args.length > 0) {
- var relativeTo = (options.rebase ? options.root : false) || commands.args[0];
- options.relativeTo = path.dirname(path.resolve(relativeTo));
-
- options.sources = commands.args.map(function(source) {
- var isRemote = /^https?:\/\//.test(source);
-
- if (options.processImport === false)
- source += '@shallow';
-
- return isRemote ?
- source :
- path.relative(options.relativeTo, path.resolve(source));
- });
-}
+if (options.root || commands.args.length > 0)
+ options.relativeTo = path.dirname(path.resolve(options.root || commands.args[0]));
if (options.sourceMap && !options.target) {
outputFeedback(['Source maps will not be built because you have not specified an output file.'], true);
}
// ... and do the magic!
-if (options.sources) {
- var data = options.sources
- .map(function(source) {
- return '@import url(' + source + ');';
- })
- .join('');
- minify(data);
+if (commands.args.length > 0) {
+ minify(commands.args);
} else {
var stdin = process.openStdin();
stdin.setEncoding('utf-8');
var Compatibility = require('./utils/compatibility');
var InputSourceMapTracker = require('./utils/input-source-map-tracker');
var SourceTracker = require('./utils/source-tracker');
+var SourceReader = require('./utils/source-reader');
var DEFAULT_TIMEOUT = 5000;
sourceTracker: new SourceTracker()
};
- if (Buffer.isBuffer(data))
- data = data.toString();
+ data = new SourceReader(context, data).toString();
if (context.options.processImport || data.indexOf('@shallow') > 0) {
// inline all imports
--- /dev/null
+var path = require('path');
+
+function SourceReader(context, data) {
+ this.outerContext = context;
+ this.data = data;
+}
+
+SourceReader.prototype.toString = function () {
+ if (typeof this.data == 'string')
+ return this.data;
+ if (Buffer.isBuffer(this.data))
+ return this.data.toString();
+ if (Array.isArray(this.data))
+ return fromArray(this.outerContext, this.data);
+
+ return this.data;
+};
+
+function fromArray(outerContext, sources) {
+ return sources
+ .map(function (source) {
+ return outerContext.options.processImport === false ?
+ source + '@shallow' :
+ source;
+ })
+ .map(function (source) {
+ return !outerContext.options.relativeTo || /^https?:\/\//.test(source) ?
+ source :
+ path.relative(outerContext.options.relativeTo, source);
+ })
+ .map(function (source) { return '@import url(' + source + ');'; })
+ .join('');
+}
+
+module.exports = SourceReader;
'should include source map': function (minified) {
assert.instanceOf(minified.sourceMap, SourceMapGenerator);
}
+ },
+ 'accepts a list of source files as array': {
+ 'rebased to the current dir': {
+ 'relative': {
+ 'topic': new CleanCSS().minify(['test/data/partials/one.css', 'test/data/partials/three.css']),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '.one{color:red}.three{background-image:url(test/data/partials/extra/down.gif)}');
+ }
+ },
+ 'absolute': {
+ 'topic': new CleanCSS({ relativeTo: process.cwd() }).minify([path.resolve('test/data/partials/one.css'), path.resolve('test/data/partials/three.css')]),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '.one{color:red}.three{background-image:url(test/data/partials/extra/down.gif)}');
+ }
+ }
+ },
+ 'rebased to a path': {
+ 'relative': {
+ 'topic': new CleanCSS({ relativeTo: 'test/data' }).minify(['test/data/partials/one.css', 'test/data/partials/three.css']),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '.one{color:red}.three{background-image:url(partials/extra/down.gif)}');
+ }
+ },
+ 'absolute': {
+ 'topic': new CleanCSS({ relativeTo: 'test/data' }).minify([path.resolve('test/data/partials/one.css'), path.resolve('test/data/partials/three.css')]),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '.one{color:red}.three{background-image:url(partials/extra/down.gif)}');
+ }
+ }
+ },
+ 'rebased to root': {
+ 'relative': {
+ 'topic': new CleanCSS({ root: 'test/data', relativeTo: 'test/data' }).minify(['test/data/partials/one.css', 'test/data/partials/three.css']),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '.one{color:red}.three{background-image:url(/partials/extra/down.gif)}');
+ }
+ },
+ 'absolute': {
+ 'topic': new CleanCSS({ root: 'test/data', relativeTo: 'test/data' }).minify([path.resolve('test/data/partials/one.css'), path.resolve('test/data/partials/three.css')]),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '.one{color:red}.three{background-image:url(/partials/extra/down.gif)}');
+ }
+ }
+ },
+ 'with imports off': {
+ 'topic': new CleanCSS({ processImport: false }).minify(['./test/data/partials/two.css']),
+ 'should give right output': function (minified) {
+ assert.equal(minified.styles, '@import url(one.css);@import url(extra/three.css);@import url(./extra/four.css);.two{color:#fff}');
+ }
+ }
}
}).export(module);