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));
+ });
});
});