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']