Skip to content

Commit 3ef5b6c

Browse files
lovekyevilebottnawi
authored andcommitted
fix: allow square brackets in path (#264)
* fix #231 allow brackets in path * only need take care of [ * use character sets to escape special character to avoid issue on Windows * [fix 220] create special directory/file through scripts * rm helpers directory on every test * add new line to the end of scripts * update code, add tests
1 parent c779a30 commit 3ef5b6c

File tree

9 files changed

+78
-15
lines changed

9 files changed

+78
-15
lines changed

package-lock.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"pretest": "npm run lint && npm run build && npm run build:tests",
1919
"test": "mocha compiled_tests/",
2020
"build": "babel src/ --out-dir dist/",
21-
"build:tests": "babel tests/ --out-dir compiled_tests/ && ncp tests/helpers compiled_tests/helpers"
21+
"build:tests": "babel tests/ --out-dir compiled_tests/ && rimraf compiled_tests/helpers && ncp tests/helpers compiled_tests/helpers && node scripts/createSpecialDirectory.js"
2222
},
2323
"dependencies": {
2424
"globby": "^7.1.1",
@@ -34,12 +34,14 @@
3434
"babel-cli": "^6.8.0",
3535
"babel-preset-es2015": "^6.6.0",
3636
"chai": "^3.4.0",
37-
"eslint": "^2.9.0",
3837
"enhanced-resolve": "^3.4.1",
38+
"eslint": "^2.9.0",
39+
"is-gzip": "^2.0.0",
40+
"mkdirp": "^0.5.1",
3941
"mocha": "^2.4.5",
4042
"ncp": "^2.0.0",
41-
"standard-version": "^4.2.0",
42-
"is-gzip": "^2.0.0"
43+
"rimraf": "^2.6.2",
44+
"standard-version": "^4.2.0"
4345
},
4446
"homepage": "https://github.com/webpack-contrib/copy-webpack-plugin",
4547
"bugs": "https://github.com/webpack-contrib/copy-webpack-plugin/issues",

scripts/createSpecialDirectory.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const mkdirp = require('mkdirp');
2+
const path = require('path');
3+
const fs = require('fs');
4+
const removeIllegalCharacterForWindows = require('../tests/utils/removeIllegalCharacterForWindows');
5+
6+
const baseDir = 'compiled_tests/helpers';
7+
8+
const specialFiles = {
9+
'[special?directory]/nested/nestedfile.txt': '',
10+
'[special?directory]/(special-*file).txt': 'special',
11+
'[special?directory]/directoryfile.txt': 'new'
12+
};
13+
14+
Object.keys(specialFiles).forEach(function (originFile) {
15+
const file = removeIllegalCharacterForWindows(originFile);
16+
const dir = path.dirname(file);
17+
mkdirp.sync(path.join(baseDir, dir));
18+
fs.writeFileSync(path.join(baseDir, file), specialFiles[originFile]);
19+
});
20+

src/utils/escape.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ export default function escape(context, from) {
77
// Ensure context is escaped before globbing
88
// Handles special characters in paths
99
const absoluteContext = path.resolve(context)
10-
.replace(/\\/, '/')
11-
.replace(/[\*|\?|\!|\(|\)|\[|\]|\{|\}]/g, (substring) => `\\${substring}`);
10+
.replace(/[\*|\?|\!|\(|\)|\[|\]|\{|\}]/g, (substring) => `[${substring}]`);
1211

1312
if (!from) {
1413
return absoluteContext;

tests/helpers/[special?directory]/(special-*file).txt

-1
This file was deleted.

tests/helpers/[special?directory]/directoryfile.txt

-1
This file was deleted.

tests/index.js

+44-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import cacache from 'cacache';
1515
import isGzip from 'is-gzip';
1616
import zlib from 'zlib';
1717

18+
import removeIllegalCharacterForWindows from './utils/removeIllegalCharacterForWindows';
19+
1820
const BUILD_DIR = path.join(__dirname, 'build');
1921
const HELPER_DIR = path.join(__dirname, 'helpers');
2022
const TEMP_DIR = path.join(__dirname, 'tempdir');
@@ -58,6 +60,13 @@ describe('apply function', () => {
5860
// Ideally we pass in patterns and confirm the resulting assets
5961
const run = (opts) => {
6062
return new Promise((resolve, reject) => {
63+
if (Array.isArray(opts.patterns)) {
64+
opts.patterns.forEach(function (pattern) {
65+
if (pattern.context) {
66+
pattern.context = removeIllegalCharacterForWindows(pattern.context);
67+
}
68+
});
69+
}
6170
const plugin = CopyWebpackPlugin(opts.patterns, opts.options);
6271

6372
// Get a mock compiler to pass to plugin.apply
@@ -109,7 +118,7 @@ describe('apply function', () => {
109118
return run(opts)
110119
.then((compilation) => {
111120
if (opts.expectedAssetKeys && opts.expectedAssetKeys.length > 0) {
112-
expect(compilation.assets).to.have.all.keys(opts.expectedAssetKeys);
121+
expect(compilation.assets).to.have.all.keys(opts.expectedAssetKeys.map(removeIllegalCharacterForWindows));
113122
} else {
114123
expect(compilation.assets).to.deep.equal({});
115124
}
@@ -268,6 +277,7 @@ describe('apply function', () => {
268277
it('can use a glob to move multiple files to the root directory', (done) => {
269278
runEmit({
270279
expectedAssetKeys: [
280+
'[!]/hello.txt',
271281
'binextension.bin',
272282
'file.txt',
273283
'file.txt.gz',
@@ -289,6 +299,7 @@ describe('apply function', () => {
289299
it('can use a glob to move multiple files to a non-root directory', (done) => {
290300
runEmit({
291301
expectedAssetKeys: [
302+
'nested/[!]/hello.txt',
292303
'nested/binextension.bin',
293304
'nested/file.txt',
294305
'nested/file.txt.gz',
@@ -405,6 +416,7 @@ describe('apply function', () => {
405416
it('can use a glob with a full path to move multiple files to the root directory', (done) => {
406417
runEmit({
407418
expectedAssetKeys: [
419+
'[!]/hello.txt',
408420
'file.txt',
409421
'directory/directoryfile.txt',
410422
'directory/nested/nestedfile.txt',
@@ -423,6 +435,7 @@ describe('apply function', () => {
423435
it('can use a glob to move multiple files to a non-root directory with name, hash and ext', (done) => {
424436
runEmit({
425437
expectedAssetKeys: [
438+
'nested/[!]/hello-d41d8c.txt',
426439
'nested/binextension-d41d8c.bin',
427440
'nested/file-22af64.txt',
428441
'nested/file.txt-5b311c.gz',
@@ -445,13 +458,14 @@ describe('apply function', () => {
445458
it('can flatten or normalize glob matches', (done) => {
446459
runEmit({
447460
expectedAssetKeys: [
461+
'[!]-hello.txt',
448462
'[special?directory]-(special-*file).txt',
449463
'[special?directory]-directoryfile.txt',
450464
'directory-directoryfile.txt'
451465
],
452466
patterns: [{
453467
from: '*/*.*',
454-
test: /([^\/]+)\/([^\/]+)\.\w+$/,
468+
test: `([^\\${path.sep}]+)\\${path.sep}([^\\${path.sep}]+)\\.\\w+$`,
455469
to: '[1]-[2].[ext]'
456470
}]
457471
})
@@ -887,6 +901,7 @@ describe('apply function', () => {
887901
it('ignores files in pattern', (done) => {
888902
runEmit({
889903
expectedAssetKeys: [
904+
'[!]/hello.txt',
890905
'binextension.bin',
891906
'directory/directoryfile.txt',
892907
'directory/nested/nestedfile.txt',
@@ -984,7 +999,7 @@ describe('apply function', () => {
984999
'nested/nestedfile.txt'
9851000
],
9861001
patterns: [{
987-
from: '[special?directory]'
1002+
from: (path.sep === '/' ? '[special?directory]' : '[specialdirectory]')
9881003
}]
9891004
})
9901005
.then(done)
@@ -1324,6 +1339,7 @@ describe('apply function', () => {
13241339
it('ignores files that start with a dot', (done) => {
13251340
runEmit({
13261341
expectedAssetKeys: [
1342+
'[!]/hello.txt',
13271343
'binextension.bin',
13281344
'file.txt',
13291345
'file.txt.gz',
@@ -1384,13 +1400,14 @@ describe('apply function', () => {
13841400
it('ignores nested directory', (done) => {
13851401
runEmit({
13861402
expectedAssetKeys: [
1403+
'[!]/hello.txt',
13871404
'binextension.bin',
13881405
'file.txt',
13891406
'file.txt.gz',
13901407
'noextension'
13911408
],
13921409
options: {
1393-
ignore: ['directory/**/*', '\\[special\\?directory\\]/**/*']
1410+
ignore: ['directory/**/*', `[[]special${process.platform === 'win32' ? '' : '[?]'}directory]/**/*`]
13941411
},
13951412
patterns: [{
13961413
from: '.'
@@ -1401,6 +1418,29 @@ describe('apply function', () => {
14011418
.catch(done);
14021419
});
14031420

1421+
if (path.sep === '/') {
1422+
it('ignores nested directory(can use "\\" to escape if path.sep is "/")', (done) => {
1423+
runEmit({
1424+
expectedAssetKeys: [
1425+
'[!]/hello.txt',
1426+
'binextension.bin',
1427+
'file.txt',
1428+
'file.txt.gz',
1429+
'noextension'
1430+
],
1431+
options: {
1432+
ignore: ['directory/**/*', '\\[special\\?directory\\]/**/*']
1433+
},
1434+
patterns: [{
1435+
from: '.'
1436+
}]
1437+
1438+
})
1439+
.then(done)
1440+
.catch(done);
1441+
});
1442+
}
1443+
14041444
it('ignores nested directory (glob)', (done) => {
14051445
runEmit({
14061446
expectedAssetKeys: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = function (string) {
2+
return process.platform !== 'win32' ? string : string.replace(/[*?"<>|]/g, '');
3+
};
4+

0 commit comments

Comments
 (0)