diff --git a/README.md b/README.md index b7acb7e..1549b26 100644 --- a/README.md +++ b/README.md @@ -283,23 +283,6 @@ _Note: If `[0]` is used, it will be replaced by the entire tested string, whereas `[1]` will contain the first capturing parenthesis of your regex and so on..._ -### `useRelativePath` - -Type: `Boolean` -Default: `false` - -Specifies whether or not to generate a relative URI for each target file context. - -```js -// webpack.config.js -{ - loader: 'file-loader', - options: { - useRelativePath: process.env.NODE_ENV === "production" - } -} -``` - ## Placeholders ### `[ext]` diff --git a/src/index.js b/src/index.js index 5bd5e39..4acfa15 100644 --- a/src/index.js +++ b/src/index.js @@ -28,38 +28,17 @@ export default function loader(content) { } } - if (options.useRelativePath) { - const filePath = this.resourcePath; - - const issuer = options.context - ? context - : this._module && this._module.issuer && this._module.issuer.context; - - const relativeUrl = - issuer && - path - .relative(issuer, filePath) - .split(path.sep) - .join('/'); - - const relativePath = relativeUrl && `${path.dirname(relativeUrl)}/`; - // eslint-disable-next-line no-bitwise - if (~relativePath.indexOf('../')) { - outputPath = path.posix.join(outputPath, relativePath, url); - } else { - outputPath = path.posix.join(relativePath, url); - } - } - let publicPath = `__webpack_public_path__ + ${JSON.stringify(outputPath)}`; if (options.publicPath) { if (typeof options.publicPath === 'function') { publicPath = options.publicPath(url, this.resourcePath, context); - } else if (options.publicPath.endsWith('/')) { - publicPath = options.publicPath + url; } else { - publicPath = `${options.publicPath}/${url}`; + publicPath = `${ + options.publicPath.endsWith('/') + ? options.publicPath + : `${options.publicPath}/` + }${url}`; } publicPath = JSON.stringify(publicPath); diff --git a/src/options.json b/src/options.json index 998dc45..67224e2 100644 --- a/src/options.json +++ b/src/options.json @@ -1,24 +1,60 @@ { - "type": "object", + "additionalProperties": false, "properties": { - "name": {}, - "regExp": {}, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "outputPath": { + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "publicPath": { + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, "context": { "type": "string" }, - "publicPath": {}, - "outputPath": {}, - "useRelativePath": { - "type": "boolean" - }, "emitFile": { "type": "boolean" + }, + "regExp": { + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "RegExp" + } + ] } }, "errorMessages": { + "name": "should be {String} or {Function} (https://github.com/webpack-contrib/file-loader#name)", + "outputPath": "should be {String} or {Function} (https://github.com/webpack-contrib/file-loader#outputpath)", + "publicPath": "should be {String} or {Function} (https://github.com/webpack-contrib/file-loader#publicpath)", "context": "should be {String} (https://github.com/webpack-contrib/file-loader#context)", - "useRelativePath": "should be {Boolean} (https://github.com/webpack-contrib/file-loader#userelativepath)", - "emitFile": "should be {Boolean} (https://github.com/webpack-contrib/file-loader#emitfile)" + "emitFile": "should be {Boolean} (https://github.com/webpack-contrib/file-loader#emitfile)", + "regExp": "should be {String} or {RegExp} (https://github.com/webpack-contrib/file-loader#regexp)" }, - "additionalProperties": true + "type": "object" } diff --git a/test/__snapshots__/errors.test.js.snap b/test/__snapshots__/errors.test.js.snap index 872f9e8..0c978d5 100644 --- a/test/__snapshots__/errors.test.js.snap +++ b/test/__snapshots__/errors.test.js.snap @@ -1,8 +1,58 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`errors validation errors 1`] = ` +exports[`validation errors 1`] = ` "File Loader Invalid Options -options.useRelativePath should be boolean +options should NOT have additional properties +" +`; + +exports[`validation errors 2`] = ` +"File Loader Invalid Options + +options.name should be string +options.name should pass \\"instanceof\\" keyword validation +options.name should match some schema in anyOf +" +`; + +exports[`validation errors 3`] = ` +"File Loader Invalid Options + +options.outputPath should be string +options.outputPath should pass \\"instanceof\\" keyword validation +options.outputPath should match some schema in anyOf +" +`; + +exports[`validation errors 4`] = ` +"File Loader Invalid Options + +options.publicPath should be string +options.publicPath should pass \\"instanceof\\" keyword validation +options.publicPath should match some schema in anyOf +" +`; + +exports[`validation errors 5`] = ` +"File Loader Invalid Options + +options.context should be string +" +`; + +exports[`validation errors 6`] = ` +"File Loader Invalid Options + +options.emitFile should be boolean +" +`; + +exports[`validation errors 7`] = ` +"File Loader Invalid Options + +options.regExp should be string +options.regExp should pass \\"instanceof\\" keyword validation +options.regExp should match some schema in anyOf " `; diff --git a/test/__snapshots__/outputPath-option.test.js.snap b/test/__snapshots__/outputPath-option.test.js.snap index 37181aa..fd13711 100644 --- a/test/__snapshots__/outputPath-option.test.js.snap +++ b/test/__snapshots__/outputPath-option.test.js.snap @@ -107,3 +107,12 @@ Object { "source": "module.exports = __webpack_public_path__ + \\"output_path/file.png\\";", } `; + +exports[`when applied with \`outputPath\` option matches snapshot without value 1`] = ` +Object { + "assets": Array [ + "9c87cbf3ba33126ffd25ae7f2f6bbafb.png", + ], + "source": "module.exports = __webpack_public_path__ + \\"9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", +} +`; diff --git a/test/__snapshots__/publicPath-option.test.js.snap b/test/__snapshots__/publicPath-option.test.js.snap index 916eafa..676eeba 100644 --- a/test/__snapshots__/publicPath-option.test.js.snap +++ b/test/__snapshots__/publicPath-option.test.js.snap @@ -53,3 +53,12 @@ Object { "source": "module.exports = \\"public_path/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", } `; + +exports[`when applied with \`publicPath\` option matches snapshot without value 1`] = ` +Object { + "assets": Array [ + "9c87cbf3ba33126ffd25ae7f2f6bbafb.png", + ], + "source": "module.exports = __webpack_public_path__ + \\"9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", +} +`; diff --git a/test/__snapshots__/useRelativePath-option.test.js.snap b/test/__snapshots__/useRelativePath-option.test.js.snap deleted file mode 100644 index d9bd4cf..0000000 --- a/test/__snapshots__/useRelativePath-option.test.js.snap +++ /dev/null @@ -1,37 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`when applied with \`useRelativePath\` option matches snapshot for \`false\` value (\`{Boolean}\`) 1`] = ` -Object { - "assets": Array [ - "9c87cbf3ba33126ffd25ae7f2f6bbafb.png", - ], - "source": "module.exports = __webpack_public_path__ + \\"9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", -} -`; - -exports[`when applied with \`useRelativePath\` option matches snapshot for \`true\` value (\`{Boolean}\`) 1`] = ` -Object { - "assets": Array [ - "assets/9c87cbf3ba33126ffd25ae7f2f6bbafb.png", - ], - "source": "module.exports = __webpack_public_path__ + \\"assets/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", -} -`; - -exports[`when applied with \`useRelativePath\` option matches snapshot for \`true\` value (\`{Boolean}\`) and with absolute \`context\` 1`] = ` -Object { - "assets": Array [ - "file-loader/test/fixtures/nested/assets/9c87cbf3ba33126ffd25ae7f2f6bbafb.png", - ], - "source": "module.exports = __webpack_public_path__ + \\"file-loader/test/fixtures/nested/assets/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", -} -`; - -exports[`when applied with \`useRelativePath\` option matches snapshot for \`true\` value (\`{Boolean}\`) and with relative \`context\` 1`] = ` -Object { - "assets": Array [ - "assets/9c87cbf3ba33126ffd25ae7f2f6bbafb.png", - ], - "source": "module.exports = __webpack_public_path__ + \\"assets/9c87cbf3ba33126ffd25ae7f2f6bbafb.png\\";", -} -`; diff --git a/test/errors.test.js b/test/errors.test.js index fb9f879..97510aa 100644 --- a/test/errors.test.js +++ b/test/errors.test.js @@ -1,14 +1,57 @@ import loader from '../src'; -describe('errors', () => { - it('validation errors', () => { - const err = () => - loader.call({ - query: { useRelativePath: 1 }, - emitFile: true, - }); - - expect(err).toThrow(); - expect(err).toThrowErrorMatchingSnapshot(); +describe('validation', () => { + it('errors', () => { + const validate = (options) => + loader.call( + Object.assign( + {}, + { + resourcePath: 'image.png', + query: options, + emitFile: () => {}, + } + ), + 'a { color: red; }' + ); + + expect(() => + validate({ unknown: 'unknown' }) + ).toThrowErrorMatchingSnapshot(); + + expect(() => validate({ name: '[path][name].[ext]' })).not.toThrow(); + expect(() => + validate({ + name: () => '[hash].[ext]', + }) + ).not.toThrow(); + expect(() => validate({ name: true })).toThrowErrorMatchingSnapshot(); + + expect(() => validate({ outputPath: 'assets' })).not.toThrow(); + expect(() => + validate({ + outputPath: () => 'assets', + }) + ).not.toThrow(); + expect(() => validate({ outputPath: true })).toThrowErrorMatchingSnapshot(); + + expect(() => validate({ publicPath: 'assets' })).not.toThrow(); + expect(() => + validate({ + publicPath: () => 'assets', + }) + ).not.toThrow(); + expect(() => validate({ publicPath: true })).toThrowErrorMatchingSnapshot(); + + expect(() => validate({ context: 'assets' })).not.toThrow(); + expect(() => validate({ context: true })).toThrowErrorMatchingSnapshot(); + + expect(() => validate({ emitFile: true })).not.toThrow(); + expect(() => validate({ emitFile: false })).not.toThrow(); + expect(() => validate({ emitFile: 'true' })).toThrowErrorMatchingSnapshot(); + + expect(() => validate({ regExp: /image\.png/ })).not.toThrow(); + expect(() => validate({ regExp: 'image\\.png' })).not.toThrow(); + expect(() => validate({ regExp: true })).toThrowErrorMatchingSnapshot(); }); }); diff --git a/test/outputPath-option.test.js b/test/outputPath-option.test.js index ac6b7a8..9905584 100644 --- a/test/outputPath-option.test.js +++ b/test/outputPath-option.test.js @@ -1,6 +1,20 @@ import webpack from './helpers/compiler'; describe('when applied with `outputPath` option', () => { + it('matches snapshot without value', async () => { + const config = { + loader: { + test: /(png|jpg|svg)/, + }, + }; + + const stats = await webpack('fixture.js', config); + const [module] = stats.toJson().modules; + const { assets, source } = module; + + expect({ assets, source }).toMatchSnapshot(); + }); + it('matches snapshot for `{String}` value', async () => { const config = { loader: { diff --git a/test/publicPath-option.test.js b/test/publicPath-option.test.js index cc153d6..6980fb2 100644 --- a/test/publicPath-option.test.js +++ b/test/publicPath-option.test.js @@ -1,6 +1,20 @@ import webpack from './helpers/compiler'; describe('when applied with `publicPath` option', () => { + it('matches snapshot without value', async () => { + const config = { + loader: { + test: /(png|jpg|svg)/, + }, + }; + + const stats = await webpack('fixture.js', config); + const [module] = stats.toJson().modules; + const { assets, source } = module; + + expect({ assets, source }).toMatchSnapshot(); + }); + it('matches snapshot for `{String}` value', async () => { const config = { loader: { diff --git a/test/useRelativePath-option.test.js b/test/useRelativePath-option.test.js deleted file mode 100644 index f7e9dfb..0000000 --- a/test/useRelativePath-option.test.js +++ /dev/null @@ -1,78 +0,0 @@ -import webpack from './helpers/compiler'; - -describe('when applied with `useRelativePath` option', () => { - it('matches snapshot for `false` value (`{Boolean}`)', async () => { - const config = { - loader: { - test: /(png|jpg|svg)/, - options: { - useRelativePath: false, - }, - }, - }; - - const stats = await webpack('nested/fixture.js', config); - const [module] = stats.toJson().modules; - const { assets, source } = module; - - expect({ assets, source }).toMatchSnapshot(); - }); - - it('matches snapshot for `true` value (`{Boolean}`)', async () => { - const config = { - loader: { - test: /(png|jpg|svg)/, - options: { - useRelativePath: true, - }, - }, - }; - - const stats = await webpack('nested/fixture.js', config); - const [module] = stats.toJson().modules; - const { assets, source } = module; - - expect({ assets, source }).toMatchSnapshot(); - }); - - it('matches snapshot for `true` value (`{Boolean}`) and with relative `context`', async () => { - const config = { - loader: { - test: /(png|jpg|svg)/, - options: { - context: './test/fixtures/nested/', - useRelativePath: true, - }, - }, - }; - - const stats = await webpack('nested/fixture.js', config); - const [module] = stats.toJson().modules; - const { assets, source } = module; - - expect({ assets, source }).toMatchSnapshot(); - }); - - it('matches snapshot for `true` value (`{Boolean}`) and with absolute `context`', async () => { - const config = { - loader: { - test: /(png|jpg|svg)/, - options: { - context: '../nested/', - useRelativePath: true, - }, - }, - }; - - const stats = await webpack('nested/fixture.js', config); - const [module] = stats.toJson().modules; - let { assets, source } = module; - - if (process.env.CIRCLECI) { - assets = [assets[0].replace('project', 'file-loader')]; - source = source.replace('project', 'file-loader'); - } - - expect({ assets, source }).toMatchSnapshot(); - }); -});