diff --git a/src/index.js b/src/index.js index f2b8b651..b8fbbce0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,31 @@ +import path from 'path'; +import os from 'os'; +import crypto from 'crypto'; + import webpack from 'webpack'; import validateOptions from 'schema-utils'; import pLimit from 'p-limit'; +import globby from 'globby'; +import findCacheDir from 'find-cache-dir'; +import serialize from 'serialize-javascript'; +import cacache from 'cacache'; +import loaderUtils from 'loader-utils'; +import normalizePath from 'normalize-path'; +import globParent from 'glob-parent'; +import fastGlob from 'fast-glob'; + +import { version } from '../package.json'; import schema from './options.json'; -import preProcessPattern from './preProcessPattern'; -import processPattern from './processPattern'; -import postProcessPattern from './postProcessPattern'; +import { readFile, stat } from './utils/promisify'; // webpack 5 exposes the sources property to ensure the right version of webpack-sources is used const { RawSource } = // eslint-disable-next-line global-require webpack.sources || require('webpack-sources'); +const template = /(\[ext\])|(\[name\])|(\[path\])|(\[folder\])|(\[emoji(?::(\d+))?\])|(\[(?:([^:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*))?(?::(\d+))?\])|(\[\d+\])/; + class CopyPlugin { constructor(options = {}) { validateOptions(schema, options, { @@ -23,6 +37,341 @@ class CopyPlugin { this.options = options.options || {}; } + // eslint-disable-next-line class-methods-use-this + async runPattern(compiler, compilation, logger, inputPattern) { + const pattern = + typeof inputPattern === 'string' + ? { from: inputPattern } + : { ...inputPattern }; + + pattern.fromOrigin = pattern.from; + pattern.from = path.normalize(pattern.from); + pattern.to = path.normalize( + typeof pattern.to !== 'undefined' ? pattern.to : '' + ); + + pattern.context = path.normalize( + typeof pattern.context !== 'undefined' + ? !path.isAbsolute(pattern.context) + ? path.join(compiler.options.context, pattern.context) + : pattern.context + : compiler.options.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: + break; + case template.test(pattern.to): + pattern.toType = 'template'; + break; + case isToDirectory: + pattern.toType = 'dir'; + break; + default: + pattern.toType = 'file'; + } + + if (path.isAbsolute(pattern.from)) { + pattern.absoluteFrom = pattern.from; + } else { + pattern.absoluteFrom = path.resolve(pattern.context, pattern.from); + } + + logger.debug( + `getting stats for "${pattern.absoluteFrom}" to determinate "fromType"` + ); + + let stats; + + try { + stats = await stat(compiler.inputFileSystem, pattern.absoluteFrom); + } catch (error) { + // Nothing + } + + if (stats) { + if (stats.isDirectory()) { + pattern.fromType = 'dir'; + } else if (stats.isFile()) { + pattern.fromType = 'file'; + } + } + + // eslint-disable-next-line no-param-reassign + pattern.globOptions = { + ...{ followSymbolicLinks: true }, + ...(pattern.globOptions || {}), + ...{ cwd: pattern.context, objectMode: true }, + }; + + switch (pattern.fromType) { + case 'dir': + logger.debug(`determined "${pattern.absoluteFrom}" is a directory`); + + compilation.contextDependencies.add(pattern.absoluteFrom); + + logger.debug(`add "${pattern.absoluteFrom}" as a context dependency`); + + /* eslint-disable no-param-reassign */ + pattern.context = pattern.absoluteFrom; + pattern.glob = path.posix.join( + fastGlob.escapePath( + normalizePath(path.resolve(pattern.absoluteFrom)) + ), + '**/*' + ); + pattern.absoluteFrom = path.join(pattern.absoluteFrom, '**/*'); + + if (typeof pattern.globOptions.dot === 'undefined') { + pattern.globOptions.dot = true; + } + /* eslint-enable no-param-reassign */ + break; + case 'file': + logger.debug(`determined "${pattern.absoluteFrom}" is a file`); + + compilation.fileDependencies.add(pattern.absoluteFrom); + + logger.debug(`add "${pattern.absoluteFrom}" as a file dependency`); + + /* eslint-disable no-param-reassign */ + pattern.context = path.dirname(pattern.absoluteFrom); + pattern.glob = fastGlob.escapePath( + normalizePath(path.resolve(pattern.absoluteFrom)) + ); + + if (typeof pattern.globOptions.dot === 'undefined') { + pattern.globOptions.dot = true; + } + /* eslint-enable no-param-reassign */ + break; + default: { + logger.debug(`determined "${pattern.absoluteFrom}" is a glob`); + + const contextDependencies = path.normalize( + globParent(pattern.absoluteFrom) + ); + + compilation.contextDependencies.add(contextDependencies); + + logger.debug(`add "${contextDependencies}" as a context dependency`); + + /* eslint-disable no-param-reassign */ + pattern.fromType = 'glob'; + pattern.glob = path.isAbsolute(pattern.fromOrigin) + ? pattern.fromOrigin + : path.posix.join( + fastGlob.escapePath(normalizePath(path.resolve(pattern.context))), + pattern.fromOrigin + ); + /* eslint-enable no-param-reassign */ + } + } + + logger.log( + `begin globbing "${pattern.glob}" with a context of "${pattern.context}"` + ); + + const paths = await globby(pattern.glob, pattern.globOptions); + + if (paths.length === 0) { + if (pattern.noErrorOnMissing) { + return Promise.resolve(); + } + + const missingError = new Error( + `unable to locate "${pattern.from}" at "${pattern.absoluteFrom}"` + ); + + logger.error(missingError.message); + + compilation.errors.push(missingError); + + return Promise.resolve(); + } + + const filteredPaths = ( + await Promise.all( + paths.map(async (item) => { + // Exclude directories + if (!item.dirent.isFile()) { + return false; + } + + if (pattern.filter) { + const isFiltered = await pattern.filter(item.path); + + return isFiltered ? item : false; + } + + return item; + }) + ) + ).filter((item) => item); + + if (filteredPaths.length === 0) { + return Promise.resolve(); + } + + const files = filteredPaths.map((item) => { + const from = item.path; + + logger.debug(`found "${from}"`); + + // `globby`/`fast-glob` return the relative path when the path contains special characters on windows + const absoluteFrom = path.resolve(pattern.context, from); + const relativeFrom = pattern.flatten + ? path.basename(absoluteFrom) + : path.relative(pattern.context, absoluteFrom); + let webpackTo = + pattern.toType === 'dir' + ? path.join(pattern.to, relativeFrom) + : pattern.to; + + if (path.isAbsolute(webpackTo)) { + webpackTo = path.relative(compiler.options.output.path, webpackTo); + } + + logger.log(`determined that "${from}" should write to "${webpackTo}"`); + + return { absoluteFrom, relativeFrom, webpackTo }; + }); + + return Promise.all( + files.map(async (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); + } + + logger.debug(`reading "${file.absoluteFrom}" to write to assets`); + + let data; + + try { + data = await readFile(compiler.inputFileSystem, file.absoluteFrom); + } catch (error) { + compilation.errors.push(error); + + return; + } + + if (pattern.transform) { + logger.log(`transforming content for "${file.absoluteFrom}"`); + + if (pattern.cacheTransform) { + const cacheDirectory = pattern.cacheTransform.directory + ? pattern.cacheTransform.directory + : typeof pattern.cacheTransform === 'string' + ? pattern.cacheTransform + : findCacheDir({ name: 'copy-webpack-plugin' }) || os.tmpdir(); + let defaultCacheKeys = { + version, + transform: pattern.transform, + contentHash: crypto.createHash('md4').update(data).digest('hex'), + }; + + if (typeof pattern.cacheTransform.keys === 'function') { + defaultCacheKeys = await pattern.cacheTransform.keys( + defaultCacheKeys, + file.absoluteFrom + ); + } else { + defaultCacheKeys = { + ...defaultCacheKeys, + ...pattern.cacheTransform.keys, + }; + } + + const cacheKeys = serialize(defaultCacheKeys); + + try { + const result = await cacache.get(cacheDirectory, cacheKeys); + + logger.debug( + `getting cached transformation for "${file.absoluteFrom}"` + ); + + ({ data } = result); + } catch (_ignoreError) { + data = await pattern.transform(data, file.absoluteFrom); + + logger.debug(`caching transformation for "${file.absoluteFrom}"`); + + await cacache.put(cacheDirectory, cacheKeys, data); + } + } else { + data = await pattern.transform(data, file.absoluteFrom); + } + } + + if (pattern.toType === 'template') { + logger.log( + `interpolating template "${file.webpackTo}" for "${file.relativeFrom}"` + ); + + // 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)) { + // eslint-disable-next-line no-param-reassign + file.webpackTo = file.webpackTo.replace(/\.?\[ext]/g, ''); + } + + // eslint-disable-next-line no-param-reassign + file.immutable = /\[(?:([^:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*))?(?::(\d+))?\]/gi.test( + file.webpackTo + ); + + // eslint-disable-next-line no-param-reassign + file.webpackTo = loaderUtils.interpolateName( + { resourcePath: file.absoluteFrom }, + file.webpackTo, + { + content: data, + context: pattern.context, + } + ); + + // Bug in `loader-utils`, package convert `\\` to `/`, need fix in loader-utils + // eslint-disable-next-line no-param-reassign + file.webpackTo = path.normalize(file.webpackTo); + } + + if (pattern.transformPath) { + logger.log( + `transforming path "${file.webpackTo}" for "${file.absoluteFrom}"` + ); + + // eslint-disable-next-line no-param-reassign + file.immutable = false; + // eslint-disable-next-line no-param-reassign + file.webpackTo = await pattern.transformPath( + file.webpackTo, + file.absoluteFrom + ); + } + + // eslint-disable-next-line no-param-reassign + file.data = data; + // eslint-disable-next-line no-param-reassign + file.targetPath = normalizePath(file.webpackTo); + // eslint-disable-next-line no-param-reassign + file.force = pattern.force; + + // eslint-disable-next-line consistent-return + return file; + }) + ); + } + apply(compiler) { const pluginName = this.constructor.name; const limit = pLimit(this.options.concurrency || 100); @@ -35,46 +384,14 @@ class CopyPlugin { async (callback) => { logger.debug('start to adding additional assets'); - const globalRef = { - context: compiler.options.context, - logger, - compilation, - inputFileSystem: compiler.inputFileSystem, - output: compiler.options.output.path, - }; - let assets; try { assets = await Promise.all( - this.patterns.map((pattern) => - limit(async () => { - const patternAfterPreProcess = await preProcessPattern( - globalRef, - pattern - ); - - const files = await processPattern( - globalRef, - patternAfterPreProcess - ); - - if (!files) { - return Promise.resolve(); - } - - return Promise.all( - files - .filter(Boolean) - .map((file) => - postProcessPattern( - globalRef, - patternAfterPreProcess, - file - ) - ) - ); - }) + this.patterns.map((item) => + limit(async () => + this.runPattern(compiler, compilation, logger, item) + ) ) ); } catch (error) { @@ -115,7 +432,7 @@ class CopyPlugin { if (existingAsset) { if (force) { logger.log( - `force updating '${webpackTo}' to compilation assets from '${absoluteFrom}'` + `force updating "${webpackTo}" to compilation assets from "${absoluteFrom}"` ); const info = { copied: true }; @@ -130,14 +447,14 @@ class CopyPlugin { } logger.log( - `skipping '${webpackTo}', because it already exists` + `skipping "${webpackTo}", because it already exists` ); return; } logger.log( - `writing '${webpackTo}' to compilation assets from '${absoluteFrom}'` + `writing "${webpackTo}" to compilation assets from "${absoluteFrom}"` ); const info = { copied: true }; diff --git a/src/postProcessPattern.js b/src/postProcessPattern.js deleted file mode 100644 index d7d96e06..00000000 --- a/src/postProcessPattern.js +++ /dev/null @@ -1,133 +0,0 @@ -import path from 'path'; -import os from 'os'; -import crypto from 'crypto'; - -import loaderUtils from 'loader-utils'; -import cacache from 'cacache'; -import serialize from 'serialize-javascript'; -import findCacheDir from 'find-cache-dir'; -import normalizePath from 'normalize-path'; - -import { version } from '../package.json'; - -import { readFile } from './utils/promisify'; - -/* eslint-disable no-param-reassign */ -export default async function postProcessPattern(globalRef, pattern, file) { - const { logger, compilation, inputFileSystem } = globalRef; - - // 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); - } - - logger.debug(`reading '${file.absoluteFrom}' to write to assets`); - - let data; - - try { - data = await readFile(inputFileSystem, file.absoluteFrom); - } catch (error) { - compilation.errors.push(error); - - return; - } - - if (pattern.transform) { - logger.log(`transforming content for '${file.absoluteFrom}'`); - - if (pattern.cacheTransform) { - const cacheDirectory = pattern.cacheTransform.directory - ? pattern.cacheTransform.directory - : typeof pattern.cacheTransform === 'string' - ? pattern.cacheTransform - : findCacheDir({ name: 'copy-webpack-plugin' }) || os.tmpdir(); - let defaultCacheKeys = { - version, - transform: pattern.transform, - contentHash: crypto.createHash('md4').update(data).digest('hex'), - }; - - if (typeof pattern.cacheTransform.keys === 'function') { - defaultCacheKeys = await pattern.cacheTransform.keys( - defaultCacheKeys, - file.absoluteFrom - ); - } else { - defaultCacheKeys = { - ...defaultCacheKeys, - ...pattern.cacheTransform.keys, - }; - } - - const cacheKeys = serialize(defaultCacheKeys); - - try { - const result = await cacache.get(cacheDirectory, cacheKeys); - - logger.debug( - `getting cached transformation for '${file.absoluteFrom}'` - ); - - ({ data } = result); - } catch (_ignoreError) { - data = await pattern.transform(data, file.absoluteFrom); - - logger.debug(`caching transformation for '${file.absoluteFrom}'`); - - await cacache.put(cacheDirectory, cacheKeys, data); - } - } else { - data = await pattern.transform(data, file.absoluteFrom); - } - } - - if (pattern.toType === 'template') { - logger.log( - `interpolating template '${file.webpackTo}' for '${file.relativeFrom}'` - ); - - // 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.immutable = /\[(?:([^:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*))?(?::(\d+))?\]/gi.test( - file.webpackTo - ); - - file.webpackTo = loaderUtils.interpolateName( - { resourcePath: file.absoluteFrom }, - file.webpackTo, - { - content: data, - context: pattern.context, - } - ); - - // Bug in `loader-utils`, package convert `\\` to `/`, need fix in loader-utils - file.webpackTo = path.normalize(file.webpackTo); - } - - if (pattern.transformPath) { - logger.log( - `transforming path '${file.webpackTo}' for '${file.absoluteFrom}'` - ); - - file.immutable = false; - file.webpackTo = await pattern.transformPath( - file.webpackTo, - file.absoluteFrom - ); - } - - file.data = data; - file.targetPath = normalizePath(file.webpackTo); - file.force = pattern.force; - - // eslint-disable-next-line consistent-return - return file; -} diff --git a/src/preProcessPattern.js b/src/preProcessPattern.js deleted file mode 100644 index 99f952d1..00000000 --- a/src/preProcessPattern.js +++ /dev/null @@ -1,69 +0,0 @@ -import path from 'path'; - -import isTemplateLike from './utils/isTemplateLike'; -import { stat } from './utils/promisify'; - -/* eslint-disable no-param-reassign */ - -export default async function preProcessPattern(globalRef, pattern) { - const { context, logger, inputFileSystem } = globalRef; - - pattern = typeof pattern === 'string' ? { from: pattern } : { ...pattern }; - pattern.fromOrigin = pattern.from; - pattern.from = path.normalize(pattern.from); - 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: - break; - case isTemplateLike(pattern.to): - pattern.toType = 'template'; - break; - case isToDirectory: - pattern.toType = 'dir'; - break; - default: - pattern.toType = 'file'; - } - - if (path.isAbsolute(pattern.from)) { - pattern.absoluteFrom = pattern.from; - } else { - pattern.absoluteFrom = path.resolve(pattern.context, pattern.from); - } - - logger.debug( - `getting stats for '${pattern.absoluteFrom}' to determinate 'fromType'` - ); - - let stats; - - try { - stats = await stat(inputFileSystem, pattern.absoluteFrom); - } catch (error) { - return pattern; - } - - if (stats.isDirectory()) { - pattern.fromType = 'dir'; - } else if (stats.isFile()) { - pattern.fromType = 'file'; - } - - return pattern; -} diff --git a/src/processPattern.js b/src/processPattern.js deleted file mode 100644 index a961a501..00000000 --- a/src/processPattern.js +++ /dev/null @@ -1,76 +0,0 @@ -import path from 'path'; - -import globby from 'globby'; - -import createPatternGlob from './utils/createPatternGlob'; - -export default async function processPattern(globalRef, pattern) { - const { logger, output, compilation } = globalRef; - - createPatternGlob(pattern, globalRef); - - logger.log( - `begin globbing '${pattern.glob}' with a context of '${pattern.context}'` - ); - - const paths = await globby(pattern.glob, pattern.globOptions); - - if (paths.length === 0) { - if (pattern.noErrorOnMissing) { - return Promise.resolve(); - } - - const missingError = new Error( - `unable to locate '${pattern.from}' at '${pattern.absoluteFrom}'` - ); - - logger.error(missingError.message); - - compilation.errors.push(missingError); - - return Promise.resolve(); - } - - const filteredPaths = ( - await Promise.all( - paths.map(async (item) => { - // Exclude directories - if (!item.dirent.isFile()) { - return false; - } - - if (pattern.filter) { - const isFiltered = await pattern.filter(item.path); - - return isFiltered ? item : false; - } - - return item; - }) - ) - ).filter((item) => item); - - return filteredPaths.map((item) => { - const from = item.path; - - logger.debug(`found ${from}`); - - // `globby`/`fast-glob` return the relative path when the path contains special characters on windows - const absoluteFrom = path.resolve(pattern.context, from); - const relativeFrom = pattern.flatten - ? path.basename(absoluteFrom) - : path.relative(pattern.context, absoluteFrom); - let webpackTo = - pattern.toType === 'dir' - ? path.join(pattern.to, relativeFrom) - : pattern.to; - - if (path.isAbsolute(webpackTo)) { - webpackTo = path.relative(output, webpackTo); - } - - logger.log(`determined that '${from}' should write to '${webpackTo}'`); - - return { absoluteFrom, relativeFrom, webpackTo }; - }); -} diff --git a/src/utils/createPatternGlob.js b/src/utils/createPatternGlob.js deleted file mode 100644 index 4e9033a9..00000000 --- a/src/utils/createPatternGlob.js +++ /dev/null @@ -1,82 +0,0 @@ -import path from 'path'; - -import normalizePath from 'normalize-path'; -import globParent from 'glob-parent'; -import fastGlob from 'fast-glob'; - -function getAbsoluteContext(context) { - return fastGlob.escapePath(normalizePath(path.resolve(context))); -} - -function createPatternGlob(pattern, globalRef) { - const { logger, compilation } = globalRef; - - // eslint-disable-next-line no-param-reassign - pattern.globOptions = { - ...{ followSymbolicLinks: true }, - ...(pattern.globOptions || {}), - ...{ cwd: pattern.context, objectMode: true }, - }; - - switch (pattern.fromType) { - case 'dir': - logger.debug(`determined '${pattern.absoluteFrom}' is a directory`); - logger.debug(`add ${pattern.absoluteFrom} as contextDependencies`); - - compilation.contextDependencies.add(pattern.absoluteFrom); - - /* eslint-disable no-param-reassign */ - pattern.context = pattern.absoluteFrom; - pattern.glob = path.posix.join( - getAbsoluteContext(pattern.absoluteFrom), - '**/*' - ); - pattern.absoluteFrom = path.join(pattern.absoluteFrom, '**/*'); - - if (typeof pattern.globOptions.dot === 'undefined') { - pattern.globOptions.dot = true; - } - /* eslint-enable no-param-reassign */ - break; - case 'file': - logger.debug(`determined '${pattern.absoluteFrom}' is a file`); - logger.debug(`add ${pattern.absoluteFrom} as fileDependencies`); - - compilation.fileDependencies.add(pattern.absoluteFrom); - - /* eslint-disable no-param-reassign */ - pattern.context = path.dirname(pattern.absoluteFrom); - pattern.glob = getAbsoluteContext(pattern.absoluteFrom); - - if (typeof pattern.globOptions.dot === 'undefined') { - pattern.globOptions.dot = true; - } - /* eslint-enable no-param-reassign */ - break; - default: { - logger.debug(`determined '${pattern.absoluteFrom}' is a glob`); - - const contextDependencies = path.normalize( - globParent(pattern.absoluteFrom) - ); - - logger.debug(`add ${contextDependencies} as contextDependencies`); - - compilation.contextDependencies.add(contextDependencies); - - /* eslint-disable no-param-reassign */ - pattern.fromType = 'glob'; - pattern.glob = path.isAbsolute(pattern.fromOrigin) - ? pattern.fromOrigin - : path.posix.join( - getAbsoluteContext(pattern.context), - pattern.fromOrigin - ); - /* eslint-enable no-param-reassign */ - } - } - - return pattern; -} - -export default createPatternGlob; diff --git a/src/utils/isTemplateLike.js b/src/utils/isTemplateLike.js deleted file mode 100644 index a06b396e..00000000 --- a/src/utils/isTemplateLike.js +++ /dev/null @@ -1,4 +0,0 @@ -export default (pattern) => - /(\[ext\])|(\[name\])|(\[path\])|(\[folder\])|(\[emoji(?::(\d+))?\])|(\[(?:([^:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*))?(?::(\d+))?\])|(\[\d+\])/.test( - pattern - ); diff --git a/test/__snapshots__/CopyPlugin.test.js.snap b/test/__snapshots__/CopyPlugin.test.js.snap index 9294be16..4c768dc6 100644 --- a/test/__snapshots__/CopyPlugin.test.js.snap +++ b/test/__snapshots__/CopyPlugin.test.js.snap @@ -3,29 +3,29 @@ exports[`CopyPlugin logging should logging when "from" is a directory: logs 1`] = ` Object { "logs": Array [ - "add ./fixtures/directory as contextDependencies", - "begin globbing './fixtures/directory/**/*' with a context of './fixtures/directory'", - "determined './fixtures/directory' is a directory", - "determined that './fixtures/directory/.dottedfile' should write to '.dottedfile'", - "determined that './fixtures/directory/directoryfile.txt' should write to 'directoryfile.txt'", - "determined that './fixtures/directory/nested/deep-nested/deepnested.txt' should write to 'nested/deep-nested/deepnested.txt'", - "determined that './fixtures/directory/nested/nestedfile.txt' should write to 'nested/nestedfile.txt'", + "add \\"./fixtures/directory\\" as a context dependency", + "begin globbing \\"./fixtures/directory/**/*\\" with a context of \\"./fixtures/directory\\"", + "determined \\"./fixtures/directory\\" is a directory", + "determined that \\"./fixtures/directory/.dottedfile\\" should write to \\".dottedfile\\"", + "determined that \\"./fixtures/directory/directoryfile.txt\\" should write to \\"directoryfile.txt\\"", + "determined that \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" should write to \\"nested/deep-nested/deepnested.txt\\"", + "determined that \\"./fixtures/directory/nested/nestedfile.txt\\" should write to \\"nested/nestedfile.txt\\"", "end to adding additional assets", - "found ./fixtures/directory/.dottedfile", - "found ./fixtures/directory/directoryfile.txt", - "found ./fixtures/directory/nested/deep-nested/deepnested.txt", - "found ./fixtures/directory/nested/nestedfile.txt", - "getting stats for './fixtures/directory' to determinate 'fromType'", - "processing from: 'directory' to: '.'", - "reading './fixtures/directory/.dottedfile' to write to assets", - "reading './fixtures/directory/directoryfile.txt' to write to assets", - "reading './fixtures/directory/nested/deep-nested/deepnested.txt' to write to assets", - "reading './fixtures/directory/nested/nestedfile.txt' to write to assets", + "found \\"./fixtures/directory/.dottedfile\\"", + "found \\"./fixtures/directory/directoryfile.txt\\"", + "found \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "found \\"./fixtures/directory/nested/nestedfile.txt\\"", + "getting stats for \\"./fixtures/directory\\" to determinate \\"fromType\\"", + "processing from \\"directory\\" to \\".\\"", + "reading \\"./fixtures/directory/.dottedfile\\" to write to assets", + "reading \\"./fixtures/directory/directoryfile.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/nestedfile.txt\\" to write to assets", "start to adding additional assets", - "writing '.dottedfile' to compilation assets from './fixtures/directory/.dottedfile'", - "writing 'directoryfile.txt' to compilation assets from './fixtures/directory/directoryfile.txt'", - "writing 'nested/deep-nested/deepnested.txt' to compilation assets from './fixtures/directory/nested/deep-nested/deepnested.txt'", - "writing 'nested/nestedfile.txt' to compilation assets from './fixtures/directory/nested/nestedfile.txt'", + "writing \\".dottedfile\\" to compilation assets from \\"./fixtures/directory/.dottedfile\\"", + "writing \\"directoryfile.txt\\" to compilation assets from \\"./fixtures/directory/directoryfile.txt\\"", + "writing \\"nested/deep-nested/deepnested.txt\\" to compilation assets from \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "writing \\"nested/nestedfile.txt\\" to compilation assets from \\"./fixtures/directory/nested/nestedfile.txt\\"", ], } `; @@ -33,17 +33,17 @@ Object { exports[`CopyPlugin logging should logging when "from" is a file: logs 1`] = ` Object { "logs": Array [ - "add ./fixtures/file.txt as fileDependencies", - "begin globbing './fixtures/file.txt' with a context of './fixtures'", - "determined './fixtures/file.txt' is a file", - "determined that './fixtures/file.txt' should write to 'file.txt'", + "add \\"./fixtures/file.txt\\" as a file dependency", + "begin globbing \\"./fixtures/file.txt\\" with a context of \\"./fixtures\\"", + "determined \\"./fixtures/file.txt\\" is a file", + "determined that \\"./fixtures/file.txt\\" should write to \\"file.txt\\"", "end to adding additional assets", - "found ./fixtures/file.txt", - "getting stats for './fixtures/file.txt' to determinate 'fromType'", - "processing from: 'file.txt' to: '.'", - "reading './fixtures/file.txt' to write to assets", + "found \\"./fixtures/file.txt\\"", + "getting stats for \\"./fixtures/file.txt\\" to determinate \\"fromType\\"", + "processing from \\"file.txt\\" to \\".\\"", + "reading \\"./fixtures/file.txt\\" to write to assets", "start to adding additional assets", - "writing 'file.txt' to compilation assets from './fixtures/file.txt'", + "writing \\"file.txt\\" to compilation assets from \\"./fixtures/file.txt\\"", ], } `; @@ -51,28 +51,28 @@ Object { exports[`CopyPlugin logging should logging when "from" is a glob: logs 1`] = ` Object { "logs": Array [ - "add ./fixtures/directory as contextDependencies", + "add \\"./fixtures/directory\\" as a context dependency", "add ./fixtures/directory/directoryfile.txt as fileDependencies", "add ./fixtures/directory/nested/deep-nested/deepnested.txt as fileDependencies", "add ./fixtures/directory/nested/nestedfile.txt as fileDependencies", - "begin globbing './fixtures/directory/**' with a context of './fixtures'", - "determined './fixtures/directory/**' is a glob", - "determined that './fixtures/directory/directoryfile.txt' should write to 'directory/directoryfile.txt'", - "determined that './fixtures/directory/nested/deep-nested/deepnested.txt' should write to 'directory/nested/deep-nested/deepnested.txt'", - "determined that './fixtures/directory/nested/nestedfile.txt' should write to 'directory/nested/nestedfile.txt'", + "begin globbing \\"./fixtures/directory/**\\" with a context of \\"./fixtures\\"", + "determined \\"./fixtures/directory/**\\" is a glob", + "determined that \\"./fixtures/directory/directoryfile.txt\\" should write to \\"directory/directoryfile.txt\\"", + "determined that \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" should write to \\"directory/nested/deep-nested/deepnested.txt\\"", + "determined that \\"./fixtures/directory/nested/nestedfile.txt\\" should write to \\"directory/nested/nestedfile.txt\\"", "end to adding additional assets", - "found ./fixtures/directory/directoryfile.txt", - "found ./fixtures/directory/nested/deep-nested/deepnested.txt", - "found ./fixtures/directory/nested/nestedfile.txt", - "getting stats for './fixtures/directory/**' to determinate 'fromType'", - "processing from: 'directory/**' to: '.'", - "reading './fixtures/directory/directoryfile.txt' to write to assets", - "reading './fixtures/directory/nested/deep-nested/deepnested.txt' to write to assets", - "reading './fixtures/directory/nested/nestedfile.txt' to write to assets", + "found \\"./fixtures/directory/directoryfile.txt\\"", + "found \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "found \\"./fixtures/directory/nested/nestedfile.txt\\"", + "getting stats for \\"./fixtures/directory/**\\" to determinate \\"fromType\\"", + "processing from \\"directory/**\\" to \\".\\"", + "reading \\"./fixtures/directory/directoryfile.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\" to write to assets", + "reading \\"./fixtures/directory/nested/nestedfile.txt\\" to write to assets", "start to adding additional assets", - "writing 'directory/directoryfile.txt' to compilation assets from './fixtures/directory/directoryfile.txt'", - "writing 'directory/nested/deep-nested/deepnested.txt' to compilation assets from './fixtures/directory/nested/deep-nested/deepnested.txt'", - "writing 'directory/nested/nestedfile.txt' to compilation assets from './fixtures/directory/nested/nestedfile.txt'", + "writing \\"directory/directoryfile.txt\\" to compilation assets from \\"./fixtures/directory/directoryfile.txt\\"", + "writing \\"directory/nested/deep-nested/deepnested.txt\\" to compilation assets from \\"./fixtures/directory/nested/deep-nested/deepnested.txt\\"", + "writing \\"directory/nested/nestedfile.txt\\" to compilation assets from \\"./fixtures/directory/nested/nestedfile.txt\\"", ], } `; diff --git a/test/from-option.test.js b/test/from-option.test.js index 0ddc678c..2762f997 100644 --- a/test/from-option.test.js +++ b/test/from-option.test.js @@ -71,7 +71,7 @@ describe('from option', () => { process.platform === 'win32' ? [ new Error( - `unable to locate 'symlink${path.sep}file-ln.txt' at '${FIXTURES_DIR}${path.sep}symlink${path.sep}file-ln.txt'` + `unable to locate "symlink${path.sep}file-ln.txt" at "${FIXTURES_DIR}${path.sep}symlink${path.sep}file-ln.txt"` ), ] : [], @@ -91,7 +91,7 @@ describe('from option', () => { expectedAssetKeys: [], expectedErrors: [ new Error( - `unable to locate 'nonexistent.txt' at '${FIXTURES_DIR}${path.sep}nonexistent.txt'` + `unable to locate "nonexistent.txt" at "${FIXTURES_DIR}${path.sep}nonexistent.txt"` ), ], patterns: [ @@ -210,7 +210,7 @@ describe('from option', () => { process.platform === 'win32' ? [ new Error( - `unable to locate 'symlink${path.sep}directory-ln' at '${FIXTURES_DIR}${path.sep}symlink${path.sep}directory-ln\\**\\*'` + `unable to locate "symlink${path.sep}directory-ln" at "${FIXTURES_DIR}${path.sep}symlink${path.sep}directory-ln\\**\\*"` ), ] : [], @@ -295,7 +295,7 @@ describe('from option', () => { expectedAssetKeys: [], expectedErrors: [ new Error( - `unable to locate 'nonexistent' at '${FIXTURES_DIR}${path.sep}nonexistent'` + `unable to locate "nonexistent" at "${FIXTURES_DIR}${path.sep}nonexistent"` ), ], patterns: [ @@ -475,7 +475,7 @@ describe('from option', () => { process.platform === 'win32' ? [ new Error( - `unable to locate 'symlink\\**\\*.txt' at '${FIXTURES_DIR}${path.sep}symlink\\**\\*.txt'` + `unable to locate "symlink\\**\\*.txt" at "${FIXTURES_DIR}${path.sep}symlink\\**\\*.txt"` ), ] : [], @@ -505,7 +505,7 @@ describe('from option', () => { expectedAssetKeys: [], expectedErrors: [ new Error( - `unable to locate 'nonexistent${path.sep}**${path.sep}*' at '${FIXTURES_DIR}${path.sep}nonexistent${path.sep}**${path.sep}*'` + `unable to locate "nonexistent${path.sep}**${path.sep}*" at "${FIXTURES_DIR}${path.sep}nonexistent${path.sep}**${path.sep}*"` ), ], patterns: [ diff --git a/test/globOptions-option.test.js b/test/globOptions-option.test.js index 595ca352..7eab8b45 100644 --- a/test/globOptions-option.test.js +++ b/test/globOptions-option.test.js @@ -78,7 +78,7 @@ describe('globOptions option', () => { runEmit({ expectedErrors: [ new Error( - `unable to locate 'file.txt' at '${FIXTURES_DIR}${path.sep}file.txt'` + `unable to locate "file.txt" at "${FIXTURES_DIR}${path.sep}file.txt"` ), ], patterns: [ @@ -255,7 +255,7 @@ describe('globOptions option', () => { runEmit({ expectedErrors: [ new Error( - `unable to locate 'directory' at '${FIXTURES_DIR}${path.sep}directory${path.sep}**${path.sep}*'` + `unable to locate "directory" at "${FIXTURES_DIR}${path.sep}directory${path.sep}**${path.sep}*"` ), ], patterns: [ @@ -275,7 +275,7 @@ describe('globOptions option', () => { runEmit({ expectedErrors: [ new Error( - `unable to locate 'file.txt' at '${FIXTURES_DIR}${path.sep}file.txt'` + `unable to locate "file.txt" at "${FIXTURES_DIR}${path.sep}file.txt"` ), ], patterns: [ diff --git a/test/toType-option.test.js b/test/toType-option.test.js index 7940b926..bcef65fa 100644 --- a/test/toType-option.test.js +++ b/test/toType-option.test.js @@ -88,7 +88,7 @@ describe('toType option', () => { expectedAssetKeys: [], expectedErrors: [ new Error( - `unable to locate 'nonexistent.txt' at '${FIXTURES_DIR}${path.sep}nonexistent.txt'` + `unable to locate "nonexistent.txt" at "${FIXTURES_DIR}${path.sep}nonexistent.txt"` ), ], patterns: [