Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b5424cadb | |||
| 48571f5032 | |||
| c6c9f65040 | |||
| ace6c20164 | |||
| d64b64f39e | |||
| 41a687a63e | |||
| f4f6704510 | |||
| 65fc0fadb3 | |||
| 64b686713b | |||
| 9c6d3e37d4 | |||
| 37abe9db39 | |||
| 9ebef4a268 | |||
| e60f7c7e77 | |||
| 36aadd0604 | |||
| e4598a5e37 | |||
| db5c22809c | |||
| c61fa8f858 | |||
| 5fe4681620 | |||
| 80d384361b | |||
| a1e72c0749 | |||
| e3a80b8247 | |||
| c0013acadc | |||
| f472c53da7 | |||
| 032f7931e8 |
@@ -121,6 +121,8 @@ const chromeExtensionIds = [
|
||||
'lapnciffpekdengooeolaienkeoilfeo', // All API Hub – AI Relay & New API Manager - https://github.com/qixing-jk/all-api-hub
|
||||
'bhgobenflkkhfcgkikejaaejenoddcmo', // Scrape Similar - Extract data from websites into spreadsheets - https://github.com/zizzfizzix/scrape-similar
|
||||
'kinlknncggaihnhdcalijdmpbhbflalm', // isTrust - https://github.com/Internet-Society-Belgium/isTrust/
|
||||
'ojpakgiekphppgkcdihbjpafobhnhlkp', // Dymo
|
||||
'pmgehhllikbjmadpenhabejhpemplhmd', // Extension Rank Checker - Extension Ranker
|
||||
];
|
||||
|
||||
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
|
||||
|
||||
@@ -76,6 +76,28 @@ Alternatively, if you're trying to use similar APIs under different names (to su
|
||||
});
|
||||
```
|
||||
|
||||
### Augmenting the Browser Type
|
||||
|
||||
WXT's `browser` types are based on the `@types/chrome` package. That means some Firefox-specific APIs may not be typed, like `browser.sidebarAction`. If you want to add types for these APIs, you can augment the browser type to add them yourself:
|
||||
|
||||
```ts
|
||||
// <srcDir>/browser-types.d.ts
|
||||
import '@wxt-dev/browser';
|
||||
import type { SidebarAction } from 'webextension-polyfill';
|
||||
|
||||
declare module '@wxt-dev/browser' {
|
||||
namespace Browser {
|
||||
export const sidebarAction: SidebarAction.Static;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> For this to work, you may need to install `@wxt-dev/browser` as a direct dependency.
|
||||
>
|
||||
> ```sh
|
||||
> pnpm add @wxt-dev/browser
|
||||
> ```
|
||||
|
||||
## Entrypoint Limitations
|
||||
|
||||
Because WXT imports your entrypoint files into a NodeJS, non-extension environment, the `chrome`/`browser` variables provided to extensions by the browser **will not be available**.
|
||||
|
||||
+3
-5
@@ -20,17 +20,15 @@
|
||||
"@aklinker1/check": "^2.2.0",
|
||||
"@commitlint/config-conventional": "^20.4.3",
|
||||
"@commitlint/types": "^20.4.3",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"changelogen": "^0.6.2",
|
||||
"consola": "^3.4.2",
|
||||
"feed": "^5.2.0",
|
||||
"fs-extra": "^11.3.4",
|
||||
"lint-staged": "^16.3.2",
|
||||
"markdown-it-footnote": "^4.0.0",
|
||||
"markdownlint-cli": "^0.48.0",
|
||||
"nano-spawn": "^2.0.0",
|
||||
"nano-staged": "^0.8.0",
|
||||
"p-map": "^7.0.4",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-jsdoc": "^1.8.0",
|
||||
@@ -53,9 +51,9 @@
|
||||
"wxt": "workspace:*"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "pnpm lint-staged"
|
||||
"pre-commit": "./node_modules/.bin/nano-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"nano-staged": {
|
||||
"*": "prettier --ignore-unknown --write"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"dev:build": "buildc --deps-only -- wxt build",
|
||||
"check": "pnpm build && check",
|
||||
"build": "buildc -- tsdown",
|
||||
"prepack": "pnpm -s build",
|
||||
"prepack": "pnpm build",
|
||||
"prepare": "buildc --deps-only -- wxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -40,14 +40,14 @@
|
||||
"scripts": {
|
||||
"build": "buildc -- tsdown",
|
||||
"check": "pnpm build && check",
|
||||
"test": "buildc --deps-only -- vitest"
|
||||
"test": "buildc --deps-only -- vitest",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.19.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"defu": "^6.1.4",
|
||||
"fs-extra": "^11.3.4",
|
||||
"sharp": "^0.34.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
|
||||
import { resolve } from 'node:path';
|
||||
import * as fsExtra from 'fs-extra';
|
||||
import * as fsPromises from 'node:fs/promises';
|
||||
import sharp from 'sharp';
|
||||
import type { Wxt, UserManifest } from 'wxt';
|
||||
|
||||
@@ -9,9 +9,9 @@ import autoIconsModule from '../index';
|
||||
import type { AutoIconsOptions } from '../index';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('fs-extra', () => ({
|
||||
ensureDir: vi.fn(),
|
||||
pathExists: vi.fn(),
|
||||
vi.mock('node:fs/promises', () => ({
|
||||
mkdir: vi.fn(),
|
||||
access: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('sharp', () => ({
|
||||
@@ -86,8 +86,8 @@ describe('auto-icons module', () => {
|
||||
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);
|
||||
vi.mocked(fsPromises.access).mockResolvedValue(undefined);
|
||||
vi.mocked(fsPromises.mkdir).mockResolvedValue(undefined as any);
|
||||
});
|
||||
|
||||
describe('module setup', () => {
|
||||
@@ -158,7 +158,7 @@ describe('auto-icons module', () => {
|
||||
});
|
||||
|
||||
it('should warn when base icon not found', async () => {
|
||||
vi.mocked(fsExtra.pathExists).mockResolvedValue(false as any);
|
||||
vi.mocked(fsPromises.access).mockRejectedValue(new Error('ENOENT'));
|
||||
|
||||
const options: AutoIconsOptions = {
|
||||
enabled: true,
|
||||
@@ -293,8 +293,9 @@ describe('auto-icons module', () => {
|
||||
expect(mockSharpInstance.resize).toHaveBeenCalledWith(32);
|
||||
expect(mockSharpInstance.resize).toHaveBeenCalledWith(16);
|
||||
|
||||
expect(fsExtra.ensureDir).toHaveBeenCalledWith(
|
||||
expect(fsPromises.mkdir).toHaveBeenCalledWith(
|
||||
resolve('/mock/dist', 'icons'),
|
||||
{ recursive: true },
|
||||
);
|
||||
|
||||
expect(output.publicAssets).toEqual([
|
||||
@@ -514,7 +515,7 @@ describe('auto-icons module', () => {
|
||||
};
|
||||
|
||||
// Make ensureDir throw an error
|
||||
vi.mocked(fsExtra.ensureDir).mockRejectedValue(
|
||||
vi.mocked(fsPromises.mkdir).mockRejectedValue(
|
||||
new Error('Directory creation failed'),
|
||||
);
|
||||
|
||||
@@ -530,7 +531,7 @@ describe('auto-icons module', () => {
|
||||
if (buildHook) {
|
||||
await buildHook(mockWxt as unknown as Wxt, output);
|
||||
// But ensureDir should have been called
|
||||
expect(fsExtra.ensureDir).toHaveBeenCalled();
|
||||
expect(fsPromises.mkdir).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { defineWxtModule } from 'wxt/modules';
|
||||
import { resolve, relative } from 'node:path';
|
||||
import defu from 'defu';
|
||||
import sharp from 'sharp';
|
||||
import { ensureDir, pathExists } from 'fs-extra';
|
||||
import { access, mkdir } from 'node:fs/promises';
|
||||
|
||||
export default defineWxtModule<AutoIconsOptions>({
|
||||
name: '@wxt-dev/auto-icons',
|
||||
@@ -37,7 +37,11 @@ export default defineWxtModule<AutoIconsOptions>({
|
||||
if (!parsedOptions.enabled)
|
||||
return wxt.logger.warn(`\`[auto-icons]\` ${this.name} disabled`);
|
||||
|
||||
if (!(await pathExists(resolvedPath))) {
|
||||
const iconExists = await access(resolvedPath).then(
|
||||
() => true,
|
||||
() => false,
|
||||
);
|
||||
if (!iconExists) {
|
||||
return wxt.logger.warn(
|
||||
`\`[auto-icons]\` Skipping icon generation, no base icon found at ${relative(process.cwd(), resolvedPath)}`,
|
||||
);
|
||||
@@ -91,7 +95,7 @@ export default defineWxtModule<AutoIconsOptions>({
|
||||
}
|
||||
}
|
||||
|
||||
ensureDir(resolve(outputFolder, 'icons'));
|
||||
mkdir(resolve(outputFolder, 'icons'), { recursive: true });
|
||||
await resizedImage.toFile(resolve(outputFolder, `icons/${size}.png`));
|
||||
|
||||
output.publicAssets.push({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@wxt-dev/browser",
|
||||
"description": "Provides a cross-browser API for using extension APIs and types based on @types/chrome",
|
||||
"version": "0.1.37",
|
||||
"version": "0.1.38",
|
||||
"type": "module",
|
||||
"main": "src/index.mjs",
|
||||
"types": "src/index.d.ts",
|
||||
@@ -23,8 +23,8 @@
|
||||
"src"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/chrome": "0.1.37",
|
||||
"fs-extra": "^11.3.4",
|
||||
"@types/chrome": "0.1.38",
|
||||
"@types/node": "^20.0.0",
|
||||
"nano-spawn": "^2.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.18"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import spawn from 'nano-spawn';
|
||||
import fs from 'fs-extra';
|
||||
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join, resolve, sep } from 'node:path';
|
||||
import { sep as posixSep } from 'node:path/posix';
|
||||
@@ -17,8 +17,8 @@ const pkgJsonPath = fileURLToPath(
|
||||
import.meta.resolve('@types/chrome/package.json'),
|
||||
);
|
||||
const pkgDir = dirname(pkgJsonPath);
|
||||
const pkgJson = await fs.readJson(pkgJsonPath);
|
||||
const pkgJsonTemplate = await fs.readFile('templates/package.json', 'utf8');
|
||||
const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));
|
||||
const pkgJsonTemplate = await readFile('templates/package.json', 'utf8');
|
||||
const newPkgJson = JSON.parse(
|
||||
pkgJsonTemplate.replaceAll('{{chromeTypesVersion}}', pkgJson.version),
|
||||
);
|
||||
@@ -27,7 +27,7 @@ newPkgJson.peerDependencies = pkgJson.peerDependencies;
|
||||
newPkgJson.peerDependenciesMeta = pkgJson.peerDependenciesMeta;
|
||||
|
||||
const outPkgJsonPath = resolve('package.json');
|
||||
await fs.writeJson(outPkgJsonPath, newPkgJson);
|
||||
await writeFile(outPkgJsonPath, JSON.stringify(newPkgJson, null, 2));
|
||||
await spawn('pnpm', ['-w', 'prettier', '--write', outPkgJsonPath]);
|
||||
|
||||
// Generate declaration files
|
||||
@@ -35,7 +35,7 @@ await spawn('pnpm', ['-w', 'prettier', '--write', outPkgJsonPath]);
|
||||
console.log('Generating declaration files');
|
||||
const outDir = resolve('src/gen');
|
||||
const declarationFileMapping = (
|
||||
await fs.readdir(pkgDir, {
|
||||
await readdir(pkgDir, {
|
||||
recursive: true,
|
||||
encoding: 'utf8',
|
||||
})
|
||||
@@ -50,11 +50,11 @@ const declarationFileMapping = (
|
||||
}));
|
||||
|
||||
for (const { file, srcPath, destPath } of declarationFileMapping) {
|
||||
const content = await fs.readFile(srcPath, 'utf8');
|
||||
const content = await readFile(srcPath, 'utf8');
|
||||
const transformedContent = transformFile(file, content);
|
||||
const destDir = dirname(destPath);
|
||||
await fs.mkdir(destDir, { recursive: true });
|
||||
await fs.writeFile(destPath, transformedContent);
|
||||
await mkdir(destDir, { recursive: true });
|
||||
await writeFile(destPath, transformedContent);
|
||||
console.log(` \x1b[2m-\x1b[0m \x1b[36m${file}\x1b[0m`);
|
||||
}
|
||||
|
||||
|
||||
+11
-8
@@ -4076,14 +4076,17 @@ export namespace Browser {
|
||||
id: string;
|
||||
/**
|
||||
* Implements the WebCrypto's SubtleCrypto interface. The cryptographic operations, including key generation, are hardware-backed.
|
||||
* Only non-extractable keys can be generated. The supported key types are RSASSA-PKCS1-V1_5 and RSA-OAEP (on Chrome versions 134+) with `modulusLength` up to 2048 and ECDSA with `namedCurve` P-256. Each RSASSA-PKCS1-V1_5 and ECDSA key can be used for signing data at most once, unless the extension is allowlisted through the KeyPermissions policy, in which case the key can be used indefinitely. RSA-OAEP keys are supported since Chrome version 134 and can be used by extensions allowlisted through that same policy to unwrap other keys.
|
||||
*
|
||||
* Only non-extractable keys can be generated. The supported key types are RSASSA-PKCS1-V1_5 with `modulusLength` up to 2048 and ECDSA with `namedCurve` P-256. Each key can be used for signing data at most once, unless the extension is allowlisted by the KeyPermissions policy, in which case the key can be used indefinitely.
|
||||
*
|
||||
* Keys generated on a specific `Token` cannot be used with any other Tokens, nor can they be used with `window.crypto.subtle`. Equally, `Key` objects created with `window.crypto.subtle` cannot be used with this interface.
|
||||
*/
|
||||
subtleCrypto: SubtleCrypto;
|
||||
/**
|
||||
* Implements the WebCrypto's SubtleCrypto interface. The cryptographic operations, including key generation, are software-backed.
|
||||
* Protection of the keys, and thus implementation of the non-extractable property, is done in software, so the keys are less protected than hardware-backed keys.
|
||||
* Only non-extractable keys can be generated. The supported key types are RSASSA-PKCS1-V1_5 and RSA-OAEP (on Chrome versions 134+) with `modulusLength` up to 2048. Each RSASSA-PKCS1-V1_5 key can be used for signing data at most once, unless the extension is allowlisted through the KeyPermissions policy, in which case the key can be used indefinitely. RSA-OAEP keys are supported since Chrome version 134 and can be used by extensions allowlisted through that same policy to unwrap other keys.
|
||||
* Implements the WebCrypto's SubtleCrypto interface. The cryptographic operations, including key generation, are software-backed. Protection of the keys, and thus implementation of the non-extractable property, is done in software, so the keys are less protected than hardware-backed keys.
|
||||
*
|
||||
* Only non-extractable keys can be generated. The only supported key type is RSASSA-PKCS1-V1_5 with `modulusLength` up to 2048. up to 2048. Each key can be used for signing data at most once, unless the extension is allowlisted through the KeyPermissions policy, in which case the key can be used indefinitely.
|
||||
*
|
||||
* Keys generated on a specific `Token` cannot be used with any other Tokens, nor can they be used with `window.crypto.subtle`. Equally, `Key` objects created with `window.crypto.subtle` cannot be used with this interface.
|
||||
* @since Chrome 97
|
||||
*/
|
||||
@@ -9692,7 +9695,7 @@ export namespace Browser {
|
||||
/** Sent after onSuspend to indicate that the app won't be unloaded after all. */
|
||||
export const onSuspendCanceled: events.Event<() => void>;
|
||||
|
||||
/** Fired when a message is sent from either an extension process (by {@link runtime.sendMessage}) or a content script (by {@link tabs.sendMessage}). */
|
||||
/** Fired when a message is sent from either {@link runtime.sendMessage} or {@link tabs.sendMessage}. */
|
||||
export const onMessage: events.Event<
|
||||
(message: any, sender: MessageSender, sendResponse: (response?: any) => void) => void
|
||||
>;
|
||||
@@ -11058,7 +11061,7 @@ export namespace Browser {
|
||||
sessionId?: string | undefined;
|
||||
/**
|
||||
* The ID of the Split View that the tab belongs to.
|
||||
* @since Chrome 145
|
||||
* @since Chrome 140
|
||||
*/
|
||||
splitViewId?: number | undefined;
|
||||
/**
|
||||
@@ -11134,7 +11137,7 @@ export namespace Browser {
|
||||
|
||||
/**
|
||||
* An ID that represents the absence of a split tab.
|
||||
* @since Chrome 145
|
||||
* @since Chrome 140
|
||||
*/
|
||||
export const SPLIT_VIEW_ID_NONE: -1;
|
||||
|
||||
@@ -11581,7 +11584,7 @@ export namespace Browser {
|
||||
export function duplicate(tabId: number, callback: (tab?: Tab) => void): void;
|
||||
|
||||
/**
|
||||
* Sends a single message to the content script(s) in the specified tab, with an optional callback to run when a response is sent back. The {@link runtime.onMessage} event is fired in each content script running in the specified tab for the current extension.
|
||||
* Sends a single message to the content script(s) in the specified tab. The {@link runtime.onMessage} event is fired in each content script running in the specified tab for the current extension.
|
||||
*
|
||||
* Can return its result via Promise in Manifest V3 or later since Chrome 99.
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/chrome": "{{chromeTypesVersion}}",
|
||||
"fs-extra": "^11.3.4",
|
||||
"@types/node": "^20.0.0",
|
||||
"nano-spawn": "^2.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.0.18"
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"scripts": {
|
||||
"build": "buildc -- tsdown",
|
||||
"check": "buildc --deps-only -- check",
|
||||
"test": "buildc --deps-only -- vitest"
|
||||
"test": "buildc --deps-only -- vitest",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wxt-dev/browser": "workspace:^",
|
||||
|
||||
@@ -16,12 +16,25 @@ export { SUPPORTED_LOCALES } from './supported-locales';
|
||||
// TYPES
|
||||
//
|
||||
|
||||
export type SimpleMessage = string;
|
||||
|
||||
export type PluralMessage = Record<'n' | number, string>;
|
||||
|
||||
export interface ChromeMessage {
|
||||
message: string;
|
||||
description?: string;
|
||||
placeholders?: Record<string, { content: string; example?: string }>;
|
||||
}
|
||||
|
||||
export type Message =
|
||||
| SimpleMessage
|
||||
| PluralMessage
|
||||
| ChromeMessage
|
||||
| Message[]
|
||||
| { [key: string]: Message };
|
||||
|
||||
export type MessagesObject = Record<string, Message>;
|
||||
|
||||
export interface ParsedBaseMessage {
|
||||
key: string[];
|
||||
substitutions: number;
|
||||
@@ -95,7 +108,7 @@ const EXT_FORMATS_MAP: Record<string, MessageFormat> = {
|
||||
'.toml': 'TOML',
|
||||
};
|
||||
|
||||
const PARSERS: Record<MessageFormat, (text: string) => any> = {
|
||||
const PARSERS: Record<MessageFormat, (text: string) => MessagesObject> = {
|
||||
YAML: parseYAML,
|
||||
JSON5: parseJSON5,
|
||||
TOML: parseTOML,
|
||||
@@ -117,6 +130,7 @@ export async function parseMessagesFile(
|
||||
): Promise<ParsedMessage[]> {
|
||||
const text = await readFile(file, 'utf8');
|
||||
const ext = extname(file).toLowerCase();
|
||||
|
||||
return parseMessagesText(text, EXT_FORMATS_MAP[ext] ?? 'JSON5');
|
||||
}
|
||||
|
||||
@@ -129,7 +143,7 @@ export function parseMessagesText(
|
||||
}
|
||||
|
||||
/** Given the JS object form of a raw messages file, extract the messages. */
|
||||
export function parseMessagesObject(object: any): ParsedMessage[] {
|
||||
export function parseMessagesObject(object: MessagesObject): ParsedMessage[] {
|
||||
return _parseMessagesObject(
|
||||
[],
|
||||
{
|
||||
@@ -142,7 +156,7 @@ export function parseMessagesObject(object: any): ParsedMessage[] {
|
||||
|
||||
function _parseMessagesObject(
|
||||
path: string[],
|
||||
object: any,
|
||||
object: Message,
|
||||
depth: number,
|
||||
): ParsedMessage[] {
|
||||
switch (typeof object) {
|
||||
@@ -163,15 +177,17 @@ function _parseMessagesObject(
|
||||
];
|
||||
}
|
||||
case 'object':
|
||||
if ([null, undefined].includes(object)) {
|
||||
if (object == null) {
|
||||
throw new Error(
|
||||
`Messages file should not contain \`${object}\` (found at "${path.join('.')}")`,
|
||||
);
|
||||
}
|
||||
|
||||
if (Array.isArray(object))
|
||||
return object.flatMap((item, i) =>
|
||||
_parseMessagesObject(path.concat(String(i)), item, depth + 1),
|
||||
);
|
||||
|
||||
if (isPluralMessage(object)) {
|
||||
const message = Object.values(object).join('|');
|
||||
const substitutions = getSubstitutionCount(message);
|
||||
@@ -184,6 +200,7 @@ function _parseMessagesObject(
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (depth === 1 && isChromeMessage(object)) {
|
||||
const message = applyChromeMessagePlaceholders(object);
|
||||
const substitutions = getSubstitutionCount(message);
|
||||
@@ -196,6 +213,7 @@ function _parseMessagesObject(
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return Object.entries(object).flatMap(([key, value]) =>
|
||||
_parseMessagesObject(path.concat(key), value, depth + 1),
|
||||
);
|
||||
@@ -204,13 +222,13 @@ function _parseMessagesObject(
|
||||
}
|
||||
}
|
||||
|
||||
function isPluralMessage(object: any): object is Record<number | 'n', string> {
|
||||
function isPluralMessage(object: Message): object is PluralMessage {
|
||||
return Object.keys(object).every(
|
||||
(key) => key === 'n' || isFinite(Number(key)),
|
||||
);
|
||||
}
|
||||
|
||||
function isChromeMessage(object: any): object is ChromeMessage {
|
||||
function isChromeMessage(object: Message): object is ChromeMessage {
|
||||
return Object.keys(object).every((key) =>
|
||||
ALLOWED_CHROME_MESSAGE_KEYS.has(key),
|
||||
);
|
||||
@@ -222,7 +240,7 @@ function isChromeMessage(object: any): object is ChromeMessage {
|
||||
|
||||
export function generateTypeText(messages: ParsedMessage[]): string {
|
||||
const renderMessageEntry = (message: ParsedMessage): string => {
|
||||
// Use . for deep keys at runtime and types
|
||||
// Use '.' for deep keys at runtime and types
|
||||
const key = message.key.join('.');
|
||||
|
||||
const features = [
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
## v1.2.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-react-v1.2.1...module-react-v1.2.2)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Add `@vitejs/plugin-react` v6 support ([c61fa8f8](https://github.com/wxt-dev/wxt/commit/c61fa8f8))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v1.2.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-react-v1.2.0...module-react-v1.2.1)
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Add prepack script to all packages ([032f7931](https://github.com/wxt-dev/wxt/commit/032f7931))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v1.2.0
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-react-v1.1.5...module-react-v1.2.0)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.2",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
@@ -42,14 +42,15 @@
|
||||
"dev": "wxt",
|
||||
"check": "pnpm build && check",
|
||||
"build": "buildc -- tsdown",
|
||||
"prepare": "buildc --deps-only -- wxt prepare"
|
||||
"prepare": "buildc --deps-only -- wxt prepare",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^5.4.19 || ^6.3.4 || ^7.0.0 || ^8.0.0-0",
|
||||
"wxt": ">=0.19.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vitejs/plugin-react": "^4.4.1 || ^5.0.0"
|
||||
"@vitejs/plugin-react": "^4.4.1 || ^5.0.0 || ^6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.2.14",
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"dev": "wxt",
|
||||
"check": "pnpm build && check",
|
||||
"build": "buildc -- tsdown",
|
||||
"prepare": "buildc --deps-only -- wxt prepare"
|
||||
"prepare": "buildc --deps-only -- wxt prepare",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.19.16"
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## v2.0.5
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-svelte-v2.0.4...module-svelte-v2.0.5)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Update `@sveltejs/vite-plugin-svelte` version range to support Vite 8 ([48571f50](https://github.com/wxt-dev/wxt/commit/48571f50))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- 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))
|
||||
- **deps:** Upgrade deps ([#2175](https://github.com/wxt-dev/wxt/pull/2175))
|
||||
- Add prepack script to all packages ([032f7931](https://github.com/wxt-dev/wxt/commit/032f7931))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
|
||||
## v2.0.4
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/module-svelte-v2.0.3...module-svelte-v2.0.4)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"version": "2.0.4",
|
||||
"version": "2.0.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
@@ -40,14 +40,15 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "buildc -- tsdown",
|
||||
"check": "pnpm build && check"
|
||||
"check": "pnpm build && check",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.18.6",
|
||||
"svelte": ">=5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.0 || ^5.0.0 || ^6.0.0"
|
||||
"@sveltejs/vite-plugin-svelte": ">=4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"publint": "^0.3.18",
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "buildc -- tsdown",
|
||||
"check": "pnpm build && check"
|
||||
"check": "pnpm build && check",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.19.16"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"test": "buildc --deps-only -- vitest",
|
||||
"dev": "tsx --trace-warnings dev.ts",
|
||||
"build": "buildc -- tsdown",
|
||||
"prepublishOnly": "pnpm build"
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"oxlint": "^1.51.0",
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
"scripts": {
|
||||
"build": "buildc -- tsdown",
|
||||
"check": "buildc --deps-only -- check",
|
||||
"test": "buildc --deps-only -- vitest"
|
||||
"test": "buildc --deps-only -- vitest",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wxt-dev/browser": "workspace:^",
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "buildc -- tsdown",
|
||||
"check": "buildc --deps-only -- check"
|
||||
"check": "buildc --deps-only -- check",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"unocss": ">=0.60.0",
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
"dev": "wxt",
|
||||
"check": "pnpm build && check",
|
||||
"build": "buildc -- tsdown",
|
||||
"prepare": "buildc --deps-only -- wxt prepare"
|
||||
"prepare": "buildc --deps-only -- wxt prepare",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webextension-polyfill": "*",
|
||||
|
||||
@@ -1,5 +1,65 @@
|
||||
# Changelog
|
||||
|
||||
## v0.20.20
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.19...wxt-v0.20.20)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Unlisted script return values broken with Vite 8 sourcemaps ([#2197](https://github.com/wxt-dev/wxt/pull/2197))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Add Dymo extension ID to UsingWxtSection.vue ([#2187](https://github.com/wxt-dev/wxt/pull/2187))
|
||||
- Add Extension Rank Checker to the list of extensions ([#2193](https://github.com/wxt-dev/wxt/pull/2193))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- **deps:** Add vite-node 6 support ([64b68671](https://github.com/wxt-dev/wxt/commit/64b68671))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
- Joseph Hu ([@KiJO94GO](https://github.com/KiJO94GO))
|
||||
- FJRG2007 ツ ([@FJRG2007](https://github.com/FJRG2007))
|
||||
- Hampus Tågerud ([@hampustagerud](https://github.com/hampustagerud))
|
||||
|
||||
## v0.20.19
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.18...wxt-v0.20.19)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Vite 8 support ([bfd4af5d](https://github.com/wxt-dev/wxt/commit/bfd4af5d))
|
||||
|
||||
### 🔥 Performance
|
||||
|
||||
- Use filter to improve plugin performance with rolldown ([#1787](https://github.com/wxt-dev/wxt/pull/1787))
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- List eslint 10 as supported ([55dc263d](https://github.com/wxt-dev/wxt/commit/55dc263d))
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- Added "Scrape Similar" to the homepage ([#2158](https://github.com/wxt-dev/wxt/pull/2158))
|
||||
- Added "isTrust" to the homepage ([#2161](https://github.com/wxt-dev/wxt/pull/2161))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Add `prettier-plugin-jsdoc` to project ([#2171](https://github.com/wxt-dev/wxt/pull/2171))
|
||||
- Replace fast-glob and ora with lighter alternatives ([#2173](https://github.com/wxt-dev/wxt/pull/2173))
|
||||
- **deps:** Upgrade deps ([#2175](https://github.com/wxt-dev/wxt/pull/2175))
|
||||
- Replace `fs-extra` with `node:fs/promises` ([#2174](https://github.com/wxt-dev/wxt/pull/2174))
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
- Florian Metz ([@Timeraa](https://github.com/Timeraa))
|
||||
- Aaron ([@aklinker1](https://github.com/aklinker1))
|
||||
- Patryk Kuniczak ([@PatrykKuniczak](https://github.com/PatrykKuniczak))
|
||||
- Etoome ([@etoome](https://github.com/etoome))
|
||||
- Kuba ([@zizzfizzix](https://github.com/zizzfizzix))
|
||||
|
||||
## v0.20.18
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.20.17...wxt-v0.20.18)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { TestProject, WXT_PACKAGE_DIR } from '../utils';
|
||||
import spawn from 'nano-spawn';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { mkdir, writeJson } from 'fs-extra';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { TestProject, WXT_PACKAGE_DIR } from '../utils';
|
||||
|
||||
describe('Init command', () => {
|
||||
it('should download and create a template', async () => {
|
||||
@@ -53,7 +53,7 @@ describe('Init command', () => {
|
||||
it('should throw an error if the directory is not empty', async () => {
|
||||
const project = new TestProject();
|
||||
await mkdir(project.root, { recursive: true });
|
||||
await writeJson(project.resolvePath('package.json'), {});
|
||||
await writeFile(project.resolvePath('package.json'), JSON.stringify({}));
|
||||
|
||||
await expect(() =>
|
||||
spawn(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { TestProject } from '../utils';
|
||||
import type { InlineConfig, UnlistedScriptEntrypoint } from '../../src';
|
||||
import { readFile } from 'fs-extra';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { normalizePath } from '../../src';
|
||||
|
||||
describe('Module Helpers', () => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
import { TestProject } from '../utils';
|
||||
import extract from 'extract-zip';
|
||||
import spawn from 'nano-spawn';
|
||||
import { readFile, writeFile } from 'fs-extra';
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
|
||||
process.env.WXT_PNPM_IGNORE_WORKSPACE = 'true';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { glob } from 'tinyglobby';
|
||||
import fs, { mkdir } from 'fs-extra';
|
||||
import merge from 'lodash.merge';
|
||||
import spawn from 'nano-spawn';
|
||||
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
||||
import { dirname, relative, resolve } from 'path';
|
||||
import { glob } from 'tinyglobby';
|
||||
import {
|
||||
InlineConfig,
|
||||
UserConfig,
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
zip,
|
||||
} from '../src';
|
||||
import { normalizePath } from '../src/core/utils';
|
||||
import { pathExists, readJson } from '../src/core/utils/fs';
|
||||
|
||||
// Run "pnpm wxt" to use the "wxt" dev script, not the "wxt" binary from the
|
||||
// wxt package. This uses the TS files instead of the compiled JS package
|
||||
@@ -119,8 +120,8 @@ export class TestProject {
|
||||
const [name, content] = file;
|
||||
const filePath = this.resolvePath(name);
|
||||
const fileDir = dirname(filePath);
|
||||
await fs.ensureDir(fileDir);
|
||||
await fs.writeFile(filePath, content ?? '', 'utf-8');
|
||||
await mkdir(fileDir, { recursive: true });
|
||||
await writeFile(filePath, content ?? '', 'utf-8');
|
||||
}
|
||||
|
||||
// Only install dependencies if the project has custom ones - otherwise the
|
||||
@@ -183,17 +184,19 @@ export class TestProject {
|
||||
const absolutePath = this.resolvePath(path);
|
||||
return [
|
||||
normalizePath(relative(this.root, absolutePath)),
|
||||
ignoreContents ? '<contents-ignored>' : await fs.readFile(absolutePath),
|
||||
ignoreContents
|
||||
? '<contents-ignored>'
|
||||
: await readFile(absolutePath, 'utf-8'),
|
||||
].join(`\n${''.padEnd(40, '-')}\n`);
|
||||
}
|
||||
|
||||
pathExists(...path: string[]): Promise<boolean> {
|
||||
return fs.pathExists(this.resolvePath(...path));
|
||||
return pathExists(this.resolvePath(...path));
|
||||
}
|
||||
|
||||
getOutputManifest(
|
||||
path: string = '.output/chrome-mv3/manifest.json',
|
||||
): Promise<any> {
|
||||
return fs.readJson(this.resolvePath(path));
|
||||
return readJson(this.resolvePath(path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.20.18",
|
||||
"version": "0.20.20",
|
||||
"description": "⚡ Next-gen Web Extension Framework",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@@ -30,11 +30,9 @@
|
||||
"ci-info": "^4.4.0",
|
||||
"consola": "^3.4.2",
|
||||
"defu": "^6.1.4",
|
||||
"dotenv": "^17.3.1",
|
||||
"dotenv-expand": "^12.0.3",
|
||||
"esbuild": "^0.27.1",
|
||||
"filesize": "^11.0.13",
|
||||
"fs-extra": "^11.3.4",
|
||||
"get-port-please": "^3.2.0",
|
||||
"giget": "^1.2.3 || ^2.0.0 || ^3.0.0",
|
||||
"hookable": "^6.0.1",
|
||||
@@ -44,7 +42,6 @@
|
||||
"jszip": "^3.10.1",
|
||||
"linkedom": "^0.18.12",
|
||||
"magicast": "^0.5.2",
|
||||
"minimatch": "^10.2.4",
|
||||
"nano-spawn": "^2.0.0",
|
||||
"nanospinner": "^1.2.2",
|
||||
"normalize-path": "^3.0.0",
|
||||
@@ -53,13 +50,14 @@
|
||||
"open": "^11.0.0",
|
||||
"perfect-debounce": "^2.1.0",
|
||||
"picocolors": "^1.1.1",
|
||||
"picomatch": "^4.0.3",
|
||||
"prompts": "^2.4.2",
|
||||
"publish-browser-extension": "^2.3.0 || ^3.0.2 || ^4.0.4",
|
||||
"scule": "^1.3.0",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"unimport": "^3.13.1 || ^4.0.0 || ^5.0.0 || ^6.0.0",
|
||||
"vite": "^5.4.19 || ^6.3.4 || ^7.0.0 || ^8.0.0-0",
|
||||
"vite-node": "^3.2.4 || ^5.0.0",
|
||||
"vite-node": "^3.2.4 || ^5.0.0 || ^6.0.0",
|
||||
"web-ext-run": "^0.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -72,10 +70,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^10.3.0",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/lodash.merge": "^4.6.9",
|
||||
"@types/node": "^20.17.6",
|
||||
"@types/normalize-path": "^3.0.2",
|
||||
"@types/picomatch": "^4.0.2",
|
||||
"@types/prompts": "^2.4.9",
|
||||
"eslint": "^10.0.0",
|
||||
"extract-zip": "^2.0.1",
|
||||
|
||||
@@ -26,7 +26,7 @@ import { ViteNodeRunner } from 'vite-node/client';
|
||||
import { installSourcemapsSupport } from 'vite-node/source-map';
|
||||
import { createExtensionEnvironment } from '../../utils/environments';
|
||||
import { dirname, extname, join, relative } from 'node:path';
|
||||
import fs from 'fs-extra';
|
||||
import { mkdir, readdir, rename, rmdir, stat } from 'node:fs/promises';
|
||||
import { normalizePath } from '../../utils';
|
||||
|
||||
export async function createViteBuilder(
|
||||
@@ -455,8 +455,8 @@ async function moveHtmlFiles(
|
||||
);
|
||||
const oldAbsPath = join(config.outDir, oldBundlePath);
|
||||
const newAbsPath = join(config.outDir, newBundlePath);
|
||||
await fs.ensureDir(dirname(newAbsPath));
|
||||
await fs.move(oldAbsPath, newAbsPath, { overwrite: true });
|
||||
await mkdir(dirname(newAbsPath), { recursive: true });
|
||||
await rename(oldAbsPath, newAbsPath);
|
||||
|
||||
return {
|
||||
...chunk,
|
||||
@@ -473,17 +473,17 @@ async function moveHtmlFiles(
|
||||
|
||||
/** Recursively remove all directories that are empty/ */
|
||||
export async function removeEmptyDirs(dir: string): Promise<void> {
|
||||
const files = await fs.readdir(dir);
|
||||
const files = await readdir(dir);
|
||||
for (const file of files) {
|
||||
const filePath = join(dir, file);
|
||||
const stats = await fs.stat(filePath);
|
||||
const stats = await stat(filePath);
|
||||
if (stats.isDirectory()) {
|
||||
await removeEmptyDirs(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.rmdir(dir);
|
||||
await rmdir(dir);
|
||||
} catch {
|
||||
// noop on failure - this means the directory was not empty.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { iifeFooter } from '../iifeFooter';
|
||||
|
||||
interface OutputChunk {
|
||||
type: 'chunk';
|
||||
code: string;
|
||||
isEntry: boolean;
|
||||
}
|
||||
|
||||
interface OutputAsset {
|
||||
type: 'asset';
|
||||
source: string;
|
||||
}
|
||||
|
||||
type OutputBundle = Record<string, OutputChunk | OutputAsset>;
|
||||
|
||||
function dedent(code: string) {
|
||||
const lines = code.trim().split('\n');
|
||||
return lines.map((line) => line.trimStart()).join('\n');
|
||||
}
|
||||
|
||||
function createBundle(code: string): OutputBundle {
|
||||
return {
|
||||
'entry.js': {
|
||||
type: 'chunk',
|
||||
code: dedent(code),
|
||||
isEntry: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function getCode(bundle: OutputBundle): string {
|
||||
const entry = bundle['entry.js'];
|
||||
|
||||
if (entry.type !== 'chunk') {
|
||||
throw new Error('expected chunk');
|
||||
}
|
||||
|
||||
return entry.code;
|
||||
}
|
||||
|
||||
function runPlugin(name: string, bundle: OutputBundle) {
|
||||
const plugin = iifeFooter(name);
|
||||
// @ts-expect-error -- calling the hook directly
|
||||
plugin.generateBundle(undefined, bundle);
|
||||
}
|
||||
|
||||
describe('IIFE return value plugin', () => {
|
||||
it('should append return value when no sourcemap comment', () => {
|
||||
const bundle = createBundle(`
|
||||
var foo = (function(){return 1})();
|
||||
`);
|
||||
|
||||
runPlugin('foo', bundle);
|
||||
|
||||
expect(getCode(bundle)).toBe(
|
||||
dedent(`
|
||||
var foo = (function(){return 1})();
|
||||
foo;
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
||||
it('should insert return value before sourcemap comment', () => {
|
||||
const bundle = createBundle(`
|
||||
var foo = (function(){return 1})();
|
||||
//# ${'sourceMappingURL'}=foo.js.map
|
||||
`);
|
||||
|
||||
runPlugin('foo', bundle);
|
||||
|
||||
expect(getCode(bundle)).toBe(
|
||||
dedent(`
|
||||
var foo = (function(){return 1})();
|
||||
foo;
|
||||
//# ${'sourceMappingURL'}=foo.js.map
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
||||
it('should insert return value before inline sourcemap', () => {
|
||||
const bundle = createBundle(`
|
||||
var foo = (function(){return 1})();
|
||||
//# ${'sourceMappingURL'}=data:application/json;base64,abc123
|
||||
`);
|
||||
|
||||
runPlugin('foo', bundle);
|
||||
|
||||
expect(getCode(bundle)).toBe(
|
||||
dedent(`
|
||||
var foo = (function(){return 1})();
|
||||
foo;
|
||||
//# ${'sourceMappingURL'}=data:application/json;base64,abc123
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
||||
it('should skip non-entry chunks', () => {
|
||||
const bundle = createBundle('var x = 1;');
|
||||
(bundle['entry.js'] as OutputChunk).isEntry = false;
|
||||
|
||||
runPlugin('x', bundle);
|
||||
|
||||
expect(getCode(bundle)).toBe('var x = 1;');
|
||||
});
|
||||
|
||||
it('should skip assets', () => {
|
||||
const bundle: OutputBundle = {
|
||||
'style.css': {
|
||||
type: 'asset',
|
||||
source: 'body {}',
|
||||
} satisfies OutputAsset,
|
||||
};
|
||||
|
||||
runPlugin('style', bundle);
|
||||
|
||||
expect((bundle['style.css'] as OutputAsset).source).toBe('body {}');
|
||||
});
|
||||
});
|
||||
@@ -13,7 +13,20 @@ export function iifeFooter(iifeReturnValueName: string): Plugin {
|
||||
generateBundle(_, bundle) {
|
||||
for (const chunk of Object.values(bundle)) {
|
||||
if (chunk.type === 'chunk' && chunk.isEntry) {
|
||||
chunk.code += `${iifeReturnValueName};`;
|
||||
const code = chunk.code;
|
||||
const marker = '\n//# sourceMappingURL=';
|
||||
const returnValue = `${iifeReturnValueName};`;
|
||||
|
||||
const index = code.indexOf(marker);
|
||||
|
||||
if (index >= 0) {
|
||||
chunk.code =
|
||||
code.slice(0, index + 1) +
|
||||
`${returnValue}\n` +
|
||||
code.slice(index + 1);
|
||||
} else {
|
||||
chunk.code += `\n${returnValue}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { pathExists } from 'fs-extra';
|
||||
import { pathExists } from '../../../utils/fs';
|
||||
import { resolve } from 'node:path';
|
||||
import type * as vite from 'vite';
|
||||
import { ResolvedConfig } from '../../../../types';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { resolve } from 'path';
|
||||
import type { Plugin } from 'vite';
|
||||
import { ResolvedConfig } from '../../../../types';
|
||||
import { normalizePath } from '../../../utils';
|
||||
@@ -5,8 +7,6 @@ import {
|
||||
VirtualModuleId,
|
||||
virtualModuleNames,
|
||||
} from '../../../utils/virtual-modules';
|
||||
import { resolve } from 'path';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
/**
|
||||
* Resolve all the virtual modules to the `node_modules/wxt/dist/virtual`
|
||||
@@ -36,7 +36,7 @@ export function resolveVirtualModules(config: ResolvedConfig): Plugin[] {
|
||||
},
|
||||
async handler(id) {
|
||||
const inputPath = id.replace(resolvedVirtualId, '');
|
||||
const template = await fs.readFile(
|
||||
const template = await readFile(
|
||||
resolve(config.wxtModuleDir, `dist/virtual/${name}.mjs`),
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { rm } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { glob } from 'tinyglobby';
|
||||
import fs from 'fs-extra';
|
||||
import pc from 'picocolors';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { InlineConfig } from '../types';
|
||||
import { registerWxt, wxt } from './wxt';
|
||||
|
||||
@@ -60,7 +60,7 @@ export async function clean(config?: string | InlineConfig) {
|
||||
directories.map((dir) => pc.cyan(path.relative(root, dir))).join(', '),
|
||||
);
|
||||
for (const directory of directories) {
|
||||
await fs.rm(directory, { force: true, recursive: true });
|
||||
await rm(directory, { force: true, recursive: true });
|
||||
wxt.logger.debug('Deleted ' + pc.cyan(path.relative(root, directory)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Entrypoint, WxtDirEntry, WxtDirFileEntry } from '../types';
|
||||
import fs from 'fs-extra';
|
||||
import { mkdir, readFile } from 'node:fs/promises';
|
||||
import { dirname, relative, resolve } from 'node:path';
|
||||
import { getEntrypointBundlePath, isHtmlEntrypoint } from './utils/entrypoints';
|
||||
import { getEntrypointGlobals, getGlobals } from './utils/globals';
|
||||
import { normalizePath } from './utils';
|
||||
import path from 'node:path';
|
||||
import { Message, parseI18nMessages } from './utils/i18n';
|
||||
import { writeFileIfDifferent, getPublicFiles } from './utils/fs';
|
||||
import { pathExists, writeFileIfDifferent, getPublicFiles } from './utils/fs';
|
||||
import { wxt } from './wxt';
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@ import { wxt } from './wxt';
|
||||
* directory.
|
||||
*/
|
||||
export async function generateWxtDir(entrypoints: Entrypoint[]): Promise<void> {
|
||||
await fs.ensureDir(wxt.config.typesDir);
|
||||
await mkdir(wxt.config.typesDir, { recursive: true });
|
||||
|
||||
const entries: WxtDirEntry[] = [
|
||||
// Hard-coded entries
|
||||
@@ -57,7 +57,7 @@ export async function generateWxtDir(entrypoints: Entrypoint[]): Promise<void> {
|
||||
|
||||
await Promise.all(
|
||||
absoluteFileEntries.map(async (file) => {
|
||||
await fs.ensureDir(dirname(file.path));
|
||||
await mkdir(dirname(file.path), { recursive: true });
|
||||
await writeFileIfDifferent(file.path, file.text);
|
||||
}),
|
||||
);
|
||||
@@ -149,8 +149,8 @@ declare module "wxt/browser" {
|
||||
'messages.json',
|
||||
);
|
||||
let messages: Message[];
|
||||
if (await fs.pathExists(defaultLocalePath)) {
|
||||
const content = JSON.parse(await fs.readFile(defaultLocalePath, 'utf-8'));
|
||||
if (await pathExists(defaultLocalePath)) {
|
||||
const content = JSON.parse(await readFile(defaultLocalePath, 'utf-8'));
|
||||
messages = parseI18nMessages(content);
|
||||
} else {
|
||||
messages = parseI18nMessages({});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import prompts from 'prompts';
|
||||
import { consola } from 'consola';
|
||||
import { downloadTemplate } from 'giget';
|
||||
import fs from 'fs-extra';
|
||||
import { readdir, rename } from 'node:fs/promises';
|
||||
import { pathExists } from './utils/fs';
|
||||
import path from 'node:path';
|
||||
import pc from 'picocolors';
|
||||
import { Formatter } from 'picocolors/types';
|
||||
@@ -56,10 +57,10 @@ export async function initialize(options: {
|
||||
input.template ??= defaultTemplate;
|
||||
input.packageManager ??= options.packageManager;
|
||||
|
||||
const isExists = await fs.pathExists(input.directory);
|
||||
const isExists = await pathExists(input.directory);
|
||||
if (isExists) {
|
||||
const isEmpty =
|
||||
(await fs.readdir(input.directory)).filter((dir) => dir !== '.git')
|
||||
(await readdir(input.directory)).filter((dir) => dir !== '.git')
|
||||
.length === 0;
|
||||
if (!isEmpty) {
|
||||
consola.error(
|
||||
@@ -167,14 +168,12 @@ async function cloneProject({
|
||||
});
|
||||
|
||||
// 2. Move _gitignore -> .gitignore
|
||||
await fs
|
||||
.move(
|
||||
path.join(directory, '_gitignore'),
|
||||
path.join(directory, '.gitignore'),
|
||||
)
|
||||
.catch((err) =>
|
||||
consola.warn('Failed to move _gitignore to .gitignore:', err),
|
||||
);
|
||||
await rename(
|
||||
path.join(directory, '_gitignore'),
|
||||
path.join(directory, '.gitignore'),
|
||||
).catch((err) =>
|
||||
consola.warn('Failed to move _gitignore to .gitignore:', err),
|
||||
);
|
||||
|
||||
spinner.success();
|
||||
} catch (err) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import path from 'node:path';
|
||||
import { npm } from '../npm';
|
||||
import spawn from 'nano-spawn';
|
||||
import { pathExists } from 'fs-extra';
|
||||
import { pathExists } from '../../utils/fs';
|
||||
|
||||
describe('NPM Package Management Utils', () => {
|
||||
describe('listDependencies', () => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Dependency } from '../../types';
|
||||
import { WxtPackageManagerImpl } from './types';
|
||||
import path from 'node:path';
|
||||
import { ensureDir } from 'fs-extra';
|
||||
import { mkdir } from 'node:fs/promises';
|
||||
import spawn from 'nano-spawn';
|
||||
|
||||
export const npm: WxtPackageManagerImpl = {
|
||||
overridesKey: 'overrides',
|
||||
async downloadDependency(id, downloadDir) {
|
||||
await ensureDir(downloadDir);
|
||||
await mkdir(downloadDir, { recursive: true });
|
||||
const res = await spawn('npm', ['pack', id, '--json'], {
|
||||
cwd: downloadDir,
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ import { createFsCache } from './utils/cache';
|
||||
import consola, { LogLevels } from 'consola';
|
||||
import defu from 'defu';
|
||||
import { NullablyRequired } from './utils/types';
|
||||
import fs from 'fs-extra';
|
||||
import { pathExists } from './utils/fs';
|
||||
import { normalizePath } from './utils';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { builtinModules } from '../builtin-modules';
|
||||
@@ -543,7 +543,7 @@ function resolveWxtModuleDir() {
|
||||
}
|
||||
|
||||
async function isDirMissing(dir: string) {
|
||||
return !(await fs.pathExists(dir));
|
||||
return !(await pathExists(dir));
|
||||
}
|
||||
|
||||
function logMissingDir(logger: Logger, name: string, expected: string) {
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { minimatchMultiple } from '../minimatch-multiple';
|
||||
|
||||
describe('minimatchMultiple', () => {
|
||||
it('should return false if the pattern array is undefined', () => {
|
||||
const patterns = undefined;
|
||||
const search = 'test.json';
|
||||
|
||||
expect(minimatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the pattern array is empty', () => {
|
||||
const patterns: string[] = [];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(minimatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if the pattern array contains a match', () => {
|
||||
const patterns = ['test.yml', 'test.json'];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(minimatchMultiple(search, patterns)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the pattern array does not contain a match', () => {
|
||||
const patterns = ['test.yml', 'test.json'];
|
||||
const search = 'test.txt';
|
||||
|
||||
expect(minimatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the pattern matches a negative pattern', () => {
|
||||
const patterns = ['test.*', '!test.json'];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(minimatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the pattern matches a negative pattern, regardless of order', () => {
|
||||
const patterns = ['!test.json', 'test.*'];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(minimatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { picomatchMultiple } from '../picomatch-multiple';
|
||||
|
||||
describe('picomatchMultiple', () => {
|
||||
it('should return false if the pattern array is undefined', () => {
|
||||
const patterns = undefined;
|
||||
const search = 'test.json';
|
||||
|
||||
expect(picomatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the pattern array is empty', () => {
|
||||
const patterns: string[] = [];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(picomatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if the pattern array contains a match', () => {
|
||||
const patterns = ['test.yml', 'test.json'];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(picomatchMultiple(search, patterns)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the pattern array does not contain a match', () => {
|
||||
const patterns = ['test.yml', 'test.json'];
|
||||
const search = 'test.txt';
|
||||
|
||||
expect(picomatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the pattern matches a negative pattern', () => {
|
||||
const patterns = ['test.*', '!test.json'];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(picomatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the pattern matches a negative pattern, regardless of order', () => {
|
||||
const patterns = ['!test.json', 'test.*'];
|
||||
const search = 'test.json';
|
||||
|
||||
expect(picomatchMultiple(search, patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should support extglob-like extension matching', () => {
|
||||
const patterns = ['content.[jt]s?(x)'];
|
||||
|
||||
expect(picomatchMultiple('content.ts', patterns)).toBe(true);
|
||||
expect(picomatchMultiple('content.jsx', patterns)).toBe(true);
|
||||
expect(picomatchMultiple('content.css', patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should support nested paths', () => {
|
||||
const patterns = ['foo/**/*.ts'];
|
||||
|
||||
expect(picomatchMultiple('foo/bar/baz.ts', patterns)).toBe(true);
|
||||
expect(picomatchMultiple('foo/bar/baz.js', patterns)).toBe(false);
|
||||
});
|
||||
|
||||
it('should preserve include/exclude interaction used by zip filtering', () => {
|
||||
const include = ['special.txt'];
|
||||
const exclude = ['**/*.txt'];
|
||||
const search = 'special.txt';
|
||||
const shouldInclude =
|
||||
picomatchMultiple(search, include) || !picomatchMultiple(search, exclude);
|
||||
|
||||
expect(shouldInclude).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,7 @@
|
||||
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { resolve } from 'path';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
|
||||
import {
|
||||
BackgroundEntrypoint,
|
||||
BackgroundEntrypointOptions,
|
||||
@@ -9,21 +12,16 @@ import {
|
||||
PopupEntrypoint,
|
||||
SidepanelEntrypoint,
|
||||
} from '../../../../types';
|
||||
import { resolve } from 'path';
|
||||
import { findEntrypoints } from '../find-entrypoints';
|
||||
import fs from 'fs-extra';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { fakeResolvedConfig, setFakeWxt } from '../../testing/fake-objects';
|
||||
import { unnormalizePath } from '../../paths';
|
||||
import { wxt } from '../../../wxt';
|
||||
import { unnormalizePath } from '../../paths';
|
||||
import { fakeResolvedConfig, setFakeWxt } from '../../testing/fake-objects';
|
||||
import { findEntrypoints } from '../find-entrypoints';
|
||||
|
||||
vi.mock('tinyglobby');
|
||||
const globMock = vi.mocked(glob);
|
||||
|
||||
vi.mock('fs-extra');
|
||||
const readFileMock = vi.mocked(
|
||||
fs.readFile as (path: string) => Promise<string>,
|
||||
);
|
||||
vi.mock('node:fs/promises');
|
||||
const readFileMock = vi.mocked(readFile);
|
||||
|
||||
describe('findEntrypoints', () => {
|
||||
const config = fakeResolvedConfig({
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
ResolvedPublicFile,
|
||||
} from '../../../types';
|
||||
import { getPublicFiles } from '../fs';
|
||||
import fs from 'fs-extra';
|
||||
import { copyFile, mkdir, writeFile } from 'node:fs/promises';
|
||||
import { dirname, resolve } from 'path';
|
||||
import type { Spinner } from 'nanospinner';
|
||||
import pc from 'picocolors';
|
||||
@@ -50,11 +50,11 @@ async function copyPublicDirectory(): Promise<BuildOutput['publicAssets']> {
|
||||
for (const file of files) {
|
||||
const absoluteDest = resolve(wxt.config.outDir, file.relativeDest);
|
||||
|
||||
await fs.ensureDir(dirname(absoluteDest));
|
||||
await mkdir(dirname(absoluteDest), { recursive: true });
|
||||
if ('absoluteSrc' in file) {
|
||||
await fs.copyFile(file.absoluteSrc, absoluteDest);
|
||||
await copyFile(file.absoluteSrc, absoluteDest);
|
||||
} else {
|
||||
await fs.writeFile(absoluteDest, file.contents, 'utf8');
|
||||
await writeFile(absoluteDest, file.contents, 'utf8');
|
||||
}
|
||||
publicAssets.push({
|
||||
type: 'asset',
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
IsolatedWorldContentScriptEntrypointOptions,
|
||||
UnlistedScriptEntrypoint,
|
||||
} from '../../../types';
|
||||
import fs from 'fs-extra';
|
||||
import { minimatch } from 'minimatch';
|
||||
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
||||
import picomatch from 'picomatch';
|
||||
import { parseHTML } from 'linkedom';
|
||||
import JSON5 from 'json5';
|
||||
import { glob } from 'tinyglobby';
|
||||
@@ -35,11 +35,11 @@ import { camelCase } from 'scule';
|
||||
*/
|
||||
export async function findEntrypoints(): Promise<Entrypoint[]> {
|
||||
// Make sure required TSConfig file exists to load dependencies
|
||||
await fs.mkdir(wxt.config.wxtDir, { recursive: true });
|
||||
await mkdir(wxt.config.wxtDir, { recursive: true });
|
||||
try {
|
||||
await fs.writeJson(
|
||||
await writeFile(
|
||||
resolve(wxt.config.wxtDir, 'tsconfig.json'),
|
||||
{},
|
||||
JSON.stringify({}),
|
||||
{ flag: 'wx' },
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -61,7 +61,7 @@ export async function findEntrypoints(): Promise<Entrypoint[]> {
|
||||
const inputPath = resolve(wxt.config.entrypointsDir, relativePath);
|
||||
const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
|
||||
const matchingGlob = pathGlobs.find((glob) =>
|
||||
minimatch(relativePath, glob),
|
||||
picomatch(glob)(relativePath),
|
||||
);
|
||||
if (matchingGlob) {
|
||||
const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
|
||||
@@ -204,7 +204,7 @@ async function importEntrypoints(infos: EntrypointInfo[]) {
|
||||
async function importHtmlEntrypoint(
|
||||
info: EntrypointInfo,
|
||||
): Promise<Record<string, any>> {
|
||||
const content = await fs.readFile(info.inputPath, 'utf-8');
|
||||
const content = await readFile(info.inputPath, 'utf-8');
|
||||
const { document } = parseHTML(content);
|
||||
|
||||
const metaTags = document.querySelectorAll('meta');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { findEntrypoints } from './find-entrypoints';
|
||||
import { BuildOutput, Entrypoint } from '../../../types';
|
||||
import pc from 'picocolors';
|
||||
import fs from 'fs-extra';
|
||||
import { mkdir, rm } from 'node:fs/promises';
|
||||
import { groupEntrypoints } from './group-entrypoints';
|
||||
import { formatDuration } from '../time';
|
||||
import { printBuildSummary } from '../log';
|
||||
@@ -43,8 +43,8 @@ export async function internalBuild(): Promise<BuildOutput> {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Cleanup
|
||||
await fs.rm(wxt.config.outDir, { recursive: true, force: true });
|
||||
await fs.ensureDir(wxt.config.outDir);
|
||||
await rm(wxt.config.outDir, { recursive: true, force: true });
|
||||
await mkdir(wxt.config.outDir, { recursive: true });
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
wxt.logger.debug('Detected entrypoints:', entrypoints);
|
||||
@@ -111,7 +111,9 @@ async function combineAnalysisStats(): Promise<void> {
|
||||
});
|
||||
|
||||
if (!wxt.config.analysis.keepArtifacts) {
|
||||
await Promise.all(absolutePaths.map((statsFile) => fs.remove(statsFile)));
|
||||
await Promise.all(
|
||||
absolutePaths.map((statsFile) => rm(statsFile, { force: true })),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { BuildOutput, Entrypoint, EntrypointGroup } from '../../../types';
|
||||
import { generateWxtDir } from '../../generate-wxt-dir';
|
||||
import { buildEntrypoints } from './build-entrypoints';
|
||||
import { generateManifest, writeManifest } from '../../utils/manifest';
|
||||
import { wxt } from '../../wxt';
|
||||
import type { Browser } from '@wxt-dev/browser';
|
||||
import { createSpinner } from 'nanospinner';
|
||||
import { BuildOutput, Entrypoint, EntrypointGroup } from '../../../types';
|
||||
import { generateWxtDir } from '../../generate-wxt-dir';
|
||||
import { generateManifest, writeManifest } from '../../utils/manifest';
|
||||
import { wxt } from '../../wxt';
|
||||
import { buildEntrypoints } from './build-entrypoints';
|
||||
|
||||
/**
|
||||
* Given a configuration, list of entrypoints, and an existing, partial output,
|
||||
@@ -22,7 +22,7 @@ import { createSpinner } from 'nanospinner';
|
||||
* .wxt directory.
|
||||
* @param entrypointGroups The list of entrypoint groups to build.
|
||||
* @param existingOutput The previous output to combine the rebuild results
|
||||
* into. An emptry array if this is the first build.
|
||||
* into. An empty array if this is the first build.
|
||||
*/
|
||||
export async function rebuild(
|
||||
allEntrypoints: Entrypoint[],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import fs, { ensureDir } from 'fs-extra';
|
||||
import { mkdir, readFile } from 'node:fs/promises';
|
||||
import { FsCache } from '../../types';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { writeFileIfDifferent } from './fs';
|
||||
@@ -16,13 +16,13 @@ export function createFsCache(wxtDir: string): FsCache {
|
||||
return {
|
||||
async set(key: string, value: string): Promise<void> {
|
||||
const path = getPath(key);
|
||||
await ensureDir(dirname(path));
|
||||
await mkdir(dirname(path), { recursive: true });
|
||||
await writeFileIfDifferent(path, value);
|
||||
},
|
||||
async get(key: string): Promise<string | undefined> {
|
||||
const path = getPath(key);
|
||||
try {
|
||||
return await fs.readFile(path, 'utf-8');
|
||||
return await readFile(path, 'utf-8');
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,45 @@
|
||||
import { config } from 'dotenv';
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import { parseEnv } from 'node:util';
|
||||
import { expand } from 'dotenv-expand';
|
||||
import type { TargetBrowser } from '../../types';
|
||||
|
||||
/** Load environment files based on the current mode and browser. */
|
||||
export function loadEnv(mode: string, browser: TargetBrowser) {
|
||||
return expand(
|
||||
config({
|
||||
quiet: true,
|
||||
// Files on top override files below
|
||||
path: [
|
||||
`.env.${mode}.${browser}.local`,
|
||||
`.env.${mode}.${browser}`,
|
||||
`.env.${browser}.local`,
|
||||
`.env.${browser}`,
|
||||
`.env.${mode}.local`,
|
||||
`.env.${mode}`,
|
||||
`.env.local`,
|
||||
`.env`,
|
||||
],
|
||||
const envFiles = [
|
||||
// List is ordered with general files first, specific ones last, so the more
|
||||
// specific files override the more general ones in the loop below.
|
||||
`.env`,
|
||||
`.env.local`,
|
||||
`.env.${mode}`,
|
||||
`.env.${mode}.local`,
|
||||
`.env.${browser}`,
|
||||
`.env.${browser}.local`,
|
||||
`.env.${mode}.${browser}`,
|
||||
`.env.${mode}.${browser}.local`,
|
||||
];
|
||||
|
||||
const parsed = Object.fromEntries<string>(
|
||||
envFiles.flatMap((filePath) => {
|
||||
if (!existsSync(filePath)) return [];
|
||||
|
||||
try {
|
||||
const content = readFileSync(filePath, 'utf-8');
|
||||
const parsedEnv = parseEnv(content);
|
||||
return Object.entries(parsedEnv) as [string, string][];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
// Make a copy of `process.env` so that `dotenv-expand` doesn't re-assign the
|
||||
// expanded values to the global `process.env`.
|
||||
const processEnv = { ...process.env } as Record<string, string>;
|
||||
|
||||
expand({
|
||||
parsed,
|
||||
processEnv,
|
||||
});
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
import fs from 'fs-extra';
|
||||
import { access, readFile, writeFile } from 'node:fs/promises';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { unnormalizePath } from './paths';
|
||||
import { wxt } from '../wxt';
|
||||
import { unnormalizePath } from './paths';
|
||||
|
||||
export async function pathExists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await access(path);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function readJson<T = any>(path: string): Promise<T> {
|
||||
return JSON.parse(await readFile(path, 'utf-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Only write the contents to a file if it results in a change. This prevents
|
||||
@@ -15,21 +28,15 @@ export async function writeFileIfDifferent(
|
||||
file: string,
|
||||
newContents: string,
|
||||
): Promise<void> {
|
||||
const existingContents = await fs
|
||||
.readFile(file, 'utf-8')
|
||||
.catch(() => undefined);
|
||||
const existingContents = await readFile(file, 'utf-8').catch(() => undefined);
|
||||
|
||||
if (existingContents !== newContents) {
|
||||
await fs.writeFile(file, newContents);
|
||||
await writeFile(file, newContents);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the files in the project's public directory. Returned paths are
|
||||
* relative to the `config.publicDir`.
|
||||
*/
|
||||
export async function getPublicFiles(): Promise<string[]> {
|
||||
if (!(await fs.pathExists(wxt.config.publicDir))) return [];
|
||||
if (!(await pathExists(wxt.config.publicDir))) return [];
|
||||
|
||||
const files = await glob('**/*', {
|
||||
cwd: wxt.config.publicDir,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from 'node:path';
|
||||
import pc from 'picocolors';
|
||||
import fs from 'fs-extra';
|
||||
import { lstat } from 'node:fs/promises';
|
||||
import { filesize } from 'filesize';
|
||||
import { printTable } from './printTable';
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function printFileList(
|
||||
];
|
||||
const prefix = i === files.length - 1 ? ' └─' : ' ├─';
|
||||
const color = getChunkColor(file);
|
||||
const stats = await fs.lstat(file);
|
||||
const stats = await lstat(file);
|
||||
totalSize += stats.size;
|
||||
const size = String(filesize(stats.size));
|
||||
return [
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
PopupEntrypoint,
|
||||
SidepanelEntrypoint,
|
||||
} from '../../types';
|
||||
import fs from 'fs-extra';
|
||||
import { mkdir } from 'node:fs/promises';
|
||||
import { resolve } from 'path';
|
||||
import { getEntrypointBundlePath } from './entrypoints';
|
||||
import { ContentSecurityPolicy } from './content-security-policy';
|
||||
@@ -33,7 +33,7 @@ export async function writeManifest(
|
||||
? JSON.stringify(manifest)
|
||||
: JSON.stringify(manifest, null, 2);
|
||||
|
||||
await fs.ensureDir(wxt.config.outDir);
|
||||
await mkdir(wxt.config.outDir, { recursive: true });
|
||||
await writeFileIfDifferent(resolve(wxt.config.outDir, 'manifest.json'), str);
|
||||
|
||||
output.publicAssets.unshift({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { resolve } from 'node:path';
|
||||
import fs from 'fs-extra';
|
||||
import { readJson } from './fs';
|
||||
import { wxt } from '../wxt';
|
||||
|
||||
/**
|
||||
@@ -12,7 +12,7 @@ export async function getPackageJson(): Promise<
|
||||
> {
|
||||
const file = resolve(wxt.config.root, 'package.json');
|
||||
try {
|
||||
return await fs.readJson(file);
|
||||
return await readJson(file);
|
||||
} catch (err) {
|
||||
wxt.logger.debug(
|
||||
`Failed to read package.json at: ${file}. Returning undefined.`,
|
||||
|
||||
+8
-8
@@ -1,7 +1,7 @@
|
||||
import { minimatch, MinimatchOptions } from 'minimatch';
|
||||
import picomatch, { PicomatchOptions } from 'picomatch';
|
||||
|
||||
/**
|
||||
* Run [`minimatch`](https://npmjs.com/package/minimatch) against multiple
|
||||
* Run [`picomatch`](https://npmjs.com/package/picomatch) against multiple
|
||||
* patterns.
|
||||
*
|
||||
* Supports negated patterns, the order does not matter. If your `search` string
|
||||
@@ -9,14 +9,14 @@ import { minimatch, MinimatchOptions } from 'minimatch';
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* minimatchMultiple('a.json', ['*.json', '!b.json']); // => true
|
||||
* minimatchMultiple('b.json', ['*.json', '!b.json']); // => false
|
||||
* picomatchMultiple('a.json', ['*.json', '!b.json']); // => true
|
||||
* picomatchMultiple('b.json', ['*.json', '!b.json']); // => false
|
||||
* ```;
|
||||
*/
|
||||
export function minimatchMultiple(
|
||||
export function picomatchMultiple(
|
||||
search: string,
|
||||
patterns: string[] | undefined,
|
||||
options?: MinimatchOptions,
|
||||
options?: PicomatchOptions,
|
||||
): boolean {
|
||||
if (patterns == null) return false;
|
||||
|
||||
@@ -29,12 +29,12 @@ export function minimatchMultiple(
|
||||
|
||||
if (
|
||||
negatePatterns.some((negatePattern) =>
|
||||
minimatch(search, negatePattern, options),
|
||||
picomatch(negatePattern, options)(search),
|
||||
)
|
||||
)
|
||||
return false;
|
||||
|
||||
return positivePatterns.some((positivePattern) =>
|
||||
minimatch(search, positivePattern, options),
|
||||
picomatch(positivePattern, options)(search),
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { InlineConfig } from '../types';
|
||||
import path from 'node:path';
|
||||
import fs from 'fs-extra';
|
||||
import { mkdir, readFile } from 'node:fs/promises';
|
||||
import { createWriteStream } from 'node:fs';
|
||||
import { safeFilename } from './utils/strings';
|
||||
import { getPackageJson } from './utils/package';
|
||||
import { formatDuration } from './utils/time';
|
||||
@@ -10,7 +11,7 @@ import { registerWxt, wxt } from './wxt';
|
||||
import JSZip from 'jszip';
|
||||
import { glob } from 'tinyglobby';
|
||||
import { normalizePath } from './utils';
|
||||
import { minimatchMultiple } from './utils/minimatch-multiple';
|
||||
import { picomatchMultiple } from './utils/picomatch-multiple';
|
||||
|
||||
/**
|
||||
* Build and zip the extension for distribution.
|
||||
@@ -43,7 +44,7 @@ export async function zip(config?: InlineConfig): Promise<string[]> {
|
||||
.replaceAll('{{mode}}', wxt.config.mode)
|
||||
.replaceAll('{{manifestVersion}}', `mv${wxt.config.manifestVersion}`);
|
||||
|
||||
await fs.ensureDir(wxt.config.outBaseDir);
|
||||
await mkdir(wxt.config.outBaseDir, { recursive: true });
|
||||
|
||||
// ZIP output directory
|
||||
await wxt.hooks.callHook('zip:extension:start', wxt);
|
||||
@@ -124,8 +125,8 @@ async function zipDir(
|
||||
})
|
||||
).filter((relativePath) => {
|
||||
return (
|
||||
minimatchMultiple(relativePath, options?.include) ||
|
||||
!minimatchMultiple(relativePath, options?.exclude)
|
||||
picomatchMultiple(relativePath, options?.include) ||
|
||||
!picomatchMultiple(relativePath, options?.exclude)
|
||||
);
|
||||
});
|
||||
const filesToZip = [
|
||||
@@ -137,13 +138,13 @@ async function zipDir(
|
||||
for (const file of filesToZip) {
|
||||
const absolutePath = path.resolve(directory, file);
|
||||
if (file.endsWith('.json')) {
|
||||
const content = await fs.readFile(absolutePath, 'utf-8');
|
||||
const content = await readFile(absolutePath, 'utf-8');
|
||||
archive.file(
|
||||
file,
|
||||
(await options?.transform?.(absolutePath, file, content)) || content,
|
||||
);
|
||||
} else {
|
||||
const content = await fs.readFile(absolutePath);
|
||||
const content = await readFile(absolutePath);
|
||||
archive.file(file, content);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +161,7 @@ async function zipDir(
|
||||
compressionOptions: { level: wxt.config.zip.compressionLevel },
|
||||
}),
|
||||
})
|
||||
.pipe(fs.createWriteStream(outputPath))
|
||||
.pipe(createWriteStream(outputPath))
|
||||
.on('error', reject)
|
||||
.on('close', resolve),
|
||||
);
|
||||
|
||||
@@ -212,7 +212,7 @@ export interface InlineConfig {
|
||||
*/
|
||||
sourcesRoot?: string;
|
||||
/**
|
||||
* [Minimatch](https://www.npmjs.com/package/minimatch) patterns of files to
|
||||
* [Picomatch](https://www.npmjs.com/package/picomatch) patterns of files to
|
||||
* include when creating a ZIP of all your source code for Firefox. Patterns
|
||||
* are relative to your `config.zip.sourcesRoot`.
|
||||
*
|
||||
@@ -226,7 +226,7 @@ export interface InlineConfig {
|
||||
*/
|
||||
includeSources?: string[];
|
||||
/**
|
||||
* [Minimatch](https://www.npmjs.com/package/minimatch) patterns of files to
|
||||
* [Picomatch](https://www.npmjs.com/package/picomatch) patterns of files to
|
||||
* exclude when creating a ZIP of all your source code for Firefox. Patterns
|
||||
* are relative to your `config.zip.sourcesRoot`.
|
||||
*
|
||||
@@ -239,7 +239,7 @@ export interface InlineConfig {
|
||||
*/
|
||||
excludeSources?: string[];
|
||||
/**
|
||||
* [Minimatch](https://www.npmjs.com/package/minimatch) patterns of files to
|
||||
* [Picomatch](https://www.npmjs.com/package/picomatch) patterns of files to
|
||||
* exclude when zipping the extension.
|
||||
*
|
||||
* @example
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { pathExists, rm } from 'fs-extra';
|
||||
import { access, rm } from 'node:fs/promises';
|
||||
|
||||
let setupHappened = false;
|
||||
|
||||
@@ -12,7 +12,10 @@ export async function setup() {
|
||||
globalThis.__ENTRYPOINT__ = 'test';
|
||||
|
||||
const e2eDistPath = './e2e/dist/';
|
||||
if (await pathExists(e2eDistPath)) {
|
||||
try {
|
||||
await access(e2eDistPath);
|
||||
await rm(e2eDistPath, { recursive: true, force: true });
|
||||
} catch {
|
||||
// Directory doesn't exist, nothing to clean up
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+34
-95
@@ -25,9 +25,6 @@ importers:
|
||||
'@commitlint/types':
|
||||
specifier: ^20.4.3
|
||||
version: 20.4.3
|
||||
'@types/fs-extra':
|
||||
specifier: ^11.0.4
|
||||
version: 11.0.4
|
||||
'@types/semver':
|
||||
specifier: ^7.7.1
|
||||
version: 7.7.1
|
||||
@@ -43,12 +40,6 @@ importers:
|
||||
feed:
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0
|
||||
fs-extra:
|
||||
specifier: ^11.3.4
|
||||
version: 11.3.4
|
||||
lint-staged:
|
||||
specifier: ^16.3.2
|
||||
version: 16.3.2
|
||||
markdown-it-footnote:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0(patch_hash=5b74a0001a771ff5df790dd36b6883c4794e1f666b231499edb2d65eae8f4930)
|
||||
@@ -58,6 +49,9 @@ importers:
|
||||
nano-spawn:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
nano-staged:
|
||||
specifier: ^0.8.0
|
||||
version: 0.8.0
|
||||
p-map:
|
||||
specifier: ^7.0.4
|
||||
version: 7.0.4
|
||||
@@ -149,9 +143,6 @@ importers:
|
||||
defu:
|
||||
specifier: ^6.1.4
|
||||
version: 6.1.4
|
||||
fs-extra:
|
||||
specifier: ^11.3.4
|
||||
version: 11.3.4
|
||||
sharp:
|
||||
specifier: ^0.34.5
|
||||
version: 0.34.5
|
||||
@@ -182,11 +173,11 @@ importers:
|
||||
version: 1.2.16
|
||||
devDependencies:
|
||||
'@types/chrome':
|
||||
specifier: 0.1.37
|
||||
version: 0.1.37
|
||||
fs-extra:
|
||||
specifier: ^11.3.4
|
||||
version: 11.3.4
|
||||
specifier: 0.1.38
|
||||
version: 0.1.38
|
||||
'@types/node':
|
||||
specifier: ^20.0.0
|
||||
version: 20.19.32
|
||||
nano-spawn:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
@@ -256,7 +247,7 @@ importers:
|
||||
packages/module-react:
|
||||
dependencies:
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.4.1 || ^5.0.0
|
||||
specifier: ^4.4.1 || ^5.0.0 || ^6.0.0
|
||||
version: 5.1.4(vite@7.3.1(@types/node@20.19.32)(jiti@2.6.1)(sass@1.97.3)(tsx@4.21.0)(yaml@2.8.2))
|
||||
devDependencies:
|
||||
'@types/react':
|
||||
@@ -306,7 +297,7 @@ importers:
|
||||
packages/module-svelte:
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^4.0.0 || ^5.0.0 || ^6.0.0
|
||||
specifier: '>=4'
|
||||
version: 6.2.4(vite@7.3.1(@types/node@20.19.32)(jiti@2.6.1)(sass@1.97.3)(tsx@4.21.0)(yaml@2.8.2))
|
||||
devDependencies:
|
||||
publint:
|
||||
@@ -465,9 +456,6 @@ importers:
|
||||
defu:
|
||||
specifier: ^6.1.4
|
||||
version: 6.1.4
|
||||
dotenv:
|
||||
specifier: ^17.3.1
|
||||
version: 17.3.1
|
||||
dotenv-expand:
|
||||
specifier: ^12.0.3
|
||||
version: 12.0.3
|
||||
@@ -477,9 +465,6 @@ importers:
|
||||
filesize:
|
||||
specifier: ^11.0.13
|
||||
version: 11.0.13
|
||||
fs-extra:
|
||||
specifier: ^11.3.4
|
||||
version: 11.3.4
|
||||
get-port-please:
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0
|
||||
@@ -507,9 +492,6 @@ importers:
|
||||
magicast:
|
||||
specifier: ^0.5.2
|
||||
version: 0.5.2
|
||||
minimatch:
|
||||
specifier: ^10.2.4
|
||||
version: 10.2.4
|
||||
nano-spawn:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
@@ -534,6 +516,9 @@ importers:
|
||||
picocolors:
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1
|
||||
picomatch:
|
||||
specifier: ^4.0.3
|
||||
version: 4.0.3
|
||||
prompts:
|
||||
specifier: ^2.4.2
|
||||
version: 2.4.2
|
||||
@@ -553,7 +538,7 @@ importers:
|
||||
specifier: ^5.4.19 || ^6.3.4 || ^7.0.0 || ^8.0.0-0
|
||||
version: 7.3.1(@types/node@20.19.32)(jiti@2.6.1)(sass@1.97.3)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vite-node:
|
||||
specifier: ^3.2.4 || ^5.0.0
|
||||
specifier: ^3.2.4 || ^5.0.0 || ^6.0.0
|
||||
version: 5.3.0(@types/node@20.19.32)(jiti@2.6.1)(sass@1.97.3)(tsx@4.21.0)(yaml@2.8.2)
|
||||
web-ext-run:
|
||||
specifier: ^0.2.4
|
||||
@@ -562,9 +547,6 @@ importers:
|
||||
'@faker-js/faker':
|
||||
specifier: ^10.3.0
|
||||
version: 10.3.0
|
||||
'@types/fs-extra':
|
||||
specifier: ^11.0.4
|
||||
version: 11.0.4
|
||||
'@types/lodash.merge':
|
||||
specifier: ^4.6.9
|
||||
version: 4.6.9
|
||||
@@ -574,6 +556,9 @@ importers:
|
||||
'@types/normalize-path':
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
'@types/picomatch':
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2
|
||||
'@types/prompts':
|
||||
specifier: ^2.4.9
|
||||
version: 2.4.9
|
||||
@@ -2144,8 +2129,8 @@ packages:
|
||||
'@types/chai@5.2.3':
|
||||
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
||||
|
||||
'@types/chrome@0.1.37':
|
||||
resolution: {integrity: sha512-IJE4ceuDO7lrEuua7Pow47zwNcI8E6qqkowRP7aFPaZ0lrjxh6y836OPqqkIZeTX64FTogbw+4RNH0+QrweCTQ==}
|
||||
'@types/chrome@0.1.38':
|
||||
resolution: {integrity: sha512-5aK4m9wZqoWAoB98aElESLm/5pXpqJnFWMNoiCs/XdPsXR6wNdVkJFSdQ9Wr4PnTuUrxD0SuNuDHh3EG5QeBzA==}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
@@ -2165,9 +2150,6 @@ packages:
|
||||
'@types/filewriter@0.0.33':
|
||||
resolution: {integrity: sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==}
|
||||
|
||||
'@types/fs-extra@11.0.4':
|
||||
resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
|
||||
|
||||
'@types/har-format@1.2.16':
|
||||
resolution: {integrity: sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==}
|
||||
|
||||
@@ -2180,9 +2162,6 @@ packages:
|
||||
'@types/json-schema@7.0.15':
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
|
||||
'@types/jsonfile@6.1.4':
|
||||
resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==}
|
||||
|
||||
'@types/katex@0.16.8':
|
||||
resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==}
|
||||
|
||||
@@ -2216,6 +2195,9 @@ packages:
|
||||
'@types/normalize-path@3.0.2':
|
||||
resolution: {integrity: sha512-DO++toKYPaFn0Z8hQ7Tx+3iT9t77IJo/nDiqTXilgEP+kPNIYdpS9kh3fXuc53ugqwp9pxC1PVjCpV1tQDyqMA==}
|
||||
|
||||
'@types/picomatch@4.0.2':
|
||||
resolution: {integrity: sha512-qHHxQ+P9PysNEGbALT8f8YOSHW0KJu6l2xU8DYY0fu/EmGxXdVnuTLvFUvBgPJMSqXq29SYHveejeAha+4AYgA==}
|
||||
|
||||
'@types/prompts@2.4.9':
|
||||
resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==}
|
||||
|
||||
@@ -3630,19 +3612,10 @@ packages:
|
||||
linkify-it@5.0.0:
|
||||
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
|
||||
|
||||
lint-staged@16.3.2:
|
||||
resolution: {integrity: sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==}
|
||||
engines: {node: '>=20.17'}
|
||||
hasBin: true
|
||||
|
||||
listr2@10.1.0:
|
||||
resolution: {integrity: sha512-/6t2KgDYIcCjhELwvrRxi1gaJ4xCGLTjNvh6mSjYenBkrZxggek8EwCbwBU33GMUCpyyrOzz2TzylrO5mTiI1w==}
|
||||
engines: {node: '>=22.0.0'}
|
||||
|
||||
listr2@9.0.5:
|
||||
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
|
||||
local-pkg@1.1.2:
|
||||
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -3675,10 +3648,6 @@ packages:
|
||||
lodash.once@4.1.1:
|
||||
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||
|
||||
log-update@6.1.0:
|
||||
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
log-update@7.1.0:
|
||||
resolution: {integrity: sha512-y9pi/ZOQQVvTgfRDEHV1Cj4zQUkJZPipEUNOxhn1R6KgmdMs7LKvXWCd9eMVPGJgvYzFLCenecWr0Ps8ChVv2A==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -3924,6 +3893,11 @@ packages:
|
||||
resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==}
|
||||
engines: {node: '>=20.17'}
|
||||
|
||||
nano-staged@0.8.0:
|
||||
resolution: {integrity: sha512-QSEqPGTCJbkHU2yLvfY6huqYPjdBrOaTMKatO1F8nCSrkQGXeKwtCiCnsdxnuMhbg3DTVywKaeWLGCE5oJpq0g==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
hasBin: true
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
@@ -4501,10 +4475,6 @@ packages:
|
||||
std-env@3.10.0:
|
||||
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
|
||||
|
||||
string-argv@0.3.2:
|
||||
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
||||
engines: {node: '>=0.6.19'}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -6270,7 +6240,7 @@ snapshots:
|
||||
'@types/deep-eql': 4.0.2
|
||||
assertion-error: 2.0.1
|
||||
|
||||
'@types/chrome@0.1.37':
|
||||
'@types/chrome@0.1.38':
|
||||
dependencies:
|
||||
'@types/filesystem': 0.0.36
|
||||
'@types/har-format': 1.2.16
|
||||
@@ -6291,11 +6261,6 @@ snapshots:
|
||||
|
||||
'@types/filewriter@0.0.33': {}
|
||||
|
||||
'@types/fs-extra@11.0.4':
|
||||
dependencies:
|
||||
'@types/jsonfile': 6.1.4
|
||||
'@types/node': 20.19.32
|
||||
|
||||
'@types/har-format@1.2.16': {}
|
||||
|
||||
'@types/hast@3.0.4':
|
||||
@@ -6306,10 +6271,6 @@ snapshots:
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/jsonfile@6.1.4':
|
||||
dependencies:
|
||||
'@types/node': 20.19.32
|
||||
|
||||
'@types/katex@0.16.8': {}
|
||||
|
||||
'@types/linkify-it@5.0.0': {}
|
||||
@@ -6341,6 +6302,8 @@ snapshots:
|
||||
|
||||
'@types/normalize-path@3.0.2': {}
|
||||
|
||||
'@types/picomatch@4.0.2': {}
|
||||
|
||||
'@types/prompts@2.4.9':
|
||||
dependencies:
|
||||
'@types/node': 20.19.32
|
||||
@@ -7803,15 +7766,6 @@ snapshots:
|
||||
dependencies:
|
||||
uc.micro: 2.1.0
|
||||
|
||||
lint-staged@16.3.2:
|
||||
dependencies:
|
||||
commander: 14.0.3
|
||||
listr2: 9.0.5
|
||||
micromatch: 4.0.8
|
||||
string-argv: 0.3.2
|
||||
tinyexec: 1.0.2
|
||||
yaml: 2.8.2
|
||||
|
||||
listr2@10.1.0:
|
||||
dependencies:
|
||||
cli-truncate: 5.1.1
|
||||
@@ -7821,15 +7775,6 @@ snapshots:
|
||||
rfdc: 1.4.1
|
||||
wrap-ansi: 9.0.2
|
||||
|
||||
listr2@9.0.5:
|
||||
dependencies:
|
||||
cli-truncate: 5.1.1
|
||||
colorette: 2.0.20
|
||||
eventemitter3: 5.0.4
|
||||
log-update: 6.1.0
|
||||
rfdc: 1.4.1
|
||||
wrap-ansi: 9.0.2
|
||||
|
||||
local-pkg@1.1.2:
|
||||
dependencies:
|
||||
mlly: 1.8.1
|
||||
@@ -7856,14 +7801,6 @@ snapshots:
|
||||
|
||||
lodash.once@4.1.1: {}
|
||||
|
||||
log-update@6.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
|
||||
|
||||
log-update@7.1.0:
|
||||
dependencies:
|
||||
ansi-escapes: 7.3.0
|
||||
@@ -8288,6 +8225,10 @@ snapshots:
|
||||
|
||||
nano-spawn@2.0.0: {}
|
||||
|
||||
nano-staged@0.8.0:
|
||||
dependencies:
|
||||
picocolors: 1.1.1
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
nanospinner@1.2.2:
|
||||
@@ -8997,8 +8938,6 @@ snapshots:
|
||||
|
||||
std-env@3.10.0: {}
|
||||
|
||||
string-argv@0.3.2: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
parseCommits,
|
||||
} from 'changelogen';
|
||||
import { consola } from 'consola';
|
||||
import fs from 'fs-extra';
|
||||
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
||||
import spawn from 'nano-spawn';
|
||||
import path from 'node:path';
|
||||
import { getPkgTag, grabPackageDetails, listCommitsInDir } from './git';
|
||||
@@ -41,7 +41,7 @@ if (currentVersion.startsWith('0.')) {
|
||||
await spawn('pnpm', ['version', bumpType], {
|
||||
cwd: pkgDir,
|
||||
});
|
||||
const updatedPkgJson = await fs.readJson(pkgJsonPath);
|
||||
const updatedPkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));
|
||||
const newVersion: string = updatedPkgJson.version;
|
||||
const newTag = getPkgTag(pkg, newVersion);
|
||||
consola.info('Bump:', { currentVersion, bumpType, newVersion });
|
||||
@@ -63,8 +63,7 @@ if (originalBumpType === 'major') {
|
||||
`[⚠️ breaking changes](https://wxt.dev/guide/resources/upgrading.html) • [compare changes]`,
|
||||
);
|
||||
}
|
||||
const { releases: prevReleases } = await fs
|
||||
.readFile(changelogPath, 'utf8')
|
||||
const { releases: prevReleases } = await readFile(changelogPath, 'utf8')
|
||||
.then(parseChangelogMarkdown)
|
||||
.catch(() => ({ releases: [] }));
|
||||
const allReleases = [
|
||||
@@ -80,29 +79,34 @@ const newChangelog =
|
||||
allReleases
|
||||
.map((release) => [`## v${release.version}`, release.body].join('\n\n'))
|
||||
.join('\n\n');
|
||||
await fs.writeFile(changelogPath, newChangelog, 'utf8');
|
||||
await writeFile(changelogPath, newChangelog, 'utf8');
|
||||
consola.success('Updated changelog');
|
||||
|
||||
// Update WXT version in templates when releasing wxt package
|
||||
const templatePkgJsonPaths: string[] = [];
|
||||
if (pkg === 'wxt') {
|
||||
const templatesDir = 'templates';
|
||||
const templateDirs = await fs.readdir(templatesDir);
|
||||
const templateDirs = await readdir(templatesDir);
|
||||
for (const templateDir of templateDirs) {
|
||||
const templatePkgJsonPath = path.join(
|
||||
templatesDir,
|
||||
templateDir,
|
||||
'package.json',
|
||||
);
|
||||
if (await fs.pathExists(templatePkgJsonPath)) {
|
||||
const templatePkgJson = await fs.readJson(templatePkgJsonPath);
|
||||
try {
|
||||
const templatePkgJson = JSON.parse(
|
||||
await readFile(templatePkgJsonPath, 'utf-8'),
|
||||
);
|
||||
if (templatePkgJson.devDependencies?.wxt) {
|
||||
templatePkgJson.devDependencies.wxt = `^${newVersion}`;
|
||||
await fs.writeJson(templatePkgJsonPath, templatePkgJson, { spaces: 2 });
|
||||
await writeFile(
|
||||
templatePkgJsonPath,
|
||||
JSON.stringify(templatePkgJson, null, 2),
|
||||
);
|
||||
templatePkgJsonPaths.push(templatePkgJsonPath);
|
||||
consola.success(`Updated wxt version in ${templatePkgJsonPath}`);
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
loadChangelogConfig,
|
||||
parseChangelogMarkdown,
|
||||
} from 'changelogen';
|
||||
import fs from 'fs-extra';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { grabPackageDetails } from './git';
|
||||
import consola from 'consola';
|
||||
|
||||
@@ -19,8 +19,7 @@ const { pkgName, prevTag, currentVersion, changelogPath } =
|
||||
await grabPackageDetails(pkg);
|
||||
consola.info('Creating release for:', { pkg, pkgName, prevTag });
|
||||
|
||||
const { releases } = await fs
|
||||
.readFile(changelogPath, 'utf8')
|
||||
const { releases } = await readFile(changelogPath, 'utf8')
|
||||
.then(parseChangelogMarkdown)
|
||||
.catch(() => ({ releases: [] }));
|
||||
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { RawGitCommit, getGitDiff } from 'changelogen';
|
||||
import { consola } from 'consola';
|
||||
import fs from 'fs-extra';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
export async function grabPackageDetails(pkg: string) {
|
||||
const pkgDir = `packages/${pkg}`;
|
||||
const pkgJsonPath = `${pkgDir}/package.json`;
|
||||
const pkgJson = await fs.readJson(pkgJsonPath);
|
||||
const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8'));
|
||||
const currentVersion: string = pkgJson.version;
|
||||
return {
|
||||
pkgDir,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
updateGithubRelease,
|
||||
} from 'changelogen';
|
||||
import { getPkgTag, grabPackageDetails } from './git';
|
||||
import fs from 'fs-extra';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import consola from 'consola';
|
||||
|
||||
const pkg = process.argv[2];
|
||||
@@ -17,8 +17,7 @@ if (!pkg) {
|
||||
|
||||
// Update
|
||||
const { changelogPath, pkgName } = await grabPackageDetails(pkg);
|
||||
const { releases } = await fs
|
||||
.readFile(changelogPath, 'utf8')
|
||||
const { releases } = await readFile(changelogPath, 'utf8')
|
||||
.then(parseChangelogMarkdown)
|
||||
.catch(() => ({ releases: [] }));
|
||||
const config = await loadChangelogConfig(process.cwd());
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { glob } from 'tinyglobby';
|
||||
import fs from 'fs-extra';
|
||||
import * as semver from 'semver';
|
||||
import { dirname } from 'node:path';
|
||||
import consola from 'consola';
|
||||
import spawn from 'nano-spawn';
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { dirname } from 'node:path';
|
||||
import pMap from 'p-map';
|
||||
import * as semver from 'semver';
|
||||
import { glob } from 'tinyglobby';
|
||||
|
||||
const HELP_MESSAGE = `
|
||||
Upgrades dependencies throughout WXT using custom rules.
|
||||
@@ -101,7 +101,7 @@ async function getPackageJsonDependencies(
|
||||
);
|
||||
const packageJsons: PackageJsonData[] = await Promise.all(
|
||||
packageJsonFiles.map(async (path) => ({
|
||||
content: await fs.readJson(path),
|
||||
content: JSON.parse(await readFile(path, 'utf-8')),
|
||||
path,
|
||||
folder: dirname(path),
|
||||
})),
|
||||
@@ -341,7 +341,7 @@ async function writeUpgrades(
|
||||
upgrades: UpgradeDetails[],
|
||||
) {
|
||||
for (const packageJsonFile of packageJsonFiles) {
|
||||
const oldText = await fs.readFile(packageJsonFile, 'utf8');
|
||||
const oldText = await readFile(packageJsonFile, 'utf8');
|
||||
let newText = oldText;
|
||||
for (const upgrade of upgrades) {
|
||||
const search = `"${upgrade.name}": "${upgrade.currentRange}"`;
|
||||
@@ -349,7 +349,7 @@ async function writeUpgrades(
|
||||
newText = newText.replaceAll(search, replace);
|
||||
}
|
||||
if (newText !== oldText) {
|
||||
await fs.writeFile(packageJsonFile, newText, 'utf8');
|
||||
await writeFile(packageJsonFile, newText, 'utf8');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -23,6 +23,6 @@
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@wxt-dev/module-react": "^1.1.5",
|
||||
"typescript": "^5.9.3",
|
||||
"wxt": "^0.20.18"
|
||||
"wxt": "^0.20.20"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -20,6 +20,6 @@
|
||||
"devDependencies": {
|
||||
"@wxt-dev/module-solid": "^1.1.4",
|
||||
"typescript": "^5.9.3",
|
||||
"wxt": "^0.20.18"
|
||||
"wxt": "^0.20.20"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -21,6 +21,6 @@
|
||||
"svelte-check": "^4.4.4",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.9.3",
|
||||
"wxt": "^0.20.18"
|
||||
"wxt": "^0.20.20"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-4
@@ -1,6 +1,3 @@
|
||||
{
|
||||
"extends": "./.wxt/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"useDefineForClassFields": true
|
||||
}
|
||||
"extends": "./.wxt/tsconfig.json"
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -16,6 +16,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.9.3",
|
||||
"wxt": "^0.20.18"
|
||||
"wxt": "^0.20.20"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -21,6 +21,6 @@
|
||||
"@wxt-dev/module-vue": "^1.0.3",
|
||||
"typescript": "^5.9.3",
|
||||
"vue-tsc": "^3.2.5",
|
||||
"wxt": "^0.20.18"
|
||||
"wxt": "^0.20.20"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user