From 592edc48989b967dc5cece566160fe7c722de29e Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Fri, 27 May 2016 14:14:23 -0400 Subject: [PATCH] add new spike-util version, refactor getFilesFromGlob --- lib/plugins/css_plugin.js | 4 +- lib/plugins/fs_plugin.js | 147 +++++++++++++++++++---------------- lib/plugins/jade_plugin.js | 8 +- lib/plugins/static_plugin.js | 4 +- package.json | 3 +- 5 files changed, 90 insertions(+), 76 deletions(-) diff --git a/lib/plugins/css_plugin.js b/lib/plugins/css_plugin.js index 05a4abd..ab8544e 100644 --- a/lib/plugins/css_plugin.js +++ b/lib/plugins/css_plugin.js @@ -28,7 +28,7 @@ module.exports = class CSSWebpackPlugin { compiler.plugin('make', (compilation, done) => { cssFiles = compiler.options.spike.files.css this.util.addFilesAsWebpackEntries(compilation, cssFiles) - .done(() => done()) + .done(() => done(), done) }) // grab the sources and dependencies and export them into the right files @@ -48,7 +48,7 @@ module.exports = class CSSWebpackPlugin { let src = _eval(srcFn, f) // eslint-disable-line src = src[0][1] // this part is questionable, but it is what it is const outputPath = this.util.getOutputPath(f) - const newPath = outputPath.replace(/\.[^/.]+$/, '.css') + const newPath = outputPath.relative.replace(/\.[^/.]+$/, '.css') compilation.assets[newPath] = { source: () => { return src }, size: () => { return src.length } diff --git a/lib/plugins/fs_plugin.js b/lib/plugins/fs_plugin.js index 32a6713..c115ffe 100644 --- a/lib/plugins/fs_plugin.js +++ b/lib/plugins/fs_plugin.js @@ -5,6 +5,7 @@ const path = require('path') const glob = require('glob') const micromatch = require('micromatch') +const File = require('filewrap') /** * @class FsWebpackPlugin @@ -23,81 +24,93 @@ module.exports = class FsWebpackPlugin { this.util = util } + /** + * Main webpack plugin entry point + */ apply (compiler) { - compiler.plugin('run', run.bind(this, compiler)) - compiler.plugin('watch-run', run.bind(this, compiler)) + this.util.runAll(compiler, this.run.bind(this, compiler)) } -} -function run (compiler, compilation, done) { - compiler.options.spike.files = getFilesFromGlob(this.util) - compiler.options.module.loaders.map((l) => { - if (!l._core) { return } - const files = compiler.options.spike.files[l._core] - l.test = pathToRegex(files) - }) - done() -} + /** + * Function that is executed at the beginning of the compile process + */ + run (compiler, compilation, done) { + compiler.options.spike.files = this.getFilesFromGlob() + compiler.options.module.loaders.map((l) => { + if (!l._core) { return } + const files = compiler.options.spike.files[l._core] + l.test = pathToRegex(files) + }) + done() + } -function pathToRegex (paths) { - if (!paths.length) { return new RegExp('^.^') } - return new RegExp(paths.map((p, i) => { - return p.replace(/\//g, '\\/') - }).join('|')) -} + /** + * Given the config options, pulls all files from the fs that match any of the + * provided matchers. + * @return {Array} all matching file paths, absolute + */ + getFilesFromGlob () { + let files = {} + const util = this.util -/** - * Given the config options, pulls all files from the fs that match any of the - * provided matchers. - * @param {Object} util - spikeUtils object - * @param {Object} util.conf - configuration values from webpack + spike - * @param {String} util.conf.context - the root path of your spike project - * @param {String} util.conf.module.loaders - configured webpack loaders - * @param {Object} util.conf.spike - spike specific config values - * @param {Array} util.conf.spike.ignore - a glob pattern of files/dirs to ignore - * @param {Array} util.conf.spike.vendor - an array of glob patterns of files to vendor - * @param {Object} util.conf.spike.matchers - core spike matchers - * @return {Array} all matching file paths, absolute - */ -function getFilesFromGlob (util) { - let files = {} - const matcher = path.join(util.conf.context, '**/**') - files.all = glob.sync(matcher, { ignore: util.conf.spike.ignore, dot: true, nodir: true }) - - // Grab any file match tests from user-provided loaders - const customLoaderTests = util.conf.module.loaders.reduce((m, l) => { - if (!l._core) m.push(l.test) - return m - }, []) - - files.vendored = [] - if (util.conf.spike.vendor) { - // push all matched vendored paths into `static` category - const vendorTests = util.conf.spike.vendor.map(micromatch.makeRe) - for (const vendorTest of vendorTests) { - files.all.forEach((f) => { - if (util.getOutputPath(f).match(vendorTest)) { files.vendored.push(f) } - }) - } - } + // First, we grab all the files in the project, other than the ignored + // files of course. + + const matcher = path.join(util.conf.context, '**/**') + files.all = glob.sync(matcher, { ignore: util.conf.spike.ignore, dot: true, nodir: true }) + + // There are two special types of files we want to *not* be processed by + // spike's core plugins. Any files that are already being processed by a + // user-added loader, and any files in the `vendored` config. Here, we find + // these two types of files and push them into their own custom categories. - // push all files matched by custom loaders into a `custom` category - files.custom = [] - for (const loaderTest of customLoaderTests) { - files.all.forEach((f) => { - if (f.match(loaderTest)) { files.custom.push(f) } + const customLoaderTests = util.conf.module.loaders.reduce((m, l) => { + if (!l._core) m.push(l.test); return m + }, []) + + files.custom = files.all.filter((f) => { + return customLoaderTests.find((t) => f.match(t) && f) }) - } - // Core matchers do not match files that are already covered by custom loaders or vendored paths - const excludedFiles = files.custom.concat(files.vendored) - const allWithoutCustomOrVendored = files.all.filter((f) => excludedFiles.indexOf(f) < 0) - for (const key in util.conf.spike.matchers) { - files[key] = micromatch(allWithoutCustomOrVendored, util.conf.spike.matchers[key], { dot: true }) - } + files.vendored = files.all.filter((f) => { + const file = new File(util.conf.context, f) + return util.matchGlobs(file.relative, util.conf.spike.vendor)[0] + }) + + // Now we go through the rest of the eligible files and sort them into + // categories according to which plugin will process them, using the + // `matchers` config, which matches by file extension. This does not + // include any ignored, vendored, or custom loader processed files, as we + // have separared these earlier. - // add vendored files to files.static to be emitted by webpack - if (util.conf.spike.vendor) { files.static = files.vendored.concat(files.static) } + const allWithoutCustomOrVendored = files.all.filter((f) => { + return files.custom.concat(files.vendored).indexOf(f) < 0 + }) + + for (const key in util.conf.spike.matchers) { + files[key] = micromatch(allWithoutCustomOrVendored, util.conf.spike.matchers[key], { dot: true }) + } + + // Finally, we add vendored files to files.static so that they are written + // by the static plugin, without modification. + + if (files.vendored.length) { + files.static = files.static.concat(files.vendored) + } - return files + return files + } +} + +/** + * Given an array of paths, convert to a regex that matches for presence of + * any of the given paths in a single path. + * @param {Array} paths - array of absolute paths + * @return {RegExp} regex that matches presence of any of the input paths + */ +function pathToRegex (paths) { + if (!paths.length) { return new RegExp('^.^') } + return new RegExp(paths.map((p, i) => { + return p.replace(/\//g, '\\/') + }).join('|')) } diff --git a/lib/plugins/jade_plugin.js b/lib/plugins/jade_plugin.js index 898ddbd..4d5ac40 100644 --- a/lib/plugins/jade_plugin.js +++ b/lib/plugins/jade_plugin.js @@ -28,7 +28,7 @@ module.exports = class JadeWebpackPlugin { compiler.plugin('make', (compilation, done) => { jadeFiles = compiler.options.spike.files.jade this.util.addFilesAsWebpackEntries(compilation, jadeFiles) - .done(() => done()) + .done(() => done(), done) }) // grab the sources and dependencies and export them into the right files @@ -64,11 +64,11 @@ module.exports = class JadeWebpackPlugin { // add HTML asset references as dependencies in webpack srcs.forEach((src) => { - const p = this.util.resolveRelativeSourcePath(src) - dep.fileDependencies.push(p) + const p = this.util.getSourcePath(src) + dep.fileDependencies.push(p.relative) }) - const outputPath = this.util.getOutputPath(f).replace(/\.jade$/, '.html') + const outputPath = this.util.getOutputPath(f).relative.replace(/\.jade$/, '.html') compilation.assets[outputPath] = { source: () => { return src }, size: () => { return src.length } diff --git a/lib/plugins/static_plugin.js b/lib/plugins/static_plugin.js index 88287fc..c2867ee 100644 --- a/lib/plugins/static_plugin.js +++ b/lib/plugins/static_plugin.js @@ -26,7 +26,7 @@ module.exports = class StaticWebpackPlugin { compiler.plugin('make', (compilation, done) => { staticFiles = compiler.options.spike.files.static this.util.addFilesAsWebpackEntries(compilation, staticFiles) - .done(() => done()) + .done(() => done(), done) }) // grab the sources and dependencies and export them into the right files @@ -44,7 +44,7 @@ module.exports = class StaticWebpackPlugin { const src = dep._src - const outputPath = this.util.getOutputPath(f) + const outputPath = this.util.getOutputPath(f).relative compilation.assets[outputPath] = { source: () => { return src }, size: () => { return src.length } diff --git a/package.json b/package.json index d948d57..e94834b 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "browser-sync-webpack-plugin": "^1.0.1", "cheerio": "^0.20.0", "css-loader": "^0.23.1", + "filewrap": "^0.1.0", "glob": "^7.0.3", "hygienist-middleware": "^0.1.1", "jade": "^1.11.0", @@ -30,7 +31,7 @@ "require-from-string": "^1.2.0", "rimraf": "^2.5.2", "source-loader": "^0.1.0", - "spike-util": "0.0.1", + "spike-util": "^0.1.0", "sprout": "^1.2.0", "webpack": "^1.13.0", "when": "^3.7.7"