Skip to content

Commit

Permalink
refactor: code
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the missing file error is now an error
  • Loading branch information
evilebottnawi committed May 15, 2020
1 parent e3803ce commit bebafcf
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 146 deletions.
4 changes: 2 additions & 2 deletions src/index.js
Expand Up @@ -27,7 +27,7 @@ class CopyPlugin {
compilation.hooks.additionalAssets.tapAsync(
'copy-webpack-plugin',
async (callback) => {
logger.debug('start to adding additionalAssets');
logger.debug('start to adding additional assets');

const globalRef = {
context: compiler.options.context,
Expand Down Expand Up @@ -70,7 +70,7 @@ class CopyPlugin {
)
);

logger.debug('end to adding additionalAssets');
logger.debug('end to adding additional assets');

callback();
} catch (error) {
Expand Down
21 changes: 9 additions & 12 deletions src/postProcessPattern.js
Expand Up @@ -43,6 +43,7 @@ export default async function postProcessPattern(globalRef, pattern, file) {
// If this came from a glob, add it to the file watchlist
if (pattern.fromType === 'glob') {
logger.debug(`add ${file.absoluteFrom} as fileDependencies`);

compilation.fileDependencies.add(file.absoluteFrom);
}

Expand All @@ -54,16 +55,13 @@ export default async function postProcessPattern(globalRef, pattern, file) {
content = await readFile(inputFileSystem, file.absoluteFrom);
} catch (error) {
compilation.errors.push(error);

return;
}

if (pattern.transform) {
logger.log(`transforming content for '${file.absoluteFrom}'`);

// eslint-disable-next-line no-shadow
const transform = (content, absoluteFrom) =>
pattern.transform(content, absoluteFrom);

if (pattern.cacheTransform) {
if (!globalRef.cacheDir) {
globalRef.cacheDir =
Expand All @@ -87,8 +85,8 @@ export default async function postProcessPattern(globalRef, pattern, file) {
);

content = result.data;
} catch (e) {
content = await transform(content, file.absoluteFrom);
} catch (_ignoreError) {
content = await pattern.transform(content, file.absoluteFrom);

logger.debug(`caching transformation for '${file.absoluteFrom}'`);

Expand All @@ -97,7 +95,7 @@ export default async function postProcessPattern(globalRef, pattern, file) {
.then(() => content);
}
} else {
content = await transform(content, file.absoluteFrom);
content = await pattern.transform(content, file.absoluteFrom);
}
}

Expand All @@ -109,7 +107,7 @@ export default async function postProcessPattern(globalRef, pattern, file) {
// If it doesn't have an extension, remove it from the pattern
// ie. [name].[ext] or [name][ext] both become [name]
if (!path.extname(file.relativeFrom)) {
file.webpackTo = file.webpackTo.replace(/\.?\[ext\]/g, '');
file.webpackTo = file.webpackTo.replace(/\.?\[ext]/g, '');
}

file.webpackTo = loaderUtils.interpolateName(
Expand Down Expand Up @@ -137,13 +135,10 @@ export default async function postProcessPattern(globalRef, pattern, file) {
}

const targetPath = normalizePath(file.webpackTo);

const source = new RawSource(content);

const hasAssetsAPI = typeof compilation.emitAsset === 'function';

// For old version webpack 4
if (!hasAssetsAPI) {
if (typeof compilation.emitAsset !== 'function') {
compilation.assets[targetPath] = source;

return;
Expand All @@ -156,10 +151,12 @@ export default async function postProcessPattern(globalRef, pattern, file) {
);

compilation.updateAsset(targetPath, source);

return;
}

logger.log(`skipping '${file.webpackTo}', because it already exists`);

return;
}

Expand Down
39 changes: 15 additions & 24 deletions src/preProcessPattern.js
Expand Up @@ -8,31 +8,25 @@ import { stat } from './utils/promisify';
export default async function preProcessPattern(globalRef, pattern) {
const { context, logger, inputFileSystem } = globalRef;

pattern =
typeof pattern === 'string'
? { from: pattern }
: Object.assign({}, pattern);

pattern.to = pattern.to || '';
pattern.context = pattern.context || context;

if (!path.isAbsolute(pattern.context)) {
pattern.context = path.join(context, pattern.context);
}

pattern.noErrorOnMissing = pattern.noErrorOnMissing || false;

// Todo remove this in next major
const isToDirectory =
path.extname(pattern.to) === '' || pattern.to.slice(-1) === path.sep;

pattern = typeof pattern === 'string' ? { from: pattern } : { ...pattern };
pattern.fromOrigin = pattern.from;
pattern.from = path.normalize(pattern.from);
pattern.context = path.normalize(pattern.context);
pattern.to = path.normalize(pattern.to);
pattern.to = path.normalize(
typeof pattern.to !== 'undefined' ? pattern.to : ''
);
pattern.context = path.normalize(
typeof pattern.context !== 'undefined'
? !path.isAbsolute(pattern.context)
? path.join(context, pattern.context)
: pattern.context
: context
);

logger.debug(`processing from: '${pattern.from}' to: '${pattern.to}'`);

const isToDirectory =
path.extname(pattern.to) === '' || pattern.to.slice(-1) === path.sep;

switch (true) {
// if toType already exists
case !!pattern.toType:
Expand Down Expand Up @@ -67,10 +61,7 @@ export default async function preProcessPattern(globalRef, pattern) {

if (stats.isDirectory()) {
pattern.fromType = 'dir';
return pattern;
}

if (stats.isFile()) {
} else if (stats.isFile()) {
pattern.fromType = 'file';
pattern.stats = stats;
}
Expand Down
15 changes: 3 additions & 12 deletions src/processPattern.js
Expand Up @@ -4,8 +4,6 @@ import globby from 'globby';

import createPatternGlob from './utils/createPatternGlob';

/* eslint-disable no-param-reassign */

export default async function processPattern(globalRef, pattern) {
const { logger, output, compilation } = globalRef;

Expand All @@ -22,20 +20,13 @@ export default async function processPattern(globalRef, pattern) {
return Promise.resolve();
}

const newWarning = new Error(
const missingError = new Error(
`unable to locate '${pattern.from}' at '${pattern.absoluteFrom}'`
);
const hasWarning = compilation.warnings.some(
// eslint-disable-next-line no-shadow
(warning) => warning.message === newWarning.message
);

// Only display the same message once
if (!hasWarning) {
logger.warn(newWarning.message);
logger.error(missingError.message);

compilation.warnings.push(newWarning);
}
compilation.errors.push(missingError);

return Promise.resolve();
}
Expand Down
7 changes: 3 additions & 4 deletions src/utils/createPatternGlob.js
Expand Up @@ -62,11 +62,9 @@ function createPatternGlob(pattern, globalRef) {
/* eslint-enable no-param-reassign */

break;

default:
default: {
logger.debug(`determined '${pattern.absoluteFrom}' is a glob`);

// eslint-disable-next-line no-case-declarations
const contextDependencies = path.normalize(
globParent(pattern.absoluteFrom)
);
Expand All @@ -83,7 +81,8 @@ function createPatternGlob(pattern, globalRef) {
getAbsoluteContext(pattern.context),
pattern.fromOrigin
);
/* eslint-enable no-param-reassign */
/* eslint-enable no-param-reassign */
}
}

return pattern;
Expand Down
104 changes: 26 additions & 78 deletions test/CopyPlugin.test.js
Expand Up @@ -6,7 +6,7 @@ import { readAssets } from './helpers';

const FIXTURES_DIR = path.join(__dirname, 'fixtures');

describe('apply function', () => {
describe('CopyPlugin', () => {
describe('basic', () => {
it('should copy a file', (done) => {
runEmit({
Expand Down Expand Up @@ -221,9 +221,7 @@ describe('apply function', () => {
.then(done)
.catch(done);
});
});

describe('difference path segment separation', () => {
it('should work with linux path segment separation path when "from" is glob', (done) => {
runEmit({
expectedAssetKeys: ['directory/nested/nestedfile.txt'],
Expand All @@ -237,34 +235,6 @@ describe('apply function', () => {
.catch(done);
});

// Windows path segment (\\) can not use as path segment in glob, but can use as dirname at linux
it.skip('should work with windows path segment separation path when "from" is glob', (done) => {
runEmit({
expectedAssetKeys: ['directory/nested/nestedfile.txt'],
patterns: [
{
from: 'directory\\nested\\*',
},
],
})
.then(done)
.catch(done);
});

// Windows path segment (\\) can not use as path segment in glob, but can use as dirname at linux
it.skip('should work with mixed path segment separation path when "from" is glob', (done) => {
runEmit({
expectedAssetKeys: ['directory/nested/nestedfile.txt'],
patterns: [
{
from: 'directory/nested\\*',
},
],
})
.then(done)
.catch(done);
});

it('should exclude path with linux path segment separators', (done) => {
runEmit({
expectedAssetKeys: [
Expand All @@ -285,28 +255,6 @@ describe('apply function', () => {
.then(done)
.catch(done);
});

// Windows path segment (\\) can not use as path segment in glob, but can use as dirname at linux
it.skip('should exclude path with windows path segment separators', (done) => {
runEmit({
expectedAssetKeys: [
'[!]/hello.txt',
'[special?directory]/(special-*file).txt',
'[special?directory]/directoryfile.txt',
'[special?directory]/nested/nestedfile.txt',
'dir (86)/file.txt',
'dir (86)/nesteddir/deepnesteddir/deepnesteddir.txt',
'dir (86)/nesteddir/nestedfile.txt',
],
patterns: [
{
from: '!(directory)\\**\\*.txt',
},
],
})
.then(done)
.catch(done);
});
});

describe('watch mode', () => {
Expand Down Expand Up @@ -538,33 +486,33 @@ describe('apply function', () => {
.catch(done);
});
});
});

describe('logging', () => {
it('should logging', (done) => {
const expectedAssetKeys = ['file.txt'];

run({
patterns: [
{
from: 'file.txt',
},
],
})
.then(({ compiler, stats }) => {
const root = path.resolve(__dirname).replace(/\\/g, '/');
const logs = stats.compilation.logging
.get('copy-webpack-plugin')
.map((entry) =>
entry.args[0].replace(/\\/g, '/').split(root).join('.')
);
describe('logging', () => {
it('should logging', (done) => {
const expectedAssetKeys = ['file.txt'];

expect(
Array.from(Object.keys(readAssets(compiler, stats))).sort()
).toEqual(expectedAssetKeys);
expect({ result: logs }).toMatchSnapshot({ result: logs });
run({
patterns: [
{
from: 'file.txt',
},
],
})
.then(done)
.catch(done);
.then(({ compiler, stats }) => {
const root = path.resolve(__dirname).replace(/\\/g, '/');
const logs = stats.compilation.logging
.get('copy-webpack-plugin')
.map((entry) =>
entry.args[0].replace(/\\/g, '/').split(root).join('.')
);

expect(
Array.from(Object.keys(readAssets(compiler, stats))).sort()
).toEqual(expectedAssetKeys);
expect({ result: logs }).toMatchSnapshot({ result: logs });
})
.then(done)
.catch(done);
});
});
});
6 changes: 3 additions & 3 deletions test/__snapshots__/CopyPlugin.test.js.snap
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`logging should logging 1`] = `
exports[`CopyPlugin logging should logging 1`] = `
Object {
"result": Array [
"start to adding additionalAssets",
"start to adding additional assets",
"processing from: 'file.txt' to: '.'",
"getting stats for './fixtures/file.txt' to determinate 'fromType'",
"determined './fixtures/file.txt' is a file",
Expand All @@ -14,7 +14,7 @@ Object {
"getting stats for './fixtures/file.txt' to write to assets",
"reading './fixtures/file.txt' to write to assets",
"writing 'file.txt' to compilation assets from './fixtures/file.txt'",
"end to adding additionalAssets",
"end to adding additional assets",
],
}
`;

0 comments on commit bebafcf

Please sign in to comment.