From: Jakub Pawlowicz Date: Mon, 12 Jan 2015 23:12:53 +0000 (+0000) Subject: Fixes #416 - accepts hash as a list of arguments. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=99c17e50a6c4dcedd7ebd94d3f4b152dd91bc107;p=clean-css.git Fixes #416 - accepts hash as a list of arguments. Such a hash is now accepted as the first argument to `minify` method: ```javascript { 'path/to/file/one': { styles: 'contents of file one' }, 'path/to/file/two': { styles: 'contents of file two' } } ``` This is also prepares us to implement #419 - merging input source maps. --- diff --git a/History.md b/History.md index 47e9bd53..1568cee8 100644 --- a/History.md +++ b/History.md @@ -6,6 +6,7 @@ * Fixed issue [#158](https://github.com/GoalSmashers/clean-css/issues/158) - adds body-based selectors reduction. * Fixed issue [#182](https://github.com/GoalSmashers/clean-css/issues/182) - removing space after closing brace. * Fixed issue [#357](https://github.com/GoalSmashers/clean-css/issues/357) - non-standard but valid URLs. +* Fixed issue [#416](https://github.com/GoalSmashers/clean-css/issues/416) - accepts hash as `minify` argument. [3.0.4 / 2015-01-11](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.3...v3.0.4) ================== diff --git a/README.md b/README.md index 20950b0a..8e86dd4d 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,21 @@ new CleanCSS({ sourceMap: inputSourceMapAsString, target: pathToOutputDirectory * Shorthand compacting is currently disabled when source maps are enabled, see [#399](https://github.com/GoalSmashers/clean-css/issues/399) * Sources inlined in source maps are not supported, see [#397](https://github.com/GoalSmashers/clean-css/issues/397) +### How to minify multiple files with API + +#### Passing a hash + +```javascript +new CleanCSS().minify({ + 'path/to/file/one': { + styles: 'contents of file one' + }, + 'path/to/file/two': { + styles: 'contents of file two' + } +}); +``` + ### How to set compatibility mode Compatibility settings are controlled by `--compatibility` switch (CLI) and `compatibility` option (library mode). diff --git a/lib/images/url-rewriter.js b/lib/images/url-rewriter.js index 69c24432..955ea0c7 100644 --- a/lib/images/url-rewriter.js +++ b/lib/images/url-rewriter.js @@ -35,14 +35,23 @@ UrlRewriter.prototype.process = function (data) { }; function rebase(resource, options) { + // TODO: this is getting insane now - pending refactor in #436 + var importUrl = resource.substring(resource.length - 4) == '.css'; var specialUrl = resource[0] == '/' || resource[0] == '#' || - resource.substring(resource.length - 4) == '.css' || + (!options.imports && importUrl) || resource.indexOf('data:') === 0 || /^https?:\/\//.exec(resource) !== null || /__\w+__/.exec(resource) !== null; var rebased; + if (false === options.urls) { + if (options.imports && importUrl) + specialUrl = false; + else + specialUrl = true; + } + if (specialUrl) return resource; diff --git a/lib/utils/source-reader.js b/lib/utils/source-reader.js index c98eb0ba..4bc31f3c 100644 --- a/lib/utils/source-reader.js +++ b/lib/utils/source-reader.js @@ -1,4 +1,5 @@ var path = require('path'); +var UrlRewriter = require('../images/url-rewriter'); function SourceReader(context, data) { this.outerContext = context; @@ -13,7 +14,7 @@ SourceReader.prototype.toString = function () { if (Array.isArray(this.data)) return fromArray(this.outerContext, this.data); - return this.data; + return fromHash(this.outerContext, this.data); }; function fromArray(outerContext, sources) { @@ -32,4 +33,26 @@ function fromArray(outerContext, sources) { .join(''); } +function fromHash(outerContext, sources) { + var data = []; + var toBase = path.resolve(outerContext.options.target || process.cwd()); + + for (var source in sources) { + var styles = sources[source].styles; + var rewriter = new UrlRewriter({ + absolute: !!outerContext.options.root, + relative: !outerContext.options.root, + imports: true, + urls: outerContext.options.rebase, + fromBase: path.dirname(path.resolve(source)), + toBase: toBase + }); + + styles = rewriter.process(styles); + data.push(styles); + } + + return data.join(''); +} + module.exports = SourceReader; diff --git a/test/module-test.js b/test/module-test.js index df76624f..28ae768d 100644 --- a/test/module-test.js +++ b/test/module-test.js @@ -1,9 +1,23 @@ var vows = require('vows'); var assert = require('assert'); var path = require('path'); +var fs = require('fs'); var CleanCSS = require('../index'); var SourceMapGenerator = require('source-map').SourceMapGenerator; +function sourcesAsHash(sources, resolve) { + var inputHash = {}; + + sources.forEach(function (source) { + source = resolve ? path.resolve(source) : source; + inputHash[source] = { + styles: fs.readFileSync(source, 'utf-8') + }; + }); + + return inputHash; +} + vows.describe('module tests').addBatch({ 'imported as a function': { topic: function() { @@ -287,5 +301,95 @@ vows.describe('module tests').addBatch({ assert.equal(minified.styles, '@import url(one.css);@import url(extra/three.css);@import url(./extra/four.css);.two{color:#fff}'); } } + }, + 'accepts a list of source files as hash': { + 'rebased to the current dir': { + 'with relative paths': { + 'topic': new CleanCSS().minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/partials/three.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{background-image:url(test/fixtures/partials/extra/down.gif)}'); + } + }, + 'with absolute paths': { + 'topic': new CleanCSS().minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/partials/three.css'], true)), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{background-image:url(test/fixtures/partials/extra/down.gif)}'); + } + } + }, + 'rebased to a relative path': { + 'with relative paths': { + 'topic': new CleanCSS({ target: 'test/fixtures' }).minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/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 absolute paths': { + 'topic': new CleanCSS({ target: 'test/fixtures' }).minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/partials/three.css'], true)), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{background-image:url(partials/extra/down.gif)}'); + } + } + }, + 'rebased to an absolute root': { + 'with relative paths': { + 'topic': new CleanCSS({ root: 'test/fixtures', target: 'test/fixtures' }).minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/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 absolute paths': { + 'topic': new CleanCSS({ root: 'test/fixtures', target: 'test/fixtures' }).minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/partials/three.css'], true)), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{background-image:url(/partials/extra/down.gif)}'); + } + } + }, + 'with rebasing off': { + 'with relative paths': { + 'topic': new CleanCSS({ rebase: false }).minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/partials/three.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{background-image:url(extra/down.gif)}'); + } + }, + 'with absolute paths': { + 'topic': new CleanCSS({ rebase: false }).minify(sourcesAsHash(['test/fixtures/partials/one.css', 'test/fixtures/partials/three.css'], true)), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{background-image:url(extra/down.gif)}'); + } + } + }, + 'with other imports': { + 'topic': new CleanCSS().minify(sourcesAsHash(['test/fixtures/partials/two.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{color:#0f0}.four{color:#00f}.two{color:#fff}'); + } + }, + 'with other imports and rebasing off': { + 'topic': new CleanCSS({ rebase: false }).minify(sourcesAsHash(['test/fixtures/partials/two.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '.one{color:red}.three{color:#0f0}.four{color:#00f}.two{color:#fff}'); + } + }, + 'with other imports and processing imports off': { + 'relative to current path': { + 'topic': new CleanCSS({ processImport: false }).minify(sourcesAsHash(['test/fixtures/partials/two.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '@import url(test/fixtures/partials/one.css);@import url(test/fixtures/partials/extra/three.css);@import url(test/fixtures/partials/extra/four.css);.two{color:#fff}'); + } + }, + 'relative to different path': { + 'topic': new CleanCSS({ processImport: false, target: 'test/fixtures' }).minify(sourcesAsHash(['test/fixtures/partials/two.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '@import url(partials/one.css);@import url(partials/extra/three.css);@import url(partials/extra/four.css);.two{color:#fff}'); + } + }, + 'absolute': { + 'topic': new CleanCSS({ processImport: false, root: 'test/fixtures', target: 'test/fixtures' }).minify(sourcesAsHash(['test/fixtures/partials/two.css'])), + 'should give right output': function (minified) { + assert.equal(minified.styles, '@import url(/partials/one.css);@import url(/partials/extra/three.css);@import url(/partials/extra/four.css);.two{color:#fff}'); + } + } + } } }).export(module);