diff --git a/packages/wxt/e2e/tests/zip.test.ts b/packages/wxt/e2e/tests/zip.test.ts index 3ff265aad..efde648f8 100644 --- a/packages/wxt/e2e/tests/zip.test.ts +++ b/packages/wxt/e2e/tests/zip.test.ts @@ -285,4 +285,26 @@ describe('Zipping', () => { expect(await project.fileExists(sourcesZip)).toBe(false); }, ); + + it('exclude files in .zip except those with a bang !', async () => { + const project = new TestProject({ + name: 'test', + version: '1.0.0', + }); + project.addFile( + 'entrypoints/background.ts', + 'export default defineBackground(() => {});', + ); + const unzipDir = project.resolvePath('.output/test-1.0.0-chrome'); + const sourcesZip = project.resolvePath('.output/test-1.0.0-chrome.zip'); + + await project.zip({ + zip: { + exclude: ['**/*.json', '!manifest.json'], + }, + }); + + await extract(sourcesZip, { dir: unzipDir }); + expect(await project.fileExists(unzipDir, 'manifest.json')).toBe(true); + }); }); diff --git a/packages/wxt/src/core/zip.ts b/packages/wxt/src/core/zip.ts index 092d5c27d..e155739af 100644 --- a/packages/wxt/src/core/zip.ts +++ b/packages/wxt/src/core/zip.ts @@ -121,9 +121,19 @@ async function zipDir( onlyFiles: true, }) ).filter((relativePath) => { + const isNegated = options?.exclude?.some( + (option) => + option.startsWith('!') && minimatch(relativePath, option.slice(1)), + ); + if (isNegated) return true; + const updatedExcludeOptions = options?.exclude?.filter( + (option) => !option.startsWith('!'), + ); return ( options?.include?.some((pattern) => minimatch(relativePath, pattern)) || - !options?.exclude?.some((pattern) => minimatch(relativePath, pattern)) + !updatedExcludeOptions?.some((pattern) => + minimatch(relativePath, pattern), + ) ); }); const filesToZip = [