Compare commits

...

11 Commits

Author SHA1 Message Date
GitHub Actions d270250633 chore(release): wxt v0.19.11
vhs / vhs (push) Waiting to run
2024-10-02 13:59:29 +00:00
Florian Metz d75f64df79 feat(zip): wxt zip --sources and auto sources for opera (#1014)
Co-authored-by: Timeraa <Timeraa@users.noreply.github.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-10-02 08:55:08 -05:00
Gurvir Singh 5faa5d7537 fix: #1005 fixed, by updating type-definations to getItem method. (#1007)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-10-02 08:20:32 -05:00
mezannic 177223c625 fix: Reverse env files priority (#1016)
Co-authored-by: Mathieu Ezannic <mathieu.ezannic@plebicom.com>
2024-10-01 16:00:52 -05:00
deyu a64ff22917 docs: Add "Discord Message Translator" extension to homepage (#1011) 2024-09-29 21:57:23 -05:00
Gourav Goyal 0bf08329b0 docs: Add "ChatGPT Writer" to homepage (#1006) 2024-09-27 20:50:21 -05:00
Guilherme Oenning e3f00d2797 docs: Add "Dofollow Links for SEO" to homepage (#1001)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-09-27 08:03:06 -05:00
Andy Zhou 09de72895e docs: Add "social-media-copilot" to homepage (#1000) 2024-09-27 08:02:23 -05:00
Aaron c0aa12089e chore: Move some files around (#996) 2024-09-25 20:54:40 -05:00
Aaron 0248f58785 chore: Add Aaron back to changelog contributions 2024-09-25 20:11:02 -05:00
Florian Metz 247cd66f74 feat(zip): hooks (#993)
Co-authored-by: Timeraa <Timeraa@users.noreply.github.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-09-25 20:08:54 -05:00
21 changed files with 321 additions and 42 deletions
@@ -40,6 +40,10 @@ const chromeExtensionIds = [
'fonflmjnjbkigocpoommgmhljdpljain', // NiceTab - https://github.com/web-dahuyou/NiceTab
'fcffekbnfcfdemeekijbbmgmkognnmkd', // Draftly for LinkedIn
'nkndldfehcidpejfkokbeghpnlbppdmo', // YouTube Summarized - Summarize any YouTube video
'dbichmdlbjdeplpkhcejgkakobjbjalc', // 社媒助手 - https://github.com/iszhouhua/social-media-copilot
'opepfpjeogkbgeigkbepobceinnfmjdd', // Dofollow Links for SEO
'pdnenlnelpdomajfejgapbdpmjkfpjkp', // ChatGPT Writer: Use AI on Any Site (GPT-4o, Claude, Gemini, and More)
'jobnhifpphkgoelnhnopgkdhbdkiadmj', // discord message translator
];
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 136 KiB

-5
View File
@@ -56,10 +56,5 @@
"search-insights"
]
}
},
"changelog": {
"excludeAuthors": [
"aaronklinker1@gmail.com"
]
}
}
+25
View File
@@ -1,5 +1,30 @@
# Changelog
## v0.19.11
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.10...wxt-v0.19.11)
### 🚀 Enhancements
- **zip:** Hooks ([#993](https://github.com/wxt-dev/wxt/pull/993))
- **zip:** `wxt zip --sources` and auto sources for opera ([#1014](https://github.com/wxt-dev/wxt/pull/1014))
### 🩹 Fixes
- Reverse env files priority ([#1016](https://github.com/wxt-dev/wxt/pull/1016))
- #1005 fixed, by updating type-definations to getItem method. ([#1007](https://github.com/wxt-dev/wxt/pull/1007), [#1005](https://github.com/wxt-dev/wxt/issues/1005))
### 🏡 Chore
- Move some files around ([#996](https://github.com/wxt-dev/wxt/pull/996))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
- Gurvir Singh ([@baraich](http://github.com/baraich))
- Mezannic <mezannic@gmail.com>
- Aaron ([@aklinker1](http://github.com/aklinker1))
## v0.19.10
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.9...wxt-v0.19.10)
+57
View File
@@ -14,6 +14,12 @@ const hooks: WxtHooks = {
'entrypoints:grouped': vi.fn(),
'vite:build:extendConfig': vi.fn(),
'vite:devServer:extendConfig': vi.fn(),
'zip:start': vi.fn(),
'zip:extension:start': vi.fn(),
'zip:extension:done': vi.fn(),
'zip:sources:start': vi.fn(),
'zip:sources:done': vi.fn(),
'zip:done': vi.fn(),
};
function expectHooksToBeCalled(
@@ -53,6 +59,12 @@ describe('Hooks', () => {
'entrypoints:resolved': true,
'vite:build:extendConfig': false,
'vite:devServer:extendConfig': false,
'zip:start': false,
'zip:extension:start': false,
'zip:extension:done': false,
'zip:sources:start': false,
'zip:sources:done': false,
'zip:done': false,
});
});
@@ -74,6 +86,12 @@ describe('Hooks', () => {
'entrypoints:resolved': true,
'vite:build:extendConfig': 1,
'vite:devServer:extendConfig': false,
'zip:start': false,
'zip:extension:start': false,
'zip:extension:done': false,
'zip:sources:start': false,
'zip:sources:done': false,
'zip:done': false,
});
});
@@ -95,6 +113,39 @@ describe('Hooks', () => {
'entrypoints:resolved': true,
'vite:build:extendConfig': 1,
'vite:devServer:extendConfig': false,
'zip:start': true,
'zip:extension:start': true,
'zip:extension:done': true,
'zip:sources:start': false,
'zip:sources:done': false,
'zip:done': true,
});
});
it('zip -b firefox should call hooks', async () => {
const project = new TestProject();
project.addFile('entrypoints/popup.html', '<html></html>');
await project.zip({ hooks, browser: 'firefox' });
expectHooksToBeCalled({
ready: true,
'prepare:types': true,
'prepare:publicPaths': true,
'build:before': true,
'build:done': true,
'build:publicAssets': true,
'build:manifestGenerated': true,
'entrypoints:grouped': true,
'entrypoints:resolved': true,
'vite:build:extendConfig': 1,
'vite:devServer:extendConfig': false,
'zip:start': true,
'zip:extension:start': true,
'zip:extension:done': true,
'zip:sources:start': true,
'zip:sources:done': true,
'zip:done': true,
});
});
@@ -122,6 +173,12 @@ describe('Hooks', () => {
'entrypoints:resolved': true,
'vite:build:extendConfig': 2,
'vite:devServer:extendConfig': 1,
'zip:start': false,
'zip:extension:start': false,
'zip:extension:done': false,
'zip:sources:start': false,
'zip:sources:done': false,
'zip:done': false,
});
});
});
+69
View File
@@ -178,4 +178,73 @@ describe('Zipping', () => {
true,
);
});
it.each(['firefox', 'opera'])(
'should create sources zip for "%s" browser when sourcesZip is undefined',
async (browser) => {
const project = new TestProject({
name: 'test',
version: '1.0.0',
});
project.addFile(
'entrypoints/background.ts',
'export default defineBackground(() => {});',
);
const sourcesZip = project.resolvePath('.output/test-1.0.0-sources.zip');
await project.zip({
browser,
});
expect(await project.fileExists(sourcesZip)).toBe(true);
},
);
it.each(['firefox', 'chrome'])(
'should create sources zip for "%s" when sourcesZip is true',
async (browser) => {
const project = new TestProject({
name: 'test',
version: '1.0.0',
});
project.addFile(
'entrypoints/background.ts',
'export default defineBackground(() => {});',
);
const sourcesZip = project.resolvePath('.output/test-1.0.0-sources.zip');
await project.zip({
browser,
zip: {
zipSources: true,
},
});
expect(await project.fileExists(sourcesZip)).toBe(true);
},
);
it.each(['firefox', 'chrome'])(
'should not create sources zip for "%s" when sourcesZip is false',
async (browser) => {
const project = new TestProject({
name: 'test',
version: '1.0.0',
});
project.addFile(
'entrypoints/background.ts',
'export default defineBackground(() => {});',
);
const sourcesZip = project.resolvePath('.output/test-1.0.0-sources.zip');
await project.zip({
browser,
zip: {
zipSources: false,
},
});
expect(await project.fileExists(sourcesZip)).toBe(false);
},
);
});
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.19.10",
"version": "0.19.11",
"description": "Next gen framework for developing web extensions",
"repository": {
"type": "git",
@@ -903,5 +903,24 @@ describe('Storage Utils', () => {
// @ts-expect-error
await storage.getItem('loca:test').catch(() => {});
});
it('should return a nullable type when getItem is called without a fallback', async () => {
const res = await storage.getItem<string>('local:test');
expectTypeOf(res).toBeNullable();
});
it('should return a non-null type when getItem is called with a fallback', async () => {
const res = await storage.getItem('local:test', {
fallback: 'test',
});
expectTypeOf(res).not.toBeNullable();
});
it('should return a non-null type when getItem is called with a fallback and the first type parameter is passed', async () => {
const res = await storage.getItem<string>('local:test', {
fallback: 'test',
});
expectTypeOf(res).not.toBeNullable();
});
});
});
+43 -1
View File
@@ -237,7 +237,9 @@ describe('CLI', () => {
mockArgv('zip');
await importCli();
expect(zipMock).toBeCalledWith({});
expect(zipMock).toBeCalledWith({
zip: {},
});
});
it('should respect passing a custom root', async () => {
@@ -246,6 +248,7 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
root: 'path/to/root',
zip: {},
});
});
@@ -255,6 +258,7 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
configFile: './path/to/config.ts',
zip: {},
});
});
@@ -264,6 +268,7 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
mode: 'development',
zip: {},
});
});
@@ -273,6 +278,7 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
browser: 'firefox',
zip: {},
});
});
@@ -282,6 +288,7 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
manifestVersion: 2,
zip: {},
});
});
@@ -291,6 +298,7 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
manifestVersion: 3,
zip: {},
});
});
@@ -300,6 +308,40 @@ describe('CLI', () => {
expect(zipMock).toBeCalledWith({
debug: true,
zip: {},
});
});
it('should pass undefined for zipSources when --sources is not passed', async () => {
mockArgv('zip');
await importCli();
expect(zipMock).toBeCalledWith({
zip: {
zipSources: undefined,
},
});
});
it('should pass true for zipSources when --sources is passed', async () => {
mockArgv('zip', '--sources');
await importCli();
expect(zipMock).toBeCalledWith({
zip: {
zipSources: true,
},
});
});
it('should pass false for zipSources when --sources=false is passed', async () => {
mockArgv('zip', '--sources=false');
await importCli();
expect(zipMock).toBeCalledWith({
zip: {
zipSources: false,
},
});
});
});
+4
View File
@@ -95,6 +95,7 @@ cli
.option('-b, --browser <browser>', 'specify a browser')
.option('--mv3', 'target manifest v3')
.option('--mv2', 'target manifest v2')
.option('--sources', 'always create sources zip')
.action(
wrapAction(async (root, flags) => {
await zip({
@@ -104,6 +105,9 @@ cli
manifestVersion: flags.mv3 ? 3 : flags.mv2 ? 2 : undefined,
configFile: flags.config,
debug: flags.debug,
zip: {
zipSources: flags.sources,
},
});
}),
);
@@ -1,23 +1,18 @@
import { Entrypoint, WxtDirEntry, WxtDirFileEntry } from '../../../types';
import { Entrypoint, WxtDirEntry, WxtDirFileEntry } from '../types';
import fs from 'fs-extra';
import { dirname, relative, resolve } from 'node:path';
import {
getEntrypointBundlePath,
isHtmlEntrypoint,
} from '../../utils/entrypoints';
import { getEntrypointGlobals, getGlobals } from '../../utils/globals';
import { normalizePath } from '../../utils/paths';
import { getEntrypointBundlePath, isHtmlEntrypoint } from './utils/entrypoints';
import { getEntrypointGlobals, getGlobals } from './utils/globals';
import { normalizePath } from './utils/paths';
import path from 'node:path';
import { Message, parseI18nMessages } from '../../utils/i18n';
import { writeFileIfDifferent, getPublicFiles } from '../../utils/fs';
import { wxt } from '../../wxt';
import { Message, parseI18nMessages } from './utils/i18n';
import { writeFileIfDifferent, getPublicFiles } from './utils/fs';
import { wxt } from './wxt';
/**
* Generate and write all the files inside the `InternalConfig.typesDir` directory.
*/
export async function generateTypesDir(
entrypoints: Entrypoint[],
): Promise<void> {
export async function generateWxtDir(entrypoints: Entrypoint[]): Promise<void> {
await fs.ensureDir(wxt.config.typesDir);
const entries: WxtDirEntry[] = [
+3 -2
View File
@@ -1,5 +1,6 @@
import { InlineConfig } from '../types';
import { findEntrypoints, generateTypesDir } from './utils/building';
import { findEntrypoints } from './utils/building';
import { generateWxtDir } from './generate-wxt-dir';
import { registerWxt, wxt } from './wxt';
export async function prepare(config: InlineConfig) {
@@ -7,5 +8,5 @@ export async function prepare(config: InlineConfig) {
wxt.logger.info('Generating types...');
const entrypoints = await findEntrypoints();
await generateTypesDir(entrypoints);
await generateWxtDir(entrypoints);
}
@@ -14,19 +14,19 @@ import {
WxtModuleWithMetadata,
ResolvedEslintrc,
Eslintrc,
} from '../../../types';
} from '../types';
import path from 'node:path';
import { createFsCache } from '../../utils/cache';
import { createFsCache } from './utils/cache';
import consola, { LogLevels } from 'consola';
import defu from 'defu';
import { NullablyRequired } from '../types';
import { NullablyRequired } from './utils/types';
import fs from 'fs-extra';
import { normalizePath } from '../paths';
import { normalizePath } from './utils/paths';
import glob from 'fast-glob';
import { builtinModules } from '../../../builtin-modules';
import { getEslintVersion } from '../eslint';
import { safeStringToNumber } from '../number';
import { loadEnv } from '../env';
import { builtinModules } from '../builtin-modules';
import { getEslintVersion } from './utils/eslint';
import { safeStringToNumber } from './utils/number';
import { loadEnv } from './utils/env';
/**
* Given an inline config, discover the config file if necessary, merge the results, resolve any
@@ -179,7 +179,7 @@ export async function resolveConfig(
srcDir,
typesDir,
wxtDir,
zip: resolveZipConfig(root, outBaseDir, mergedConfig),
zip: resolveZipConfig(root, browser, outBaseDir, mergedConfig),
transformManifest: mergedConfig.transformManifest,
analysis: resolveAnalysisConfig(root, mergedConfig),
userConfigMetadata: userConfigMetadata ?? {},
@@ -258,6 +258,7 @@ async function mergeInlineConfig(
function resolveZipConfig(
root: string,
browser: string,
outBaseDir: string,
mergedConfig: InlineConfig,
): NullablyRequired<ResolvedConfig['zip']> {
@@ -270,6 +271,8 @@ function resolveZipConfig(
includeSources: [],
compressionLevel: 9,
...mergedConfig.zip,
zipSources:
mergedConfig.zip?.zipSources ?? ['firefox', 'opera'].includes(browser),
exclude: mergedConfig.zip?.exclude ?? [],
excludeSources: [
'**/node_modules',
@@ -1,8 +1,6 @@
export * from './build-entrypoints';
export * from './detect-dev-changes';
export * from './find-entrypoints';
export * from './generate-wxt-dir';
export * from './resolve-config';
export * from './group-entrypoints';
export * from './import-entrypoint';
export * from './internal-build';
@@ -1,6 +1,6 @@
import type { Manifest } from 'wxt/browser';
import { BuildOutput, Entrypoint, EntrypointGroup } from '../../../types';
import { generateTypesDir } from './generate-wxt-dir';
import { generateWxtDir } from '../../generate-wxt-dir';
import { buildEntrypoints } from './build-entrypoints';
import { generateManifest, writeManifest } from '../../utils/manifest';
import { wxt } from '../../wxt';
@@ -37,7 +37,7 @@ export async function rebuild(
const spinner = ora(`Preparing...`).start();
// Update types directory with new files and types
await generateTypesDir(allEntrypoints).catch((err) => {
await generateWxtDir(allEntrypoints).catch((err) => {
wxt.logger.warn('Failed to update .wxt directory:', err);
// Throw the error if doing a regular build, don't for dev mode.
if (wxt.config.command === 'build') throw err;
+1 -1
View File
@@ -5,6 +5,6 @@ import { config } from 'dotenv';
*/
export function loadEnv(mode: string) {
return config({
path: [`.env`, `.env.local`, `.env.${mode}`, `.env.${mode}.local`],
path: [`.env.${mode}.local`, `.env.${mode}`, `.env.local`, `.env`],
});
}
@@ -293,6 +293,7 @@ export const fakeResolvedConfig = fakeObjectCreator<ResolvedConfig>(() => {
downloadedPackagesDir: fakeDir(),
downloadPackages: [],
compressionLevel: 9,
zipSources: false,
},
transformManifest: () => {},
userConfigMetadata: {},
+1 -1
View File
@@ -7,7 +7,7 @@ import {
WxtHooks,
WxtModule,
} from '../types';
import { resolveConfig } from './utils/building';
import { resolveConfig } from './resolve-config';
import { createHooks } from 'hookable';
import { createWxtPackageManager } from './package-managers';
import { createViteBuilder } from './builders/vite';
+9 -4
View File
@@ -20,6 +20,7 @@ import { normalizePath } from './utils/paths';
export async function zip(config?: InlineConfig): Promise<string[]> {
await registerWxt('build', config);
const output = await internalBuild();
await wxt.hooks.callHook('zip:start', wxt);
const start = Date.now();
wxt.logger.info('Zipping extension...');
@@ -42,17 +43,17 @@ export async function zip(config?: InlineConfig): Promise<string[]> {
await fs.ensureDir(wxt.config.outBaseDir);
// ZIP output directory
await wxt.hooks.callHook('zip:extension:start', wxt);
const outZipFilename = applyTemplate(wxt.config.zip.artifactTemplate);
const outZipPath = path.resolve(wxt.config.outBaseDir, outZipFilename);
await zipDir(wxt.config.outDir, outZipPath, {
exclude: wxt.config.zip.exclude,
});
zipFiles.push(outZipPath);
await wxt.hooks.callHook('zip:extension:done', wxt, outZipPath);
// ZIP sources for Firefox
if (wxt.config.browser === 'firefox') {
if (wxt.config.zip.zipSources) {
await wxt.hooks.callHook('zip:sources:start', wxt);
const { overrides, files: downloadedPackages } =
await downloadPrivatePackages();
const sourcesZipFilename = applyTemplate(wxt.config.zip.sourcesTemplate);
@@ -71,6 +72,7 @@ export async function zip(config?: InlineConfig): Promise<string[]> {
additionalFiles: downloadedPackages,
});
zipFiles.push(sourcesZipPath);
await wxt.hooks.callHook('zip:sources:done', wxt, sourcesZipPath);
}
await printFileList(
@@ -80,8 +82,11 @@ export async function zip(config?: InlineConfig): Promise<string[]> {
zipFiles,
);
await wxt.hooks.callHook('zip:done', wxt, zipFiles);
return zipFiles;
}
async function zipDir(
directory: string,
outputPath: string,
+10 -1
View File
@@ -461,7 +461,16 @@ export interface WxtStorage {
* @example
* await storage.getItem<number>("local:installDate");
*/
getItem<T>(key: StorageItemKey, opts?: GetItemOptions<T>): Promise<T | null>;
getItem<TValue>(
key: StorageItemKey,
opts: GetItemOptions<TValue> & { fallback: TValue },
): Promise<TValue>;
getItem<TValue>(
key: StorageItemKey,
opts?: GetItemOptions<TValue>,
): Promise<TValue | null>;
/**
* Get multiple items from storage. The return order is guaranteed to be the same as the order
* requested.
+52
View File
@@ -130,6 +130,16 @@ export interface InlineConfig {
* @default "{{name}}-{{version}}-{{browser}}.zip"
*/
artifactTemplate?: string;
/**
* When zipping the extension, also zip sources.
*
* - `undefined`: zip sources if the target browser is "firefox" or "opera"
* - `true`: always zip sources
* - `false`: never zip sources
*
* @default undefined
*/
zipSources?: boolean;
/**
* Configure the filename output when zipping files.
*
@@ -1164,6 +1174,44 @@ export interface WxtHooks {
* @param entrypoints The list of files that will be copied into the output directory
*/
'build:publicAssets': (wxt: Wxt, files: ResolvedPublicFile[]) => HookResult;
/**
* Called before the zip process starts.
* @param wxt The configured WXT object
*/
'zip:start': (wxt: Wxt) => HookResult;
/**
* Called before zipping the extension files.
* @param wxt The configured WXT object
*/
'zip:extension:start': (wxt: Wxt) => HookResult;
/**
* Called after zipping the extension files.
* @param wxt The configured WXT object
* @param zipPath The path to the created extension zip file
*/
'zip:extension:done': (wxt: Wxt, zipPath: string) => HookResult;
/**
* Called before zipping the source files (for Firefox).
* @param wxt The configured WXT object
*/
'zip:sources:start': (wxt: Wxt) => HookResult;
/**
* Called after zipping the source files (for Firefox).
* @param wxt The configured WXT object
* @param zipPath The path to the created sources zip file
*/
'zip:sources:done': (wxt: Wxt, zipPath: string) => HookResult;
/**
* Called after the entire zip process is complete.
* @param wxt The configured WXT object
* @param zipFiles An array of paths to all created zip files
*/
'zip:done': (wxt: Wxt, zipFiles: string[]) => HookResult;
}
export interface Wxt {
@@ -1247,6 +1295,10 @@ export interface ResolvedConfig {
downloadPackages: string[];
compressionLevel: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
exclude: string[];
/**
* If true, when zipping the extension, also zip the sources.
*/
zipSources: boolean;
};
/**
* @deprecated Use `build:manifestGenerated` hook instead.