Skip to content

Commit aedd2bd

Browse files
authoredApr 28, 2020
refactor: plugin options (#451)
BREAKING CHANGE: the plugin now accepts an object as options, you should change `new CopyPlugin(patterns, options)` to `new CopyPlugin( { patterns, options })`
1 parent 383ff9d commit aedd2bd

File tree

6 files changed

+291
-159
lines changed

6 files changed

+291
-159
lines changed
 

‎README.md

+201-143
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ const CopyPlugin = require('copy-webpack-plugin');
3434

3535
module.exports = {
3636
plugins: [
37-
new CopyPlugin([
38-
{ from: 'source', to: 'dest' },
39-
{ from: 'other', to: 'public' },
40-
]),
37+
new CopyPlugin({
38+
patterns: [
39+
{ from: 'source', to: 'dest' },
40+
{ from: 'other', to: 'public' },
41+
],
42+
}),
4143
],
4244
};
4345
```
@@ -53,8 +55,20 @@ The plugin's signature:
5355
**webpack.config.js**
5456

5557
```js
58+
const CopyPlugin = require('copy-webpack-plugin');
59+
5660
module.exports = {
57-
plugins: [new CopyPlugin(patterns, options)],
61+
plugins: [
62+
new CopyPlugin({
63+
patterns: [
64+
{ from: 'source', to: 'dest' },
65+
{ from: 'other', to: 'public' },
66+
],
67+
options: {
68+
ignore: ['*.bin'],
69+
},
70+
}),
71+
],
5872
};
5973
```
6074

@@ -92,16 +106,18 @@ Globs accept [minimatch options](https://github.com/isaacs/minimatch).
92106
```js
93107
module.exports = {
94108
plugins: [
95-
new CopyPlugin([
96-
'relative/path/to/file.ext',
97-
'/absolute/path/to/file.ext',
98-
'relative/path/to/dir',
99-
'/absolute/path/to/dir',
100-
'**/*',
101-
{
102-
from: '**/*',
103-
},
104-
]),
109+
new CopyPlugin({
110+
patterns: [
111+
'relative/path/to/file.ext',
112+
'/absolute/path/to/file.ext',
113+
'relative/path/to/dir',
114+
'/absolute/path/to/dir',
115+
'**/*',
116+
{
117+
from: '**/*',
118+
},
119+
],
120+
}),
105121
],
106122
};
107123
```
@@ -122,20 +138,22 @@ Output path.
122138
```js
123139
module.exports = {
124140
plugins: [
125-
new CopyPlugin([
126-
{
127-
from: '**/*',
128-
to: 'relative/path/to/dest/',
129-
},
130-
{
131-
from: '**/*',
132-
to: '/absolute/path/to/dest/',
133-
},
134-
{
135-
from: '**/*',
136-
to: '[path][name].[contenthash].[ext]',
137-
},
138-
]),
141+
new CopyPlugin({
142+
patterns: [
143+
{
144+
from: '**/*',
145+
to: 'relative/path/to/dest/',
146+
},
147+
{
148+
from: '**/*',
149+
to: '/absolute/path/to/dest/',
150+
},
151+
{
152+
from: '**/*',
153+
to: '[path][name].[contenthash].[ext]',
154+
},
155+
],
156+
}),
139157
],
140158
};
141159
```
@@ -156,13 +174,15 @@ A path that determines how to interpret the `from` path.
156174
```js
157175
module.exports = {
158176
plugins: [
159-
new CopyPlugin([
160-
{
161-
from: 'src/*.txt',
162-
to: 'dest/',
163-
context: 'app/',
164-
},
165-
]),
177+
new CopyPlugin({
178+
patterns: [
179+
{
180+
from: 'src/*.txt',
181+
to: 'dest/',
182+
context: 'app/',
183+
},
184+
],
185+
}),
166186
],
167187
};
168188
```
@@ -190,13 +210,15 @@ We try to automatically determine the `type` so you most likely do not need this
190210
```js
191211
module.exports = {
192212
plugins: [
193-
new CopyPlugin([
194-
{
195-
from: 'path/to/file.txt',
196-
to: 'directory/with/extension.ext',
197-
toType: 'dir',
198-
},
199-
]),
213+
new CopyPlugin({
214+
patterns: [
215+
{
216+
from: 'path/to/file.txt',
217+
to: 'directory/with/extension.ext',
218+
toType: 'dir',
219+
},
220+
],
221+
}),
200222
],
201223
};
202224
```
@@ -208,13 +230,15 @@ module.exports = {
208230
```js
209231
module.exports = {
210232
plugins: [
211-
new CopyPlugin([
212-
{
213-
from: 'path/to/file.txt',
214-
to: 'file/without/extension',
215-
toType: 'file',
216-
},
217-
]),
233+
new CopyPlugin({
234+
patterns: [
235+
{
236+
from: 'path/to/file.txt',
237+
to: 'file/without/extension',
238+
toType: 'file',
239+
},
240+
],
241+
}),
218242
],
219243
};
220244
```
@@ -226,13 +250,15 @@ module.exports = {
226250
```js
227251
module.exports = {
228252
plugins: [
229-
new CopyPlugin([
230-
{
231-
from: 'src/',
232-
to: 'dest/[name].[hash].[ext]',
233-
toType: 'template',
234-
},
235-
]),
253+
new CopyPlugin({
254+
patterns: [
255+
{
256+
from: 'src/',
257+
to: 'dest/[name].[hash].[ext]',
258+
toType: 'template',
259+
},
260+
],
261+
}),
236262
],
237263
};
238264
```
@@ -255,13 +281,15 @@ and so on...
255281
```js
256282
module.exports = {
257283
plugins: [
258-
new CopyPlugin([
259-
{
260-
from: '*/*',
261-
to: '[1]-[2].[hash].[ext]',
262-
test: /([^/]+)\/(.+)\.png$/,
263-
},
264-
]),
284+
new CopyPlugin({
285+
patterns: [
286+
{
287+
from: '*/*',
288+
to: '[1]-[2].[hash].[ext]',
289+
test: /([^/]+)\/(.+)\.png$/,
290+
},
291+
],
292+
}),
265293
],
266294
};
267295
```
@@ -278,13 +306,15 @@ Overwrites files already in `compilation.assets` (usually added by other plugins
278306
```js
279307
module.exports = {
280308
plugins: [
281-
new CopyPlugin([
282-
{
283-
from: 'src/**/*',
284-
to: 'dest/',
285-
force: true,
286-
},
287-
]),
309+
new CopyPlugin({
310+
patterns: [
311+
{
312+
from: 'src/**/*',
313+
to: 'dest/',
314+
force: true,
315+
},
316+
],
317+
}),
288318
],
289319
};
290320
```
@@ -301,13 +331,15 @@ Globs to ignore files.
301331
```js
302332
module.exports = {
303333
plugins: [
304-
new CopyPlugin([
305-
{
306-
from: 'src/**/*',
307-
to: 'dest/',
308-
ignore: ['*.js'],
309-
},
310-
]),
334+
new CopyPlugin({
335+
patterns: [
336+
{
337+
from: 'src/**/*',
338+
to: 'dest/',
339+
ignore: ['*.js'],
340+
},
341+
],
342+
}),
311343
],
312344
};
313345
```
@@ -319,13 +351,15 @@ module.exports = {
319351
```js
320352
module.exports = {
321353
plugins: [
322-
new CopyPlugin([
323-
{
324-
from: 'src/assets',
325-
to: 'dest/',
326-
ignore: ['subfolder/ignorefile.js'],
327-
},
328-
]),
354+
new CopyPlugin({
355+
patterns: [
356+
{
357+
from: 'src/assets',
358+
to: 'dest/',
359+
ignore: ['subfolder/ignorefile.js'],
360+
},
361+
],
362+
}),
329363
],
330364
};
331365
```
@@ -344,13 +378,15 @@ Removes all directory references and only copies file names.
344378
```js
345379
module.exports = {
346380
plugins: [
347-
new CopyPlugin([
348-
{
349-
from: 'src/**/*',
350-
to: 'dest/',
351-
flatten: true,
352-
},
353-
]),
381+
new CopyPlugin({
382+
patterns: [
383+
{
384+
from: 'src/**/*',
385+
to: 'dest/',
386+
flatten: true,
387+
},
388+
],
389+
}),
354390
],
355391
};
356392
```
@@ -368,16 +404,18 @@ Default path to cache directory: `node_modules/.cache/copy-webpack-plugin`.
368404
```js
369405
module.exports = {
370406
plugins: [
371-
new CopyPlugin([
372-
{
373-
from: 'src/*.png',
374-
to: 'dest/',
375-
transform(content, path) {
376-
return optimize(content);
407+
new CopyPlugin({
408+
patterns: [
409+
{
410+
from: 'src/*.png',
411+
to: 'dest/',
412+
transform(content, path) {
413+
return optimize(content);
414+
},
415+
cache: true,
377416
},
378-
cache: true,
379-
},
380-
]),
417+
],
418+
}),
381419
],
382420
};
383421
```
@@ -394,15 +432,17 @@ Allows to modify the file contents.
394432
```js
395433
module.exports = {
396434
plugins: [
397-
new CopyPlugin([
398-
{
399-
from: 'src/*.png',
400-
to: 'dest/',
401-
transform(content, path) {
402-
return optimize(content);
435+
new CopyPlugin({
436+
patterns: [
437+
{
438+
from: 'src/*.png',
439+
to: 'dest/',
440+
transform(content, path) {
441+
return optimize(content);
442+
},
403443
},
404-
},
405-
]),
444+
],
445+
}),
406446
],
407447
};
408448
```
@@ -412,15 +452,17 @@ module.exports = {
412452
```js
413453
module.exports = {
414454
plugins: [
415-
new CopyPlugin([
416-
{
417-
from: 'src/*.png',
418-
to: 'dest/',
419-
transform(content, path) {
420-
return Promise.resolve(optimize(content));
455+
new CopyPlugin({
456+
patterns: [
457+
{
458+
from: 'src/*.png',
459+
to: 'dest/',
460+
transform(content, path) {
461+
return Promise.resolve(optimize(content));
462+
},
421463
},
422-
},
423-
]),
464+
],
465+
}),
424466
],
425467
};
426468
```
@@ -441,15 +483,17 @@ Allows to modify the writing path.
441483
```js
442484
module.exports = {
443485
plugins: [
444-
new CopyPlugin([
445-
{
446-
from: 'src/*.png',
447-
to: 'dest/',
448-
transformPath(targetPath, absolutePath) {
449-
return 'newPath';
486+
new CopyPlugin({
487+
patterns: [
488+
{
489+
from: 'src/*.png',
490+
to: 'dest/',
491+
transformPath(targetPath, absolutePath) {
492+
return 'newPath';
493+
},
450494
},
451-
},
452-
]),
495+
],
496+
}),
453497
],
454498
};
455499
```
@@ -459,15 +503,17 @@ module.exports = {
459503
```js
460504
module.exports = {
461505
plugins: [
462-
new CopyPlugin([
463-
{
464-
from: 'src/*.png',
465-
to: 'dest/',
466-
transformPath(targetPath, absolutePath) {
467-
return Promise.resolve('newPath');
506+
new CopyPlugin({
507+
patterns: [
508+
{
509+
from: 'src/*.png',
510+
to: 'dest/',
511+
transformPath(targetPath, absolutePath) {
512+
return Promise.resolve('newPath');
513+
},
468514
},
469-
},
470-
]),
515+
],
516+
}),
471517
],
472518
};
473519
```
@@ -484,15 +530,17 @@ Allows to configute the glob pattern matching library used by the plugin. [See t
484530
```js
485531
module.exports = {
486532
plugins: [
487-
new CopyPlugin([
488-
{
489-
from: 'public/**/*',
490-
globOptions: {
491-
dot: true,
492-
gitignore: true,
533+
new CopyPlugin({
534+
patterns: [
535+
{
536+
from: 'public/**/*',
537+
globOptions: {
538+
dot: true,
539+
gitignore: true,
540+
},
493541
},
494-
},
495-
]),
542+
],
543+
}),
496544
],
497545
};
498546
```
@@ -512,7 +560,12 @@ Array of globs to ignore (applied to `from`).
512560

513561
```js
514562
module.exports = {
515-
plugins: [new CopyPlugin([...patterns], { ignore: ['*.js', '*.css'] })],
563+
plugins: [
564+
new CopyPlugin({
565+
patterns: [...patterns],
566+
options: { ignore: ['*.js', '*.css'] },
567+
}),
568+
],
516569
};
517570
```
518571

@@ -524,7 +577,12 @@ A path that determines how to interpret the `from` path, shared for all patterns
524577

525578
```js
526579
module.exports = {
527-
plugins: [new CopyPlugin([...patterns], { context: '/app' })],
580+
plugins: [
581+
new CopyPlugin({
582+
patterns: [...patterns],
583+
options: { context: '/app' },
584+
}),
585+
],
528586
};
529587
```
530588

‎src/index.js

+8-9
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ import processPattern from './processPattern';
88
import postProcessPattern from './postProcessPattern';
99

1010
class CopyPlugin {
11-
constructor(patterns = [], options = {}) {
12-
validateOptions(
13-
schema,
14-
{ patterns, options },
15-
{ name: 'Copy Plugin', baseDataPath: 'options' }
16-
);
17-
18-
this.patterns = patterns;
19-
this.options = options;
11+
constructor(options = {}) {
12+
validateOptions(schema, options, {
13+
name: 'Copy Plugin',
14+
baseDataPath: 'options',
15+
});
16+
17+
this.patterns = options.patterns;
18+
this.options = options.options || {};
2019
}
2120

2221
apply(compiler) {

‎src/options.json

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"properties": {
7575
"patterns": {
7676
"type": "array",
77+
"minItems": 1,
7778
"items": {
7879
"anyOf": [
7980
{

‎test/__snapshots__/validate-options.test.js.snap

+68-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`validate options should throw an error on the "options" option with "{"context":true}" value 1`] = `
4+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
5+
- options.options.context should be a string."
6+
`;
7+
8+
exports[`validate options should throw an error on the "options" option with "{"ignore":true}" value 1`] = `
9+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
10+
- options.options.ignore should be an array:
11+
[any, ...]"
12+
`;
13+
314
exports[`validate options should throw an error on the "patterns" option with "" value 1`] = `
415
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
516
- options.patterns should be an array:
6-
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...]"
17+
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...] (should not have fewer than 1 item)"
718
`;
819
920
exports[`validate options should throw an error on the "patterns" option with "[""]" value 1`] = `
1021
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
1122
- options.patterns[0] should be an non-empty string."
1223
`;
1324
25+
exports[`validate options should throw an error on the "patterns" option with "[]" value 1`] = `
26+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
27+
- options.patterns should be an non-empty array."
28+
`;
29+
1430
exports[`validate options should throw an error on the "patterns" option with "[{"from":"","to":"dir","context":"context"}]" value 1`] = `
1531
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
1632
- options.patterns[0].from should be an non-empty string."
@@ -128,17 +144,65 @@ exports[`validate options should throw an error on the "patterns" option with "[
128144
exports[`validate options should throw an error on the "patterns" option with "{}" value 1`] = `
129145
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
130146
- options.patterns should be an array:
131-
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...]"
147+
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...] (should not have fewer than 1 item)"
132148
`;
133149
134150
exports[`validate options should throw an error on the "patterns" option with "true" value 1`] = `
135151
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
136152
- options.patterns should be an array:
137-
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...]"
153+
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...] (should not have fewer than 1 item)"
138154
`;
139155
140156
exports[`validate options should throw an error on the "patterns" option with "true" value 2`] = `
141157
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
142158
- options.patterns should be an array:
143-
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...]"
159+
[non-empty string | object { from, to?, context?, toType?, test?, force?, ignore?, flatten?, cache?, transform?, transformPath?, … }, ...] (should not have fewer than 1 item)"
160+
`;
161+
162+
exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = `
163+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
164+
- options has an unknown property 'unknown'. These properties are valid:
165+
object { patterns?, options? }"
166+
`;
167+
168+
exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = `
169+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
170+
- options has an unknown property 'unknown'. These properties are valid:
171+
object { patterns?, options? }"
172+
`;
173+
174+
exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = `
175+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
176+
- options has an unknown property 'unknown'. These properties are valid:
177+
object { patterns?, options? }"
178+
`;
179+
180+
exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = `
181+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
182+
- options has an unknown property 'unknown'. These properties are valid:
183+
object { patterns?, options? }"
184+
`;
185+
186+
exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = `
187+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
188+
- options has an unknown property 'unknown'. These properties are valid:
189+
object { patterns?, options? }"
190+
`;
191+
192+
exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = `
193+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
194+
- options has an unknown property 'unknown'. These properties are valid:
195+
object { patterns?, options? }"
196+
`;
197+
198+
exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = `
199+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
200+
- options has an unknown property 'unknown'. These properties are valid:
201+
object { patterns?, options? }"
202+
`;
203+
204+
exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = `
205+
"Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
206+
- options has an unknown property 'unknown'. These properties are valid:
207+
object { patterns?, options? }"
144208
`;

‎test/helpers/run.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ function run(opts) {
4242
);
4343
}
4444

45-
new CopyPlugin(opts.patterns, opts.options).apply(compiler);
45+
new CopyPlugin({ patterns: opts.patterns, options: opts.options }).apply(
46+
compiler
47+
);
4648

4749
// Call the registered function with a mock compilation and callback
4850
const compilation = Object.assign(

‎test/validate-options.test.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ describe('validate options', () => {
2020
const tests = {
2121
patterns: {
2222
success: [
23-
[],
2423
['test.txt'],
2524
['test.txt', 'test-other.txt'],
2625
[
@@ -112,6 +111,7 @@ describe('validate options', () => {
112111
'true',
113112
'',
114113
{},
114+
[],
115115
[''],
116116
[{}],
117117
[
@@ -234,6 +234,14 @@ describe('validate options', () => {
234234
],
235235
],
236236
},
237+
options: {
238+
success: [{ context: 'context' }, { ignore: ['test'] }],
239+
failure: [{ context: true }, { ignore: true }],
240+
},
241+
unknown: {
242+
success: [],
243+
failure: [1, true, false, 'test', /test/, [], {}, { foo: 'bar' }],
244+
},
237245
};
238246

239247
function stringifyValue(value) {
@@ -255,7 +263,7 @@ describe('validate options', () => {
255263

256264
try {
257265
// eslint-disable-next-line no-new
258-
new CopyPlugin(key === 'patterns' ? value : { [key]: value });
266+
new CopyPlugin({ [key]: value });
259267
} catch (errorFromPlugin) {
260268
if (errorFromPlugin.name !== 'ValidationError') {
261269
throw errorFromPlugin;

0 commit comments

Comments
 (0)
Please sign in to comment.