From cda3b4b8959fc063962fe9b9b52d8b2b4bdb7e74 Mon Sep 17 00:00:00 2001 From: Michael Ledin Date: Wed, 17 May 2017 15:34:03 +0300 Subject: [PATCH 1/2] eslint fixes --- cmify.js | 18 +++++++++--------- tests/index.js | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmify.js b/cmify.js index 1ad8294..f477d77 100644 --- a/cmify.js +++ b/cmify.js @@ -3,7 +3,7 @@ var path = require("path"); var util = require("util"); util.inherits(Cmify, stream.Transform); -function Cmify(filename, opts) { +function Cmify (filename, opts) { if (!(this instanceof Cmify)) { return new Cmify(filename, opts); } @@ -11,24 +11,24 @@ function Cmify(filename, opts) { stream.Transform.call(this); this.cssFilePattern = new RegExp(opts.cssFilePattern || '\.css$'); - this._data = ""; + this._data = ''; this._filename = filename; this._cssOutFilename = opts.cssOutFilename; } Cmify.prototype.isCssFile = function (filename) { - return this.cssFilePattern.test(filename) -} + return this.cssFilePattern.test(filename); +}; Cmify.prototype._transform = function (buf, enc, callback) { // only handle .css files if (!this.isCssFile(this._filename)) { - this.push(buf) - return callback() + this.push(buf); + return callback(); } - this._data += buf - callback() + this._data += buf; + callback(); }; -module.exports = Cmify +module.exports = Cmify; diff --git a/tests/index.js b/tests/index.js index 97a3615..0270550 100644 --- a/tests/index.js +++ b/tests/index.js @@ -11,13 +11,13 @@ var cssOutFilename = 'out.css'; function runTestCase (dir) { tape('case: ' + dir, function (t) { // load (optional) custom setup for this testcase - var customPath = path.join(casesDir, dir, 'custom.js') - var customOpts + var customPath = path.join(casesDir, dir, 'custom.js'); + var customOpts; try { - fs.accessSync(customPath) - customOpts = require(customPath) + fs.accessSync(customPath); + customOpts = require(customPath); } catch (e) { - customOpts = {} + customOpts = {}; } var fakeFs = { From 1e817d1d0c20d276c1196dd1ad1faaa5fc957365 Mon Sep 17 00:00:00 2001 From: Michael Ledin Date: Wed, 17 May 2017 18:40:11 +0300 Subject: [PATCH 2/2] Move Cmify.prototype_flush to cmify module. Move plugin loading to separate function. Use cache option instead of global cache. --- README.md | 1 + cmify.js | 59 +++++++++++++++++++++-- index.js | 125 ++++++++++++++++++------------------------------- tests/cache.js | 2 + 4 files changed, 105 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index c5c8954..f806a7a 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ b.on('css stream', function (css) { - `generateScopedName`: (API only) a function to override the default behaviour of creating locally scoped classnames. - `global`: optional boolean. Set to `true` if you want `css-modulesify` to apply to `node_modules` as well as local files. You can read more about it in the [browserify docs](https://github.com/substack/node-browserify/#btransformtr-opts). - `filePattern`: optional regular expression string to specify css file names. (default: `\.css$`) +- `cache`: optional object to persist cache between runs. ### Events - `b.on('css stream', callback)` The callback is called with a readable stream containing the compiled CSS. You can write this to a file. diff --git a/cmify.js b/cmify.js index f477d77..a8dec5a 100644 --- a/cmify.js +++ b/cmify.js @@ -1,6 +1,7 @@ -var stream = require("stream"); -var path = require("path"); -var util = require("util"); +var stream = require('stream'); +var util = require('util'); +var assign = require('object-assign'); +var path = require('path'); util.inherits(Cmify, stream.Transform); function Cmify (filename, opts) { @@ -14,6 +15,10 @@ function Cmify (filename, opts) { this._data = ''; this._filename = filename; this._cssOutFilename = opts.cssOutFilename; + this._loader = opts.loader; + this._tokensByFile = opts.tokensByFile; + this._rootDir = opts.rootDir; + opts.cssFiles.push(filename); } Cmify.prototype.isCssFile = function (filename) { @@ -31,4 +36,52 @@ Cmify.prototype._transform = function (buf, enc, callback) { callback(); }; +Cmify.prototype._flush = function (callback) { + var self = this; + var filename = this._filename; + + // only handle .css files + if (!this.isCssFile(filename)) { return callback(); } + + // grab the correct loader + var loader = this._loader; + var tokensByFile = this._tokensByFile; + + // convert css to js before pushing + // reset the `tokensByFile` state + var relFilename = path.relative(this._rootDir, filename); + tokensByFile[filename] = loader.tokensByFile[filename] = null; + + loader.fetch(relFilename, '/').then(function (tokens) { + var deps = loader.deps.dependenciesOf(filename); + var output = deps.map(function (f) { + return 'require("' + f + '")'; + }); + output.push('module.exports = ' + JSON.stringify(tokens)); + + var isValid = true; + var isUndefined = /\bundefined\b/; + Object.keys(tokens).forEach(function (k) { + if (isUndefined.test(tokens[k])) { + isValid = false; + } + }); + + if (!isValid) { + var err = 'Composition in ' + filename + ' contains an undefined reference'; + console.error(err); + output.push('console.error("' + err + '");'); + } + + assign(tokensByFile, loader.tokensByFile); + + self.push(output.join('\n')); + return callback(); + }).catch(function (err) { + self.push('console.error("' + err + '");'); + self.emit('error', err); + return callback(); + }); +}; + module.exports = Cmify; diff --git a/index.js b/index.js index a921694..d71525e 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,6 @@ var path = require('path'); var Cmify = require('./cmify'); var Core = require('css-modules-loader-core'); var FileSystemLoader = require('./file-system-loader'); -var assign = require('object-assign'); var stringHash = require('string-hash'); var ReadableStream = require('stream').Readable; var through = require('through2'); @@ -75,35 +74,8 @@ function normalizeManifestPaths (tokensByFile, rootDir) { return output; } -// caches -// -// persist these for as long as the process is running. #32 - -// keep track of all tokens so we can avoid duplicates -var tokensByFile = {}; - -// we need a separate loader for each entry point -var loadersByFile = {}; - -module.exports = function (browserify, options) { - options = options || {}; - - // if no root directory is specified, assume the cwd - var rootDir = options.rootDir || options.d || browserify._options.basedir; - if (rootDir) { rootDir = path.resolve(rootDir); } - if (!rootDir) { rootDir = process.cwd(); } - - var transformOpts = {}; - if (options.global || options.g) { - transformOpts.global = true; - } - - var cssOutFilename = options.output || options.o; - var jsonOutFilename = options.json || options.jsonOutput; - transformOpts.cssOutFilename = cssOutFilename; - transformOpts.cssFilePattern = options.filePattern; - - // PostCSS plugins passed to FileSystemLoader +// PostCSS plugins passed to FileSystemLoader +function getPlugins (options) { var plugins = options.use || options.u; if (!plugins) { plugins = getDefaultPlugins(options); @@ -119,7 +91,7 @@ module.exports = function (browserify, options) { plugins = (Array.isArray(postcssBefore) ? postcssBefore : [postcssBefore]).concat(plugins).concat(postcssAfter); // load plugins by name (if a string is used) - plugins = plugins.map(function requirePlugin (name) { + return plugins.map(function requirePlugin (name) { // assume not strings are already required plugins if (typeof name !== 'string') { return name; @@ -144,58 +116,54 @@ module.exports = function (browserify, options) { return plugin; }); +} - // create a loader for this entry file - if (!loadersByFile[cssOutFilename]) { - loadersByFile[cssOutFilename] = new FileSystemLoader(rootDir, plugins); +module.exports = function (browserify, options) { + options = options || {}; + + // if no root directory is specified, assume the cwd + var rootDir = options.rootDir || options.d || browserify._options.basedir; + if (rootDir) { + rootDir = path.resolve(rootDir); + } + if (!rootDir) { + rootDir = process.cwd(); } - // TODO: clean this up so there's less scope crossing - Cmify.prototype._flush = function (callback) { - var self = this; - var filename = this._filename; - - // only handle .css files - if (!this.isCssFile(filename)) { return callback(); } - - // grab the correct loader - var loader = loadersByFile[this._cssOutFilename]; - - // convert css to js before pushing - // reset the `tokensByFile` cache - var relFilename = path.relative(rootDir, filename); - tokensByFile[filename] = loader.tokensByFile[filename] = null; - - loader.fetch(relFilename, '/').then(function (tokens) { - var deps = loader.deps.dependenciesOf(filename); - var output = deps.map(function (f) { - return 'require("' + f + '")'; - }); - output.push('module.exports = ' + JSON.stringify(tokens)); - - var isValid = true; - var isUndefined = /\bundefined\b/; - Object.keys(tokens).forEach(function (k) { - if (isUndefined.test(tokens[k])) { - isValid = false; - } - }); - - if (!isValid) { - var err = 'Composition in ' + filename + ' contains an undefined reference'; - console.error(err); - output.push('console.error("' + err + '");'); - } + var cssOutFilename = options.output || options.o; + var jsonOutFilename = options.json || options.jsonOutput; + var loader; + // keep track of all tokens so we can avoid duplicates + var tokensByFile; + if (options.cache) { + if (options.cache.loaders) { + loader = options.cache.loaders[cssOutFilename]; + } else { + options.cache.loaders = {}; + } + if (options.cache.tokens) { + tokensByFile = options.cache.tokens; + } else { + options.cache.tokens = {}; + } + } - assign(tokensByFile, loader.tokensByFile); + loader = loader || new FileSystemLoader(rootDir, getPlugins(options)); + tokensByFile = tokensByFile || {}; - self.push(output.join('\n')); - return callback(); - }).catch(function (err) { - self.push('console.error("' + err + '");'); - self.emit('error', err); - return callback(); - }); + if (options.cache) { + options.cache.loaders[cssOutFilename] = loader; + options.cache.tokens = tokensByFile; + } + + var transformOpts = { + cssFilePattern: options.filePattern + , cssFiles: [] + , cssOutFilename: cssOutFilename + , global: options.global || options.g + , loader: loader + , rootDir: rootDir + , tokensByFile: tokensByFile }; browserify.transform(Cmify, transformOpts); @@ -214,7 +182,6 @@ module.exports = function (browserify, options) { // Combine the collected sources for a single bundle into a single CSS file var self = this; - var loader = loadersByFile[cssOutFilename]; var css = loader.finalSource; // end the output stream diff --git a/tests/cache.js b/tests/cache.js index 45c3c59..3f59240 100644 --- a/tests/cache.js +++ b/tests/cache.js @@ -25,6 +25,7 @@ tape('multiple builds', function (t) { fs: fakeFs }); + var cssModulesifyCache = {}; var getBundler = rebundler(function (cache, packageCache) { return browserify(path.join(simpleCaseDir, 'main.js'), { cache: cache @@ -34,6 +35,7 @@ tape('multiple builds', function (t) { .plugin(cssModulesify, { rootDir: path.join(simpleCaseDir) , output: cssOutFilename + , cache: cssModulesifyCache }); });