From f22cb6838caa14e30b33f9115d5626eaf588c484 Mon Sep 17 00:00:00 2001 From: Matthieu Lemoine Date: Thu, 17 Aug 2017 06:41:17 +0200 Subject: [PATCH] fix: Fix strip extensions for RN support (#205) --- README.md | 18 +++++++++++++++ src/resolvePath.js | 1 + src/utils.js | 17 ++++++++++++-- test/index.test.js | 28 ++++++++++++++++++++++++ test/testproject/src/rn/index.android.js | 0 test/testproject/src/rn/index.ios.js | 0 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 test/testproject/src/rn/index.android.js create mode 100644 test/testproject/src/rn/index.ios.js diff --git a/README.md b/README.md index 11cea6e..a029974 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,24 @@ To use the backslash character (`\`) just escape it like so: `'\\\\'` (double es If you're using ESLint, you should use [eslint-plugin-import][eslint-plugin-import], and [eslint-import-resolver-babel-module][eslint-import-resolver-babel-module] to remove falsy unresolved modules. +## Usage with React Native + +To let the packager resolve the right module for each platform, you have to add the ```.ios.js```and ```.android.js``` extensions : + +```json +{ + "plugins": [ + [ + "module-resolver", + { + "root": ["./src"], + "extensions": [".js", ".ios.js", ".android.js"] + } + ] + ] +} +``` + ## Usage with Flow To allow Flow to find your modules, add configuration options diff --git a/src/resolvePath.js b/src/resolvePath.js index 8ac816d..bb05a76 100644 --- a/src/resolvePath.js +++ b/src/resolvePath.js @@ -33,6 +33,7 @@ function resolvePathFromRootConfig(sourcePath, currentFile, opts) { return toLocalPath(toPosixPath(replaceExtension( mapToRelative(opts.cwd, currentFile, absFileInRoot), ext, + opts, ))); } diff --git a/src/utils.js b/src/utils.js index 8dd8907..ceb87a7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -21,8 +21,21 @@ export function toLocalPath(modulePath) { .replace(/^(?!\.)/, './'); // insert `./` to make it a local path } -export function replaceExtension(modulePath, ext) { - const filename = path.basename(modulePath, path.extname(modulePath)) + ext; +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; + } + return filename; + }, path.basename(modulePath, path.extname(modulePath))); +} + +export function replaceExtension(modulePath, ext, opts) { + const filename = stripExtension(modulePath, opts.extensions) + ext; return path.join(path.dirname(modulePath), filename); } diff --git a/test/index.test.js b/test/index.test.js index aa6c098..df2d0c4 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -235,6 +235,34 @@ describe('module-resolver', () => { }); }); + describe('non-standard double extensions', () => { + const rootTransformerOpts = { + babelrc: false, + plugins: [ + [plugin, { + root: './test/testproject/src', + extensions: ['.js', '.ios.js', '.android.js'], + }], + ], + }; + + 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 & strip the extension', () => { + testWithImport( + 'rn', + './test/testproject/src/rn', + rootTransformerOpts, + ); + }); + }); + describe('root and alias', () => { const rootTransformerOpts = { babelrc: false, diff --git a/test/testproject/src/rn/index.android.js b/test/testproject/src/rn/index.android.js new file mode 100644 index 0000000..e69de29 diff --git a/test/testproject/src/rn/index.ios.js b/test/testproject/src/rn/index.ios.js new file mode 100644 index 0000000..e69de29