diff --git a/.eslintrc.json b/.eslintrc.json index b78236fc..2345dba1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,7 +1,8 @@ { "env": { "es6": true, - "node": true + "node": true, + "mocha": true }, "extends": "eslint:recommended", "parserOptions": { @@ -25,4 +26,4 @@ "always" ] } -} \ No newline at end of file +} diff --git a/README.md b/README.md index a093d80c..814f6f9f 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,15 @@ Or, in the simple case of just a `from` with the default destination, you can us | Name | Required | Default | Details | |------|----------|------------ |---------------------------------------------------------| -| `from` | Y | | _examples:_
'relative/file.txt'
'/absolute/file.txt'
'relative/dir'
'/absolute/dir'
'\*\*/\*'
{glob:'\*\*/\*', dot: true}

Globs accept [minimatch options](https://github.com/isaacs/minimatch) | -| `to` | N | output root if `from` is file or dir

resolved glob path if `from` is glob | _examples:_
'relative/file.txt'
'/absolute/file.txt'
'relative/dir'
'/absolute/dir'
'relative/[name].[ext]'
'/absolute/[name].[ext]'

Templates are [file-loader patterns](https://github.com/webpack/file-loader) | +| `from` | Y | | _examples:_
'relative/file.txt'
'/absolute/file.txt'
'relative/dir'
'/absolute/dir'
'\*\*/\*'
{glob:'\*\*/\*', dot: true}

Globs accept [minimatch options](https://github.com/isaacs/minimatch) | +| `to` | N | output root if `from` is file or dir

resolved glob path if `from` is glob | _examples:_
'relative/file.txt'
'/absolute/file.txt'
'relative/dir'
'/absolute/dir'
'relative/[name].[ext]'
'/absolute/[name].[ext]'

Templates are [file-loader patterns](https://github.com/webpack/file-loader) | | `toType` | N | **'file'** if `to` has extension or `from` is file

**'dir'** if `from` is directory, `to` has no extension or ends in '/'

**'template'** if `to` contains [a template pattern](https://github.com/webpack/file-loader) | | | `context` | N | options.context \|\| compiler.options.context | A path that determines how to interpret the `from` path | | `flatten` | N | false | Removes all directory references and only copies file names

If files have the same name, the result is non-deterministic | | `ignore` | N | [] | Additional globs to ignore for this pattern | | `transform` | N | function(content, path) {
  return content;
} | Function that modifies file contents before writing to webpack | | `force` | N | false | Overwrites files already in compilation.assets (usually added by other plugins) | +| `cache` | N | false | Enable `transform` caching. You can use `{ cache: { key: 'my-cache-key'} }` to invalidate cache. | #### Available options: diff --git a/package-lock.json b/package-lock.json index 62c814e6..a849851a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,6 +99,11 @@ "normalize-path": "2.1.1" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", @@ -772,6 +777,11 @@ "dev": true, "optional": true }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -799,6 +809,26 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "cacache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.1.tgz", + "integrity": "sha512-dRHYcs9LvG9cHgdPzjiI+/eS7e1xRhULrcyOx04RZQsszNJXU2SL9CyG60yLnge282Qq5nwTv+ieK2fH+WPZmA==", + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.1", + "mississippi": "1.3.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.0.0", + "unique-filename": "1.1.0", + "y18n": "3.2.1" + } + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -901,6 +931,11 @@ } } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -961,6 +996,11 @@ "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, "compare-func": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", @@ -980,7 +1020,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.3", @@ -1173,6 +1212,19 @@ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, "core-js": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", @@ -1182,8 +1234,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cross-spawn": { "version": "5.1.0", @@ -1194,18 +1245,6 @@ "lru-cache": "4.1.1", "shebang-command": "1.2.0", "which": "1.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - } } }, "currently-unhandled": { @@ -1217,6 +1256,11 @@ "array-find-index": "1.0.2" } }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -1363,11 +1407,30 @@ "is-obj": "1.0.1" } }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "requires": { + "once": "1.4.0" + } + }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -1672,14 +1735,22 @@ "repeat-string": "1.6.1" } }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "requires": { + "commondir": "1.0.1", + "make-dir": "1.1.0", + "pkg-dir": "2.0.0" + } + }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "locate-path": "2.0.0" } }, "flat-cache": { @@ -1694,6 +1765,15 @@ "write": "0.2.1" } }, + "flush-write-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", + "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1711,6 +1791,15 @@ "for-in": "1.0.2" } }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "fs-access": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", @@ -1726,6 +1815,17 @@ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", "dev": true }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1918,8 +2018,7 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "growl": { "version": "1.9.2", @@ -1975,6 +2074,11 @@ "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", @@ -1983,8 +2087,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", @@ -2177,13 +2280,13 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" @@ -2248,8 +2351,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -2422,18 +2524,9 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } } }, "lodash": { @@ -2492,10 +2585,21 @@ } }, "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "requires": { + "pify": "3.0.0" + } }, "map-obj": { "version": "1.0.1", @@ -2595,14 +2699,29 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mississippi": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz", + "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=", + "requires": { + "concat-stream": "1.6.0", + "duplexify": "3.5.1", + "end-of-stream": "1.4.0", + "flush-write-stream": "1.0.2", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "1.0.3", + "pumpify": "1.3.5", + "stream-each": "1.2.2", + "through2": "2.0.3" + } }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -2656,6 +2775,12 @@ "minimatch": "0.3.0" } }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, "minimatch": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", @@ -2686,6 +2811,19 @@ "integrity": "sha1-4rbN65zhn5kxelNyLz2/XfXqqrI=", "dev": true }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2842,14 +2980,6 @@ "object-assign": "4.1.1" } }, - "p-all": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-all/-/p-all-1.0.0.tgz", - "integrity": "sha1-k731OlWiOCH9+pi0F0qZv38x340=", - "requires": { - "p-map": "1.2.0" - } - }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -2859,22 +2989,25 @@ "p-limit": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=" }, "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, "requires": { "p-limit": "1.1.0" } }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } }, "parse-github-repo-url": { "version": "1.4.1", @@ -2923,13 +3056,9 @@ } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", @@ -2976,6 +3105,14 @@ "pinkie": "2.0.4" } }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "2.1.0" + } + }, "pluralize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", @@ -3004,8 +3141,7 @@ "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "progress": { "version": "1.1.8", @@ -3013,11 +3149,34 @@ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.0", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", + "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "requires": { + "duplexify": "3.5.1", + "inherits": "2.0.3", + "pump": "1.0.3" + } }, "q": { "version": "1.5.1", @@ -3108,13 +3267,33 @@ "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } } }, "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -3305,7 +3484,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "7.1.2" } @@ -3319,6 +3497,14 @@ "once": "1.4.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "1.2.0" + } + }, "rx-lite": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", @@ -3328,8 +3514,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "semver": { "version": "5.4.1", @@ -3337,6 +3522,11 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "serialize-javascript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=" + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -3454,6 +3644,14 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "ssri": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.0.0.tgz", + "integrity": "sha512-728D4yoQcQm1ooZvSbywLkV1RjfITZXh0oWrhM/lnsx3nAHx7LsRGJWB/YyvoceAYRq98xqbstiN4JBv1/wNHg==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "standard-version": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-4.2.0.tgz", @@ -3469,6 +3667,20 @@ "yargs": "8.0.2" } }, + "stream-each": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "requires": { + "end-of-stream": "1.4.0", + "stream-shift": "1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -3484,7 +3696,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -3603,7 +3814,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, "requires": { "readable-stream": "2.3.3", "xtend": "4.0.1" @@ -3663,8 +3873,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-js": { "version": "2.8.29", @@ -3707,6 +3916,22 @@ "dev": true, "optional": true }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "requires": { + "imurmurhash": "0.1.4" + } + }, "user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", @@ -3716,8 +3941,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "v8flags": { "version": "2.1.1", @@ -3793,20 +4017,17 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "8.0.2", @@ -3865,15 +4086,6 @@ } } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", diff --git a/package.json b/package.json index b7646770..4ed1c76b 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,9 @@ }, "dependencies": { "globby": "^7.1.1", + "cacache": "^10.0.1", + "find-cache-dir": "^1.0.0", + "serialize-javascript": "^1.4.0", "is-glob": "^4.0.0", "loader-utils": "^0.2.15", "lodash": "^4.3.0", diff --git a/src/index.js b/src/index.js index 74dc3249..2b1f92f0 100644 --- a/src/index.js +++ b/src/index.js @@ -91,11 +91,10 @@ function CopyWebpackPlugin(patterns = [], options = {}) { patterns.forEach((pattern) => { tasks.push( - preProcessPattern(globalRef, pattern) - .then((pattern) => { - // Every source (from) is assumed to exist here - return processPattern(globalRef, pattern); - }) + Promise.resolve() + .then(() => preProcessPattern(globalRef, pattern)) + // Every source (from) is assumed to exist here + .then((pattern) => processPattern(globalRef, pattern)) ); }); diff --git a/src/writeFile.js b/src/writeFile.js index 7092062b..fcff826d 100644 --- a/src/writeFile.js +++ b/src/writeFile.js @@ -2,6 +2,10 @@ import fs from 'fs'; import pify from 'pify'; import loaderUtils from 'loader-utils'; import path from 'path'; +import cacache from 'cacache'; +import serialize from 'serialize-javascript'; +import { name, version } from '../package.json'; +import findCacheDir from 'find-cache-dir'; export default function writeFile(globalRef, pattern, file) { const {info, debug, compilation, fileDependencies, written, copyUnmodified} = globalRef; @@ -22,7 +26,42 @@ export default function writeFile(globalRef, pattern, file) { return pify(fs.readFile)(file.absoluteFrom) .then((content) => { if (pattern.transform) { - content = pattern.transform(content, file.absoluteFrom); + const transform = (content, absoluteFrom) => { + return pattern.transform(content, absoluteFrom); + }; + + if (pattern.cache) { + if (!globalRef.cacheDir) { + globalRef.cacheDir = findCacheDir({ name: 'copy-webpack-plugin' }); + } + + const cacheKey = pattern.cache.key + ? pattern.cache.key + : serialize({ + name, + version, + pattern, + content + }); + + return cacache + .get(globalRef.cacheDir, cacheKey) + .then( + (result) => JSON.parse(result.data), + () => { + return Promise + .resolve() + .then(() => transform(content, file.absoluteFrom)) + .then((content) => cacache.put( + globalRef.cacheDir, + cacheKey, + JSON.stringify(content) + ).then(() => content)); + } + ); + } + + content = transform(content, file.absoluteFrom); } return content; diff --git a/tests/index.js b/tests/index.js index f08c607a..106d5497 100644 --- a/tests/index.js +++ b/tests/index.js @@ -9,6 +9,8 @@ const CopyWebpackPlugin = require('./../dist/index'); import fs from 'fs'; import path from 'path'; import _ from 'lodash'; +import findCacheDir from 'find-cache-dir'; +import cacache from 'cacache'; const BUILD_DIR = path.join(__dirname, 'build'); const HELPER_DIR = path.join(__dirname, 'helpers'); @@ -1322,5 +1324,175 @@ describe('apply function', () => { .catch(done); }); }); + + describe('cache', () => { + const cacheDir = findCacheDir({ name: 'copy-webpack-plugin' }); + + beforeEach(() => cacache.rm.all(cacheDir)); + + it('file should be cached', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: [ + 'file.txt' + ], + expectedAssetContent: { + 'file.txt': newContent + }, + patterns: [{ + from: from, + cache: true, + transform: function(content) { + return new Promise((resolve) => { + resolve(content + 'changed!'); + }); + } + }] + }) + .then(() => { + return cacache + .ls(cacheDir) + .then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).to.have.lengthOf(1); + + cacheKeys.forEach((cacheKey) => { + const cacheEntry = new Function(`'use strict'\nreturn ${cacheKey}`)(); + + expect(cacheEntry.pattern.from).to.equal(from); + }); + }); + }) + .then(done) + .catch(done); + }); + + it('files in directory should be cached', (done) => { + const from = 'directory'; + + runEmit({ + expectedAssetKeys: [ + '.dottedfile', + 'directoryfile.txt', + 'nested/nestedfile.txt' + ], + expectedAssetContent: { + '.dottedfile': 'dottedfile contents\nchanged!', + 'directoryfile.txt': 'newchanged!', + 'nested/nestedfile.txt': 'changed!' + }, + patterns: [{ + from: from, + cache: true, + transform: function(content) { + return new Promise((resolve) => { + resolve(content + 'changed!'); + }); + } + }] + }) + .then(() => { + return cacache + .ls(cacheDir) + .then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).to.have.lengthOf(3); + + cacheKeys.forEach((cacheKey) => { + const cacheEntry = new Function(`'use strict'\nreturn ${cacheKey}`)(); + + expect(cacheEntry.pattern.from).to.equal(from); + }); + }); + }) + .then(done) + .catch(done); + }); + + it('glob should be cached', (done) => { + const from = '*.txt'; + + runEmit({ + expectedAssetKeys: [ + 'file.txt' + ], + expectedAssetContent: { + 'file.txt': 'newchanged!' + }, + patterns: [{ + from: from, + cache: true, + transform: function(content) { + return new Promise((resolve) => { + resolve(content + 'changed!'); + }); + } + }] + }) + .then(() => { + return cacache + .ls(cacheDir) + .then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).to.have.lengthOf(1); + + cacheKeys.forEach((cacheKey) => { + const cacheEntry = new Function(`'use strict'\nreturn ${cacheKey}`)(); + + expect(cacheEntry.pattern.from).to.equal(from); + }); + }); + }) + .then(done) + .catch(done); + }); + + it('file should be cached with custom cache key', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: [ + 'file.txt' + ], + expectedAssetContent: { + 'file.txt': newContent + }, + patterns: [{ + from: from, + cache: { + key: 'foobar' + }, + transform: function(content) { + return new Promise((resolve) => { + resolve(content + 'changed!'); + }); + } + }] + }) + .then(() => { + return cacache + .ls(cacheDir) + .then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).to.have.lengthOf(1); + + cacheKeys.forEach((cacheKey) => { + expect(cacheKey).to.equal('foobar'); + }); + }); + }) + .then(done) + .catch(done); + }); + + after(() => cacache.rm.all(cacheDir)); + }); }); });