@crxjs/vite-plugin 2.0.0-beta.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/client.d.ts +15 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +131 -17
- package/dist/index.mjs +267 -101
- package/index.cjs +8 -0
- package/package.json +20 -18
package/README.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
> [!IMPORTANT]
|
|
2
|
+
> CRXJS is seeking new maintainers. If no maintenance team is established by March 31, 2025, this repository will be archived. [Learn more](https://github.com/crxjs/chrome-extension-tools/discussions/974).
|
|
3
|
+
|
|
1
4
|
# 
|
|
2
5
|
|
|
3
6
|
[](https://www.npmjs.com/package/@crxjs/vite-plugin)
|
package/client.d.ts
CHANGED
|
@@ -57,3 +57,18 @@ declare module '*?script&module' {
|
|
|
57
57
|
const fileName: string
|
|
58
58
|
export default fileName
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
declare namespace ContentScriptAPI {
|
|
62
|
+
export interface ExecuteFnOptions {
|
|
63
|
+
perf: {
|
|
64
|
+
injectTime: number
|
|
65
|
+
loadTime: number
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export interface ExecuteFn {
|
|
69
|
+
(options: ExecuteFnOptions): void
|
|
70
|
+
}
|
|
71
|
+
export interface ModuleExports {
|
|
72
|
+
onExecute?: ExecuteFn
|
|
73
|
+
}
|
|
74
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
const defineManifest = (manifest) => manifest;
|
|
6
6
|
const defineDynamicResource = ({
|
|
7
7
|
matches = ["http://*/*", "https://*/*"],
|
|
8
|
-
use_dynamic_url =
|
|
8
|
+
use_dynamic_url = false
|
|
9
9
|
}) => ({
|
|
10
10
|
matches,
|
|
11
11
|
resources: [DYNAMIC_RESOURCE],
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,14 @@ interface WebAccessibleResourceById {
|
|
|
17
17
|
resources: string[];
|
|
18
18
|
use_dynamic_url?: boolean;
|
|
19
19
|
}
|
|
20
|
+
interface ChromeManifestBackground {
|
|
21
|
+
service_worker: string;
|
|
22
|
+
type?: 'module' | (string & {});
|
|
23
|
+
}
|
|
24
|
+
interface FirefoxManifestBackground {
|
|
25
|
+
scripts: string[];
|
|
26
|
+
persistent?: false;
|
|
27
|
+
}
|
|
20
28
|
interface ManifestV3 {
|
|
21
29
|
manifest_version: number;
|
|
22
30
|
name: string;
|
|
@@ -25,11 +33,13 @@ interface ManifestV3 {
|
|
|
25
33
|
description?: string | undefined;
|
|
26
34
|
icons?: chrome.runtime.ManifestIcons | undefined;
|
|
27
35
|
action?: chrome.runtime.ManifestAction | undefined;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
/**
|
|
37
|
+
* @see https://developer.chrome.com/docs/extensions/reference/manifest/author
|
|
38
|
+
*/
|
|
39
|
+
author?: {
|
|
40
|
+
email: string;
|
|
32
41
|
} | undefined;
|
|
42
|
+
background?: ChromeManifestBackground | FirefoxManifestBackground | undefined;
|
|
33
43
|
chrome_settings_overrides?: {
|
|
34
44
|
homepage?: string | undefined;
|
|
35
45
|
search_provider?: chrome.runtime.SearchProvider | undefined;
|
|
@@ -118,12 +128,12 @@ interface ManifestV3 {
|
|
|
118
128
|
} | undefined;
|
|
119
129
|
incognito?: string | undefined;
|
|
120
130
|
input_components?: {
|
|
121
|
-
name
|
|
122
|
-
type?: string | undefined;
|
|
131
|
+
name: string;
|
|
123
132
|
id?: string | undefined;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
language?: string | string[] | undefined;
|
|
134
|
+
layouts?: string | string[] | undefined;
|
|
135
|
+
input_view?: string | undefined;
|
|
136
|
+
options_page?: string | undefined;
|
|
127
137
|
}[] | undefined;
|
|
128
138
|
key?: string | undefined;
|
|
129
139
|
minimum_chrome_version?: string | undefined;
|
|
@@ -166,6 +176,9 @@ interface ManifestV3 {
|
|
|
166
176
|
pages: string[];
|
|
167
177
|
content_security_policy?: string | undefined;
|
|
168
178
|
} | undefined;
|
|
179
|
+
side_panel?: {
|
|
180
|
+
default_path?: string | undefined;
|
|
181
|
+
} | undefined;
|
|
169
182
|
short_name?: string | undefined;
|
|
170
183
|
spellcheck?: {
|
|
171
184
|
dictionary_language?: string | undefined;
|
|
@@ -189,9 +202,98 @@ interface ManifestV3 {
|
|
|
189
202
|
web_accessible_resources?: (WebAccessibleResourceById | WebAccessibleResourceByMatch)[] | undefined;
|
|
190
203
|
}
|
|
191
204
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
205
|
+
type ManifestV3Fn = (env: ConfigEnv) => ManifestV3 | Promise<ManifestV3>;
|
|
206
|
+
type ManifestV3Export = ManifestV3 | Promise<ManifestV3> | ManifestV3Fn;
|
|
207
|
+
type Code = '.' | '/' | '\\';
|
|
208
|
+
type ManifestFilePath<T extends string> = T extends `${Code}${string}` ? never : T extends `${string}.${infer Ext}` ? Ext extends '' ? never : T : never;
|
|
209
|
+
interface ManifestIcons<T extends string> {
|
|
210
|
+
[size: number]: ManifestFilePath<T>;
|
|
211
|
+
}
|
|
212
|
+
type FilePathFields<T extends string> = {
|
|
213
|
+
icons?: ManifestIcons<T>;
|
|
214
|
+
action?: {
|
|
215
|
+
/**
|
|
216
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
217
|
+
* - Format: "subdir/icon.png" (no leading ./ or /)
|
|
218
|
+
*
|
|
219
|
+
* @example "assets/icon.png"
|
|
220
|
+
*/
|
|
221
|
+
default_icon?: ManifestIcons<T>;
|
|
222
|
+
default_title?: string;
|
|
223
|
+
/**
|
|
224
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
225
|
+
* - Format: "subdir/index.html" (no leading ./ or /)
|
|
226
|
+
*
|
|
227
|
+
* @example "src/popup.html"
|
|
228
|
+
*/
|
|
229
|
+
default_popup?: ManifestFilePath<T>;
|
|
230
|
+
};
|
|
231
|
+
background?: {
|
|
232
|
+
/**
|
|
233
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
234
|
+
* - Format: "subdir/index.js" (no leading ./ or /)
|
|
235
|
+
*
|
|
236
|
+
* @example "src/background.js"
|
|
237
|
+
*/
|
|
238
|
+
service_worker: ManifestFilePath<T>;
|
|
239
|
+
type?: 'module' | (string & {});
|
|
240
|
+
} | FirefoxManifestBackground;
|
|
241
|
+
content_scripts?: {
|
|
242
|
+
matches?: string[];
|
|
243
|
+
exclude_matches?: string[];
|
|
244
|
+
/**
|
|
245
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
246
|
+
* - Format: "subdir/content.css" (no leading ./ or /)
|
|
247
|
+
*
|
|
248
|
+
* @example "src/content.css"
|
|
249
|
+
*/
|
|
250
|
+
css?: ManifestFilePath<T>[];
|
|
251
|
+
/**
|
|
252
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
253
|
+
* - Format: "subdir/content.js" (no leading ./ or /)
|
|
254
|
+
*
|
|
255
|
+
* @example "src/content.js"
|
|
256
|
+
*/
|
|
257
|
+
js?: ManifestFilePath<T>[];
|
|
258
|
+
run_at?: string;
|
|
259
|
+
all_frames?: boolean;
|
|
260
|
+
match_about_blank?: boolean;
|
|
261
|
+
include_globs?: string[];
|
|
262
|
+
exclude_globs?: string[];
|
|
263
|
+
}[];
|
|
264
|
+
input_components?: {
|
|
265
|
+
name: string;
|
|
266
|
+
id?: string;
|
|
267
|
+
language?: string | string[];
|
|
268
|
+
layouts?: string | string[];
|
|
269
|
+
input_view?: string;
|
|
270
|
+
/**
|
|
271
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
272
|
+
* - Format: "subdir/options.html" (no leading ./ or /)
|
|
273
|
+
*
|
|
274
|
+
* @example "src/options.html"
|
|
275
|
+
*/
|
|
276
|
+
options_page?: ManifestFilePath<T>;
|
|
277
|
+
}[];
|
|
278
|
+
/**
|
|
279
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
280
|
+
* - Format: "subdir/options.html" (no leading ./ or /)
|
|
281
|
+
*
|
|
282
|
+
* @example "src/options.html"
|
|
283
|
+
*/
|
|
284
|
+
options_page?: ManifestFilePath<T>;
|
|
285
|
+
/**
|
|
286
|
+
* - Relative to Vite project root (where vite.config.js is)
|
|
287
|
+
* - Format: "subdir/devtools.html" (no leading ./ or /)
|
|
288
|
+
*
|
|
289
|
+
* @example "src/devtools.html"
|
|
290
|
+
*/
|
|
291
|
+
devtools_page?: ManifestFilePath<T>;
|
|
292
|
+
};
|
|
293
|
+
type ManifestOptions<T extends string> = Omit<ManifestV3, keyof FilePathFields<string>> & FilePathFields<T>;
|
|
294
|
+
type ManifestV3Options<T extends string = string> = ManifestOptions<T> | Promise<ManifestOptions<T>> | ManifestV3Define<T>;
|
|
295
|
+
type ManifestV3Define<T extends string> = (env: ConfigEnv) => ManifestOptions<T> | Promise<ManifestOptions<T>>;
|
|
296
|
+
declare const defineManifest: <T extends string>(manifest: ManifestV3Options<T>) => ManifestV3Export;
|
|
195
297
|
/**
|
|
196
298
|
* Content script resources like CSS and image files must be declared in the
|
|
197
299
|
* manifest under `web_accessible_resources`. Manifest V3 uses a match pattern
|
|
@@ -219,19 +321,25 @@ declare const defineManifest: (manifest: ManifestV3Export) => ManifestV3Export;
|
|
|
219
321
|
*/
|
|
220
322
|
declare const defineDynamicResource: ({ matches, use_dynamic_url, }: Omit<WebAccessibleResourceByMatch, 'resources'>) => WebAccessibleResourceByMatch;
|
|
221
323
|
|
|
222
|
-
|
|
324
|
+
type CrxDevAssetId = {
|
|
223
325
|
id: string;
|
|
224
326
|
type: 'asset';
|
|
225
327
|
source?: string | Uint8Array;
|
|
226
328
|
};
|
|
227
|
-
|
|
329
|
+
type CrxDevScriptId = {
|
|
228
330
|
id: string;
|
|
229
331
|
type: 'module' | 'iife';
|
|
230
332
|
};
|
|
231
333
|
interface CrxPlugin extends Plugin {
|
|
232
|
-
/**
|
|
334
|
+
/**
|
|
335
|
+
* Runs during the transform hook for the manifest. Filenames use input
|
|
336
|
+
* filenames.
|
|
337
|
+
*/
|
|
233
338
|
transformCrxManifest?: (this: PluginContext, manifest: ManifestV3) => Promise<ManifestV3 | null | undefined> | ManifestV3 | null | undefined;
|
|
234
|
-
/**
|
|
339
|
+
/**
|
|
340
|
+
* Runs during generateBundle, before manifest output. Filenames use output
|
|
341
|
+
* filenames.
|
|
342
|
+
*/
|
|
235
343
|
renderCrxManifest?: (this: PluginContext, manifest: ManifestV3, bundle: OutputBundle) => Promise<ManifestV3 | null | undefined> | ManifestV3 | null | undefined;
|
|
236
344
|
/**
|
|
237
345
|
* Runs in the file writer on content scripts during development. `script.id`
|
|
@@ -246,12 +354,18 @@ interface CrxOptions {
|
|
|
246
354
|
injectCss?: boolean;
|
|
247
355
|
};
|
|
248
356
|
fastGlobOptions?: Options;
|
|
357
|
+
/**
|
|
358
|
+
* The browser that this extension is targeting, can be "firefox" or "chrome".
|
|
359
|
+
* Default is "chrome".
|
|
360
|
+
*/
|
|
361
|
+
browser?: Browser;
|
|
249
362
|
}
|
|
363
|
+
type Browser = 'firefox' | 'chrome';
|
|
250
364
|
|
|
251
365
|
/** Resolves when all existing files in scriptFiles are written. */
|
|
252
366
|
declare function allFilesReady(): Promise<void>;
|
|
253
367
|
|
|
254
|
-
|
|
368
|
+
type FileWriterId = {
|
|
255
369
|
type: CrxDevAssetId['type'] | CrxDevScriptId['type'] | 'loader';
|
|
256
370
|
id: string;
|
|
257
371
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { simple } from 'acorn-walk';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
-
import debug$
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import { Subject, filter, ReplaySubject, switchMap, of, startWith, map, mergeMap, firstValueFrom, takeUntil, first, toArray, retry, concatWith, Subscription, buffer } from 'rxjs';
|
|
3
|
+
import debug$3 from 'debug';
|
|
4
|
+
import { join, normalize, isAbsolute, basename, relative, resolve, dirname, parse } from 'pathe';
|
|
5
|
+
import { Subject, filter, ReplaySubject, switchMap, of, startWith, map, BehaviorSubject, mergeMap, firstValueFrom, takeUntil, first, toArray, retry, concatWith, Subscription, buffer } from 'rxjs';
|
|
7
6
|
import fsx from 'fs-extra';
|
|
8
7
|
import { performance } from 'perf_hooks';
|
|
9
8
|
import { rollup } from 'rollup';
|
|
10
9
|
import * as lexer from 'es-module-lexer';
|
|
11
10
|
import { readFile as readFile$1 } from 'fs/promises';
|
|
12
11
|
import MagicString from 'magic-string';
|
|
13
|
-
import
|
|
12
|
+
import convertSourceMap from 'convert-source-map';
|
|
13
|
+
import { createLogger, version } from 'vite';
|
|
14
14
|
import { readFileSync, existsSync, promises } from 'fs';
|
|
15
15
|
import { createRequire } from 'module';
|
|
16
16
|
import fg from 'fast-glob';
|
|
@@ -24,8 +24,10 @@ const pluginOptionsProvider = (options) => {
|
|
|
24
24
|
name: pluginName$1,
|
|
25
25
|
api: {
|
|
26
26
|
crx: {
|
|
27
|
+
// during testing this can be null, we don't provide options through the test config
|
|
27
28
|
options
|
|
28
29
|
}
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
31
|
}
|
|
30
32
|
};
|
|
31
33
|
};
|
|
@@ -56,12 +58,9 @@ function isCrxPlugin(p) {
|
|
|
56
58
|
return !!p && typeof p === "object" && !(p instanceof Promise) && !Array.isArray(p) && p.name.startsWith("crx:");
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
var workerHmrClient = "const ownOrigin =
|
|
61
|
+
var workerHmrClient = "const ownOrigin = `chrome-extension://${chrome.runtime.id}`;\nself.addEventListener(\"fetch\", (fetchEvent) => {\n const url = new URL(fetchEvent.request.url);\n if (url.origin === ownOrigin) {\n fetchEvent.respondWith(sendToServer(fetchEvent.request));\n }\n});\nasync function sendToServer(req) {\n const url = new URL(req.url);\n const requestHeaders = new Headers(req.headers);\n url.protocol = \"http:\";\n url.host = \"localhost\";\n url.port = __SERVER_PORT__;\n url.searchParams.set(\"t\", Date.now().toString());\n const response = await fetch(url.href.replace(/=$|=(?=&)/g, \"\"), {\n headers: requestHeaders\n });\n const responseHeaders = new Headers(response.headers);\n responseHeaders.set(\"Content-Type\", responseHeaders.get(\"Content-Type\") ?? \"text/javascript\");\n responseHeaders.set(\"Cache-Control\", responseHeaders.get(\"Cache-Control\") ?? \"\");\n return new Response(response.body, {\n headers: responseHeaders\n });\n}\nconst ports = /* @__PURE__ */ new Set();\nchrome.runtime.onConnect.addListener((port) => {\n if (port.name === \"@crx/client\") {\n ports.add(port);\n port.onDisconnect.addListener((port2) => {\n if (chrome.runtime.lastError) {\n console.error(chrome.runtime.lastError);\n }\n ports.delete(port2);\n });\n port.onMessage.addListener((message) => {\n });\n port.postMessage({ data: JSON.stringify({ type: \"connected\" }) });\n }\n});\nfunction notifyContentScripts(payload) {\n const data = JSON.stringify(payload);\n for (const port of ports)\n port.postMessage({ data });\n}\nconsole.log(\"[vite] connecting...\");\nconst socketProtocol = __HMR_PROTOCOL__ || (location.protocol === \"https:\" ? \"wss\" : \"ws\");\nconst socketToken = __HMR_TOKEN__;\nconst socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`;\nconst socket = new WebSocket(`${socketProtocol}://${socketHost}?token=${socketToken}`, \"vite-hmr\");\nconst base = __BASE__ || \"/\";\nsocket.addEventListener(\"message\", async ({ data }) => {\n handleSocketMessage(JSON.parse(data));\n});\nfunction isCrxHmrPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nfunction handleSocketMessage(payload) {\n if (isCrxHmrPayload(payload)) {\n handleCrxHmrPayload(payload);\n } else if (payload.type === \"connected\") {\n console.log(`[vite] connected.`);\n const interval = setInterval(() => socket.send(\"ping\"), __HMR_TIMEOUT__);\n socket.addEventListener(\"close\", () => clearInterval(interval));\n }\n}\nfunction handleCrxHmrPayload(payload) {\n notifyContentScripts(payload);\n switch (payload.event) {\n case \"crx:runtime-reload\":\n console.log(\"[crx] runtime reload\");\n chrome.runtime.reload();\n break;\n }\n}\nasync function waitForSuccessfulPing(ms = 1e3) {\n while (true) {\n try {\n await fetch(`${base}__vite_ping`);\n break;\n } catch (e) {\n await new Promise((resolve) => setTimeout(resolve, ms));\n }\n }\n}\nsocket.addEventListener(\"close\", async ({ wasClean }) => {\n if (wasClean)\n return;\n console.log(`[vite] server connection lost. polling for restart...`);\n await waitForSuccessfulPing();\n handleCrxHmrPayload({\n type: \"custom\",\n event: \"crx:runtime-reload\"\n });\n});\n";
|
|
60
62
|
|
|
61
|
-
const _debug = (id) => debug$
|
|
62
|
-
const structuredClone = (obj) => {
|
|
63
|
-
return v8.deserialize(v8.serialize(obj));
|
|
64
|
-
};
|
|
63
|
+
const _debug = (id) => debug$3("crx").extend(id);
|
|
65
64
|
const hash = (data, length = 5) => createHash("sha1").update(data).digest("base64").replace(/[^A-Za-z0-9]/g, "").slice(0, length);
|
|
66
65
|
const isString = (x) => typeof x === "string";
|
|
67
66
|
function isObject(value) {
|
|
@@ -113,22 +112,6 @@ const getMatchPatternOrigin = (pattern) => {
|
|
|
113
112
|
return pathname ? `${root}/*` : root;
|
|
114
113
|
};
|
|
115
114
|
|
|
116
|
-
const {
|
|
117
|
-
basename,
|
|
118
|
-
dirname,
|
|
119
|
-
extname,
|
|
120
|
-
delimiter,
|
|
121
|
-
format,
|
|
122
|
-
isAbsolute,
|
|
123
|
-
join,
|
|
124
|
-
normalize,
|
|
125
|
-
parse,
|
|
126
|
-
relative,
|
|
127
|
-
resolve,
|
|
128
|
-
toNamespacedPath,
|
|
129
|
-
sep
|
|
130
|
-
} = posix;
|
|
131
|
-
|
|
132
115
|
function defineClientValues(code, config) {
|
|
133
116
|
let options = config.server.hmr;
|
|
134
117
|
options = options && typeof options !== "boolean" ? options : {};
|
|
@@ -152,7 +135,7 @@ function defineClientValues(code, config) {
|
|
|
152
135
|
if (hmrBase !== "/") {
|
|
153
136
|
hmrPort = normalize(`${hmrPort}${hmrBase}`);
|
|
154
137
|
}
|
|
155
|
-
return code.replace(`__MODE__`, JSON.stringify(config.mode)).replace(`__BASE__`, JSON.stringify(config.base)).replace(`__DEFINES__`, serializeDefine(config.define || {})).replace(`__HMR_PROTOCOL__`, JSON.stringify(protocol)).replace(`__HMR_HOSTNAME__`, JSON.stringify(host)).replace(`__HMR_PORT__`, JSON.stringify(hmrPort)).replace(`__HMR_TIMEOUT__`, JSON.stringify(timeout)).replace(`__HMR_ENABLE_OVERLAY__`, JSON.stringify(overlay)).replace(`__SERVER_PORT__`, JSON.stringify(config.server.port?.toString()));
|
|
138
|
+
return code.replace(`__MODE__`, JSON.stringify(config.mode)).replace(`__BASE__`, JSON.stringify(config.base)).replace(`__DEFINES__`, serializeDefine(config.define || {})).replace(`__HMR_TOKEN__`, JSON.stringify(config.webSocketToken || "")).replace(`__HMR_PROTOCOL__`, JSON.stringify(protocol)).replace(`__HMR_HOSTNAME__`, JSON.stringify(host)).replace(`__HMR_PORT__`, JSON.stringify(hmrPort)).replace(`__HMR_TIMEOUT__`, JSON.stringify(timeout)).replace(`__HMR_ENABLE_OVERLAY__`, JSON.stringify(overlay)).replace(`__SERVER_PORT__`, JSON.stringify(config.server.port?.toString()));
|
|
156
139
|
function serializeDefine(define) {
|
|
157
140
|
let res = `{`;
|
|
158
141
|
for (const key in define) {
|
|
@@ -204,7 +187,7 @@ function formatFileData(script) {
|
|
|
204
187
|
return script;
|
|
205
188
|
}
|
|
206
189
|
function getFileName({ type, id }) {
|
|
207
|
-
let fileName = id.replace(/t=\d+&/, "").replace(/^\//, "").replace(/\?/g, "__").replace(/&/g, "_").replace(/=/g, "--");
|
|
190
|
+
let fileName = id.replace(/t=\d+&/, "").replace(/\?t=\d+$/, "").replace(/^\//, "").replace(/\?/g, "__").replace(/&/g, "_").replace(/=/g, "--");
|
|
208
191
|
if (fileName.includes("node_modules/")) {
|
|
209
192
|
fileName = `vendor/${fileName.split("node_modules/").pop().replace(/\//g, "-")}`;
|
|
210
193
|
} else if (fileName.startsWith("@")) {
|
|
@@ -272,6 +255,7 @@ const workerClientId = "/@crx/client-worker";
|
|
|
272
255
|
|
|
273
256
|
const pluginBackground = () => {
|
|
274
257
|
let config;
|
|
258
|
+
let browser;
|
|
275
259
|
return [
|
|
276
260
|
{
|
|
277
261
|
name: "crx:background-client",
|
|
@@ -292,24 +276,39 @@ const pluginBackground = () => {
|
|
|
292
276
|
},
|
|
293
277
|
{
|
|
294
278
|
name: "crx:background-loader-file",
|
|
279
|
+
// this should happen after other plugins; the loader file is an implementation detail
|
|
295
280
|
enforce: "post",
|
|
281
|
+
async config(config2) {
|
|
282
|
+
const opts = await getOptions(config2);
|
|
283
|
+
browser = opts.browser || "chrome";
|
|
284
|
+
},
|
|
296
285
|
configResolved(_config) {
|
|
297
286
|
config = _config;
|
|
298
287
|
},
|
|
299
288
|
renderCrxManifest(manifest) {
|
|
300
|
-
const worker = manifest.background?.service_worker;
|
|
289
|
+
const worker = browser === "firefox" ? manifest.background?.scripts[0] : manifest.background?.service_worker;
|
|
301
290
|
let loader;
|
|
302
291
|
if (config.command === "serve") {
|
|
303
292
|
const port = config.server.port?.toString();
|
|
304
293
|
if (typeof port === "undefined")
|
|
305
294
|
throw new Error("server port is undefined in watch mode");
|
|
306
|
-
|
|
295
|
+
if (browser === "firefox") {
|
|
296
|
+
loader = `import('http://localhost:${port}/@vite/env');
|
|
307
297
|
`;
|
|
308
|
-
|
|
298
|
+
loader += `import('http://localhost:${port}${workerClientId}');
|
|
299
|
+
`;
|
|
300
|
+
if (worker)
|
|
301
|
+
loader += `import('http://localhost:${port}/${worker}');
|
|
302
|
+
`;
|
|
303
|
+
} else {
|
|
304
|
+
loader = `import 'http://localhost:${port}/@vite/env';
|
|
309
305
|
`;
|
|
310
|
-
|
|
311
|
-
loader += `import 'http://localhost:${port}/${worker}';
|
|
306
|
+
loader += `import 'http://localhost:${port}${workerClientId}';
|
|
312
307
|
`;
|
|
308
|
+
if (worker)
|
|
309
|
+
loader += `import 'http://localhost:${port}/${worker}';
|
|
310
|
+
`;
|
|
311
|
+
}
|
|
313
312
|
} else if (worker) {
|
|
314
313
|
loader = `import './${worker}';
|
|
315
314
|
`;
|
|
@@ -318,13 +317,21 @@ const pluginBackground = () => {
|
|
|
318
317
|
}
|
|
319
318
|
const refId = this.emitFile({
|
|
320
319
|
type: "asset",
|
|
320
|
+
// fileName b/c service worker must be at root of crx
|
|
321
321
|
fileName: getFileName({ type: "loader", id: "service-worker" }),
|
|
322
322
|
source: loader
|
|
323
323
|
});
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
324
|
+
if (browser !== "firefox") {
|
|
325
|
+
manifest.background = {
|
|
326
|
+
service_worker: this.getFileName(refId),
|
|
327
|
+
type: "module"
|
|
328
|
+
};
|
|
329
|
+
} else {
|
|
330
|
+
manifest.background = {
|
|
331
|
+
scripts: [this.getFileName(refId)],
|
|
332
|
+
type: "module"
|
|
333
|
+
};
|
|
334
|
+
}
|
|
328
335
|
return manifest;
|
|
329
336
|
}
|
|
330
337
|
}
|
|
@@ -333,9 +340,9 @@ const pluginBackground = () => {
|
|
|
333
340
|
|
|
334
341
|
var contentHmrPort = "function isCrxHMRPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nclass HMRPort {\n port;\n callbacks = /* @__PURE__ */ new Map();\n constructor() {\n setInterval(() => {\n try {\n this.port?.postMessage({ data: \"ping\" });\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Extension context invalidated.\")) {\n location.reload();\n } else\n throw error;\n }\n }, __CRX_HMR_TIMEOUT__);\n setInterval(this.initPort, 5 * 60 * 1e3);\n this.initPort();\n }\n initPort = () => {\n this.port?.disconnect();\n this.port = chrome.runtime.connect({ name: \"@crx/client\" });\n this.port.onDisconnect.addListener(this.handleDisconnect.bind(this));\n this.port.onMessage.addListener(this.handleMessage.bind(this));\n this.port.postMessage({ type: \"connected\" });\n };\n handleDisconnect = () => {\n if (this.callbacks.has(\"close\"))\n for (const cb of this.callbacks.get(\"close\")) {\n cb({ wasClean: true });\n }\n };\n handleMessage = (message) => {\n const forward = (data) => {\n if (this.callbacks.has(\"message\"))\n for (const cb of this.callbacks.get(\"message\")) {\n cb({ data });\n }\n };\n const payload = JSON.parse(message.data);\n if (isCrxHMRPayload(payload)) {\n if (payload.event === \"crx:runtime-reload\") {\n console.log(\"[crx] runtime reload\");\n setTimeout(() => location.reload(), 500);\n } else {\n forward(JSON.stringify(payload.data));\n }\n } else {\n forward(message.data);\n }\n };\n addEventListener = (event, callback) => {\n const cbs = this.callbacks.get(event) ?? /* @__PURE__ */ new Set();\n cbs.add(callback);\n this.callbacks.set(event, cbs);\n };\n send = (data) => {\n if (this.port)\n this.port.postMessage({ data });\n else\n throw new Error(\"HMRPort is not initialized\");\n };\n}\n\nexport { HMRPort };\n";
|
|
335
342
|
|
|
336
|
-
var contentDevLoader = "(function () {\n 'use strict';\n\n (async () => {\n if (__PREAMBLE__)\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__PREAMBLE__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__CLIENT__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__SCRIPT__)\n );\n })().catch(console.error);\n\n})();\n";
|
|
343
|
+
var contentDevLoader = "(function () {\n 'use strict';\n\n const injectTime = performance.now();\n (async () => {\n if (__PREAMBLE__)\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__PREAMBLE__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__CLIENT__)\n );\n const { onExecute } = await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__SCRIPT__)\n );\n onExecute?.({ perf: { injectTime, loadTime: performance.now() - injectTime } });\n })().catch(console.error);\n\n})();\n";
|
|
337
344
|
|
|
338
|
-
var contentProLoader = "(function () {\n 'use strict';\n\n (async () => {\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__SCRIPT__)\n );\n })().catch(console.error);\n\n})();\n";
|
|
345
|
+
var contentProLoader = "(function () {\n 'use strict';\n\n const injectTime = performance.now();\n (async () => {\n const { onExecute } = await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__SCRIPT__)\n );\n onExecute?.({ perf: { injectTime, loadTime: performance.now() - injectTime } });\n })().catch(console.error);\n\n})();\n";
|
|
339
346
|
|
|
340
347
|
const contentScripts = new RxMap();
|
|
341
348
|
contentScripts.change$.pipe(filter(RxMap.isChangeType.set)).subscribe(({ map, value }) => {
|
|
@@ -393,6 +400,10 @@ const allFilesReady$ = buildEnd$.pipe(
|
|
|
393
400
|
map(() => [...outputFiles.values()]),
|
|
394
401
|
switchMap((files) => Promise.allSettled(files.map(({ file }) => file)))
|
|
395
402
|
);
|
|
403
|
+
const timestamp$ = new BehaviorSubject(Date.now());
|
|
404
|
+
allFilesReady$.subscribe(() => {
|
|
405
|
+
timestamp$.next(Date.now());
|
|
406
|
+
});
|
|
396
407
|
const isRejected = (x) => x?.status === "rejected";
|
|
397
408
|
const fileWriterError$ = allFilesReady$.pipe(
|
|
398
409
|
mergeMap((results) => results.filter(isRejected)),
|
|
@@ -426,16 +437,36 @@ function prepAsset(fileName, { id, source }) {
|
|
|
426
437
|
}
|
|
427
438
|
function prepScript(fileName, script) {
|
|
428
439
|
return ($) => $.pipe(
|
|
440
|
+
// get script contents from dev server
|
|
429
441
|
mergeMap(async ({ server }) => {
|
|
430
442
|
const target = getOutputPath(server, fileName);
|
|
431
443
|
const viteUrl = getViteUrl(script);
|
|
432
444
|
const transformResult = await server.transformRequest(viteUrl);
|
|
433
445
|
if (!transformResult)
|
|
434
446
|
throw new TypeError(`Unable to load "${script.id}" from server.`);
|
|
435
|
-
const {
|
|
436
|
-
|
|
447
|
+
const { deps = [], dynamicDeps = [], map: map2 } = transformResult;
|
|
448
|
+
let { code } = transformResult;
|
|
449
|
+
try {
|
|
450
|
+
if (map2 && server.config.build.sourcemap === "inline") {
|
|
451
|
+
code = code.replace(/\n*\/\/# sourceMappingURL=[^\n]+/g, "");
|
|
452
|
+
const sourceMap = convertSourceMap.fromObject(map2).toComment();
|
|
453
|
+
code += `
|
|
454
|
+
${sourceMap}
|
|
455
|
+
`;
|
|
456
|
+
}
|
|
457
|
+
} catch (error) {
|
|
458
|
+
console.warn("Failed to inline source map", error);
|
|
459
|
+
}
|
|
460
|
+
return {
|
|
461
|
+
target,
|
|
462
|
+
code,
|
|
463
|
+
deps: [...deps, ...dynamicDeps].flat(),
|
|
464
|
+
server
|
|
465
|
+
};
|
|
437
466
|
}),
|
|
467
|
+
// retry in case of dependency rebundle
|
|
438
468
|
retry({ count: 10, delay: 100 }),
|
|
469
|
+
// patch content scripts
|
|
439
470
|
mergeMap(async ({ target, server, ...rest }) => {
|
|
440
471
|
const plugins = server.config.plugins;
|
|
441
472
|
let { code, deps } = rest;
|
|
@@ -455,7 +486,8 @@ function prepScript(fileName, script) {
|
|
|
455
486
|
if (i.n) {
|
|
456
487
|
depSet.add(i.n);
|
|
457
488
|
const fileName2 = getFileName({ type: "module", id: i.n });
|
|
458
|
-
|
|
489
|
+
const fullImport = code.substring(i.s, i.e);
|
|
490
|
+
magic.overwrite(i.s, i.e, fullImport.replace(i.n, `/${fileName2}`));
|
|
459
491
|
}
|
|
460
492
|
return { target, source: magic.toString(), deps: [...depSet] };
|
|
461
493
|
})
|
|
@@ -526,8 +558,11 @@ function update(_id) {
|
|
|
526
558
|
async function write(fileId) {
|
|
527
559
|
const start2 = performance.now();
|
|
528
560
|
const deps = await firstValueFrom(
|
|
561
|
+
// wait for start event
|
|
529
562
|
start$.pipe(
|
|
563
|
+
// prepare either asset or script contents
|
|
530
564
|
prepFileData(fileId),
|
|
565
|
+
// output file and add dependencies to file writer
|
|
531
566
|
mergeMap(async ({ target, source, deps: deps2 }) => {
|
|
532
567
|
const files = deps2.map((id) => {
|
|
533
568
|
const r = [add({ id, type: "module" })];
|
|
@@ -543,6 +578,7 @@ async function write(fileId) {
|
|
|
543
578
|
await outputFile(target, source, { encoding: "utf8" });
|
|
544
579
|
return files;
|
|
545
580
|
}),
|
|
581
|
+
// abort write operation on close event
|
|
546
582
|
takeUntil(close$),
|
|
547
583
|
concatWith(of([]))
|
|
548
584
|
)
|
|
@@ -568,7 +604,7 @@ const pluginContentScripts = () => {
|
|
|
568
604
|
async configureServer(_server) {
|
|
569
605
|
server = _server;
|
|
570
606
|
if (typeof preambleCode === "undefined" && server.config.plugins.some(
|
|
571
|
-
({ name = "none" }) => name.toLowerCase().includes("react")
|
|
607
|
+
({ name = "none" }) => name.toLowerCase().includes("react") && !name.toLowerCase().includes("preact")
|
|
572
608
|
)) {
|
|
573
609
|
try {
|
|
574
610
|
const react = await import('@vitejs/plugin-react');
|
|
@@ -633,7 +669,20 @@ const pluginContentScripts = () => {
|
|
|
633
669
|
name: "crx:content-scripts",
|
|
634
670
|
apply: "build",
|
|
635
671
|
enforce: "pre",
|
|
636
|
-
|
|
672
|
+
config(config) {
|
|
673
|
+
return {
|
|
674
|
+
...config,
|
|
675
|
+
build: {
|
|
676
|
+
...config.build,
|
|
677
|
+
rollupOptions: {
|
|
678
|
+
...config.build?.rollupOptions,
|
|
679
|
+
// keep exports for content script module api
|
|
680
|
+
preserveEntrySignatures: config.build?.rollupOptions?.preserveEntrySignatures ?? "exports-only"
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
},
|
|
685
|
+
generateBundle(_options, bundle) {
|
|
637
686
|
for (const [key, script] of contentScripts)
|
|
638
687
|
if (key === script.refId) {
|
|
639
688
|
if (script.type === "module") {
|
|
@@ -642,12 +691,22 @@ const pluginContentScripts = () => {
|
|
|
642
691
|
} else if (script.type === "loader") {
|
|
643
692
|
const fileName = this.getFileName(script.refId);
|
|
644
693
|
script.fileName = fileName;
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
694
|
+
const bundleFileInfo = bundle[fileName];
|
|
695
|
+
const shouldUseLoader = !(bundleFileInfo.type === "chunk" && bundleFileInfo.imports.length === 0 && bundleFileInfo.dynamicImports.length === 0 && bundleFileInfo.exports.length === 0);
|
|
696
|
+
if (shouldUseLoader) {
|
|
697
|
+
const refId = this.emitFile({
|
|
698
|
+
type: "asset",
|
|
699
|
+
name: getFileName({
|
|
700
|
+
type: "loader",
|
|
701
|
+
id: basename(script.id)
|
|
702
|
+
}),
|
|
703
|
+
source: createProLoader({ fileName })
|
|
704
|
+
});
|
|
705
|
+
script.loaderName = this.getFileName(refId);
|
|
706
|
+
} else {
|
|
707
|
+
bundleFileInfo.code = `(function(){${bundleFileInfo.code}})()
|
|
708
|
+
`;
|
|
709
|
+
}
|
|
651
710
|
} else if (script.type === "iife") {
|
|
652
711
|
throw new Error("IIFE content scripts are not implemented");
|
|
653
712
|
}
|
|
@@ -707,6 +766,34 @@ const pluginDynamicContentScripts = () => {
|
|
|
707
766
|
configResolved(_config) {
|
|
708
767
|
config = _config;
|
|
709
768
|
},
|
|
769
|
+
configureServer(server) {
|
|
770
|
+
return () => {
|
|
771
|
+
server.middlewares.use(async (req, res, next) => {
|
|
772
|
+
try {
|
|
773
|
+
await allFilesReady();
|
|
774
|
+
next();
|
|
775
|
+
} catch (error) {
|
|
776
|
+
let err;
|
|
777
|
+
if (error instanceof Error) {
|
|
778
|
+
err = error;
|
|
779
|
+
} else if (typeof error === "string") {
|
|
780
|
+
err = new Error(error);
|
|
781
|
+
} else {
|
|
782
|
+
err = new Error(
|
|
783
|
+
`Unexpected error "${error}" in middleware for "${req.url}"`
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
server.ws.send({
|
|
787
|
+
type: "error",
|
|
788
|
+
err: {
|
|
789
|
+
message: err.message,
|
|
790
|
+
stack: err.stack ?? "no stack available"
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
};
|
|
796
|
+
},
|
|
710
797
|
async resolveId(_source, importer) {
|
|
711
798
|
if (importer && _source.includes("?script")) {
|
|
712
799
|
const url = new URL(_source, "stub://stub");
|
|
@@ -775,7 +862,6 @@ const pluginDynamicContentScripts = () => {
|
|
|
775
862
|
if (config.command === "build") {
|
|
776
863
|
return `export default import.meta.CRX_DYNAMIC_SCRIPT_${script.refId};`;
|
|
777
864
|
} else if (typeof script.fileName === "string") {
|
|
778
|
-
await fileReady(script);
|
|
779
865
|
return `export default ${JSON.stringify(script.fileName)};`;
|
|
780
866
|
} else {
|
|
781
867
|
throw new Error(
|
|
@@ -788,6 +874,12 @@ const pluginDynamicContentScripts = () => {
|
|
|
788
874
|
{
|
|
789
875
|
name: "crx:dynamic-content-scripts-build",
|
|
790
876
|
apply: "build",
|
|
877
|
+
/**
|
|
878
|
+
* Replace dynamic script placeholders during build.
|
|
879
|
+
*
|
|
880
|
+
* Can't use `renderChunk` b/c pre plugin crx:content-scripts uses
|
|
881
|
+
* `generateBundle` to emit loaders. Must come after "enforce: pre".
|
|
882
|
+
*/
|
|
791
883
|
generateBundle(options, bundle) {
|
|
792
884
|
for (const chunk of Object.values(bundle))
|
|
793
885
|
if (chunk.type === "chunk") {
|
|
@@ -806,7 +898,7 @@ const pluginDynamicContentScripts = () => {
|
|
|
806
898
|
);
|
|
807
899
|
return `${JSON.stringify(
|
|
808
900
|
`/${script.loaderName ?? script.fileName}`
|
|
809
|
-
)}
|
|
901
|
+
)}${match.split(scriptKey)[1]}`;
|
|
810
902
|
}
|
|
811
903
|
);
|
|
812
904
|
chunk.code = replaced;
|
|
@@ -817,29 +909,42 @@ const pluginDynamicContentScripts = () => {
|
|
|
817
909
|
];
|
|
818
910
|
};
|
|
819
911
|
|
|
912
|
+
const { remove } = fsx;
|
|
820
913
|
const logger = createLogger("error", { prefix: "crxjs" });
|
|
821
914
|
const pluginFileWriter = () => {
|
|
822
915
|
fileWriterError$.subscribe((error) => {
|
|
823
916
|
logger.error(error.err.message, { error: error.err });
|
|
824
917
|
});
|
|
825
|
-
return
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
console.error(error);
|
|
834
|
-
server.close();
|
|
918
|
+
return [
|
|
919
|
+
{
|
|
920
|
+
name: "crx:file-writer-empty-out-dir",
|
|
921
|
+
apply: "serve",
|
|
922
|
+
enforce: "pre",
|
|
923
|
+
async configResolved(config) {
|
|
924
|
+
if (config.build.emptyOutDir) {
|
|
925
|
+
await remove(config.build.outDir);
|
|
835
926
|
}
|
|
836
|
-
}
|
|
837
|
-
server.httpServer?.on("close", () => close());
|
|
927
|
+
}
|
|
838
928
|
},
|
|
839
|
-
|
|
840
|
-
|
|
929
|
+
{
|
|
930
|
+
name: "crx:file-writer",
|
|
931
|
+
apply: "serve",
|
|
932
|
+
configureServer(server) {
|
|
933
|
+
server.httpServer?.on("listening", async () => {
|
|
934
|
+
try {
|
|
935
|
+
await start({ server });
|
|
936
|
+
} catch (error) {
|
|
937
|
+
console.error(error);
|
|
938
|
+
server.close();
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
server.httpServer?.on("close", () => close());
|
|
942
|
+
},
|
|
943
|
+
closeBundle() {
|
|
944
|
+
outputFiles.clear();
|
|
945
|
+
}
|
|
841
946
|
}
|
|
842
|
-
|
|
947
|
+
];
|
|
843
948
|
};
|
|
844
949
|
|
|
845
950
|
const _require = typeof require === "undefined" ? createRequire(import.meta.url) : require;
|
|
@@ -884,7 +989,9 @@ async function manifestFiles(manifest, options = {}) {
|
|
|
884
989
|
) ?? [];
|
|
885
990
|
const contentScripts = manifest.content_scripts?.flatMap(({ js }) => js) ?? [];
|
|
886
991
|
const contentStyles = manifest.content_scripts?.flatMap(({ css }) => css);
|
|
887
|
-
const serviceWorker = manifest.background
|
|
992
|
+
const serviceWorker = manifest.background && "service_worker" in manifest.background ? manifest.background.service_worker : void 0;
|
|
993
|
+
const backgroundScripts = manifest.background && "scripts" in manifest.background ? manifest.background.scripts : void 0;
|
|
994
|
+
const background = serviceWorker ? [serviceWorker].filter(isString) : backgroundScripts ? backgroundScripts.filter(isString) : [];
|
|
888
995
|
const htmlPages = htmlFiles(manifest);
|
|
889
996
|
const icons = [
|
|
890
997
|
Object.values(
|
|
@@ -905,7 +1012,7 @@ async function manifestFiles(manifest, options = {}) {
|
|
|
905
1012
|
return r;
|
|
906
1013
|
})
|
|
907
1014
|
);
|
|
908
|
-
webAccessibleResources = resources.flat().filter(isString);
|
|
1015
|
+
webAccessibleResources = [...new Set(resources.flat())].filter(isString);
|
|
909
1016
|
}
|
|
910
1017
|
return {
|
|
911
1018
|
contentScripts: [...new Set(contentScripts)].filter(isString),
|
|
@@ -914,12 +1021,12 @@ async function manifestFiles(manifest, options = {}) {
|
|
|
914
1021
|
icons: [...new Set(icons)].filter(isString),
|
|
915
1022
|
locales: [...new Set(locales)].filter(isString),
|
|
916
1023
|
rulesets: [...new Set(rulesets)].filter(isString),
|
|
917
|
-
background
|
|
1024
|
+
background,
|
|
918
1025
|
webAccessibleResources
|
|
919
1026
|
};
|
|
920
1027
|
}
|
|
921
1028
|
async function dirFiles(dir) {
|
|
922
|
-
const files = await fg(
|
|
1029
|
+
const files = await fg(join(dir, "**", "*"));
|
|
923
1030
|
return files;
|
|
924
1031
|
}
|
|
925
1032
|
function htmlFiles(manifest) {
|
|
@@ -929,7 +1036,8 @@ function htmlFiles(manifest) {
|
|
|
929
1036
|
manifest.devtools_page,
|
|
930
1037
|
manifest.options_page,
|
|
931
1038
|
manifest.options_ui?.page,
|
|
932
|
-
manifest.sandbox?.pages
|
|
1039
|
+
manifest.sandbox?.pages,
|
|
1040
|
+
manifest.side_panel?.default_path
|
|
933
1041
|
].flat().filter(isString).map((s) => s.split("#")[0]).sort();
|
|
934
1042
|
return [...new Set(files)];
|
|
935
1043
|
}
|
|
@@ -954,11 +1062,13 @@ const pluginFileWriterPublic = () => {
|
|
|
954
1062
|
};
|
|
955
1063
|
};
|
|
956
1064
|
|
|
957
|
-
_debug("file-writer").extend("hmr");
|
|
958
|
-
const
|
|
1065
|
+
const debug$2 = _debug("file-writer").extend("hmr");
|
|
1066
|
+
const isCustomPayload = (p) => {
|
|
1067
|
+
return p.type === "custom";
|
|
1068
|
+
};
|
|
959
1069
|
const hmrPayload$ = new Subject();
|
|
960
1070
|
const crxHMRPayload$ = hmrPayload$.pipe(
|
|
961
|
-
filter((p) => !
|
|
1071
|
+
filter((p) => !isCustomPayload(p)),
|
|
962
1072
|
buffer(allFilesReady$),
|
|
963
1073
|
mergeMap((pps) => {
|
|
964
1074
|
let fullReload;
|
|
@@ -1017,6 +1127,7 @@ const crxHMRPayload$ = hmrPayload$.pipe(
|
|
|
1017
1127
|
}
|
|
1018
1128
|
}),
|
|
1019
1129
|
map((data) => {
|
|
1130
|
+
debug$2(`hmr payload`, data);
|
|
1020
1131
|
return {
|
|
1021
1132
|
type: "custom",
|
|
1022
1133
|
event: "crx:content-script-payload",
|
|
@@ -1056,6 +1167,7 @@ const pluginHMR = () => {
|
|
|
1056
1167
|
name: "crx:hmr",
|
|
1057
1168
|
apply: "serve",
|
|
1058
1169
|
enforce: "pre",
|
|
1170
|
+
// server hmr host should be localhost
|
|
1059
1171
|
async config({ server = {}, ...config2 }) {
|
|
1060
1172
|
if (server.hmr === false)
|
|
1061
1173
|
return;
|
|
@@ -1065,6 +1177,7 @@ const pluginHMR = () => {
|
|
|
1065
1177
|
server.hmr.host = "localhost";
|
|
1066
1178
|
return { server, ...config2 };
|
|
1067
1179
|
},
|
|
1180
|
+
// server should ignore outdir
|
|
1068
1181
|
configResolved(_config) {
|
|
1069
1182
|
config = _config;
|
|
1070
1183
|
const { watch = {} } = config.server;
|
|
@@ -1102,19 +1215,24 @@ const pluginHMR = () => {
|
|
|
1102
1215
|
closeBundle() {
|
|
1103
1216
|
subs.unsubscribe();
|
|
1104
1217
|
},
|
|
1218
|
+
// background changes require a full extension reload
|
|
1105
1219
|
handleHotUpdate({ modules, server }) {
|
|
1106
1220
|
const { root } = server.config;
|
|
1107
1221
|
const relFiles = /* @__PURE__ */ new Set();
|
|
1108
|
-
|
|
1222
|
+
const fsFiles = /* @__PURE__ */ new Set();
|
|
1223
|
+
for (const m of modules) {
|
|
1109
1224
|
if (m.id?.startsWith(root)) {
|
|
1110
1225
|
relFiles.add(m.id.slice(server.config.root.length));
|
|
1226
|
+
} else if (m.url?.startsWith("/@fs")) {
|
|
1227
|
+
fsFiles.add(m.url);
|
|
1111
1228
|
}
|
|
1229
|
+
}
|
|
1230
|
+
fsFiles.forEach((file) => update(file));
|
|
1112
1231
|
if (inputManifestFiles.background.length) {
|
|
1113
1232
|
const background = prefix$1("/", inputManifestFiles.background[0]);
|
|
1114
1233
|
if (relFiles.has(background) || modules.some(isImporter(join(server.config.root, background)))) {
|
|
1115
1234
|
debug$1("sending runtime reload");
|
|
1116
1235
|
server.ws.send(crxRuntimeReload);
|
|
1117
|
-
return [];
|
|
1118
1236
|
}
|
|
1119
1237
|
}
|
|
1120
1238
|
for (const [key, script] of contentScripts)
|
|
@@ -1129,6 +1247,7 @@ const pluginHMR = () => {
|
|
|
1129
1247
|
name: "crx:hmr",
|
|
1130
1248
|
apply: "serve",
|
|
1131
1249
|
enforce: "post",
|
|
1250
|
+
// get final output manifest for handleHotUpdate 👆
|
|
1132
1251
|
async transformCrxManifest(manifest) {
|
|
1133
1252
|
inputManifestFiles = await manifestFiles(manifest, { cwd: config.root });
|
|
1134
1253
|
return null;
|
|
@@ -1219,6 +1338,7 @@ const pluginHtmlInlineScripts = () => {
|
|
|
1219
1338
|
};
|
|
1220
1339
|
const postPlugin = {
|
|
1221
1340
|
name: "crx:html-auditor-post",
|
|
1341
|
+
// this hook isn't audited b/c we add it after we set up the auditors
|
|
1222
1342
|
transformIndexHtml(html, ctx) {
|
|
1223
1343
|
const key = toKey(ctx);
|
|
1224
1344
|
const p = pages.get(key);
|
|
@@ -1284,9 +1404,9 @@ const pluginHtmlInlineScripts = () => {
|
|
|
1284
1404
|
};
|
|
1285
1405
|
};
|
|
1286
1406
|
|
|
1287
|
-
var
|
|
1407
|
+
var loadingPageScript = "const VITE_URL = \"http://localhost:%PORT%\";\ndocument.body.innerHTML = `\n<div\n id=\"app\"\n style=\"\n border: 1px solid #ddd;\n padding: 20px;\n border-radius: 5px;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\n \"\n >\n <h1 style=\"color: #333\">Vite Dev Mode</h1>\n <p style=\"color: #666\">\n Cannot connect to the Vite Dev Server on <a href=\"${VITE_URL}\">${VITE_URL}</a>\n </p>\n <p style=\"color: #666\">\n Double-check that Vite is working and reload the extension.\n </p>\n <p style=\"color: #666\">\n This page will close when the extension reloads.\n </p>\n <button\n style=\"\n padding: 10px 20px;\n border: none;\n background-color: #007bff;\n color: #fff;\n border-radius: 5px;\n cursor: pointer;\n \"\n >\n Reload Extension\n </button>\n </div>`;\ndocument.body.querySelector(\"button\")?.addEventListener(\"click\", () => {\n chrome.runtime.reload();\n});\nlet tries = 0;\nlet ready = false;\ndo {\n try {\n await fetch(VITE_URL);\n ready = true;\n } catch {\n const timeout = Math.min(100 * Math.pow(2, ++tries), 5e3);\n console.log(`[CRXJS] Vite Dev Server is not available on ${VITE_URL}`);\n console.log(`[CRXJS] Retrying in ${timeout}ms...`);\n await new Promise((resolve) => setTimeout(resolve, timeout));\n }\n} while (!ready);\nlocation.reload();\n";
|
|
1288
1408
|
|
|
1289
|
-
var
|
|
1409
|
+
var loadingPageHtml = "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <title>Vite Dev Mode</title>\n <script src=\"%SCRIPT%\" type=\"module\"></script>\n </head>\n <body\n style=\"font-family: Arial, sans-serif; padding: 20px; text-align: center\"\n >\n <h1>Vite Dev Mode</h1>\n </body>\n</html>\n";
|
|
1290
1410
|
|
|
1291
1411
|
const { readFile } = promises;
|
|
1292
1412
|
const pluginManifest = () => {
|
|
@@ -1465,7 +1585,7 @@ const pluginManifest = () => {
|
|
|
1465
1585
|
})
|
|
1466
1586
|
);
|
|
1467
1587
|
}
|
|
1468
|
-
if (manifest2.background
|
|
1588
|
+
if (manifest2.background && "service_worker" in manifest2.background) {
|
|
1469
1589
|
const file = manifest2.background.service_worker;
|
|
1470
1590
|
const id2 = join(config.root, file);
|
|
1471
1591
|
const refId2 = this.emitFile({
|
|
@@ -1475,6 +1595,16 @@ const pluginManifest = () => {
|
|
|
1475
1595
|
});
|
|
1476
1596
|
manifest2.background.service_worker = refId2;
|
|
1477
1597
|
}
|
|
1598
|
+
if (manifest2.background && "scripts" in manifest2.background) {
|
|
1599
|
+
const file = manifest2.background.scripts[0];
|
|
1600
|
+
const id2 = join(config.root, file);
|
|
1601
|
+
const refId2 = this.emitFile({
|
|
1602
|
+
type: "chunk",
|
|
1603
|
+
id: id2,
|
|
1604
|
+
name: basename(file)
|
|
1605
|
+
});
|
|
1606
|
+
manifest2.background.scripts = [refId2];
|
|
1607
|
+
}
|
|
1478
1608
|
for (const file of htmlFiles(manifest2)) {
|
|
1479
1609
|
const id2 = join(config.root, file);
|
|
1480
1610
|
this.emitFile({
|
|
@@ -1485,7 +1615,7 @@ const pluginManifest = () => {
|
|
|
1485
1615
|
}
|
|
1486
1616
|
}
|
|
1487
1617
|
const encoded = encodeManifest(manifest2);
|
|
1488
|
-
return encoded;
|
|
1618
|
+
return { code: encoded, map: null };
|
|
1489
1619
|
},
|
|
1490
1620
|
async generateBundle(options, bundle) {
|
|
1491
1621
|
const manifestName = this.getFileName(refId);
|
|
@@ -1499,11 +1629,16 @@ const pluginManifest = () => {
|
|
|
1499
1629
|
);
|
|
1500
1630
|
}
|
|
1501
1631
|
} else {
|
|
1502
|
-
if (manifest2.background
|
|
1632
|
+
if (manifest2.background && "service_worker" in manifest2.background) {
|
|
1503
1633
|
const ref = manifest2.background.service_worker;
|
|
1504
1634
|
const name = this.getFileName(ref);
|
|
1505
1635
|
manifest2.background.service_worker = name;
|
|
1506
1636
|
}
|
|
1637
|
+
if (manifest2.background && "scripts" in manifest2.background) {
|
|
1638
|
+
const ref = manifest2.background.scripts[0];
|
|
1639
|
+
const name = this.getFileName(ref);
|
|
1640
|
+
manifest2.background.scripts = [name];
|
|
1641
|
+
}
|
|
1507
1642
|
manifest2.content_scripts = manifest2.content_scripts?.map(
|
|
1508
1643
|
({ js = [], ...rest }) => {
|
|
1509
1644
|
return {
|
|
@@ -1563,6 +1698,7 @@ Public dir: "${config.publicDir}"`
|
|
|
1563
1698
|
this.emitFile({
|
|
1564
1699
|
type: "asset",
|
|
1565
1700
|
fileName: f,
|
|
1701
|
+
// TODO: cache source buffer
|
|
1566
1702
|
source: await readFile(filename)
|
|
1567
1703
|
});
|
|
1568
1704
|
}
|
|
@@ -1571,17 +1707,20 @@ Public dir: "${config.publicDir}"`
|
|
|
1571
1707
|
if (config.command === "serve" && files.html.length) {
|
|
1572
1708
|
const refId2 = this.emitFile({
|
|
1573
1709
|
type: "asset",
|
|
1574
|
-
name: "
|
|
1575
|
-
source:
|
|
1710
|
+
name: "loading-page.js",
|
|
1711
|
+
source: loadingPageScript.replace(
|
|
1712
|
+
"%PORT%",
|
|
1713
|
+
`${config.server.port ?? 0}`
|
|
1714
|
+
)
|
|
1576
1715
|
});
|
|
1577
|
-
const
|
|
1716
|
+
const loadingPageScriptName = this.getFileName(refId2);
|
|
1578
1717
|
files.html.map(
|
|
1579
1718
|
(f) => this.emitFile({
|
|
1580
1719
|
type: "asset",
|
|
1581
1720
|
fileName: f,
|
|
1582
|
-
source:
|
|
1721
|
+
source: loadingPageHtml.replace(
|
|
1583
1722
|
"%SCRIPT%",
|
|
1584
|
-
`/${
|
|
1723
|
+
`/${loadingPageScriptName}`
|
|
1585
1724
|
)
|
|
1586
1725
|
})
|
|
1587
1726
|
);
|
|
@@ -1591,10 +1730,10 @@ Public dir: "${config.publicDir}"`
|
|
|
1591
1730
|
this.emitFile({
|
|
1592
1731
|
type: "asset",
|
|
1593
1732
|
fileName: "manifest.json",
|
|
1594
|
-
source: JSON.stringify(manifest2, null, 2)
|
|
1733
|
+
source: JSON.stringify(manifest2, null, 2) + "\n"
|
|
1595
1734
|
});
|
|
1596
1735
|
} else {
|
|
1597
|
-
manifestJson.source = JSON.stringify(manifest2, null, 2);
|
|
1736
|
+
manifestJson.source = JSON.stringify(manifest2, null, 2) + "\n";
|
|
1598
1737
|
}
|
|
1599
1738
|
delete bundle[manifestName];
|
|
1600
1739
|
}
|
|
@@ -1610,7 +1749,11 @@ function compileFileResources(fileName, {
|
|
|
1610
1749
|
assets: /* @__PURE__ */ new Set(),
|
|
1611
1750
|
css: /* @__PURE__ */ new Set(),
|
|
1612
1751
|
imports: /* @__PURE__ */ new Set()
|
|
1613
|
-
}) {
|
|
1752
|
+
}, processedFiles = /* @__PURE__ */ new Set()) {
|
|
1753
|
+
if (processedFiles.has(fileName)) {
|
|
1754
|
+
return resources;
|
|
1755
|
+
}
|
|
1756
|
+
processedFiles.add(fileName);
|
|
1614
1757
|
const chunk = chunks.get(fileName);
|
|
1615
1758
|
if (chunk) {
|
|
1616
1759
|
const { modules, facadeModuleId, imports, dynamicImports } = chunk;
|
|
@@ -1619,7 +1762,7 @@ function compileFileResources(fileName, {
|
|
|
1619
1762
|
for (const x of dynamicImports)
|
|
1620
1763
|
resources.imports.add(x);
|
|
1621
1764
|
for (const x of [...imports, ...dynamicImports])
|
|
1622
|
-
compileFileResources(x, { chunks, files, config }, resources);
|
|
1765
|
+
compileFileResources(x, { chunks, files, config }, resources, processedFiles);
|
|
1623
1766
|
for (const m of Object.keys(modules))
|
|
1624
1767
|
if (m !== facadeModuleId) {
|
|
1625
1768
|
const key = prefix$1("/", relative(config.root, m.split("?")[0]));
|
|
@@ -1632,7 +1775,8 @@ function compileFileResources(fileName, {
|
|
|
1632
1775
|
compileFileResources(
|
|
1633
1776
|
script.fileName,
|
|
1634
1777
|
{ chunks, files, config },
|
|
1635
|
-
resources
|
|
1778
|
+
resources,
|
|
1779
|
+
processedFiles
|
|
1636
1780
|
);
|
|
1637
1781
|
}
|
|
1638
1782
|
}
|
|
@@ -1651,7 +1795,7 @@ function compileFileResources(fileName, {
|
|
|
1651
1795
|
const defineManifest = (manifest) => manifest;
|
|
1652
1796
|
const defineDynamicResource = ({
|
|
1653
1797
|
matches = ["http://*/*", "https://*/*"],
|
|
1654
|
-
use_dynamic_url =
|
|
1798
|
+
use_dynamic_url = false
|
|
1655
1799
|
}) => ({
|
|
1656
1800
|
matches,
|
|
1657
1801
|
resources: [DYNAMIC_RESOURCE],
|
|
@@ -1663,22 +1807,34 @@ _debug("web-acc-res");
|
|
|
1663
1807
|
const pluginWebAccessibleResources = () => {
|
|
1664
1808
|
let config;
|
|
1665
1809
|
let injectCss;
|
|
1810
|
+
let browser;
|
|
1666
1811
|
return [
|
|
1667
1812
|
{
|
|
1668
1813
|
name: "crx:web-accessible-resources",
|
|
1669
1814
|
apply: "serve",
|
|
1670
1815
|
enforce: "post",
|
|
1816
|
+
async config(config2) {
|
|
1817
|
+
const opts = await getOptions(config2);
|
|
1818
|
+
browser = opts.browser || "chrome";
|
|
1819
|
+
},
|
|
1671
1820
|
renderCrxManifest(manifest) {
|
|
1672
1821
|
manifest.web_accessible_resources = manifest.web_accessible_resources ?? [];
|
|
1673
1822
|
manifest.web_accessible_resources = manifest.web_accessible_resources.map(({ resources, ...rest }) => ({
|
|
1674
1823
|
resources: resources.filter((r) => r !== DYNAMIC_RESOURCE),
|
|
1675
1824
|
...rest
|
|
1676
1825
|
})).filter(({ resources }) => resources.length);
|
|
1677
|
-
|
|
1678
|
-
|
|
1826
|
+
const war = {
|
|
1827
|
+
// all web origins can access
|
|
1679
1828
|
matches: ["<all_urls>"],
|
|
1680
|
-
resources
|
|
1681
|
-
|
|
1829
|
+
// all resources are web accessible
|
|
1830
|
+
resources: ["**/*", "*"],
|
|
1831
|
+
// change the extension origin on every reload
|
|
1832
|
+
use_dynamic_url: false
|
|
1833
|
+
};
|
|
1834
|
+
if (browser === "firefox") {
|
|
1835
|
+
delete war.use_dynamic_url;
|
|
1836
|
+
}
|
|
1837
|
+
manifest.web_accessible_resources.push(war);
|
|
1682
1838
|
return manifest;
|
|
1683
1839
|
}
|
|
1684
1840
|
},
|
|
@@ -1687,7 +1843,9 @@ const pluginWebAccessibleResources = () => {
|
|
|
1687
1843
|
apply: "build",
|
|
1688
1844
|
enforce: "post",
|
|
1689
1845
|
async config({ build, ...config2 }, { command }) {
|
|
1690
|
-
const
|
|
1846
|
+
const opts = await getOptions(config2);
|
|
1847
|
+
const contentScripts2 = opts.contentScripts || {};
|
|
1848
|
+
browser = opts.browser || "chrome";
|
|
1691
1849
|
injectCss = contentScripts2.injectCss ?? true;
|
|
1692
1850
|
return { ...config2, build: { ...build, manifest: command === "build" } };
|
|
1693
1851
|
},
|
|
@@ -1716,9 +1874,11 @@ const pluginWebAccessibleResources = () => {
|
|
|
1716
1874
|
dynamicScriptMatches.add("https://*/*");
|
|
1717
1875
|
}
|
|
1718
1876
|
if (contentScripts.size > 0) {
|
|
1877
|
+
const viteMajorVersion = parseInt(version.split(".")[0]);
|
|
1878
|
+
const manifestPath = viteMajorVersion > 4 ? ".vite/manifest.json" : "manifest.json";
|
|
1719
1879
|
const viteManifest = parseJsonAsset(
|
|
1720
1880
|
bundle,
|
|
1721
|
-
|
|
1881
|
+
manifestPath
|
|
1722
1882
|
);
|
|
1723
1883
|
const viteFiles = /* @__PURE__ */ new Map();
|
|
1724
1884
|
for (const [, file] of Object.entries(viteManifest))
|
|
@@ -1746,12 +1906,12 @@ const pluginWebAccessibleResources = () => {
|
|
|
1746
1906
|
{ chunks: bundleChunks, files: viteFiles, config }
|
|
1747
1907
|
);
|
|
1748
1908
|
contentScripts.get(key).css = [...css];
|
|
1749
|
-
if (type === "loader")
|
|
1909
|
+
if (type === "loader" || isDynamicScript)
|
|
1750
1910
|
imports.add(fileName);
|
|
1751
1911
|
const resource = {
|
|
1752
1912
|
matches: isDynamicScript ? [...dynamicScriptMatches] : matches,
|
|
1753
1913
|
resources: [...assets, ...imports],
|
|
1754
|
-
use_dynamic_url: isDynamicScript ? dynamicScriptDynamicUrl :
|
|
1914
|
+
use_dynamic_url: isDynamicScript ? dynamicScriptDynamicUrl : false
|
|
1755
1915
|
};
|
|
1756
1916
|
if (isDynamicScript || !injectCss) {
|
|
1757
1917
|
resource.resources.push(...css);
|
|
@@ -1795,6 +1955,11 @@ const pluginWebAccessibleResources = () => {
|
|
|
1795
1955
|
use_dynamic_url
|
|
1796
1956
|
});
|
|
1797
1957
|
}
|
|
1958
|
+
if (browser === "firefox") {
|
|
1959
|
+
for (const war of combinedResources) {
|
|
1960
|
+
delete war.use_dynamic_url;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1798
1963
|
if (combinedResources.length === 0)
|
|
1799
1964
|
delete manifest.web_accessible_resources;
|
|
1800
1965
|
else
|
|
@@ -1806,6 +1971,7 @@ const pluginWebAccessibleResources = () => {
|
|
|
1806
1971
|
};
|
|
1807
1972
|
|
|
1808
1973
|
const crx = (options) => {
|
|
1974
|
+
contentScripts.clear();
|
|
1809
1975
|
return [
|
|
1810
1976
|
pluginOptionsProvider(options),
|
|
1811
1977
|
pluginBackground(),
|
package/index.cjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Object.assign(module.exports, require('./dist/index.cjs'))
|
|
2
|
+
|
|
3
|
+
// async functions, can be redirect from ESM build
|
|
4
|
+
const asyncFunctions = ['crx', 'chromeExtension', 'allFilesReady', 'filesReady']
|
|
5
|
+
asyncFunctions.forEach((name) => {
|
|
6
|
+
module.exports[name] = (...args) =>
|
|
7
|
+
import('./dist/index.mjs').then((i) => i[name](...args))
|
|
8
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crxjs/vite-plugin",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Build Chrome Extensions with this Vite plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rollup-plugin",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"types": "./client.d.ts"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
|
-
"main": "
|
|
38
|
+
"main": "index.cjs",
|
|
39
39
|
"module": "dist/index.mjs",
|
|
40
40
|
"types": "dist/index.d.ts",
|
|
41
41
|
"files": [
|
|
42
42
|
"dist",
|
|
43
43
|
"types",
|
|
44
44
|
"manifest.schema.json",
|
|
45
|
-
"
|
|
45
|
+
"index.cjs",
|
|
46
46
|
"client.d.ts"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
@@ -50,28 +50,30 @@
|
|
|
50
50
|
"@webcomponents/custom-elements": "^1.5.0",
|
|
51
51
|
"acorn-walk": "^8.2.0",
|
|
52
52
|
"cheerio": "^1.0.0-rc.10",
|
|
53
|
-
"
|
|
53
|
+
"convert-source-map": "^1.7.0",
|
|
54
54
|
"debug": "^4.3.3",
|
|
55
55
|
"es-module-lexer": "^0.10.0",
|
|
56
56
|
"fast-glob": "^3.2.11",
|
|
57
57
|
"fs-extra": "^10.0.1",
|
|
58
58
|
"jsesc": "^3.0.2",
|
|
59
|
-
"magic-string": "^0.
|
|
59
|
+
"magic-string": "^0.30.12",
|
|
60
|
+
"pathe": "^2.0.1",
|
|
60
61
|
"picocolors": "^1.0.0",
|
|
61
62
|
"react-refresh": "^0.13.0",
|
|
62
|
-
"rollup": "2.
|
|
63
|
+
"rollup": "2.79.2",
|
|
63
64
|
"rxjs": "7.5.7"
|
|
64
65
|
},
|
|
65
66
|
"devDependencies": {
|
|
66
67
|
"@extend-chrome/messages": "1.2.2",
|
|
67
68
|
"@extend-chrome/storage": "1.5.0",
|
|
68
|
-
"@rollup/plugin-alias": "4.0.
|
|
69
|
+
"@rollup/plugin-alias": "4.0.4",
|
|
69
70
|
"@rollup/plugin-commonjs": "21.1.0",
|
|
70
71
|
"@rollup/plugin-json": "^5.0.0",
|
|
71
72
|
"@rollup/plugin-node-resolve": "13.2.0",
|
|
72
|
-
"@sveltejs/vite-plugin-svelte": "1.
|
|
73
|
+
"@sveltejs/vite-plugin-svelte": "1.4.0",
|
|
73
74
|
"@types/acorn": "4.0.6",
|
|
74
|
-
"@types/chrome": "0.0.
|
|
75
|
+
"@types/chrome": "0.0.237",
|
|
76
|
+
"@types/convert-source-map": "^2.0.0",
|
|
75
77
|
"@types/debug": "4.1.7",
|
|
76
78
|
"@types/fs-extra": "9.0.13",
|
|
77
79
|
"@types/jest-image-snapshot": "^5.1.0",
|
|
@@ -81,27 +83,27 @@
|
|
|
81
83
|
"@types/react-dom": "17.0.18",
|
|
82
84
|
"@typescript-eslint/eslint-plugin": "5.41.0",
|
|
83
85
|
"@typescript-eslint/parser": "5.41.0",
|
|
84
|
-
"@vitejs/plugin-react": "^2.
|
|
86
|
+
"@vitejs/plugin-react": "^2.2.0",
|
|
85
87
|
"@vitejs/plugin-vue": "3.2.0",
|
|
86
88
|
"chokidar": "^3.5.3",
|
|
87
|
-
"esbuild": "0.
|
|
89
|
+
"esbuild": "0.17.14",
|
|
88
90
|
"esbuild-runner": "2.2.2",
|
|
89
|
-
"eslint": "8.
|
|
91
|
+
"eslint": "8.43.0",
|
|
90
92
|
"eslint-plugin-react": "^7.29.4",
|
|
91
93
|
"jest-image-snapshot": "^5.2.0",
|
|
92
94
|
"npm-run-all": "^4.1.5",
|
|
93
|
-
"playwright-chromium": "1.
|
|
95
|
+
"playwright-chromium": "1.33.0",
|
|
94
96
|
"react": "17.0.2",
|
|
95
97
|
"react-dom": "17.0.2",
|
|
96
98
|
"rimraf": "3.0.2",
|
|
97
99
|
"rollup-plugin-dts": "^4.2.0",
|
|
98
|
-
"rollup-plugin-esbuild": "4.10.
|
|
100
|
+
"rollup-plugin-esbuild": "4.10.3",
|
|
99
101
|
"svelte": "^3.48.0",
|
|
100
102
|
"typescript": "^4.6.4",
|
|
101
|
-
"vite": "^3.
|
|
102
|
-
"vite-plugin-inspect": "0.7.
|
|
103
|
-
"vitest": "0.
|
|
104
|
-
"vue": "3.2.
|
|
103
|
+
"vite": "^3.2.11",
|
|
104
|
+
"vite-plugin-inspect": "0.7.25",
|
|
105
|
+
"vitest": "0.28.5",
|
|
106
|
+
"vue": "3.2.47"
|
|
105
107
|
},
|
|
106
108
|
"scripts": {
|
|
107
109
|
"format": "prettier -w -c ../../.prettierrc.yaml",
|