rollup / plugins

🍣 The one-stop shop for official Rollup plugins
MIT License
3.57k stars 568 forks source link

Typescript plugin behaves differently depending on whether the `include` option is a string or a regular expression #1651

Open ericmorand opened 6 months ago

ericmorand commented 6 months ago

This is a follow-up to #1650.

Rollup Plugin Name: @rollup/plugin-typescript Rollup Plugin Version: 11.1.5 Rollup Version: 4.9.0 Operating System (or Browser): Ubuntu Node Version: 16.20 Link to reproduction: https://github.com/ericmorand/rollup-plugin-typescript-issue

Expected Behavior

Passing a regular expression or a string representation of the regular expression should gives the same result.

Said differently, passing /\.ts$/ or './ts$' should gives the same result.

Actual Behavior

After investigating on #1650, I discovered that the Typescript plugin behaves differently depending on whether the include option is a string or a regular expression:

Hence:

Which is unexpected as both are strictly identical from the point of view of picomatch.

I think that either the bug should be fixed, or the documentation of the plugin should clearly express the difference of behaviour instead of just saying:

A picomatch pattern, or array of patterns, which specifies the files in the build the plugin should operate on. By default all .ts and .tsx files are targeted.

ericmorand commented 6 months ago

Actually, it seems to come from @rollup/pluginutils itself:

https://github.com/rollup/plugins/blob/33174f956304ab4aad4bbaba656f627c31679dc5/packages/pluginutils/src/createFilter.ts#L30

There, the createFilter method behaves differently depending on the type of the pattern: if it is a regular expression, it is used as-is; if it is a string, a regular expression is created from it and the current working directory, hence preventing plugins to handle files located outside of the working directory.

Is this a deliberate move or a bug? If it is a deliberate move, what is the rational?

For information, it forces plugin developers to transform the passed options to regular expressions to make sure that their plugin works in every situation, for example my own TypeScript plugin:

options.include = options.include || /\.(cts|mts|ts|tsx)$/;

if (typeof options.include === "string") {
    options.include = [options.include];
}

if (Array.isArray(options.include)) {
    options.include = options.include.map((include) => {
        if (typeof include === "string") {
            return new RegExp(include);
        }

        return include;
    });
}