Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e20c012eb3 | |||
| e88df26d7c | |||
| 9491e6845e | |||
| e4433c4212 | |||
| c6fdc5a5d5 | |||
| 68dd3fc027 | |||
| cd7aec6752 | |||
| b80556498d | |||
| 38530cdb39 | |||
| 078fd5990e | |||
| b4be5feaa6 | |||
| d982f97bd8 | |||
| 653608c98c | |||
| d63be2d6f3 | |||
| 4500ca577f | |||
| cc935daec0 | |||
| 51ff46ec58 | |||
| 206b7731cf | |||
| d16f59d33d | |||
| a5ec046346 |
+2
-6
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -2,13 +2,35 @@
|
||||
"name": "@wxt-dev/analytics",
|
||||
"version": "0.5.2",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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',
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
mockReset: true,
|
||||
restoreMocks: true,
|
||||
},
|
||||
});
|
||||
@@ -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,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",
|
||||
|
||||
@@ -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,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",
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Generated
+6
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user