diff --git a/packages/babel/README.md b/packages/babel/README.md index 110886e8a..cc5437a86 100644 --- a/packages/babel/README.md +++ b/packages/babel/README.md @@ -92,6 +92,21 @@ Type: `String | RegExp | Array[...String|RegExp]`
A [minimatch pattern](https://github.com/isaacs/minimatch), or array of patterns, which specifies the files in the build the plugin should operate on. When relying on Babel configuration files you cannot include files already excluded there. +### `filter` + +Type: (id: string) => boolean
+ +Custom [filter function](https://github.com/rollup/plugins/tree/master/packages/pluginutils#createfilter) can be used to determine whether or not certain modules should be operated upon. + +Usage: + +```js +import { createFilter } from '@rollup/pluginutils'; +const include = 'include/**.js'; +const exclude = 'exclude/**.js'; +const filter = createFilter(include, exclude, {}); +``` + ### `extensions` Type: `Array[...String]`
diff --git a/packages/babel/src/index.js b/packages/babel/src/index.js index 25144027e..e631522d3 100644 --- a/packages/babel/src/index.js +++ b/packages/babel/src/index.js @@ -122,12 +122,14 @@ function createBabelInputPluginFactory(customCallback = returnObject) { let exclude; let include; let extensions; + let customFilter; ({ exclude, extensions, babelHelpers, include, + filter: customFilter, skipPreflightCheck, ...babelOptions } = unpackInputPluginOptions(pluginOptionsWithOverrides, this.meta.rollupVersion)); @@ -135,8 +137,12 @@ function createBabelInputPluginFactory(customCallback = returnObject) { const extensionRegExp = new RegExp( `(${extensions.map(escapeRegExpCharacters).join('|')})$` ); - const includeExcludeFilter = createFilter(include, exclude); - filter = (id) => extensionRegExp.test(stripQuery(id).bareId) && includeExcludeFilter(id); + if (customFilter && (include || exclude)) { + throw new Error('Could not handle include or exclude with custom filter together'); + } + const userDefinedFilter = + typeof customFilter === 'function' ? customFilter : createFilter(include, exclude); + filter = (id) => extensionRegExp.test(stripQuery(id).bareId) && userDefinedFilter(id); return null; }, diff --git a/packages/babel/test/as-input-plugin.js b/packages/babel/test/as-input-plugin.js index 32109c4ba..f6e4af33b 100644 --- a/packages/babel/test/as-input-plugin.js +++ b/packages/babel/test/as-input-plugin.js @@ -6,6 +6,7 @@ import { rollup } from 'rollup'; import { SourceMapConsumer } from 'source-map'; import jsonPlugin from '@rollup/plugin-json'; import nodeResolvePlugin from '@rollup/plugin-node-resolve'; +import { createFilter } from '@rollup/pluginutils'; import { getCode } from '../../../util/test'; @@ -101,6 +102,65 @@ console.log("the answer is ".concat(foo())); ); }); +test('does not babelify excluded code with custom filter', async (t) => { + const filter = createFilter([], '**/foo.js'); + const code = await generate('fixtures/exclusions/main.js', { filter }); + // eslint-disable-next-line no-template-curly-in-string + t.false(code.includes('${foo()}')); + t.true(code.includes('=> 42')); + t.is( + code, + `'use strict'; + +const foo = () => 42; + +console.log("the answer is ".concat(foo())); +` + ); +}); + +test('does babelify included code with custom filter', async (t) => { + const filter = createFilter('**/foo.js', [], { + resolve: __dirname + }); + const code = await generate('fixtures/exclusions/main.js', { filter }); + // eslint-disable-next-line no-template-curly-in-string + t.true(code.includes('${foo()}')); + t.false(code.includes('=> 42')); + t.is( + code, + `'use strict'; + +var foo = function foo() { + return 42; +}; + +console.log(\`the answer is \${foo()}\`); +` + ); +}); + +test('can not pass include or exclude when custom filter specified', async (t) => { + const filter = createFilter('**/foo.js', [], { + resolve: __dirname + }); + let errorWithExclude = ''; + try { + await generate('fixtures/exclusions/main.js', { filter, exclude: [] }); + } catch (e) { + errorWithExclude = e.message; + } + t.true(!!errorWithExclude); + + let errorWithInclude = ''; + try { + await generate('fixtures/exclusions/main.js', { filter, include: [] }); + } catch (e) { + errorWithInclude = e.message; + } + t.true(!!errorWithInclude); +}); + test('generates sourcemap by default', async (t) => { const bundle = await rollup({ input: 'fixtures/class/main.js', diff --git a/packages/babel/types/index.d.ts b/packages/babel/types/index.d.ts index 52c9558be..3ba0195f4 100644 --- a/packages/babel/types/index.d.ts +++ b/packages/babel/types/index.d.ts @@ -1,5 +1,5 @@ import { Plugin, PluginContext, TransformPluginContext } from 'rollup'; -import { FilterPattern } from '@rollup/pluginutils'; +import { FilterPattern, CreateFilter } from '@rollup/pluginutils'; import * as babelCore from '@babel/core'; export interface RollupBabelInputPluginOptions @@ -14,6 +14,16 @@ export interface RollupBabelInputPluginOptions * @default undefined; */ exclude?: FilterPattern; + /** + * Custom filter function can be used to determine whether or not certain modules should be operated upon. + * Example: + * import { createFilter } from '@rollup/pluginutils'; + * const include = 'include/**.js'; + * const exclude = 'exclude/**.js'; + * const filter = createFilter(include, exclude, {}); + * @default undefined; + */ + filter?: ReturnType; /** * An array of file extensions that Babel should transpile. If you want to transpile TypeScript files with this plugin it's essential to include .ts and .tsx in this option. * @default ['.js', '.jsx', '.es6', '.es', '.mjs']