Skip to content

Commit

Permalink
feat: support nested plugin (#4657)
Browse files Browse the repository at this point in the history
* feat: support nested plugin

* refactor

* chore: rm

* fix: types

* fix: types

* refactor: extract
  • Loading branch information
sxzz committed Oct 12, 2022
1 parent e52bea3 commit f7b7689
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 24 deletions.
19 changes: 9 additions & 10 deletions cli/run/commandPlugins.ts
@@ -1,28 +1,29 @@
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import type { InputOptions } from '../../src/rollup/types';
import type { InputOptionsWithPlugins } from '../../src/rollup/types';
import { normalizePluginOption } from '../../src/utils/options/options';
import { stdinPlugin } from './stdin';
import { waitForInputPlugin } from './waitForInput';

export async function addCommandPluginsToInputOptions(
inputOptions: InputOptions,
inputOptions: InputOptionsWithPlugins,
command: Record<string, unknown>
): Promise<void> {
if (command.stdin !== false) {
inputOptions.plugins!.push(stdinPlugin(command.stdin));
inputOptions.plugins.push(stdinPlugin(command.stdin));
}
if (command.waitForBundleInput === true) {
inputOptions.plugins!.push(waitForInputPlugin());
inputOptions.plugins.push(waitForInputPlugin());
}
await addPluginsFromCommandOption(command.plugin, inputOptions);
}

export async function addPluginsFromCommandOption(
commandPlugin: unknown,
inputOptions: InputOptions
inputOptions: InputOptionsWithPlugins
): Promise<void> {
if (commandPlugin) {
const plugins = Array.isArray(commandPlugin) ? commandPlugin : [commandPlugin];
const plugins: any[] = normalizePluginOption(commandPlugin as any);
for (const plugin of plugins) {
if (/[={}]/.test(plugin)) {
// -p plugin=value
Expand All @@ -40,7 +41,7 @@ export async function addPluginsFromCommandOption(
}

async function loadAndRegisterPlugin(
inputOptions: InputOptions,
inputOptions: InputOptionsWithPlugins,
pluginText: string
): Promise<void> {
let plugin: any = null;
Expand Down Expand Up @@ -96,9 +97,7 @@ async function loadAndRegisterPlugin(
)}" for Rollup to recognize it.`
);
}
inputOptions.plugins!.push(
typeof plugin === 'function' ? plugin.call(plugin, pluginArg) : plugin
);
inputOptions.plugins.push(typeof plugin === 'function' ? plugin.call(plugin, pluginArg) : plugin);
}

function getCamelizedPluginBaseName(pluginText: string): string {
Expand Down
8 changes: 4 additions & 4 deletions docs/999-big-list-of-options.md
Expand Up @@ -258,9 +258,9 @@ this.a.b.c = ...
#### output.plugins
Type: `OutputPlugin | (OutputPlugin | void)[]`
Type: `OutputPlugin | (OutputPlugin | OutputPlugin[] | void)[]`
Adds a plugin just to this output. See [Using output plugins](guide/en/#using-output-plugins) for more information on how to use output-specific plugins and [Plugins](guide/en/#plugin-development) on how to write your own. For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins.
Adds a plugin just to this output. See [Using output plugins](guide/en/#using-output-plugins) for more information on how to use output-specific plugins and [Plugins](guide/en/#plugin-development) on how to write your own. For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. Nested plugins will be flatten.
Not every plugin can be used here. `output.plugins` is limited to plugins that only use hooks that run during `bundle.generate()` or `bundle.write()`, i.e. after Rollup's main analysis is complete. If you are a plugin author, see [output generation hooks](guide/en/#output-generation-hooks) to find out which hooks can be used.
Expand Down Expand Up @@ -288,9 +288,9 @@ export default {
#### plugins
Type: `Plugin | (Plugin | void)[]`
Type: `Plugin | (Plugin | Plugin[] | void)[]`
See [Using plugins](guide/en/#using-plugins) for more information on how to use plugins and [Plugins](guide/en/#plugin-development) on how to write your own (try it out, it's not as difficult as it may sound and very much extends what you can do with Rollup). For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins.
See [Using plugins](guide/en/#using-plugins) for more information on how to use plugins and [Plugins](guide/en/#plugin-development) on how to write your own (try it out, it's not as difficult as it may sound and very much extends what you can do with Rollup). For plugins imported from packages, remember to call the imported plugin function (i.e. `commonjs()`, not just `commonjs`). Falsy plugins will be ignored, which can be used to easily activate or deactivate plugins. Nested plugins will be flatten.
```js
// rollup.config.js
Expand Down
14 changes: 11 additions & 3 deletions src/rollup/types.d.ts
Expand Up @@ -492,6 +492,8 @@ export type SourcemapPathTransformOption = (
sourcemapPath: string
) => string;

export type InputPluginOption = Plugin | null | false | undefined | InputPluginOption[];

export interface InputOptions {
acorn?: Record<string, unknown>;
acornInjectPlugins?: (() => unknown)[] | (() => unknown);
Expand All @@ -511,7 +513,7 @@ export interface InputOptions {
moduleContext?: ((id: string) => string | null | void) | { [id: string]: string };
onwarn?: WarningHandlerWithDefault;
perf?: boolean;
plugins?: (Plugin | null | false | undefined)[];
plugins?: InputPluginOption;
preserveEntrySignatures?: PreserveEntrySignaturesOption;
/** @deprecated Use the "preserveModules" output option instead. */
preserveModules?: boolean;
Expand All @@ -522,6 +524,10 @@ export interface InputOptions {
watch?: WatcherOptions | false;
}

export interface InputOptionsWithPlugins extends InputOptions {
plugins: Plugin[];
}

export interface NormalizedInputOptions {
acorn: Record<string, unknown>;
acornInjectPlugins: (() => unknown)[];
Expand Down Expand Up @@ -610,6 +616,8 @@ export type NormalizedAmdOptions = (

type AddonFunction = (chunk: RenderedChunk) => string | Promise<string>;

type OutputPluginOption = OutputPlugin | null | false | undefined | OutputPluginOption[];

export interface OutputOptions {
amd?: AmdOptions;
assetFileNames?: string | ((chunkInfo: PreRenderedAsset) => string);
Expand Down Expand Up @@ -647,7 +655,7 @@ export interface OutputOptions {
noConflict?: boolean;
outro?: string | AddonFunction;
paths?: OptionsPaths;
plugins?: (OutputPlugin | null | false | undefined)[];
plugins?: OutputPluginOption;
/** @deprecated Use "generatedCode.constBindings" instead. */
preferConst?: boolean;
preserveModules?: boolean;
Expand Down Expand Up @@ -800,7 +808,7 @@ export interface RollupOptions extends InputOptions {
output?: OutputOptions | OutputOptions[];
}

export interface MergedRollupOptions extends InputOptions {
export interface MergedRollupOptions extends InputOptionsWithPlugins {
output: OutputOptions[];
}

Expand Down
7 changes: 5 additions & 2 deletions src/utils/options/mergeOptions.ts
@@ -1,8 +1,10 @@
import type {
ExternalOption,
InputOptions,
InputPluginOption,
MergedRollupOptions,
OutputOptions,
OutputPluginOption,
RollupCache,
WarningHandler,
WarningHandlerWithDefault
Expand All @@ -13,6 +15,7 @@ import {
defaultOnWarn,
generatedCodePresets,
type GenericConfigObject,
normalizePluginOption,
objectifyOption,
objectifyOptionWithPresets,
treeshakePresets,
Expand Down Expand Up @@ -126,7 +129,7 @@ function mergeInputOptions(
moduleContext: getOption('moduleContext'),
onwarn: getOnWarn(config, defaultOnWarnHandler),
perf: getOption('perf'),
plugins: ensureArray(config.plugins) as Plugin[],
plugins: normalizePluginOption(config.plugins as InputPluginOption),
preserveEntrySignatures: getOption('preserveEntrySignatures'),
preserveModules: getOption('preserveModules'),
preserveSymlinks: getOption('preserveSymlinks'),
Expand Down Expand Up @@ -261,7 +264,7 @@ function mergeOutputOptions(
noConflict: getOption('noConflict'),
outro: getOption('outro'),
paths: getOption('paths'),
plugins: ensureArray(config.plugins) as Plugin[],
plugins: normalizePluginOption(config.plugins as OutputPluginOption),
preferConst: getOption('preferConst'),
preserveModules: getOption('preserveModules'),
preserveModulesRoot: getOption('preserveModulesRoot'),
Expand Down
3 changes: 2 additions & 1 deletion src/utils/options/normalizeInputOptions.ts
Expand Up @@ -16,6 +16,7 @@ import {
defaultOnWarn,
type GenericConfigObject,
getOptionWithPreset,
normalizePluginOption,
treeshakePresets,
warnUnknownOptions
} from './options';
Expand Down Expand Up @@ -54,7 +55,7 @@ export function normalizeInputOptions(config: InputOptions): {
moduleContext: getModuleContext(config, context),
onwarn,
perf: config.perf || false,
plugins: ensureArray(config.plugins),
plugins: normalizePluginOption(config.plugins),
preserveEntrySignatures: config.preserveEntrySignatures ?? 'exports-only',
preserveModules: getPreserveModules(config, onwarn, strictDeprecations),
preserveSymlinks: config.preserveSymlinks || false,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/options/normalizeOutputOptions.ts
Expand Up @@ -6,7 +6,6 @@ import type {
OutputOptions,
SourcemapPathTransformOption
} from '../../rollup/types';
import { ensureArray } from '../ensureArray';
import { errInvalidExportOptionValue, errInvalidOption, error, warnDeprecation } from '../error';
import { resolve } from '../path';
import { sanitizeFileName as defaultSanitizeFileName } from '../sanitizeFileName';
Expand All @@ -15,6 +14,7 @@ import {
generatedCodePresets,
type GenericConfigObject,
getOptionWithPreset,
normalizePluginOption,
warnUnknownOptions
} from './options';

Expand Down Expand Up @@ -68,7 +68,7 @@ export function normalizeOutputOptions(
noConflict: config.noConflict || false,
outro: getAddon(config, 'outro'),
paths: config.paths || {},
plugins: ensureArray(config.plugins),
plugins: normalizePluginOption(config.plugins),
preferConst,
preserveModules,
preserveModulesRoot: getPreserveModulesRoot(config),
Expand Down
9 changes: 9 additions & 0 deletions src/utils/options/options.ts
@@ -1,9 +1,13 @@
import type {
InputOptions,
InputPluginOption,
NormalizedGeneratedCodeOptions,
NormalizedOutputOptions,
NormalizedTreeshakingOptions,
OutputOptions,
OutputPlugin,
OutputPluginOption,
Plugin,
WarningHandler
} from '../../rollup/types';
import { errInvalidOption, error, errUnknownOption } from '../error';
Expand Down Expand Up @@ -145,3 +149,8 @@ export const getOptionWithPreset = <T extends ObjectOptionWithPresets>(

const getHashFromObjectOption = (optionName: string): string =>
optionName.split('.').join('').toLowerCase();

export const normalizePluginOption: {
(plugins: InputPluginOption): Plugin[];
(plugins: OutputPluginOption): OutputPlugin[];
} = (plugins: any) => [plugins].flat(Infinity).filter(Boolean);
9 changes: 7 additions & 2 deletions src/utils/timers.ts
@@ -1,4 +1,9 @@
import type { InputOptions, Plugin, PluginHooks, SerializedTimings } from '../rollup/types';
import type {
NormalizedInputOptions,
Plugin,
PluginHooks,
SerializedTimings
} from '../rollup/types';
import performance from './performance';
import process from './process';

Expand Down Expand Up @@ -117,7 +122,7 @@ function getPluginWithTimers(plugin: any, index: number): Plugin {
return plugin;
}

export function initialiseTimers(inputOptions: InputOptions): void {
export function initialiseTimers(inputOptions: NormalizedInputOptions): void {
if (inputOptions.perf) {
timers = new Map();
timeStart = timeStartImpl;
Expand Down
22 changes: 22 additions & 0 deletions test/function/samples/nested-plugin/_config.js
@@ -0,0 +1,22 @@
const plugin = [
{
name: 'nested-plugin-1',
transform(code) {
return code.replace('foo = 1', 'foo = 2');
}
},
{
name: 'nested-plugin-2',
transform(code) {
return code.replace('answer = 41', 'answer = 42');
}
}
];

module.exports = {
description: 'works when nested plugin',
options: {
// eslint-disable-next-line no-sparse-arrays
plugins: [plugin, [undefined, [null]], ,]
}
};
5 changes: 5 additions & 0 deletions test/function/samples/nested-plugin/main.js
@@ -0,0 +1,5 @@
const foo = 1;
const answer = 41;

assert.equal(foo, 2);
assert.equal(answer, 42);

0 comments on commit f7b7689

Please sign in to comment.