From f25a9db77d22c91ea8f6bd1ed31ea8415d0a7d5d Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Tue, 17 Sep 2024 04:46:39 +0200 Subject: [PATCH] feat: add support for async `injectStyle` (#1193) --- src/esbuild/postcss.ts | 13 ++++++------- src/index.ts | 1 + src/options.ts | 2 +- test/index.test.ts | 26 +++++++++++++++++++++++++- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/esbuild/postcss.ts b/src/esbuild/postcss.ts index 1c7540229..7312d7346 100644 --- a/src/esbuild/postcss.ts +++ b/src/esbuild/postcss.ts @@ -9,7 +9,7 @@ export const postcssPlugin = ({ cssLoader, }: { css?: Map - inject?: boolean | ((css: string, fileId: string) => string) + inject?: boolean | ((css: string, fileId: string) => string | Promise) cssLoader?: Loader }): Plugin => { return { @@ -122,12 +122,11 @@ export const postcssPlugin = ({ }) ).code - contents = - typeof inject === 'function' - ? inject(JSON.stringify(contents), args.path) - : `import styleInject from '#style-inject';styleInject(${JSON.stringify( - contents, - )})` + contents = typeof inject === 'function' + ? await Promise.resolve(inject(JSON.stringify(contents), args.path)) + : `import styleInject from '#style-inject';styleInject(${JSON.stringify( + contents, + )})` return { contents, diff --git a/src/index.ts b/src/index.ts index 828bcd1ca..b3551226f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -236,6 +236,7 @@ export async function build(_options: Options) { configName: item?.name, options: { ...options, // functions cannot be cloned + injectStyle: typeof options.injectStyle === 'function' ? undefined : options.injectStyle, banner: undefined, footer: undefined, esbuildPlugins: undefined, diff --git a/src/options.ts b/src/options.ts index fed227d8d..e239db07c 100644 --- a/src/options.ts +++ b/src/options.ts @@ -211,7 +211,7 @@ export type Options = { * Inject CSS as style tags to document head * @default {false} */ - injectStyle?: boolean | ((css: string, fileId: string) => string) + injectStyle?: boolean | ((css: string, fileId: string) => string | Promise) /** * Inject cjs and esm shims if needed * @default false diff --git a/test/index.test.ts b/test/index.test.ts index 5b07554fe..5b42572e2 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -806,7 +806,7 @@ test(`should generate export {} when there are no exports in source file`, async expect(await getFileContent('dist/input.d.mts')).toMatch(/export {\s*}/) }) -test('custom inject style function', async () => { +test('custom inject style function - sync', async () => { const { outFiles, getFileContent } = await run(getTestName(), { 'input.ts': `import './style.css'`, 'style.css': `.hello { color: red }`, @@ -829,6 +829,30 @@ test('custom inject style function', async () => { ) }) +test('custom inject style function - async', async () => { + const { outFiles, getFileContent } = await run(getTestName(), { + 'input.ts': `import './style.css'`, + 'style.css': `.hello { color: red }`, + 'tsup.config.ts': ` + export default { + entry: ['src/input.ts'], + minify: true, + format: ['esm', 'cjs'], + injectStyle: async (css) => { + await new Promise(resolve => setTimeout(resolve, 100)); + return "__custom_async_inject_style__(" + css +")"; + } + }`, + }) + expect(outFiles).toEqual(['input.js', 'input.mjs']) + expect(await getFileContent('dist/input.mjs')).toContain( + '__custom_async_inject_style__(`.hello{color:red}\n`)', + ) + expect(await getFileContent('dist/input.js')).toContain( + '__custom_async_inject_style__(`.hello{color:red}\n`)', + ) +}) + test('preserve top-level variable for IIFE format', async () => { const { outFiles, getFileContent } = await run(getTestName(), { 'input.ts': `export default 'foo'`,