diff --git a/DOCS.md b/DOCS.md index 9fb41de..3ccb965 100644 --- a/DOCS.md +++ b/DOCS.md @@ -3,6 +3,7 @@ * [root](#root) * [alias](#alias) * [extensions](#extensions) + * [stripExtensions](#stripExtensions) * [cwd](#cwd) * [transformFunctions](#transformfunctions) * [resolvePath](#resolvepath) @@ -20,6 +21,7 @@ $ npm install --save-dev babel-plugin-module-resolver ``` Specify the plugin in your `.babelrc` with the custom root or alias. Here's an example: + ```json { "plugins": [ @@ -100,9 +102,29 @@ An array of extensions used in the resolver. ```json { "plugins": [ - ["module-resolver", { - "extensions": [".js", ".jsx", ".es", ".es6", ".mjs"] - }] + [ + "module-resolver", + { + "extensions": [".js", ".jsx", ".es", ".es6", ".mjs"] + } + ] + ] +} +``` + +## stripExtensions + +An array of extensions that will be stripped from file paths. Defaults to the `extensions` option value. + +```json +{ + "plugins": [ + [ + "module-resolver", + { + "stripExtensions": [".js", ".jsx", ".es", ".es6", ".mjs"] + } + ] ] } ``` diff --git a/src/normalizeOptions.js b/src/normalizeOptions.js index fd76adb..5eff27e 100644 --- a/src/normalizeOptions.js +++ b/src/normalizeOptions.js @@ -141,6 +141,7 @@ export default createSelector( const alias = normalizeAlias(opts.alias); const transformFunctions = normalizeTransformedFunctions(opts.transformFunctions); const extensions = opts.extensions || defaultExtensions; + const stripExtensions = opts.stripExtensions || extensions; const resolvePath = opts.resolvePath || defaultResolvePath; return { @@ -149,6 +150,7 @@ export default createSelector( alias, transformFunctions, extensions, + stripExtensions, resolvePath, }; }, diff --git a/src/resolvePath.js b/src/resolvePath.js index 11d0ca9..9858489 100644 --- a/src/resolvePath.js +++ b/src/resolvePath.js @@ -5,6 +5,17 @@ import mapToRelative from './mapToRelative'; import normalizeOptions from './normalizeOptions'; import { nodeResolvePath, replaceExtension, toLocalPath, toPosixPath } from './utils'; +function getRelativePath(sourcePath, currentFile, absFileInRoot, opts) { + const realSourceFileExtension = path.extname(absFileInRoot); + const sourceFileExtension = path.extname(sourcePath); + + let relativePath = mapToRelative(opts.cwd, currentFile, absFileInRoot); + if (realSourceFileExtension !== sourceFileExtension) { + relativePath = replaceExtension(relativePath, opts); + } + + return toLocalPath(toPosixPath(relativePath)); +} function findPathInRoots(sourcePath, { extensions, root }) { // Search the source path inside every custom root directory @@ -25,16 +36,7 @@ function resolvePathFromRootConfig(sourcePath, currentFile, opts) { return null; } - const realSourceFileExtension = path.extname(absFileInRoot); - const sourceFileExtension = path.extname(sourcePath); - - // Map the source and keep its extension if the import/require had one - const ext = realSourceFileExtension === sourceFileExtension ? realSourceFileExtension : ''; - return toLocalPath(toPosixPath(replaceExtension( - mapToRelative(opts.cwd, currentFile, absFileInRoot), - ext, - opts, - ))); + return getRelativePath(sourcePath, currentFile, absFileInRoot, opts); } function checkIfPackageExists(modulePath, currentFile, extensions) { diff --git a/src/utils.js b/src/utils.js index ceb87a7..4525fb9 100644 --- a/src/utils.js +++ b/src/utils.js @@ -21,21 +21,20 @@ export function toLocalPath(modulePath) { .replace(/^(?!\.)/, './'); // insert `./` to make it a local path } -export function stripExtension(modulePath, extensions) { - const [name, ...splits] = path.basename(modulePath).split('.'); - const fileExtension = `.${splits.join('.')}`; - return extensions.reduce((filename, extension) => { - // To allow filename to contain a dot - if (extension === fileExtension) { - // Strip extension - return name; +export function stripExtension(modulePath, stripExtensions) { + let name = path.basename(modulePath); + stripExtensions.some((extension) => { + if (name.endsWith(extension)) { + name = name.slice(0, name.length - extension.length); + return true; } - return filename; - }, path.basename(modulePath, path.extname(modulePath))); + return false; + }); + return name; } -export function replaceExtension(modulePath, ext, opts) { - const filename = stripExtension(modulePath, opts.extensions) + ext; +export function replaceExtension(modulePath, opts) { + const filename = stripExtension(modulePath, opts.stripExtensions); return path.join(path.dirname(modulePath), filename); } diff --git a/test/index.test.js b/test/index.test.js index 7faace4..38bd92e 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -241,7 +241,7 @@ describe('module-resolver', () => { plugins: [ [plugin, { root: './test/testproject/src', - extensions: ['.js', '.ios.js', '.android.js'], + extensions: ['.ios.js', '.android.js', '.js'], }], ], }; @@ -261,6 +261,43 @@ describe('module-resolver', () => { rootTransformerOpts, ); }); + + it('should resolve the file path with an explicit extension and not strip the extension', () => { + testWithImport( + 'rn/index.ios.js', + './test/testproject/src/rn/index.ios.js', + rootTransformerOpts, + ); + }); + }); + + describe('non-standard double extensions with strip extensions', () => { + const rootTransformerOpts = { + babelrc: false, + plugins: [ + [plugin, { + root: './test/testproject/src', + extensions: ['.js', '.ios.js', '.android.js'], + stripExtensions: [], + }], + ], + }; + + it('should not resolve the file path with an unknown extension', () => { + testWithImport( + 'text', + 'text', + rootTransformerOpts, + ); + }); + + it('should resolve the file path with a known defined extension', () => { + testWithImport( + 'rn', + './test/testproject/src/rn/index.ios.js', + rootTransformerOpts, + ); + }); }); describe('root and alias', () => {