diff --git a/index.js b/index.js index 053e5e0..5bcbc91 100644 --- a/index.js +++ b/index.js @@ -74,22 +74,30 @@ function normalizeManifestPaths (tokensByFile, rootDir) { return output; } +function dedupeSources (sources) { + var foundHashes = {} + Object.keys(sources).forEach(function (key) { + var hash = stringHash(sources[key]); + if (foundHashes[hash]) { + delete sources[key]; + } + else { + foundHashes[hash] = true; + } + }) +} + var cssExt = /\.css$/; // caches // // persist these for as long as the process is running. #32 -// keep track of css files visited -var filenames = []; - // keep track of all tokens so we can avoid duplicates var tokensByFile = {}; -// keep track of all source files for later builds: when -// using watchify, not all files will be caught on subsequent -// bundles -var sourceByFile = {}; +// we need a separate loader for each entry point +var loadersByFile = {}; module.exports = function (browserify, options) { options = options || {}; @@ -103,9 +111,10 @@ module.exports = function (browserify, options) { var jsonOutFilename = options.json || options.jsonOutput; var sourceKey = cssOutFilename; - // keying our source caches by the name of our output file means we can - // isolate css compilation of seperate bundles that are running in parallel - sourceByFile[sourceKey] = sourceByFile[sourceKey] || {}; + var loader = loadersByFile[sourceKey]; + if (!loader) { + loader = loadersByFile[sourceKey] = new FileSystemLoader(rootDir, plugins); + } // PostCSS plugins passed to FileSystemLoader var plugins = options.use || options.u; @@ -158,10 +167,6 @@ module.exports = function (browserify, options) { return through(); } - // collect visited filenames - filenames.push(filename); - - var loader = new FileSystemLoader(rootDir, plugins); return through(function noop () {}, function end () { var self = this; @@ -170,11 +175,6 @@ module.exports = function (browserify, options) { assign(tokensByFile, loader.tokensByFile); - // store this file's source to be written out to disk later - sourceByFile[sourceKey][filename] = loader.finalSource; - - compiledCssStream.push(loader.finalSource); - self.queue(output); self.queue(null); }, function (err) { @@ -195,19 +195,19 @@ module.exports = function (browserify, options) { bundle.emit('css stream', compiledCssStream); bundle.on('end', function () { + // under certain conditions (eg. with shared libraries) we can end up with + // multiple occurrences of the same rule, so we need to remove duplicates + dedupeSources(loader.sources) + // Combine the collected sources for a single bundle into a single CSS file - var files = Object.keys(sourceByFile[sourceKey]); - var css; + var css = loader.finalSource; // end the output stream + compiledCssStream.push(css); compiledCssStream.push(null); // write the css file if (cssOutFilename) { - css = files.map(function (file) { - return sourceByFile[sourceKey][file]; - }).join('\n'); - fs.writeFile(cssOutFilename, css, function (err) { if (err) { browserify.emit('error', err); diff --git a/tests/cases/compose-from-shared/expected.css b/tests/cases/compose-from-shared/expected.css new file mode 100644 index 0000000..9c004b1 --- /dev/null +++ b/tests/cases/compose-from-shared/expected.css @@ -0,0 +1,9 @@ +._shared__shared { + background: #000; +} +._styles_1__foo { + color: #F00; +} +._styles_2__bar { + background: #BAA; +} diff --git a/tests/cases/compose-from-shared/main.js b/tests/cases/compose-from-shared/main.js new file mode 100644 index 0000000..14cc992 --- /dev/null +++ b/tests/cases/compose-from-shared/main.js @@ -0,0 +1,2 @@ +require('./styles-1.css'); +require('./styles-2.css'); diff --git a/tests/cases/compose-from-shared/shared.css b/tests/cases/compose-from-shared/shared.css new file mode 100644 index 0000000..d6fc168 --- /dev/null +++ b/tests/cases/compose-from-shared/shared.css @@ -0,0 +1,3 @@ +.shared { + background: #000; +} diff --git a/tests/cases/compose-from-shared/styles-1.css b/tests/cases/compose-from-shared/styles-1.css new file mode 100644 index 0000000..2ffd802 --- /dev/null +++ b/tests/cases/compose-from-shared/styles-1.css @@ -0,0 +1,4 @@ +.foo { + composes: shared from "./shared.css"; + color: #F00; +} diff --git a/tests/cases/compose-from-shared/styles-2.css b/tests/cases/compose-from-shared/styles-2.css new file mode 100644 index 0000000..f9d32d8 --- /dev/null +++ b/tests/cases/compose-from-shared/styles-2.css @@ -0,0 +1,4 @@ +.bar { + composes: shared from "./shared.css"; + background: #BAA; +}