Compare commits

..

27 Commits

Author SHA1 Message Date
github-actions[bot] 5dab944abc chore(release): wxt v0.20.18
📼 VHS / Create VHS (push) Cancelled after 0s
2026-02-22 23:45:06 +00:00
Aaron adaae6e1a4 fix: Fix submit command (#2157) 2026-02-22 17:29:53 -06:00
Aaron 4524cbdf76 ci: Fix VHS workflow 2026-02-22 17:29:53 -06:00
github-actions[bot] 1171cf52f0 chore(release): @wxt-dev/analytics v0.5.4
📼 VHS / Create VHS (push) Cancelled after 0s
2026-02-22 17:29:53 -06:00
Aaron c5978b1072 fix: Continue using useAppConfig to support older versions of WXT 2026-02-22 17:29:53 -06:00
Aaron e5ef9367ed ci: Fix VHS action (#2155) 2026-02-22 17:29:53 -06:00
github-actions[bot] 0ca908a6cc chore(release): @wxt-dev/analytics v0.5.3
📼 VHS / Create VHS (push) Cancelled after 0s
2026-02-22 17:29:53 -06:00
github-actions[bot] e20c012eb3 chore(release): @wxt-dev/storage v1.2.8
📼 VHS / Create VHS (push) Cancelled after 0s
2026-02-22 17:29:53 -06:00
github-actions[bot] e88df26d7c chore(release): @wxt-dev/auto-icons v1.1.1
📼 VHS / Create VHS (push) Cancelled after 0s
2026-02-22 17:29:53 -06:00
github-actions[bot] 9491e6845e chore(release): @wxt-dev/i18n v0.2.5
📼 VHS / Create VHS (push) Cancelled after 0s
2026-02-22 17:29:53 -06:00
Aaron e4433c4212 ci: Fix scripts/list_unreleased_commits.sh (#2153) 2026-02-22 17:29:53 -06:00
Jonathan Viney c6fdc5a5d5 feat: Add globalName entrypoint option. (#2017) 2026-02-22 17:29:53 -06:00
Aaron 68dd3fc027 docs: Update section in SECURITY.md around reporting vulnerabilities (#2147) 2026-02-22 17:29:53 -06:00
omerfardemir cd7aec6752 fix: auto icons override default icons (#1616)
Co-authored-by: Florian Metz <me@timeraa.dev>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Smit b80556498d fix: Improve background script detection logic for analytics package (#1808)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Aaron 38530cdb39 feat: New @wxt-dev/is-background package (#2152)
Co-authored-by: Smit <sm17p@users.noreply.github.com>
2026-02-22 17:29:53 -06:00
Tam Dang 078fd5990e fix(types): include CSS entrypoints in PublicPath generation (#2150)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Aaron b4be5feaa6 ci: Fix auto-labeling workflow for forks 2026-02-22 17:29:53 -06:00
Aaron d982f97bd8 feat(modules): Add support for augumenting entrypoint options (#2149) 2026-02-22 17:29:53 -06:00
Aaron 653608c98c docs: Add deep outline to modules page to show recipes 2026-02-22 17:29:53 -06:00
Aaron d63be2d6f3 ci: Create workflow for labeling and adding authors to PRs (#2148) 2026-02-22 17:29:53 -06:00
Nick Doan 4500ca577f fix(types): Add type safety to browser.runtime.executeScript files option (#2142)
Co-authored-by: nickbar01234 <nickbar01234gmail.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Aaron cc935daec0 fix: Allow userId option to return undefined 2026-02-22 17:29:53 -06:00
Patryk Kuniczak 51ff46ec58 chore: Created new types, instead of any for analytics (#2119) 2026-02-22 17:29:53 -06:00
Patryk Kuniczak 206b7731cf chore: Remove @ts-expect-error from manifest.test.ts and fix typo (#2123) 2026-02-22 17:29:53 -06:00
Patryk Kuniczak d16f59d33d chore: Simplify imports in wxt/e2e (#2122) 2026-02-22 17:29:53 -06:00
Patryk Kuniczak a5ec046346 chore: Rename zipdir to zipDir (#2126) 2026-02-22 17:29:49 -06:00
34 changed files with 1133 additions and 102 deletions
+15 -4
View File
@@ -11,19 +11,26 @@ permissions:
jobs:
vhs:
name: Create VHS
runs-on: ubuntu-22.04
runs-on: macos-latest
if: ${{ github.repository == 'wxt-dev/wxt' }}
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.ref }}
- name: Setup
uses: ./.github/actions/setup
with:
install: false
- name: Setup Go
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00
with:
go-version: '1.25.1'
# This prevents pnpm dlx from downloading WXT in the video
- name: Pre-install WXT
run: |
@@ -31,9 +38,10 @@ jobs:
pnpm dlx wxt@latest --version
- name: Record VHS
uses: charmbracelet/vhs-action@59641cdc7fadf3978db65eb8c6937ea2752f4ec3 # v2.1.0
with:
path: 'docs/tapes/init-demo.tape'
run: |
brew install ttyd ffmpeg
go install github.com/charmbracelet/vhs@517bcda0faf416728bcf6b7fe489eb0e2469d9b5 # v0.10.0
vhs docs/tapes/init-demo.tape
- name: Save recorded GIF
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
@@ -41,5 +49,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
commit_message: 'docs: Update `wxt init` GIF'
commit_user_name: github-actions[bot]
commit_user_email: github-actions[bot]@users.noreply.github.com
commit_author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
# https://github.com/charmbracelet/vhs#output
file_pattern: 'docs/assets/*.gif'
+2 -6
View File
@@ -4,12 +4,8 @@ While WXT is in prerelease, only the latest version will receive security update
<img alt="npm version" src="https://img.shields.io/npm/v/wxt?labelColor=black&color=%234fa048">
<!--
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
If you discover a security vulnerability, please email me at <aaronklinker1@gmail.com>. I will respond within a few days to acknowledge receipt of your report.
Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
-->
If the vulnerability is accepted, I will open a public issue to track the fix. If the vulnerability is not accepted, no further action will be taken.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 136 KiB

+33
View File
@@ -1,5 +1,38 @@
# Changelog
## v0.5.4
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.3...analytics-v0.5.4)
### 🩹 Fixes
- Continue using `useAppConfig` to support older versions of WXT ([bfd94556](https://github.com/wxt-dev/wxt/commit/bfd94556))
### ❤️ Contributors
- Aaron ([@aklinker1](https://github.com/aklinker1))
## v0.5.3
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.2...analytics-v0.5.3)
### 🩹 Fixes
- Add `getAppConfig` as an alias to `useAppConfig` ([#2144](https://github.com/wxt-dev/wxt/pull/2144))
- Allow `userId` option to return `undefined` ([636cf1f8](https://github.com/wxt-dev/wxt/commit/636cf1f8))
- Improve background script detection logic for analytics package ([#1808](https://github.com/wxt-dev/wxt/pull/1808))
### 🏡 Chore
- Created new types, instead of `any` for `analytics` ([#2119](https://github.com/wxt-dev/wxt/pull/2119))
### ❤️ Contributors
- Smit ([@sm17p](https://github.com/sm17p))
- Aaron ([@aklinker1](https://github.com/aklinker1))
- Patryk Kuniczak ([@PatrykKuniczak](https://github.com/PatrykKuniczak))
- Sheng Zhang ([@Arktomson](https://github.com/Arktomson))
## v0.5.2
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.1...analytics-v0.5.2)
@@ -10,6 +10,7 @@ import type {
BaseAnalyticsEvent,
} from './types';
import { browser } from '@wxt-dev/browser';
import { isBackground } from '@wxt-dev/is-background';
type AnalyticsMessage = {
[K in keyof Analytics]: {
@@ -55,10 +56,7 @@ export function createAnalytics(config?: AnalyticsConfig): Analytics {
);
}
// TODO: This only works for standard WXT extensions, add a more generic
// background script detector that works with non-WXT projects.
if (location.pathname === '/background.js')
return createBackgroundAnalytics(config);
if (isBackground()) return createBackgroundAnalytics(config);
return createFrontendAnalytics();
}
@@ -44,9 +44,9 @@ export default defineWxtModule({
? clientModuleId
: normalizePath(relative(wxtAnalyticsFolder, clientModuleId))
}';
import { getAppConfig } from '#imports';
import { useAppConfig } from '#imports';
export const analytics = createAnalytics(getAppConfig().analytics);
export const analytics = createAnalytics(useAppConfig().analytics);
`;
addAlias(wxt, '#analytics', wxtAnalyticsIndex);
wxt.hook('prepare:types', async (_, entries) => {
+25 -24
View File
@@ -1,14 +1,36 @@
{
"name": "@wxt-dev/analytics",
"version": "0.5.2",
"version": "0.5.4",
"description": "Add analytics to your web extension",
"type": "module",
"scripts": {
"dev": "buildc --deps-only -- wxt",
"dev:build": "buildc --deps-only -- wxt build",
"check": "pnpm build && check",
"build": "buildc -- tsdown",
"prepack": "pnpm -s build",
"prepare": "buildc --deps-only -- wxt prepare"
},
"dependencies": {
"@wxt-dev/browser": "workspace:^",
"@wxt-dev/is-background": "workspace:^",
"ua-parser-js": "^1.0.40"
},
"peerDependencies": {
"wxt": ">=0.20.0"
},
"devDependencies": {
"@types/ua-parser-js": "^0.7.39",
"publint": "^0.3.17",
"typescript": "^5.9.3",
"wxt": "workspace:*"
},
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git",
"directory": "packages/analytics"
},
"license": "MIT",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.mts",
@@ -38,26 +60,5 @@
"types": "./dist/index.d.mts",
"files": [
"dist"
],
"scripts": {
"dev": "buildc --deps-only -- wxt",
"dev:build": "buildc --deps-only -- wxt build",
"check": "pnpm build && check",
"build": "buildc -- tsdown",
"prepack": "pnpm -s build",
"prepare": "buildc --deps-only -- wxt prepare"
},
"peerDependencies": {
"wxt": ">=0.20.0"
},
"devDependencies": {
"@types/ua-parser-js": "^0.7.39",
"publint": "^0.3.17",
"typescript": "^5.9.3",
"wxt": "workspace:*"
},
"dependencies": {
"@wxt-dev/browser": "workspace:^",
"ua-parser-js": "^1.0.40"
}
]
}
+29
View File
@@ -1,5 +1,34 @@
# Changelog
## v1.1.1
[compare changes](https://github.com/wxt-dev/wxt/compare/auto-icons-v1.1.0...auto-icons-v1.1.1)
### 🩹 Fixes
- Auto icons override default icons ([#1616](https://github.com/wxt-dev/wxt/pull/1616))
### 💅 Refactors
- Standardize file existence checks to `pathExists` ([#2083](https://github.com/wxt-dev/wxt/pull/2083))
### 🏡 Chore
- **deps:** Upgrade oxlint from 0.16.8 to 1.14.0 ([a01928e0](https://github.com/wxt-dev/wxt/commit/a01928e0))
- **deps:** Upgrade typescript from 5.8.3 to 5.9.2 ([a6eef643](https://github.com/wxt-dev/wxt/commit/a6eef643))
- Create script for managing dependency upgrades ([#1875](https://github.com/wxt-dev/wxt/pull/1875))
- **deps:** Upgrade all dev dependencies ([#1876](https://github.com/wxt-dev/wxt/pull/1876))
- **deps:** Upgrade non-breaking production dependencies ([#1877](https://github.com/wxt-dev/wxt/pull/1877))
- Upgrade dev and non-major prod dependencies ([#2000](https://github.com/wxt-dev/wxt/pull/2000))
- Use `tsdown` to build packages ([#2006](https://github.com/wxt-dev/wxt/pull/2006))
- Move script-only dev dependencies to top-level `package.json` ([#2007](https://github.com/wxt-dev/wxt/pull/2007))
- Update dependencies ([#2069](https://github.com/wxt-dev/wxt/pull/2069))
### ❤️ Contributors
- Omerfardemir <od080624@gmail.com>
- Aaron ([@aklinker1](https://github.com/aklinker1))
## v1.1.0
[compare changes](https://github.com/wxt-dev/wxt/compare/auto-icons-v1.0.2...auto-icons-v1.1.0)
+4 -2
View File
@@ -24,7 +24,7 @@
}
],
"license": "MIT",
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
@@ -39,7 +39,8 @@
],
"scripts": {
"build": "buildc -- tsdown",
"check": "pnpm build && check"
"check": "pnpm build && check",
"test": "buildc --deps-only -- vitest"
},
"peerDependencies": {
"wxt": ">=0.19.0"
@@ -53,6 +54,7 @@
"oxlint": "^1.43.0",
"publint": "^0.3.17",
"typescript": "^5.9.3",
"vitest": "^4.0.18",
"wxt": "workspace:*"
}
}
@@ -0,0 +1,629 @@
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
import { resolve } from 'node:path';
import * as fsExtra from 'fs-extra';
import sharp from 'sharp';
import type { Wxt, UserManifest } from 'wxt';
// Import the actual module
import autoIconsModule from '../index';
import type { AutoIconsOptions } from '../index';
// Mock dependencies
vi.mock('fs-extra', () => ({
ensureDir: vi.fn(),
pathExists: vi.fn(),
}));
vi.mock('sharp', () => ({
default: vi.fn(),
}));
// Type definitions for better type safety
interface MockWxt {
config: {
srcDir: string;
outDir: string;
mode: 'development' | 'production';
};
logger: {
warn: Mock;
};
hooks: {
hook: Mock;
};
}
interface PublicAsset {
type: string;
fileName: string;
}
interface BuildOutput {
publicAssets: PublicAsset[];
}
describe('auto-icons module', () => {
const mockWxt: MockWxt = {
config: {
srcDir: '/mock/src',
outDir: '/mock/dist',
mode: 'development',
},
logger: {
warn: vi.fn(),
},
hooks: {
hook: vi.fn(),
},
};
const createMockSharpInstance = () => {
const instance = {
png: vi.fn(),
grayscale: vi.fn(),
resize: vi.fn(),
toFile: vi.fn().mockResolvedValue(undefined),
};
// Make methods chainable
instance.png.mockReturnValue(instance);
instance.grayscale.mockReturnValue(instance);
instance.resize.mockImplementation(() => {
// Create a new instance for each resize to simulate real sharp behavior
const resizedInstance = { ...instance };
resizedInstance.toFile = vi.fn().mockResolvedValue(undefined);
return resizedInstance;
});
return instance;
};
let mockSharpInstance: ReturnType<typeof createMockSharpInstance>;
beforeEach(() => {
vi.clearAllMocks();
mockSharpInstance = createMockSharpInstance();
vi.mocked(sharp).mockReturnValue(
mockSharpInstance as unknown as sharp.Sharp,
);
vi.mocked(fsExtra.pathExists).mockResolvedValue(true as any);
vi.mocked(fsExtra.ensureDir).mockResolvedValue(undefined as any);
});
describe('module setup', () => {
it('should have correct module metadata', () => {
expect(autoIconsModule.name).toBe('@wxt-dev/auto-icons');
expect(autoIconsModule.configKey).toBe('autoIcons');
expect(typeof autoIconsModule.setup).toBe('function');
});
});
describe('options handling', () => {
it('should use default options when not provided', async () => {
const options: AutoIconsOptions = {};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
// Verify that the module was set up (hooks were registered)
expect(mockWxt.hooks.hook).toHaveBeenCalledWith(
'build:manifestGenerated',
expect.any(Function),
);
expect(mockWxt.hooks.hook).toHaveBeenCalledWith(
'build:done',
expect.any(Function),
);
expect(mockWxt.hooks.hook).toHaveBeenCalledWith(
'prepare:publicPaths',
expect.any(Function),
);
});
it('should merge custom options with defaults', async () => {
const options: AutoIconsOptions = {
sizes: [64, 32],
grayscaleOnDevelopment: false,
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
// Verify that the module was set up with custom options
expect(mockWxt.hooks.hook).toHaveBeenCalledWith(
'build:manifestGenerated',
expect.any(Function),
);
expect(mockWxt.hooks.hook).toHaveBeenCalledWith(
'build:done',
expect.any(Function),
);
expect(mockWxt.hooks.hook).toHaveBeenCalledWith(
'prepare:publicPaths',
expect.any(Function),
);
});
});
describe('error handling', () => {
it('should warn when disabled', async () => {
const options: AutoIconsOptions = {
enabled: false,
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
expect(mockWxt.logger.warn).toHaveBeenCalledWith(
'`[auto-icons]` @wxt-dev/auto-icons disabled',
);
expect(mockWxt.hooks.hook).not.toHaveBeenCalled();
});
it('should warn when base icon not found', async () => {
vi.mocked(fsExtra.pathExists).mockResolvedValue(false as any);
const options: AutoIconsOptions = {
enabled: true,
baseIconPath: 'assets/missing-icon.png',
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
expect(mockWxt.logger.warn).toHaveBeenCalledWith(
expect.stringContaining(
'Skipping icon generation, no base icon found at',
),
);
expect(mockWxt.hooks.hook).not.toHaveBeenCalled();
});
});
describe('manifest generation hook', () => {
it('should update manifest with default icons when no custom sizes provided', async () => {
const options: AutoIconsOptions = {
enabled: true,
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const manifestHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:manifestGenerated')?.[1];
expect(manifestHook).toBeDefined();
const manifest: UserManifest = {};
if (manifestHook) {
await manifestHook(mockWxt as unknown as Wxt, manifest);
}
// Should use default sizes: [128, 48, 32, 16]
expect(manifest.icons).toEqual({
128: 'icons/128.png',
48: 'icons/48.png',
32: 'icons/32.png',
16: 'icons/16.png',
});
});
it('should merge custom sizes with defaults', async () => {
const options: AutoIconsOptions = {
enabled: true,
sizes: [96, 64], // These will be merged with defaults
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const manifestHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:manifestGenerated')?.[1];
expect(manifestHook).toBeDefined();
const manifest: UserManifest = {};
if (manifestHook) {
await manifestHook(mockWxt as unknown as Wxt, manifest);
}
// defu merges arrays, so we get both custom and default sizes
expect(manifest.icons).toEqual({
96: 'icons/96.png',
64: 'icons/64.png',
128: 'icons/128.png',
48: 'icons/48.png',
32: 'icons/32.png',
16: 'icons/16.png',
});
});
it('should warn when overwriting existing icons in manifest', async () => {
const options: AutoIconsOptions = {
enabled: true,
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const manifestHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:manifestGenerated')?.[1];
const manifest: UserManifest = {
icons: {
128: 'existing-icon.png',
},
};
if (manifestHook) {
await manifestHook(mockWxt as unknown as Wxt, manifest);
}
expect(mockWxt.logger.warn).toHaveBeenCalledWith(
'`[auto-icons]` icons property found in manifest, overwriting with auto-generated icons',
);
});
});
describe('icon generation hook', () => {
it('should generate icons with default sizes', async () => {
const options: AutoIconsOptions = {
enabled: true,
};
const output: BuildOutput = {
publicAssets: [],
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
expect(buildHook).toBeDefined();
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
}
expect(sharp).toHaveBeenCalledWith(
resolve('/mock/src', 'assets/icon.png'),
);
expect(mockSharpInstance.png).toHaveBeenCalled();
// Should resize to default sizes
expect(mockSharpInstance.resize).toHaveBeenCalledWith(128);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(48);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(32);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(16);
expect(fsExtra.ensureDir).toHaveBeenCalledWith(
resolve('/mock/dist', 'icons'),
);
expect(output.publicAssets).toEqual([
{ type: 'asset', fileName: 'icons/128.png' },
{ type: 'asset', fileName: 'icons/48.png' },
{ type: 'asset', fileName: 'icons/32.png' },
{ type: 'asset', fileName: 'icons/16.png' },
]);
});
it('should generate icons with custom sizes merged with defaults', async () => {
const options: AutoIconsOptions = {
enabled: true,
sizes: [96, 64],
};
const output: BuildOutput = {
publicAssets: [],
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
expect(buildHook).toBeDefined();
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
}
// Should include both custom and default sizes
expect(mockSharpInstance.resize).toHaveBeenCalledWith(96);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(64);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(128);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(48);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(32);
expect(mockSharpInstance.resize).toHaveBeenCalledWith(16);
expect(output.publicAssets).toEqual([
{ type: 'asset', fileName: 'icons/96.png' },
{ type: 'asset', fileName: 'icons/64.png' },
{ type: 'asset', fileName: 'icons/128.png' },
{ type: 'asset', fileName: 'icons/48.png' },
{ type: 'asset', fileName: 'icons/32.png' },
{ type: 'asset', fileName: 'icons/16.png' },
]);
});
it('should apply grayscale in development mode', async () => {
const options: AutoIconsOptions = {
enabled: true,
grayscaleOnDevelopment: true,
sizes: [128],
};
const output: BuildOutput = { publicAssets: [] };
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
}
expect(mockSharpInstance.grayscale).toHaveBeenCalled();
});
it('should not apply grayscale in production mode', async () => {
const prodMockWxt = {
...mockWxt,
config: {
...mockWxt.config,
mode: 'production' as const,
},
};
const options: AutoIconsOptions = {
enabled: true,
grayscaleOnDevelopment: true,
sizes: [128],
};
const output: BuildOutput = { publicAssets: [] };
await autoIconsModule.setup!(prodMockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(prodMockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
if (buildHook) {
await buildHook(prodMockWxt as unknown as Wxt, output);
}
expect(mockSharpInstance.grayscale).not.toHaveBeenCalled();
});
it('should not apply grayscale when disabled', async () => {
const options: AutoIconsOptions = {
enabled: true,
grayscaleOnDevelopment: false,
sizes: [128],
};
const output: BuildOutput = { publicAssets: [] };
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
}
expect(mockSharpInstance.grayscale).not.toHaveBeenCalled();
});
});
describe('public paths hook', () => {
it('should add default icon paths to public paths', async () => {
const options: AutoIconsOptions = {
enabled: true,
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const pathsHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'prepare:publicPaths')?.[1];
expect(pathsHook).toBeDefined();
const paths: string[] = [];
if (pathsHook) {
pathsHook(mockWxt as unknown as Wxt, paths);
}
expect(paths).toEqual([
'icons/128.png',
'icons/48.png',
'icons/32.png',
'icons/16.png',
]);
});
});
describe('edge cases and error handling', () => {
it('should handle empty sizes array', async () => {
const options: AutoIconsOptions = {
enabled: true,
sizes: [], // Empty array should still merge with defaults
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const manifestHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:manifestGenerated')?.[1];
const manifest: UserManifest = {};
if (manifestHook) {
await manifestHook(mockWxt as unknown as Wxt, manifest);
}
// Should still have default sizes due to defu merge
expect(manifest.icons).toEqual({
128: 'icons/128.png',
48: 'icons/48.png',
32: 'icons/32.png',
16: 'icons/16.png',
});
});
it('should handle sharp processing errors gracefully', async () => {
const options: AutoIconsOptions = {
enabled: true,
};
// Make toFile throw an error - need to properly chain resize -> png -> toFile
const errorInstance = {
toFile: vi.fn().mockRejectedValue(new Error('Sharp processing failed')),
grayscale: vi.fn(),
composite: vi.fn(),
};
errorInstance.grayscale.mockReturnValue(errorInstance);
errorInstance.composite.mockReturnValue(errorInstance);
mockSharpInstance.resize = vi.fn().mockImplementation(() => ({
png: vi.fn().mockReturnValue(errorInstance),
}));
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
const output: BuildOutput = { publicAssets: [] };
// Should throw the sharp error
if (buildHook) {
await expect(
buildHook(mockWxt as unknown as Wxt, output),
).rejects.toThrow('Sharp processing failed');
}
});
it('should handle file system errors during directory creation', async () => {
const options: AutoIconsOptions = {
enabled: true,
};
// Make ensureDir throw an error
vi.mocked(fsExtra.ensureDir).mockRejectedValue(
new Error('Directory creation failed'),
);
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
const output: BuildOutput = { publicAssets: [] };
// The module doesn't await ensureDir, so it won't throw
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
// But ensureDir should have been called
expect(fsExtra.ensureDir).toHaveBeenCalled();
}
});
it('should handle custom base icon path correctly', async () => {
const customPath = 'custom/icon.png';
const options: AutoIconsOptions = {
enabled: true,
baseIconPath: customPath,
};
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
const output: BuildOutput = { publicAssets: [] };
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
}
// Should resolve the path relative to srcDir
expect(sharp).toHaveBeenCalledWith(resolve('/mock/src', customPath));
});
});
describe('integration test', () => {
it('should handle full workflow correctly', async () => {
const options: AutoIconsOptions = {
enabled: true,
baseIconPath: 'assets/custom-icon.png',
sizes: [96], // Will be merged with defaults
grayscaleOnDevelopment: false,
};
const manifest: UserManifest = {};
const output: BuildOutput = { publicAssets: [] };
const paths: string[] = [];
// Setup the module
await autoIconsModule.setup!(mockWxt as unknown as Wxt, options);
// Execute all hooks
const manifestHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:manifestGenerated')?.[1];
const buildHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'build:done')?.[1];
const pathsHook = vi
.mocked(mockWxt.hooks.hook)
.mock.calls.find((call) => call[0] === 'prepare:publicPaths')?.[1];
if (manifestHook) {
await manifestHook(mockWxt as unknown as Wxt, manifest);
}
if (buildHook) {
await buildHook(mockWxt as unknown as Wxt, output);
}
if (pathsHook) {
pathsHook(mockWxt as unknown as Wxt, paths);
}
// Verify results - defu merges arrays
expect(manifest.icons).toEqual({
96: 'icons/96.png',
128: 'icons/128.png',
48: 'icons/48.png',
32: 'icons/32.png',
16: 'icons/16.png',
});
expect(output.publicAssets).toEqual([
{ type: 'asset', fileName: 'icons/96.png' },
{ type: 'asset', fileName: 'icons/128.png' },
{ type: 'asset', fileName: 'icons/48.png' },
{ type: 'asset', fileName: 'icons/32.png' },
{ type: 'asset', fileName: 'icons/16.png' },
]);
expect(paths).toEqual([
'icons/96.png',
'icons/128.png',
'icons/48.png',
'icons/32.png',
'icons/16.png',
]);
expect(sharp).toHaveBeenCalledWith(
resolve('/mock/src', 'assets/custom-icon.png'),
);
expect(mockSharpInstance.grayscale).not.toHaveBeenCalled();
});
});
});
+1 -1
View File
@@ -45,7 +45,7 @@ export default defineWxtModule<AutoIconsOptions>({
wxt.hooks.hook('build:manifestGenerated', async (wxt, manifest) => {
if (manifest.icons)
return wxt.logger.warn(
wxt.logger.warn(
'`[auto-icons]` icons property found in manifest, overwriting with auto-generated icons',
);
+8
View File
@@ -0,0 +1,8 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
mockReset: true,
restoreMocks: true,
},
});
+26
View File
@@ -1,5 +1,31 @@
# Changelog
## v0.2.5
[compare changes](https://github.com/wxt-dev/wxt/compare/i18n-v0.2.4...i18n-v0.2.5)
### 🩹 Fixes
- Add `.jsonc` support for locale files to match docs ([#2066](https://github.com/wxt-dev/wxt/pull/2066))
### 🏡 Chore
- Manually fix markdownlint errors ([#1711](https://github.com/wxt-dev/wxt/pull/1711))
- **deps:** Upgrade oxlint from 0.16.8 to 1.14.0 ([a01928e0](https://github.com/wxt-dev/wxt/commit/a01928e0))
- **deps:** Upgrade typescript from 5.8.3 to 5.9.2 ([a6eef643](https://github.com/wxt-dev/wxt/commit/a6eef643))
- Create script for managing dependency upgrades ([#1875](https://github.com/wxt-dev/wxt/pull/1875))
- **deps:** Upgrade all dev dependencies ([#1876](https://github.com/wxt-dev/wxt/pull/1876))
- Upgrade dev and non-major prod dependencies ([#2000](https://github.com/wxt-dev/wxt/pull/2000))
- Use `tsdown` to build packages ([#2006](https://github.com/wxt-dev/wxt/pull/2006))
- Move script-only dev dependencies to top-level `package.json` ([#2007](https://github.com/wxt-dev/wxt/pull/2007))
- Update dependencies ([#2069](https://github.com/wxt-dev/wxt/pull/2069))
- Upgrade major deps ([#2070](https://github.com/wxt-dev/wxt/pull/2070))
### ❤️ Contributors
- Ilya Kubariev ([@gymnasy55](https://github.com/gymnasy55))
- Aaron ([@aklinker1](https://github.com/aklinker1))
## v0.2.4
[compare changes](https://github.com/wxt-dev/wxt/compare/i18n-v0.2.3...i18n-v0.2.4)
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@wxt-dev/i18n",
"description": "Type-safe wrapper around browser.i18n.getMessage with additional features",
"version": "0.2.4",
"version": "0.2.5",
"type": "module",
"repository": {
"type": "git",
+12
View File
@@ -1,5 +1,17 @@
# Changelog
## v1.2.8
[compare changes](https://github.com/wxt-dev/wxt/compare/storage-v1.2.7...storage-v1.2.8)
### 🩹 Fixes
- Correctly update version metadata when setting a value for the first time ([#2139](https://github.com/wxt-dev/wxt/pull/2139))
### ❤️ Contributors
- Aaron ([@aklinker1](https://github.com/aklinker1))
## v1.2.7
[compare changes](https://github.com/wxt-dev/wxt/compare/storage-v1.2.6...storage-v1.2.7)
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@wxt-dev/storage",
"description": "Web extension storage API provided by WXT, supports all browsers.",
"version": "1.2.7",
"version": "1.2.8",
"type": "module",
"repository": {
"type": "git",
+54
View File
@@ -1,5 +1,59 @@
# Changelog
## v0.20.18
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.17...wxt-v0.20.18)
### 🚀 Enhancements
- Create tests for all func of `network.ts` ([#2132](https://github.com/wxt-dev/wxt/pull/2132))
- Use Navigation API for location change detection with polling fallback ([#2136](https://github.com/wxt-dev/wxt/pull/2136))
- **modules:** Add support for augumenting entrypoint options ([#2149](https://github.com/wxt-dev/wxt/pull/2149))
- New `@wxt-dev/is-background` package ([#2152](https://github.com/wxt-dev/wxt/pull/2152))
- Add `globalName` entrypoint option. ([#2017](https://github.com/wxt-dev/wxt/pull/2017))
### 🩹 Fixes
- Add `getAppConfig` as an alias to `useAppConfig` ([#2144](https://github.com/wxt-dev/wxt/pull/2144))
- Enable mv3 dev mode with firefox 147 ([#2135](https://github.com/wxt-dev/wxt/pull/2135))
- **types:** Add type safety to `browser.runtime.executeScript` `files` option ([#2142](https://github.com/wxt-dev/wxt/pull/2142))
- **types:** Include CSS entrypoints in PublicPath generation ([#2150](https://github.com/wxt-dev/wxt/pull/2150))
- Fix submit command ([#2157](https://github.com/wxt-dev/wxt/pull/2157))
### 📖 Documentation
- Added "Glossy New Tab" to the homepage ([#2133](https://github.com/wxt-dev/wxt/pull/2133))
- Add All API Hub to showcase extensions ([#2137](https://github.com/wxt-dev/wxt/pull/2137))
- Add `wxt-local-analytics` to community resources ([#2141](https://github.com/wxt-dev/wxt/pull/2141))
- Add deep outline to modules page to show recipes ([653608c9](https://github.com/wxt-dev/wxt/commit/653608c9))
### 🏡 Chore
- Add missing `async` to network.ts ([#2107](https://github.com/wxt-dev/wxt/pull/2107))
- Make type for `__ENTRYPOINT__` of vitest.globalSetup.ts ([#2128](https://github.com/wxt-dev/wxt/pull/2128))
- Remove unnecessary `@ts-ignore` of `builders/vite` index.ts ([#2127](https://github.com/wxt-dev/wxt/pull/2127))
- Rename `zipdir` to `zipDir` ([#2126](https://github.com/wxt-dev/wxt/pull/2126))
- Simplify imports in `wxt/e2e` ([#2122](https://github.com/wxt-dev/wxt/pull/2122))
- Remove `@ts-expect-error` from manifest.test.ts and fix typo ([#2123](https://github.com/wxt-dev/wxt/pull/2123))
### 🤖 CI
- Fix VHS action ([#2155](https://github.com/wxt-dev/wxt/pull/2155))
### ❤️ Contributors
- Aaron ([@aklinker1](https://github.com/aklinker1))
- Jonathan Viney ([@jviney](https://github.com/jviney))
- Tam Dang ([@dahomita](https://github.com/dahomita))
- Nick Doan ([@nickbar01234](https://github.com/nickbar01234))
- Patryk Kuniczak ([@PatrykKuniczak](https://github.com/PatrykKuniczak))
- Anthony Ciccarello ([@aciccarello](https://github.com/aciccarello))
- Henrik Wenz ([@HaNdTriX](https://github.com/HaNdTriX))
- Sheng Zhang ([@Arktomson](https://github.com/Arktomson))
- Oleksii ([@Aler1x](https://github.com/Aler1x))
- Qixing-jk <vq3d5d8c@duck.com>
- Muzammil ([@oyzamil](https://github.com/oyzamil))
## v0.20.17
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.16...wxt-v0.20.17)
+1 -1
View File
@@ -4,4 +4,4 @@
* `publish-browser-extension` as a direct dependency (like for PNPM, which doesn't link
* sub-dependency binaries to "node_modules/.bin")
*/
import 'publish-browser-extension/cli';
await import('publish-browser-extension/cli');
+2 -2
View File
@@ -1,6 +1,6 @@
import { describe, it, expect, vi } from 'vitest';
import { TestProject } from '../utils';
import type { GenericEntrypoint, InlineConfig } from '../../src';
import type { InlineConfig, UnlistedScriptEntrypoint } from '../../src';
import { readFile } from 'fs-extra';
import { normalizePath } from '../../src';
@@ -49,7 +49,7 @@ describe('Module Helpers', () => {
'export default defineBackground(() => {})',
);
const entrypoint: GenericEntrypoint = {
const entrypoint: UnlistedScriptEntrypoint = {
type: 'unlisted-script',
inputPath: project.resolvePath('modules/test/injected.ts'),
name: 'injected',
@@ -459,4 +459,104 @@ describe('Output Directory Structure', () => {
"
`);
});
describe('globalName option', () => {
it('generates an IIFE with a default name', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/content.js',
`export default defineContentScript({
matches: ["*://*/*"],
main() {},
})`,
);
await project.build({ vite: () => ({ build: { minify: false } }) });
const output = await project.serializeFile(
'.output/chrome-mv3/content-scripts/content.js',
);
expect(output).toMatch(/^var content\s?=[\s\S]*^content;$/gm);
});
it('generates an IIFE with a specific name', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/content.js',
`export default defineContentScript({
globalName: "MyContentScript",
matches: ["*://*/*"],
main() {},
})`,
);
await project.build({ vite: () => ({ build: { minify: false } }) });
const output = await project.serializeFile(
'.output/chrome-mv3/content-scripts/content.js',
);
expect(output).toMatch(
/^var MyContentScript =[\s\S]*^MyContentScript;$/gm,
);
});
it('generates an IIFE with a specific name provided by a function', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/content.js',
`export default defineContentScript({
globalName: () => "MyContentScript",
matches: ["*://*/*"],
main() {},
})`,
);
await project.build({ vite: () => ({ build: { minify: false } }) });
const output = await project.serializeFile(
'.output/chrome-mv3/content-scripts/content.js',
);
expect(output).toMatch(
/^var MyContentScript =[\s\S]*^MyContentScript;$/gm,
);
});
it('generates an anonymous IIFE when not minified', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/content.js',
`export default defineContentScript({
globalName: false,
matches: ["*://*/*"],
main() {},
})`,
);
await project.build({ vite: () => ({ build: { minify: false } }) });
const output = await project.serializeFile(
'.output/chrome-mv3/content-scripts/content.js',
);
expect(output).toMatch(/^\(function\(\) {[\s\S]*^}\)\(\);$/gm);
});
it('generates an anonymous IIFE when minified', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/content.js',
`export default defineContentScript({
globalName: false,
matches: ["*://*/*"],
main() {},
})`,
);
await project.build({ vite: () => ({ build: { minify: true } }) });
const output = await project.serializeFile(
'.output/chrome-mv3/content-scripts/content.js',
);
expect(output).toMatch(/^\(function\(\){[\s\S]*}\)\(\);$/gm);
});
});
});
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.20.17",
"version": "0.20.18",
"description": "⚡ Next-gen Web Extension Framework",
"license": "MIT",
"scripts": {
@@ -55,7 +55,7 @@
"perfect-debounce": "^2.1.0",
"picocolors": "^1.1.1",
"prompts": "^2.4.2",
"publish-browser-extension": "^2.3.0 || ^3.0.2 || ^4.0.0",
"publish-browser-extension": "^2.3.0 || ^3.0.2 || ^4.0.4",
"scule": "^1.3.0",
"unimport": "^3.13.1 || ^4.0.0 || ^5.0.0",
"vite": "^5.4.19 || ^6.3.4 || ^7.0.0",
+12 -2
View File
@@ -109,7 +109,7 @@ export async function createViteBuilder(
const plugins: NonNullable<vite.UserConfig['plugins']> = [
wxtPlugins.entrypointGroupGlobals(entrypoint),
];
const iifeReturnValueName = safeVarName(entrypoint.name);
let iifeReturnValueName = safeVarName(entrypoint.name);
if (
entrypoint.type === 'content-script-style' ||
@@ -122,7 +122,17 @@ export async function createViteBuilder(
entrypoint.type === 'content-script' ||
entrypoint.type === 'unlisted-script'
) {
plugins.push(wxtPlugins.iifeFooter(iifeReturnValueName));
if (typeof entrypoint.options.globalName === 'string') {
iifeReturnValueName = entrypoint.options.globalName;
} else if (typeof entrypoint.options.globalName === 'function') {
iifeReturnValueName = entrypoint.options.globalName(entrypoint);
}
if (entrypoint.options.globalName === false) {
plugins.push(wxtPlugins.iifeAnonymous(iifeReturnValueName));
} else {
plugins.push(wxtPlugins.iifeFooter(iifeReturnValueName));
}
}
return {
@@ -0,0 +1,17 @@
import type { Plugin } from 'vite';
export function iifeAnonymous(iifeReturnValueName: string): Plugin {
return {
name: 'wxt:iife-anonymous',
generateBundle(_, bundle) {
for (const chunk of Object.values(bundle)) {
if (chunk.type === 'chunk' && chunk.isEntry) {
const namedIIFEPrefix = new RegExp(
`^var ${iifeReturnValueName}\\s*=\\s*(\\(function)`,
);
chunk.code = chunk.code.replace(namedIIFEPrefix, '$1');
}
}
},
};
}
@@ -14,3 +14,4 @@ export * from './removeEntrypointMainFunction';
export * from './wxtPluginLoader';
export * from './resolveAppConfig';
export * from './iifeFooter';
export * from './iifeAnonymous';
@@ -10,6 +10,7 @@ import {
SidepanelEntrypoint,
MainWorldContentScriptEntrypointOptions,
IsolatedWorldContentScriptEntrypointOptions,
UnlistedScriptEntrypoint,
} from '../../../types';
import fs from 'fs-extra';
import { minimatch } from 'minimatch';
@@ -319,7 +320,7 @@ async function getUnlistedPageEntrypoint(
async function getUnlistedScriptEntrypoint(
{ inputPath, name }: EntrypointInfo,
options: Record<string, any>,
): Promise<GenericEntrypoint> {
): Promise<UnlistedScriptEntrypoint> {
return {
type: 'unlisted-script',
name,
@@ -21,6 +21,7 @@ import {
Wxt,
SidepanelEntrypoint,
BaseEntrypoint,
UnlistedScriptEntrypoint,
} from '../../../types';
import { mock } from 'vitest-mock-extended';
import { vi } from 'vitest';
@@ -99,7 +100,7 @@ export const fakeBackgroundEntrypoint = fakeObjectCreator<BackgroundEntrypoint>(
);
export const fakeUnlistedScriptEntrypoint =
fakeObjectCreator<GenericEntrypoint>(() => ({
fakeObjectCreator<UnlistedScriptEntrypoint>(() => ({
type: 'unlisted-script',
inputPath: fakeFile('src'),
name: faker.string.alpha(),
@@ -186,7 +187,6 @@ export const fakeGenericEntrypoint = fakeObjectCreator<GenericEntrypoint>(
'newtab',
'devtools',
'unlisted-page',
'unlisted-script',
]),
inputPath: fakeFile('src'),
name: faker.string.alpha(),
+29 -3
View File
@@ -566,7 +566,28 @@ export interface BackgroundEntrypointOptions extends BaseEntrypointOptions {
type?: PerBrowserOption<'module'>;
}
export interface BaseContentScriptEntrypointOptions extends BaseEntrypointOptions {
export interface BaseScriptEntrypointOptions extends BaseEntrypointOptions {
/**
* The variable name for the IIFE in the output bundle.
*
* This option is relevant for scripts inserted into the page context where the default IIFE
* variable name may conflict with an existing variable on the target page. This applies to content
* scripts with world=MAIN, and others, such as unlisted scripts, that could be dynamically injected
* into the page with a <script> tag.
*
* Available options:
* - `true`: automatically generate a name for the IIFE based on the entrypoint name
* - `false`: Output the IIFE without a variable name, making it anonymous. This is the safest option
* to avoid conflicts with existing variables on the page. This will become the default in a future version of WXT.
* - `string`: Use the provided string as the global variable name.
* - `function`: A function that receives the entrypoint and returns a string to use as the variable name.
*
* @default true
*/
globalName?: string | boolean | ((entrypoint: Entrypoint) => string);
}
export interface BaseContentScriptEntrypointOptions extends BaseScriptEntrypointOptions {
matches?: PerBrowserOption<NonNullable<ManifestContentScript['matches']>>;
/**
* See https://developer.chrome.com/docs/extensions/mv3/content_scripts/
@@ -749,12 +770,16 @@ export interface GenericEntrypoint extends BaseEntrypoint {
| 'newtab'
| 'devtools'
| 'unlisted-page'
| 'unlisted-script'
| 'unlisted-style'
| 'content-script-style';
options: ResolvedPerBrowserOptions<BaseEntrypointOptions>;
}
export interface UnlistedScriptEntrypoint extends BaseEntrypoint {
type: 'unlisted-script';
options: ResolvedPerBrowserOptions<BaseScriptEntrypointOptions>;
}
export interface BackgroundEntrypoint extends BaseEntrypoint {
type: 'background';
options: ResolvedPerBrowserOptions<BackgroundEntrypointOptions>;
@@ -786,6 +811,7 @@ export interface SidepanelEntrypoint extends BaseEntrypoint {
export type Entrypoint =
| GenericEntrypoint
| BackgroundEntrypoint
| UnlistedScriptEntrypoint
| ContentScriptEntrypoint
| PopupEntrypoint
| OptionsEntrypoint
@@ -835,7 +861,7 @@ export interface BackgroundDefinition extends BackgroundEntrypointOptions {
main(): void;
}
export interface UnlistedScriptDefinition extends BaseEntrypointOptions {
export interface UnlistedScriptDefinition extends BaseScriptEntrypointOptions {
/**
* Main function executed when the unlisted script is ran.
*
+113 -36
View File
@@ -121,6 +121,9 @@ importers:
'@wxt-dev/browser':
specifier: workspace:^
version: link:../browser
'@wxt-dev/is-background':
specifier: workspace:^
version: link:../is-background
ua-parser-js:
specifier: ^1.0.40
version: 1.0.41
@@ -159,6 +162,9 @@ importers:
typescript:
specifier: ^5.9.3
version: 5.9.3
vitest:
specifier: ^4.0.18
version: 4.0.18(@types/node@20.19.32)(happy-dom@20.5.0)(jiti@2.6.1)(sass@1.97.3)(tsx@4.21.0)(yaml@2.8.2)
wxt:
specifier: workspace:*
version: link:../wxt
@@ -529,8 +535,8 @@ importers:
specifier: ^2.4.2
version: 2.4.2
publish-browser-extension:
specifier: ^2.3.0 || ^3.0.2 || ^4.0.0
version: 4.0.0
specifier: ^2.3.0 || ^3.0.2 || ^4.0.4
version: 4.0.4
scule:
specifier: ^1.3.0
version: 1.3.0
@@ -2422,6 +2428,9 @@ packages:
buffer-crc32@0.2.13:
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
buffer-equal-constant-time@1.0.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
@@ -2518,10 +2527,6 @@ packages:
resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==}
engines: {node: '>=18.20'}
cli-truncate@4.0.0:
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
engines: {node: '>=18'}
cli-truncate@5.1.1:
resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==}
engines: {node: '>=20'}
@@ -2746,6 +2751,9 @@ packages:
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
ecdsa-sig-formatter@1.0.11:
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
electron-to-chromium@1.5.286:
resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==}
@@ -3182,10 +3190,6 @@ packages:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
is-fullwidth-code-point@4.0.0:
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
engines: {node: '>=12'}
is-fullwidth-code-point@5.1.0:
resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
engines: {node: '>=18'}
@@ -3353,9 +3357,19 @@ packages:
resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
engines: {node: '>=0.10.0'}
jsonwebtoken@9.0.3:
resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==}
engines: {node: '>=12', npm: '>=6'}
jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
jwa@2.0.1:
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
jws@4.0.1:
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
katex@0.16.28:
resolution: {integrity: sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==}
hasBin: true
@@ -3410,9 +3424,9 @@ packages:
engines: {node: '>=20.17'}
hasBin: true
listr2@8.3.3:
resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
engines: {node: '>=18.0.0'}
listr2@10.1.0:
resolution: {integrity: sha512-/6t2KgDYIcCjhELwvrRxi1gaJ4xCGLTjNvh6mSjYenBkrZxggek8EwCbwBU33GMUCpyyrOzz2TzylrO5mTiI1w==}
engines: {node: '>=22.0.0'}
listr2@9.0.5:
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
@@ -3426,9 +3440,30 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
lodash.includes@4.3.0:
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
lodash.isboolean@3.0.3:
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
lodash.isinteger@4.0.4:
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
lodash.isnumber@3.0.3:
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
lodash.isstring@4.0.1:
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
lodash.once@4.1.1:
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
log-symbols@7.0.1:
resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==}
engines: {node: '>=18'}
@@ -3437,6 +3472,10 @@ packages:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
log-update@7.1.0:
resolution: {integrity: sha512-y9pi/ZOQQVvTgfRDEHV1Cj4zQUkJZPipEUNOxhn1R6KgmdMs7LKvXWCd9eMVPGJgvYzFLCenecWr0Ps8ChVv2A==}
engines: {node: '>=20'}
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -3913,8 +3952,9 @@ packages:
engines: {node: '>=18'}
hasBin: true
publish-browser-extension@4.0.0:
resolution: {integrity: sha512-2bsHf2m+ivNyDa67YdVhcxpF3wjWzVTqG5JWQYwi6by47XyA7jf43A9S7+UBULM/d2f82fPUGnRuecMK1CgEPA==}
publish-browser-extension@4.0.4:
resolution: {integrity: sha512-QMQbWL0FWgBfnkJ6w8HOJoIPaWLE7vTpewM4ae2vLs7SrD4eKdAk+SxOzqAICwbhEPuaLAOA+XkT9sZS5R0PmA==}
engines: {node: '>=18.0.0'}
hasBin: true
pump@3.0.3:
@@ -4175,10 +4215,6 @@ packages:
sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
slice-ansi@5.0.0:
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
engines: {node: '>=12'}
slice-ansi@7.1.2:
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
engines: {node: '>=18'}
@@ -6527,6 +6563,8 @@ snapshots:
buffer-crc32@0.2.13: {}
buffer-equal-constant-time@1.0.1: {}
buffer-from@1.1.2: {}
bundle-name@4.1.0:
@@ -6628,11 +6666,6 @@ snapshots:
cli-spinners@3.4.0: {}
cli-truncate@4.0.0:
dependencies:
slice-ansi: 5.0.0
string-width: 7.2.0
cli-truncate@5.1.1:
dependencies:
slice-ansi: 7.1.2
@@ -6822,6 +6855,10 @@ snapshots:
duplexer@0.1.2: {}
ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer: 5.1.2
electron-to-chromium@1.5.286: {}
emoji-regex-xs@1.0.0: {}
@@ -7278,8 +7315,6 @@ snapshots:
is-fullwidth-code-point@3.0.0: {}
is-fullwidth-code-point@4.0.0: {}
is-fullwidth-code-point@5.1.0:
dependencies:
get-east-asian-width: 1.4.0
@@ -7399,6 +7434,19 @@ snapshots:
jsonpointer@5.0.1: {}
jsonwebtoken@9.0.3:
dependencies:
jws: 4.0.1
lodash.includes: 4.3.0
lodash.isboolean: 3.0.3
lodash.isinteger: 4.0.4
lodash.isnumber: 3.0.3
lodash.isplainobject: 4.0.6
lodash.isstring: 4.0.1
lodash.once: 4.1.1
ms: 2.1.3
semver: 7.7.4
jszip@3.10.1:
dependencies:
lie: 3.3.0
@@ -7406,6 +7454,17 @@ snapshots:
readable-stream: 2.3.8
setimmediate: 1.0.5
jwa@2.0.1:
dependencies:
buffer-equal-constant-time: 1.0.1
ecdsa-sig-formatter: 1.0.11
safe-buffer: 5.1.2
jws@4.0.1:
dependencies:
jwa: 2.0.1
safe-buffer: 5.1.2
katex@0.16.28:
dependencies:
commander: 8.3.0
@@ -7464,12 +7523,12 @@ snapshots:
string-argv: 0.3.2
yaml: 2.8.2
listr2@8.3.3:
listr2@10.1.0:
dependencies:
cli-truncate: 4.0.0
cli-truncate: 5.1.1
colorette: 2.0.20
eventemitter3: 5.0.4
log-update: 6.1.0
log-update: 7.1.0
rfdc: 1.4.1
wrap-ansi: 9.0.2
@@ -7492,8 +7551,22 @@ snapshots:
dependencies:
p-locate: 5.0.0
lodash.includes@4.3.0: {}
lodash.isboolean@3.0.3: {}
lodash.isinteger@4.0.4: {}
lodash.isnumber@3.0.3: {}
lodash.isplainobject@4.0.6: {}
lodash.isstring@4.0.1: {}
lodash.merge@4.6.2: {}
lodash.once@4.1.1: {}
log-symbols@7.0.1:
dependencies:
is-unicode-supported: 2.1.0
@@ -7507,6 +7580,14 @@ snapshots:
strip-ansi: 7.1.2
wrap-ansi: 9.0.2
log-update@7.1.0:
dependencies:
ansi-escapes: 7.3.0
cli-cursor: 5.0.0
slice-ansi: 7.1.2
strip-ansi: 7.1.2
wrap-ansi: 9.0.2
longest-streak@3.1.0: {}
lru-cache@5.1.1:
@@ -8168,14 +8249,15 @@ snapshots:
picocolors: 1.1.1
sade: 1.8.1
publish-browser-extension@4.0.0:
publish-browser-extension@4.0.4:
dependencies:
cac: 6.7.14
consola: 3.4.2
dotenv: 17.2.4
form-data-encoder: 4.1.0
formdata-node: 6.0.3
listr2: 8.3.3
jsonwebtoken: 9.0.3
listr2: 10.1.0
ofetch: 1.5.1
zod: 4.3.6
@@ -8504,11 +8586,6 @@ snapshots:
sisteransi@1.0.5: {}
slice-ansi@5.0.0:
dependencies:
ansi-styles: 6.2.3
is-fullwidth-code-point: 4.0.0
slice-ansi@7.1.2:
dependencies:
ansi-styles: 6.2.3
+3 -3
View File
@@ -20,6 +20,7 @@ for dir in "$PACKAGES_DIR"/*; do
# Check if the package name is in the ignored directories list
if [[ " ${IGNORED_DIRS[*]} " =~ " $pkg_name " ]]; then
echo "----------------------------------------"
echo "Skipping ignored package: $pkg_name"
continue # Skip to the next directory
fi
@@ -34,12 +35,11 @@ for dir in "$PACKAGES_DIR"/*; do
if [ -n "$last_tag" ]; then
# If a tag is found, show commits since that tag for the specific package directory
echo "Commits since last tag ($last_tag):"
git log "${last_tag}..HEAD" --oneline -- "$dir" | grep -v -E "^[a-f0-9]* (chore|docs)"
git log "${last_tag}..HEAD" --oneline -- "$dir" | grep -v -E "^[a-f0-9]* (chore|docs|refactor)" || true
else
# If no tag is found, show all commits for that package directory
echo "No tags found for this package. Listing all commits:"
git log --oneline -- "$dir" | grep -v -E "^[a-f0-9]* (chore|docs)"
git log --oneline -- "$dir" | grep -v -E "^[a-f0-9]* (chore|docs|refactor)" || true
fi
echo ""
fi
done
+1 -1
View File
@@ -23,6 +23,6 @@
"@types/react-dom": "^19.2.3",
"@wxt-dev/module-react": "^1.1.5",
"typescript": "^5.9.3",
"wxt": "^0.20.17"
"wxt": "^0.20.18"
}
}
+1 -1
View File
@@ -20,6 +20,6 @@
"devDependencies": {
"@wxt-dev/module-solid": "^1.1.4",
"typescript": "^5.9.3",
"wxt": "^0.20.17"
"wxt": "^0.20.18"
}
}
+1 -1
View File
@@ -21,6 +21,6 @@
"svelte-check": "^4.3.6",
"tslib": "^2.8.1",
"typescript": "^5.9.3",
"wxt": "^0.20.17"
"wxt": "^0.20.18"
}
}
+1 -1
View File
@@ -16,6 +16,6 @@
},
"devDependencies": {
"typescript": "^5.9.3",
"wxt": "^0.20.17"
"wxt": "^0.20.18"
}
}
+1 -1
View File
@@ -21,6 +21,6 @@
"@wxt-dev/module-vue": "^1.0.3",
"typescript": "^5.9.3",
"vue-tsc": "^3.2.4",
"wxt": "^0.20.17"
"wxt": "^0.20.18"
}
}