Skip to content

Commit

Permalink
feat: Automatically convert MV3 web_accessible_resources to MV2 (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 authored Feb 6, 2024
1 parent b32c60c commit 22f82a6
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 13 deletions.
49 changes: 49 additions & 0 deletions src/core/utils/__tests__/manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,55 @@ describe('Manifest Utils', () => {
'content-scripts/one.css',
]);
});

it('should convert mv3 items to mv2 strings automatically', async () => {
setFakeWxt({
config: {
outDir,
manifestVersion: 2,
manifest: {
web_accessible_resources: [
{
matches: ['*://*/*'],
resources: ['/icon-128.png'],
},
{
matches: ['https://google.com'],
resources: ['/icon-128.png', '/icon-32.png'],
},
],
},
},
});

const { manifest: actual } = await generateManifest(
[],
fakeBuildOutput(),
);

expect(actual.web_accessible_resources).toEqual([
'/icon-128.png',
'/icon-32.png',
]);
});

it('should convert mv2 strings to mv3 items with a warning automatically', async () => {
setFakeWxt({
config: {
outDir,
manifestVersion: 3,
manifest: {
web_accessible_resources: ['/icon.svg'],
},
},
});

await expect(() =>
generateManifest([], fakeBuildOutput()),
).rejects.toThrow(
'Non-MV3 web_accessible_resources detected: ["/icon.svg"]. When manually defining web_accessible_resources, define them as MV3 objects ({ matches: [...], resources: [...] }), and WXT will automatically convert them to MV2 when necessary.',
);
});
});

describe('transformManifest option', () => {
Expand Down
70 changes: 57 additions & 13 deletions src/core/utils/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export async function generateManifest(
};
const userManifest = wxt.config.manifest;

const manifest = defu(
let manifest = defu(
userManifest,
baseManifest,
) as Manifest.WebExtensionManifest;
Expand Down Expand Up @@ -116,6 +116,13 @@ export async function generateManifest(
wxt.config.transformManifest(manifest);
await wxt.hooks.callHook('build:manifestGenerated', wxt, manifest);

if (wxt.config.manifestVersion === 2)
convertWebAccessibleResourcesToMv2(manifest);

if (wxt.config.manifestVersion === 3) {
validateMv3WebAccessbileResources(manifest);
}

if (manifest.name == null)
throw Error(
"Manifest 'name' is missing. Either:\n1. Set the name in your <rootDir>/package.json\n2. Set a name via the manifest option in your wxt.config.ts",
Expand Down Expand Up @@ -501,25 +508,22 @@ export function getContentScriptCssWebAccessibleResources(
contentScripts: ContentScriptEntrypoint[],
contentScriptCssMap: Record<string, string | undefined>,
): any[] {
const resources: any[] = [];
const resources: Manifest.WebExtensionManifestWebAccessibleResourcesC2ItemType[] =
[];

contentScripts.forEach((script) => {
if (script.options.cssInjectionMode !== 'ui') return;

const cssFile = contentScriptCssMap[script.name];
if (cssFile == null) return;

if (wxt.config.manifestVersion === 2) {
resources.push(cssFile);
} else {
resources.push({
resources: [cssFile],
matches: resolvePerBrowserOption(
script.options.matches,
wxt.config.browser,
).map((matchPattern) => stripPathFromMatchPattern(matchPattern)),
});
}
resources.push({
resources: [cssFile],
matches: resolvePerBrowserOption(
script.options.matches,
wxt.config.browser,
).map((matchPattern) => stripPathFromMatchPattern(matchPattern)),
});
});

return resources;
Expand Down Expand Up @@ -573,3 +577,43 @@ export function stripPathFromMatchPattern(pattern: string) {
const startOfPath = pattern.indexOf('/', protocolSepIndex + 3);
return pattern.substring(0, startOfPath) + '/*';
}

/**
* Converts all MV3 web accessible resources to their MV2 forms. MV3 web accessible resources are
* generated in this file, and may be defined by the user in their manifest. In both cases, when
* targetting MV2, automatically convert their definitions down to the basic MV2 array.
*/
export function convertWebAccessibleResourcesToMv2(
manifest: Manifest.WebExtensionManifest,
): void {
if (manifest.web_accessible_resources == null) return;

manifest.web_accessible_resources = Array.from(
new Set(
manifest.web_accessible_resources.flatMap((item) => {
if (typeof item === 'string') return item;
return item.resources;
}),
),
);
}

/**
* Make sure all resources are in MV3 format. If not, add a wanring
*/
export function validateMv3WebAccessbileResources(
manifest: Manifest.WebExtensionManifest,
): void {
if (manifest.web_accessible_resources == null) return;

const stringResources = manifest.web_accessible_resources.filter(
(item) => typeof item === 'string',
);
if (stringResources.length > 0) {
throw Error(
`Non-MV3 web_accessible_resources detected: ${JSON.stringify(
stringResources,
)}. When manually defining web_accessible_resources, define them as MV3 objects ({ matches: [...], resources: [...] }), and WXT will automatically convert them to MV2 when necessary.`,
);
}
}

0 comments on commit 22f82a6

Please sign in to comment.