feat: Discover icons from the public directory (#72)

This commit is contained in:
Aaron
2023-08-13 10:05:27 -05:00
committed by GitHub
parent 7ccff533ff
commit aefc8d3167
3 changed files with 110 additions and 8 deletions
+14 -8
View File
@@ -47,9 +47,9 @@ The [manifest's `version` and `version_name`](https://developer.chrome.com/docs/
}
```
## Icon
## `icons`
The [manifest's `icons`](https://developer.chrome.com/docs/extensions/mv3/manifest/icons/) property needs to be set in the config file. The files should be added to WXT's [`public` directory](/get-started/assets#public-directory).
By default, WXT will discover icons in your [`public` directory](/get-started/assets#public-directory) and use them for the [manifest's `icons`](https://developer.chrome.com/docs/extensions/mv3/manifest/icons/).
```
public/
@@ -60,21 +60,27 @@ public/
└─ icon-128.png
```
Icon files need to match the following regex to be automatically included in the manifest. Most design software can output icons in one of these formats
<<< @/../src/core/utils/manifest.ts#snippet
If you prefer to use filenames in a different format, you can add the icons manually in your `wxt.config.ts` file:
```ts
export default defineConfig({
manifest: {
icons: {
16: '/icon-16.png',
24: '/icon-24.png',
48: '/icon-48.png',
96: '/icon-96.png',
128: '/icon-128.png',
16: '/extension-icon-16.png',
24: '/extension-icon-24.png',
48: '/extension-icon-48.png',
96: '/extension-icon-96.png',
128: '/extension-icon-128.png',
},
},
});
```
## Permissions
## `permissions`
[Permissions](https://developer.chrome.com/docs/extensions/reference/permissions/) must be listed in the manifest config.
+60
View File
@@ -133,6 +133,66 @@ describe('Manifest Content', () => {
});
});
describe('icons', () => {
it('should auto-discover icons with the correct name', async () => {
const project = new TestProject();
project.addFile('public/icon-16.png');
project.addFile('public/icon/32.jpeg');
project.addFile('public/icon@48w.jpg');
project.addFile('public/icon-64x64.gif');
project.addFile('public/icon@96.bmp');
project.addFile('public/icon/128x128.ico');
await project.build();
const manifest = await project.getOutputManifest();
expect(manifest.icons).toEqual({
'16': 'icon-16.png',
'32': 'icon/32.jpeg',
'48': 'icon@48w.jpg',
'64': 'icon-64x64.gif',
'96': 'icon@96.bmp',
'128': 'icon/128x128.ico',
});
});
it('should return undefined when no icons are found', async () => {
const project = new TestProject();
project.addFile('public/logo.png');
project.addFile('public/icon.jpeg');
await project.build();
const manifest = await project.getOutputManifest();
expect(manifest.icons).toBeUndefined();
});
it('should allow icons to be overwritten from the wxt.config.ts file', async () => {
const project = new TestProject();
project.addFile('public/icon-16.png');
project.addFile('public/icon-32.png');
project.addFile('public/logo-16.png');
project.addFile('public/logo-32.png');
project.addFile('public/logo-48.png');
const icons = {
'16': 'logo-16.png',
'32': 'logo-32.png',
'48': 'logo-48.png',
};
project.setConfigFileConfig({
manifest: {
icons,
},
});
await project.build();
const manifest = await project.getOutputManifest();
expect(manifest.icons).toEqual(icons);
});
});
it('should group content scripts and styles together based on their matches and run_at', async () => {
const project = new TestProject();
project.addFile(
+36
View File
@@ -17,6 +17,7 @@ import {
mapWxtOptionsToContentScript,
} from './content-scripts';
import { getPackageJson } from './package';
import { normalizePath } from './paths';
/**
* Writes the manifest to the output directory and the build output.
@@ -65,6 +66,7 @@ export async function generateMainfest(
? pkg?.version
: undefined,
short_name: pkg?.shortName,
icons: discoverIcons(buildOutput),
},
config.manifest,
);
@@ -317,6 +319,40 @@ function addEntrypoints(
}
}
function discoverIcons(
buildOutput: Omit<BuildOutput, 'manifest'>,
): Manifest.WebExtensionManifest['icons'] {
const icons: [string, string][] = [];
// prettier-ignore
// #region snippet
const iconRegex = [
/^icon-([0-9]+)\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon-16.png
/^icon-([0-9]+)x[0-9]+\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon-16x16.png
/^icon@([0-9]+)w\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon@16w.png
/^icon@([0-9]+)h\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon@16h.png
/^icon@([0-9]+)\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon@16.png
/^icon[\/\\]([0-9]+)\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon/16.png
/^icon[\/\\]([0-9]+)x[0-9]+\.(png|bmp|jpeg|jpg|ico|gif)$/, // icon/16x16.png
];
// #endregion snippet
buildOutput.publicAssets.forEach((asset) => {
let size: string | undefined;
for (const regex of iconRegex) {
const match = asset.fileName.match(regex);
if (match?.[1] != null) {
size = match[1];
break;
}
}
if (size == null) return;
icons.push([size, normalizePath(asset.fileName)]);
});
return icons.length > 0 ? Object.fromEntries(icons) : undefined;
}
function addDevModeCsp(
manifest: Manifest.WebExtensionManifest,
config: InternalConfig,