Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 08b6360

Browse files
authored
feat: compose addon hooks (#2007)
resolves #1999
1 parent 3fe402c commit 08b6360

4 files changed

Lines changed: 124 additions & 4 deletions

File tree

packages/rolldown/src/utils/compose-js-plugins.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import { AssertNever } from './type-assert'
99

1010
const unsupportedHookName = [
1111
'augmentChunkHash',
12-
'banner',
13-
'footer',
1412
'generateBundle',
1513
'moduleParsed',
1614
'onLog',
@@ -23,8 +21,6 @@ const unsupportedHookName = [
2321
// FIXME: Conflict with the `skip` option in `PluginContext#resolve`. Since we can't detect it in advance,
2422
// we have to bailout all plugins with `resolveId` hook.
2523
'resolveId',
26-
'intro',
27-
'outro',
2824
] as const
2925
const unsupportedHooks: Set<string> = new Set(unsupportedHookName)
3026

@@ -108,6 +104,16 @@ function createComposedPlugin(plugins: Plugin[]): Plugin {
108104
}
109105
break
110106
}
107+
case 'banner':
108+
case 'footer':
109+
case 'intro':
110+
case 'outro': {
111+
const hook = plugin[pluginProp]
112+
if (hook) {
113+
;(batchedHooks[pluginProp] ??= []).push(hook)
114+
}
115+
break
116+
}
111117
default: {
112118
// All known hooks should be handled above.
113119
// User-defined custom properties will hit this branch and it's ok. Just ignore them.
@@ -236,6 +242,29 @@ function createComposedPlugin(plugins: Plugin[]): Plugin {
236242
}
237243
break
238244
}
245+
case 'banner':
246+
case 'footer':
247+
case 'intro':
248+
case 'outro': {
249+
const hooks = batchedHooks[hookName]
250+
if (hooks?.length) {
251+
composed[hookName] = async function (chunk) {
252+
const ret: string[] = []
253+
for (const hook of hooks) {
254+
{
255+
const { handler } = normalizeHook(hook)
256+
ret.push(
257+
typeof handler === 'string'
258+
? handler
259+
: await handler.call(this, chunk),
260+
)
261+
}
262+
}
263+
return ret.join('\n')
264+
}
265+
}
266+
break
267+
}
239268
default: {
240269
// Supported hooks should be handled above, otherwise it should be filtered out in the beginning.
241270
type _ExhaustiveCheck = AssertNever<typeof hookName>

packages/rolldown/tests/compose-plugins.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,43 @@ describe('compose-plugins', () => {
2020
const composed = composePlugins(plugins)
2121
expect(composed.length).toBe(1)
2222
})
23+
24+
it('should compose `banner`, `footer`, `intro`, `outro` hooks', () => {
25+
const plugins: Plugin[] = [
26+
{
27+
name: 'test-plugin-1',
28+
banner: '/*banner1*/',
29+
},
30+
{
31+
name: 'test-plugin-2',
32+
banner: () => '/*banner2*/',
33+
},
34+
{
35+
name: 'test-plugin-3',
36+
footer: '/*footer1*/',
37+
},
38+
{
39+
name: 'test-plugin-4',
40+
footer: () => '/*footer2*/',
41+
},
42+
{
43+
name: 'test-plugin-5',
44+
intro: '/*intro1*/',
45+
},
46+
{
47+
name: 'test-plugin-6',
48+
intro: () => '/*intro2*/',
49+
},
50+
{
51+
name: 'test-plugin-7',
52+
outro: '/*outro1*/',
53+
},
54+
{
55+
name: 'test-plugin-8',
56+
outro: () => '/*outro2*/',
57+
},
58+
]
59+
const composed = composePlugins(plugins)
60+
expect(composed.length).toBe(1)
61+
})
2362
})
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { expect } from 'vitest'
2+
import path from 'node:path'
3+
import { defineTest } from '@tests'
4+
5+
const entry = path.join(__dirname, './main.js')
6+
7+
export default defineTest({
8+
config: {
9+
input: entry,
10+
plugins: [
11+
{
12+
name: 'test-plugin-1',
13+
banner: '/*banner1*/',
14+
},
15+
{
16+
name: 'test-plugin-2',
17+
banner: () => '/*banner2*/',
18+
},
19+
{
20+
name: 'test-plugin-3',
21+
footer: '/*footer1*/',
22+
},
23+
{
24+
name: 'test-plugin-4',
25+
footer: () => '/*footer2*/',
26+
},
27+
{
28+
name: 'test-plugin-5',
29+
intro: '/*intro1*/',
30+
},
31+
{
32+
name: 'test-plugin-6',
33+
intro: () => '/*intro2*/',
34+
},
35+
{
36+
name: 'test-plugin-7',
37+
outro: '/*outro1*/',
38+
},
39+
{
40+
name: 'test-plugin-8',
41+
outro: () => '/*outro2*/',
42+
},
43+
],
44+
},
45+
afterTest: (output) => {
46+
expect(output.output[0].code).toMatch(/\/\*banner1\*\/\n\/\*banner2\*\//)
47+
expect(output.output[0].code).toMatch(/\/\*footer1\*\/\n\/\*footer2\*\//)
48+
expect(output.output[0].code).toMatch(/\/\*intro1\*\/\n\/\*intro2\*\//)
49+
expect(output.output[0].code).toMatch(/\/\*outro1\*\/\n\/\*outro2\*\//)
50+
},
51+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log()

0 commit comments

Comments
 (0)