Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for target path transform #284

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Expand Up @@ -60,6 +60,7 @@ Or, in case of just a `from` with the default destination, you can also use a `{
|[`ignore`](#ignore)|`{Array}`|`[]`|Globs to ignore for this pattern|
|`flatten`|`{Boolean}`|`false`|Removes all directory references and only copies file names.⚠️ If files have the same name, the result is non-deterministic|
|[`transform`](#transform)|`{Function\|Promise}`|`(content, path) => content`|Function or Promise that modifies file contents before copying|
|[`transformPath`](#transformPath)|`{Function\|Promise}`|`(targetPath, sourcePath) => path`|Function or Promise that modifies file writing path|
|[`cache`](#cache)|`{Boolean\|Object}`|`false`|Enable `transform` caching. You can use `{ cache: { key: 'my-cache-key' } }` to invalidate the cache|
|[`context`](#context)|`{String}`|`options.context \|\| compiler.options.context`|A path that determines how to interpret the `from` path|

Expand Down Expand Up @@ -234,6 +235,43 @@ and so on...
]
```

### `transformPath`

#### `{Function}`

**webpack.config.js**
```js
[
new CopyWebpackPlugin([
{
from: 'src/*.png',
to: 'dest/',
transformPath (targetPath, absolutePath) {
return 'newPath';
}
}
], options)
]
```

#### `{Promise}`

**webpack.config.js**
```js
[
new CopyWebpackPlugin([
{
from: 'src/*.png',
to: 'dest/',
transform (targePath, absolutePath) {
return Promise.resolve('newPath')
}
}
], options)
]
```


### `cache`

**webpack.config.js**
Expand Down
16 changes: 14 additions & 2 deletions src/writeFile.js
Expand Up @@ -63,8 +63,6 @@ export default function writeFile(globalRef, pattern, file) {

return content;
}).then((content) => {
const hash = loaderUtils.getHashDigest(content);

if (pattern.toType === 'template') {
info(`interpolating template '${file.webpackTo}' for '${file.relativeFrom}'`);

Expand All @@ -84,6 +82,20 @@ export default function writeFile(globalRef, pattern, file) {
}
);
}

return content;
}).then((content) => {
if (pattern.transformPath) {
return Promise.resolve(
pattern.transformPath(file.webpackTo, file.absoluteFrom)
).then((newPath) => {
file.webpackTo = newPath;
}).then(() => content);
}

return content;
}).then((content) => {
const hash = loaderUtils.getHashDigest(content);

if (!copyUnmodified &&
written[file.absoluteFrom] &&
Expand Down
124 changes: 124 additions & 0 deletions tests/index.js
Expand Up @@ -319,6 +319,57 @@ describe('apply function', () => {
.catch(done);
});

it('can transform target path of every file in glob', (done) => {
runEmit({
expectedAssetKeys: [
'/some/path/(special-*file).txt.tst',
'/some/path/binextension.bin.tst',
'/some/path/file.txt.tst',
'/some/path/file.txt.gz.tst',
'/some/path/directoryfile.txt.tst',
'/some/path/nestedfile.txt.tst',
'/some/path/noextension.tst',
'/some/path/hello.txt.tst'
],
patterns: [{
from: '**/*',
transformPath: function(targetPath, absoluteFrom) {
expect(absoluteFrom).to.have.string(HELPER_DIR);
return '/some/path/' + path.basename(targetPath) + '.tst';
}
}]
})
.then(done)
.catch(done);
});

it('can transform target path of every file in glob after applying template', (done) => {
runEmit({
expectedAssetKeys: [
'transformed/[!]/hello-d41d8c.txt',
'transformed/[special?directory]/directoryfile-22af64.txt',
'transformed/[special?directory]/(special-*file)-0bd650.txt',
'transformed/[special?directory]/nested/nestedfile-d41d8c.txt',
'transformed/binextension-d41d8c.bin',
'transformed/file-22af64.txt',
'transformed/file.txt-5b311c.gz',
'transformed/directory/directoryfile-22af64.txt',
'transformed/directory/nested/nestedfile-d41d8c.txt',
'transformed/noextension-d41d8c'
],
patterns: [{
from: '**/*',
to: 'nested/[path][name]-[hash:6].[ext]',
transformPath: function(targetPath, absoluteFrom) {
expect(absoluteFrom).to.have.string(HELPER_DIR);
return targetPath.replace('nested/', 'transformed/');
}
}]
})
.then(done)
.catch(done);
});

it('can use a glob to move multiple files in a different relative context to a non-root directory', (done) => {
runEmit({
expectedAssetKeys: [
Expand Down Expand Up @@ -539,6 +590,23 @@ describe('apply function', () => {
.catch(done);
});

it('can transform target path', (done) => {
runEmit({
expectedAssetKeys: [
'subdir/test.txt'
],
patterns: [{
from: 'file.txt',
transformPath: function(targetPath, absoluteFrom) {
expect(absoluteFrom).to.equal(path.join(HELPER_DIR, 'file.txt'));
return targetPath.replace('file.txt', 'subdir/test.txt');
}
}]
})
.then(done)
.catch(done);
});

it('warns when file not found', (done) => {
runEmit({
expectedAssetKeys: [],
Expand Down Expand Up @@ -570,6 +638,23 @@ describe('apply function', () => {
.catch(done);
});

it('warns when tranformPath failed', (done) => {
runEmit({
expectedAssetKeys: [],
expectedErrors: [
'a failure happened'
],
patterns: [{
from: 'file.txt',
transformPath: function() {
throw 'a failure happened';
}
}]
})
.then(done)
.catch(done);
});

it('can use an absolute path to move a file to the root directory', (done) => {
const absolutePath = path.resolve(HELPER_DIR, 'file.txt');

Expand Down Expand Up @@ -987,6 +1072,26 @@ describe('apply function', () => {
.catch(done);
});

it('transformPath with promise', (done) => {
runEmit({
expectedAssetKeys: [
'/some/path/file.txt'
],
patterns: [{
from: 'file.txt',
transformPath: function(targetPath, absoluteFrom) {
expect(absoluteFrom).to.have.string(HELPER_DIR);

return new Promise((resolve) => {
resolve('/some/path/' + path.basename(targetPath));
});
}
}]
})
.then(done)
.catch(done);
});

it('same file to multiple targets', (done) => {
runEmit({
expectedAssetKeys: [
Expand Down Expand Up @@ -1022,6 +1127,25 @@ describe('apply function', () => {
.catch(done);
});

it('can transform target path of every file in directory', (done) => {
runEmit({
expectedAssetKeys: [
'/some/path/.dottedfile',
'/some/path/directoryfile.txt',
'/some/path/nestedfile.txt'
],
patterns: [{
from: 'directory',
transformPath: function(targetPath, absoluteFrom) {
expect(absoluteFrom).to.have.string(path.join(HELPER_DIR, 'directory'));
return '/some/path/' + path.basename(targetPath);
}
}]
})
.then(done)
.catch(done);
});

it('can move a directory\'s contents to the root directory using from with special characters', (done) => {
runEmit({
expectedAssetKeys: [
Expand Down