Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Auto Icons Module #851

Merged
merged 8 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
- module-vue
- module-svelte
- module-solid
- auto-icons

jobs:
validate:
Expand Down
35 changes: 35 additions & 0 deletions packages/auto-icons/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@wxt-dev/auto-icons",
"version": "1.0.0",
"type": "module",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
},
"files": [
"dist"
],
"scripts": {
"build": "buildc -- unbuild",
"check": "buildc --deps-only -- check"
},
"peerDependencies": {
"wxt": ">=0.19.0"
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.9",
"typescript": "^5.5.3",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
},
"dependencies": {
"defu": "^6.1.4",
"fs-extra": "^11.2.0",
"sharp": "^0.33.4"
}
}
102 changes: 102 additions & 0 deletions packages/auto-icons/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import 'wxt';
import { defineWxtModule } from 'wxt/modules';
import { resolve, relative } from 'node:path';
import defu from 'defu';
import sharp from 'sharp';
import { ensureDir, exists } from 'fs-extra';

export default defineWxtModule<AutoIconsOptions>({
name: '@wxt-dev/auto-icons',
configKey: 'autoIcons',
async setup(wxt, options) {
const parsedOptions = defu(options, {
enabled: true,
baseIconsPath: resolve(wxt.config.srcDir, 'assets/icon.png'),
grayscaleOnDevelopment: true,
sizes: [128, 48, 32, 16],
});

if (!parsedOptions.enabled)
return wxt.logger.warn(`\`[auto-icons]\` ${this.name} disabled`);

if (!(await exists(parsedOptions.baseIconsPath))) {
const relativePath = relative(process.cwd(), parsedOptions.baseIconsPath);
return wxt.logger.warn(
`\`[auto-icons]\` Skipping icon generation, no base icon found at ${relativePath}`,
);
}

wxt.hooks.hook('build:manifestGenerated', async (wxt, manifest) => {
if (manifest.icons)
return wxt.logger.warn(
'`[auto-icons]` icons property found in manifest, overwriting with auto-generated icons',
);

manifest.icons = Object.fromEntries(
parsedOptions.sizes.map((size) => [size, `icons/${size}.png`]),
);
});

wxt.hooks.hook('build:done', async (wxt, output) => {
const image = sharp(parsedOptions.baseIconsPath).png();

if (
wxt.config.mode === 'development' &&
parsedOptions.grayscaleOnDevelopment
) {
image.grayscale();
}

const outputFolder = wxt.config.outDir;

for (const size of parsedOptions.sizes) {
const resized = image.resize(size);
ensureDir(resolve(outputFolder, 'icons'));
await resized.toFile(resolve(outputFolder, `icons/${size}.png`));

output.publicAssets.push({
type: 'asset',
fileName: `icons/${size}.png`,
});
}
});

wxt.hooks.hook('prepare:publicPaths', (wxt, paths) => {
for (const size of parsedOptions.sizes) {
paths.push(`icons/${size}.png`);
}
});
},
});

/**
* Options for the auto-icons module
*/
export interface AutoIconsOptions {
/**
* Enable auto-icons generation
* @default true
*/
enabled?: boolean;
/**
* Path to the image to use.
* @default "<srcDir>/assets/icon.png"
*/
baseIconPath?: string;
/**
* Grayscale the image when in development mode to indicate development
* @default true
*/
grayscaleOnDevelopment?: boolean;
/**
* Sizes to generate icons for
* @default [128, 48, 32, 16]
*/
sizes?: number[];
}

declare module 'wxt' {
export interface InlineConfig {
autoIcons?: AutoIconsOptions;
}
}
4 changes: 4 additions & 0 deletions packages/auto-icons/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"exclude": ["node_modules/**", "dist/**"]
}
1 change: 1 addition & 0 deletions packages/wxt-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@types/chrome": "^0.0.268",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@wxt-dev/auto-icons": "workspace:*",
"sass": "^1.77.8",
"typescript": "^5.5.3",
"vitest": "^2.0.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt-demo/src/entrypoints/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default defineBackground({
// @ts-expect-error: should only accept entrypoints or public assets
browser.runtime.getURL('/');
browser.runtime.getURL('/background.js');
browser.runtime.getURL('/icon/128.png');
browser.runtime.getURL('/icons/128.png');
browser.runtime.getURL('/example.html#hash');
browser.runtime.getURL('/example.html?query=param');
// @ts-expect-error: should only allow hashes/query params on HTML files
Expand Down
3 changes: 3 additions & 0 deletions packages/wxt-demo/src/modules/auto-icons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import autoIcons from '@wxt-dev/auto-icons';

export default autoIcons;
Binary file removed packages/wxt-demo/src/public/icon/16.png
Binary file not shown.
Binary file removed packages/wxt-demo/src/public/icon/32.png
Binary file not shown.
Binary file removed packages/wxt-demo/src/public/icon/48.png
Binary file not shown.
Binary file removed packages/wxt-demo/src/public/icon/96.png
Binary file not shown.
5 changes: 1 addition & 4 deletions packages/wxt/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ export default defineConfig({
ignored: '**/dist/**',
},
},
plugins: [
// @ts-expect-error: Vite version mismatch
RandomSeed(),
],
plugins: [RandomSeed()],
resolve: {
alias: {
'wxt/testing': path.resolve('src/testing'),
Expand Down
Loading