@crxjs/vite-plugin 2.0.0-beta.3 → 2.0.0-beta.30
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 +0 -0
- package/client.d.ts +15 -0
- package/dist/index.cjs +1 -1849
- package/dist/index.d.ts +38 -12
- package/dist/index.mjs +258 -85
- package/index.cjs +8 -0
- package/package.json +44 -43
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { simple } from 'acorn-walk';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
-
import debug$
|
|
4
|
-
import v8 from 'v8';
|
|
3
|
+
import debug$3 from 'debug';
|
|
5
4
|
import { posix } from 'path';
|
|
6
|
-
import { Subject, filter, ReplaySubject, switchMap, of, startWith, map, mergeMap, firstValueFrom, takeUntil, first, toArray, retry, concatWith, Subscription, buffer } from 'rxjs';
|
|
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';
|
|
17
|
-
import getPort, { portNumbers } from 'get-port';
|
|
18
17
|
import { load } from 'cheerio';
|
|
19
18
|
import jsesc from 'jsesc';
|
|
20
19
|
import colors from 'picocolors';
|
|
@@ -25,17 +24,22 @@ const pluginOptionsProvider = (options) => {
|
|
|
25
24
|
name: pluginName$1,
|
|
26
25
|
api: {
|
|
27
26
|
crx: {
|
|
27
|
+
// during testing this can be null, we don't provide options through the test config
|
|
28
28
|
options
|
|
29
29
|
}
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
};
|
|
33
|
-
const getOptions = ({
|
|
34
|
+
const getOptions = async ({
|
|
35
|
+
plugins
|
|
36
|
+
}) => {
|
|
34
37
|
if (typeof plugins === "undefined") {
|
|
35
38
|
throw new Error("config.plugins is undefined");
|
|
36
39
|
}
|
|
40
|
+
const awaitedPlugins = await Promise.all(plugins);
|
|
37
41
|
let options;
|
|
38
|
-
for (const p of
|
|
42
|
+
for (const p of awaitedPlugins.flat()) {
|
|
39
43
|
if (isCrxPlugin(p)) {
|
|
40
44
|
if (p.name === pluginName$1) {
|
|
41
45
|
const plugin = p;
|
|
@@ -54,12 +58,9 @@ function isCrxPlugin(p) {
|
|
|
54
58
|
return !!p && typeof p === "object" && !(p instanceof Promise) && !Array.isArray(p) && p.name.startsWith("crx:");
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
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(url));\n }\n});\nasync function sendToServer(url) {\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 return new Response(response.body, {\n headers: {\n \"Content-Type\": response.headers.get(\"Content-Type\") ?? \"text/javascript\",\n \"Cache-Control\": response.headers.get(\"Cache-Control\") ?? \"\"\n }\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) => ports.delete(port2));\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 socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`;\nconst socket = new WebSocket(`${socketProtocol}://${socketHost}`, \"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";
|
|
58
62
|
|
|
59
|
-
const _debug = (id) => debug$
|
|
60
|
-
const structuredClone = (obj) => {
|
|
61
|
-
return v8.deserialize(v8.serialize(obj));
|
|
62
|
-
};
|
|
63
|
+
const _debug = (id) => debug$3("crx").extend(id);
|
|
63
64
|
const hash = (data, length = 5) => createHash("sha1").update(data).digest("base64").replace(/[^A-Za-z0-9]/g, "").slice(0, length);
|
|
64
65
|
const isString = (x) => typeof x === "string";
|
|
65
66
|
function isObject(value) {
|
|
@@ -202,7 +203,7 @@ function formatFileData(script) {
|
|
|
202
203
|
return script;
|
|
203
204
|
}
|
|
204
205
|
function getFileName({ type, id }) {
|
|
205
|
-
let fileName = id.replace(/t=\d+&/, "").replace(/^\//, "").replace(/\?/g, "__").replace(/&/g, "_").replace(/=/g, "--");
|
|
206
|
+
let fileName = id.replace(/t=\d+&/, "").replace(/\?t=\d+$/, "").replace(/^\//, "").replace(/\?/g, "__").replace(/&/g, "_").replace(/=/g, "--");
|
|
206
207
|
if (fileName.includes("node_modules/")) {
|
|
207
208
|
fileName = `vendor/${fileName.split("node_modules/").pop().replace(/\//g, "-")}`;
|
|
208
209
|
} else if (fileName.startsWith("@")) {
|
|
@@ -270,6 +271,7 @@ const workerClientId = "/@crx/client-worker";
|
|
|
270
271
|
|
|
271
272
|
const pluginBackground = () => {
|
|
272
273
|
let config;
|
|
274
|
+
let browser;
|
|
273
275
|
return [
|
|
274
276
|
{
|
|
275
277
|
name: "crx:background-client",
|
|
@@ -290,24 +292,39 @@ const pluginBackground = () => {
|
|
|
290
292
|
},
|
|
291
293
|
{
|
|
292
294
|
name: "crx:background-loader-file",
|
|
295
|
+
// this should happen after other plugins; the loader file is an implementation detail
|
|
293
296
|
enforce: "post",
|
|
297
|
+
async config(config2) {
|
|
298
|
+
const opts = await getOptions(config2);
|
|
299
|
+
browser = opts.browser || "chrome";
|
|
300
|
+
},
|
|
294
301
|
configResolved(_config) {
|
|
295
302
|
config = _config;
|
|
296
303
|
},
|
|
297
304
|
renderCrxManifest(manifest) {
|
|
298
|
-
const worker = manifest.background?.service_worker;
|
|
305
|
+
const worker = browser === "firefox" ? manifest.background?.scripts[0] : manifest.background?.service_worker;
|
|
299
306
|
let loader;
|
|
300
307
|
if (config.command === "serve") {
|
|
301
308
|
const port = config.server.port?.toString();
|
|
302
309
|
if (typeof port === "undefined")
|
|
303
310
|
throw new Error("server port is undefined in watch mode");
|
|
304
|
-
|
|
311
|
+
if (browser === "firefox") {
|
|
312
|
+
loader = `import('http://localhost:${port}/@vite/env');
|
|
313
|
+
`;
|
|
314
|
+
loader += `import('http://localhost:${port}${workerClientId}');
|
|
315
|
+
`;
|
|
316
|
+
if (worker)
|
|
317
|
+
loader += `import('http://localhost:${port}/${worker}');
|
|
318
|
+
`;
|
|
319
|
+
} else {
|
|
320
|
+
loader = `import 'http://localhost:${port}/@vite/env';
|
|
305
321
|
`;
|
|
306
|
-
|
|
322
|
+
loader += `import 'http://localhost:${port}${workerClientId}';
|
|
307
323
|
`;
|
|
308
|
-
|
|
309
|
-
|
|
324
|
+
if (worker)
|
|
325
|
+
loader += `import 'http://localhost:${port}/${worker}';
|
|
310
326
|
`;
|
|
327
|
+
}
|
|
311
328
|
} else if (worker) {
|
|
312
329
|
loader = `import './${worker}';
|
|
313
330
|
`;
|
|
@@ -316,13 +333,21 @@ const pluginBackground = () => {
|
|
|
316
333
|
}
|
|
317
334
|
const refId = this.emitFile({
|
|
318
335
|
type: "asset",
|
|
336
|
+
// fileName b/c service worker must be at root of crx
|
|
319
337
|
fileName: getFileName({ type: "loader", id: "service-worker" }),
|
|
320
338
|
source: loader
|
|
321
339
|
});
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
340
|
+
if (browser !== "firefox") {
|
|
341
|
+
manifest.background = {
|
|
342
|
+
service_worker: this.getFileName(refId),
|
|
343
|
+
type: "module"
|
|
344
|
+
};
|
|
345
|
+
} else {
|
|
346
|
+
manifest.background = {
|
|
347
|
+
scripts: [this.getFileName(refId)],
|
|
348
|
+
type: "module"
|
|
349
|
+
};
|
|
350
|
+
}
|
|
326
351
|
return manifest;
|
|
327
352
|
}
|
|
328
353
|
}
|
|
@@ -331,9 +356,9 @@ const pluginBackground = () => {
|
|
|
331
356
|
|
|
332
357
|
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";
|
|
333
358
|
|
|
334
|
-
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";
|
|
359
|
+
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";
|
|
335
360
|
|
|
336
|
-
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";
|
|
361
|
+
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";
|
|
337
362
|
|
|
338
363
|
const contentScripts = new RxMap();
|
|
339
364
|
contentScripts.change$.pipe(filter(RxMap.isChangeType.set)).subscribe(({ map, value }) => {
|
|
@@ -391,6 +416,10 @@ const allFilesReady$ = buildEnd$.pipe(
|
|
|
391
416
|
map(() => [...outputFiles.values()]),
|
|
392
417
|
switchMap((files) => Promise.allSettled(files.map(({ file }) => file)))
|
|
393
418
|
);
|
|
419
|
+
const timestamp$ = new BehaviorSubject(Date.now());
|
|
420
|
+
allFilesReady$.subscribe(() => {
|
|
421
|
+
timestamp$.next(Date.now());
|
|
422
|
+
});
|
|
394
423
|
const isRejected = (x) => x?.status === "rejected";
|
|
395
424
|
const fileWriterError$ = allFilesReady$.pipe(
|
|
396
425
|
mergeMap((results) => results.filter(isRejected)),
|
|
@@ -424,16 +453,36 @@ function prepAsset(fileName, { id, source }) {
|
|
|
424
453
|
}
|
|
425
454
|
function prepScript(fileName, script) {
|
|
426
455
|
return ($) => $.pipe(
|
|
456
|
+
// get script contents from dev server
|
|
427
457
|
mergeMap(async ({ server }) => {
|
|
428
458
|
const target = getOutputPath(server, fileName);
|
|
429
459
|
const viteUrl = getViteUrl(script);
|
|
430
460
|
const transformResult = await server.transformRequest(viteUrl);
|
|
431
461
|
if (!transformResult)
|
|
432
462
|
throw new TypeError(`Unable to load "${script.id}" from server.`);
|
|
433
|
-
const {
|
|
434
|
-
|
|
463
|
+
const { deps = [], dynamicDeps = [], map: map2 } = transformResult;
|
|
464
|
+
let { code } = transformResult;
|
|
465
|
+
try {
|
|
466
|
+
if (map2 && server.config.build.sourcemap === "inline") {
|
|
467
|
+
code = code.replace(/\n*\/\/# sourceMappingURL=[^\n]+/g, "");
|
|
468
|
+
const sourceMap = convertSourceMap.fromObject(map2).toComment();
|
|
469
|
+
code += `
|
|
470
|
+
${sourceMap}
|
|
471
|
+
`;
|
|
472
|
+
}
|
|
473
|
+
} catch (error) {
|
|
474
|
+
console.warn("Failed to inline source map", error);
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
target,
|
|
478
|
+
code,
|
|
479
|
+
deps: [...deps, ...dynamicDeps].flat(),
|
|
480
|
+
server
|
|
481
|
+
};
|
|
435
482
|
}),
|
|
483
|
+
// retry in case of dependency rebundle
|
|
436
484
|
retry({ count: 10, delay: 100 }),
|
|
485
|
+
// patch content scripts
|
|
437
486
|
mergeMap(async ({ target, server, ...rest }) => {
|
|
438
487
|
const plugins = server.config.plugins;
|
|
439
488
|
let { code, deps } = rest;
|
|
@@ -453,7 +502,8 @@ function prepScript(fileName, script) {
|
|
|
453
502
|
if (i.n) {
|
|
454
503
|
depSet.add(i.n);
|
|
455
504
|
const fileName2 = getFileName({ type: "module", id: i.n });
|
|
456
|
-
|
|
505
|
+
const fullImport = code.substring(i.s, i.e);
|
|
506
|
+
magic.overwrite(i.s, i.e, fullImport.replace(i.n, `/${fileName2}`));
|
|
457
507
|
}
|
|
458
508
|
return { target, source: magic.toString(), deps: [...depSet] };
|
|
459
509
|
})
|
|
@@ -524,8 +574,11 @@ function update(_id) {
|
|
|
524
574
|
async function write(fileId) {
|
|
525
575
|
const start2 = performance.now();
|
|
526
576
|
const deps = await firstValueFrom(
|
|
577
|
+
// wait for start event
|
|
527
578
|
start$.pipe(
|
|
579
|
+
// prepare either asset or script contents
|
|
528
580
|
prepFileData(fileId),
|
|
581
|
+
// output file and add dependencies to file writer
|
|
529
582
|
mergeMap(async ({ target, source, deps: deps2 }) => {
|
|
530
583
|
const files = deps2.map((id) => {
|
|
531
584
|
const r = [add({ id, type: "module" })];
|
|
@@ -541,6 +594,7 @@ async function write(fileId) {
|
|
|
541
594
|
await outputFile(target, source, { encoding: "utf8" });
|
|
542
595
|
return files;
|
|
543
596
|
}),
|
|
597
|
+
// abort write operation on close event
|
|
544
598
|
takeUntil(close$),
|
|
545
599
|
concatWith(of([]))
|
|
546
600
|
)
|
|
@@ -558,15 +612,15 @@ const pluginContentScripts = () => {
|
|
|
558
612
|
{
|
|
559
613
|
name: "crx:content-scripts",
|
|
560
614
|
apply: "serve",
|
|
561
|
-
config(config) {
|
|
562
|
-
const { contentScripts: contentScripts2 = {} } = getOptions(config);
|
|
615
|
+
async config(config) {
|
|
616
|
+
const { contentScripts: contentScripts2 = {} } = await getOptions(config);
|
|
563
617
|
hmrTimeout = contentScripts2.hmrTimeout ?? 5e3;
|
|
564
618
|
preambleCode = preambleCode ?? contentScripts2.preambleCode;
|
|
565
619
|
},
|
|
566
620
|
async configureServer(_server) {
|
|
567
621
|
server = _server;
|
|
568
622
|
if (typeof preambleCode === "undefined" && server.config.plugins.some(
|
|
569
|
-
({ name = "none" }) => name.toLowerCase().includes("react")
|
|
623
|
+
({ name = "none" }) => name.toLowerCase().includes("react") && !name.toLowerCase().includes("preact")
|
|
570
624
|
)) {
|
|
571
625
|
try {
|
|
572
626
|
const react = await import('@vitejs/plugin-react');
|
|
@@ -631,6 +685,19 @@ const pluginContentScripts = () => {
|
|
|
631
685
|
name: "crx:content-scripts",
|
|
632
686
|
apply: "build",
|
|
633
687
|
enforce: "pre",
|
|
688
|
+
config(config) {
|
|
689
|
+
return {
|
|
690
|
+
...config,
|
|
691
|
+
build: {
|
|
692
|
+
...config.build,
|
|
693
|
+
rollupOptions: {
|
|
694
|
+
...config.build?.rollupOptions,
|
|
695
|
+
// keep exports for content script module api
|
|
696
|
+
preserveEntrySignatures: config.build?.rollupOptions?.preserveEntrySignatures ?? "exports-only"
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
},
|
|
634
701
|
generateBundle() {
|
|
635
702
|
for (const [key, script] of contentScripts)
|
|
636
703
|
if (key === script.refId) {
|
|
@@ -661,8 +728,8 @@ const pluginContentScriptsCss = () => {
|
|
|
661
728
|
return {
|
|
662
729
|
name: "crx:content-scripts-css",
|
|
663
730
|
enforce: "post",
|
|
664
|
-
config(config) {
|
|
665
|
-
const { contentScripts: contentScripts2 = {} } = getOptions(config);
|
|
731
|
+
async config(config) {
|
|
732
|
+
const { contentScripts: contentScripts2 = {} } = await getOptions(config);
|
|
666
733
|
injectCss = contentScripts2.injectCss ?? true;
|
|
667
734
|
},
|
|
668
735
|
renderCrxManifest(manifest) {
|
|
@@ -691,7 +758,7 @@ const pluginDeclaredContentScripts = () => {
|
|
|
691
758
|
return [];
|
|
692
759
|
};
|
|
693
760
|
|
|
694
|
-
const _dynamicScriptRegEx = /\b(import.meta).CRX_DYNAMIC_SCRIPT_(.+?)
|
|
761
|
+
const _dynamicScriptRegEx = /\b(import.meta).CRX_DYNAMIC_SCRIPT_(.+?)[,;]/gm;
|
|
695
762
|
const dynamicScriptRegEx = () => {
|
|
696
763
|
_dynamicScriptRegEx.lastIndex = 0;
|
|
697
764
|
return _dynamicScriptRegEx;
|
|
@@ -705,6 +772,34 @@ const pluginDynamicContentScripts = () => {
|
|
|
705
772
|
configResolved(_config) {
|
|
706
773
|
config = _config;
|
|
707
774
|
},
|
|
775
|
+
configureServer(server) {
|
|
776
|
+
return () => {
|
|
777
|
+
server.middlewares.use(async (req, res, next) => {
|
|
778
|
+
try {
|
|
779
|
+
await allFilesReady();
|
|
780
|
+
next();
|
|
781
|
+
} catch (error) {
|
|
782
|
+
let err;
|
|
783
|
+
if (error instanceof Error) {
|
|
784
|
+
err = error;
|
|
785
|
+
} else if (typeof error === "string") {
|
|
786
|
+
err = new Error(error);
|
|
787
|
+
} else {
|
|
788
|
+
err = new Error(
|
|
789
|
+
`Unexpected error "${error}" in middleware for "${req.url}"`
|
|
790
|
+
);
|
|
791
|
+
}
|
|
792
|
+
server.ws.send({
|
|
793
|
+
type: "error",
|
|
794
|
+
err: {
|
|
795
|
+
message: err.message,
|
|
796
|
+
stack: err.stack ?? "no stack available"
|
|
797
|
+
}
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
};
|
|
802
|
+
},
|
|
708
803
|
async resolveId(_source, importer) {
|
|
709
804
|
if (importer && _source.includes("?script")) {
|
|
710
805
|
const url = new URL(_source, "stub://stub");
|
|
@@ -773,7 +868,6 @@ const pluginDynamicContentScripts = () => {
|
|
|
773
868
|
if (config.command === "build") {
|
|
774
869
|
return `export default import.meta.CRX_DYNAMIC_SCRIPT_${script.refId};`;
|
|
775
870
|
} else if (typeof script.fileName === "string") {
|
|
776
|
-
await fileReady(script);
|
|
777
871
|
return `export default ${JSON.stringify(script.fileName)};`;
|
|
778
872
|
} else {
|
|
779
873
|
throw new Error(
|
|
@@ -786,6 +880,12 @@ const pluginDynamicContentScripts = () => {
|
|
|
786
880
|
{
|
|
787
881
|
name: "crx:dynamic-content-scripts-build",
|
|
788
882
|
apply: "build",
|
|
883
|
+
/**
|
|
884
|
+
* Replace dynamic script placeholders during build.
|
|
885
|
+
*
|
|
886
|
+
* Can't use `renderChunk` b/c pre plugin crx:content-scripts uses
|
|
887
|
+
* `generateBundle` to emit loaders. Must come after "enforce: pre".
|
|
888
|
+
*/
|
|
789
889
|
generateBundle(options, bundle) {
|
|
790
890
|
for (const chunk of Object.values(bundle))
|
|
791
891
|
if (chunk.type === "chunk") {
|
|
@@ -804,7 +904,7 @@ const pluginDynamicContentScripts = () => {
|
|
|
804
904
|
);
|
|
805
905
|
return `${JSON.stringify(
|
|
806
906
|
`/${script.loaderName ?? script.fileName}`
|
|
807
|
-
)}
|
|
907
|
+
)}${match.split(scriptKey)[1]}`;
|
|
808
908
|
}
|
|
809
909
|
);
|
|
810
910
|
chunk.code = replaced;
|
|
@@ -815,29 +915,42 @@ const pluginDynamicContentScripts = () => {
|
|
|
815
915
|
];
|
|
816
916
|
};
|
|
817
917
|
|
|
918
|
+
const { remove } = fsx;
|
|
818
919
|
const logger = createLogger("error", { prefix: "crxjs" });
|
|
819
920
|
const pluginFileWriter = () => {
|
|
820
921
|
fileWriterError$.subscribe((error) => {
|
|
821
922
|
logger.error(error.err.message, { error: error.err });
|
|
822
923
|
});
|
|
823
|
-
return
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
console.error(error);
|
|
832
|
-
server.close();
|
|
924
|
+
return [
|
|
925
|
+
{
|
|
926
|
+
name: "crx:file-writer-empty-out-dir",
|
|
927
|
+
apply: "serve",
|
|
928
|
+
enforce: "pre",
|
|
929
|
+
async configResolved(config) {
|
|
930
|
+
if (config.build.emptyOutDir) {
|
|
931
|
+
await remove(config.build.outDir);
|
|
833
932
|
}
|
|
834
|
-
}
|
|
835
|
-
server.httpServer?.on("close", () => close());
|
|
933
|
+
}
|
|
836
934
|
},
|
|
837
|
-
|
|
838
|
-
|
|
935
|
+
{
|
|
936
|
+
name: "crx:file-writer",
|
|
937
|
+
apply: "serve",
|
|
938
|
+
configureServer(server) {
|
|
939
|
+
server.httpServer?.on("listening", async () => {
|
|
940
|
+
try {
|
|
941
|
+
await start({ server });
|
|
942
|
+
} catch (error) {
|
|
943
|
+
console.error(error);
|
|
944
|
+
server.close();
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
server.httpServer?.on("close", () => close());
|
|
948
|
+
},
|
|
949
|
+
closeBundle() {
|
|
950
|
+
outputFiles.clear();
|
|
951
|
+
}
|
|
839
952
|
}
|
|
840
|
-
|
|
953
|
+
];
|
|
841
954
|
};
|
|
842
955
|
|
|
843
956
|
const _require = typeof require === "undefined" ? createRequire(import.meta.url) : require;
|
|
@@ -882,7 +995,9 @@ async function manifestFiles(manifest, options = {}) {
|
|
|
882
995
|
) ?? [];
|
|
883
996
|
const contentScripts = manifest.content_scripts?.flatMap(({ js }) => js) ?? [];
|
|
884
997
|
const contentStyles = manifest.content_scripts?.flatMap(({ css }) => css);
|
|
885
|
-
const serviceWorker = manifest.background
|
|
998
|
+
const serviceWorker = manifest.background && "service_worker" in manifest.background ? manifest.background.service_worker : void 0;
|
|
999
|
+
const backgroundScripts = manifest.background && "scripts" in manifest.background ? manifest.background.scripts : void 0;
|
|
1000
|
+
const background = serviceWorker ? [serviceWorker].filter(isString) : backgroundScripts ? backgroundScripts.filter(isString) : [];
|
|
886
1001
|
const htmlPages = htmlFiles(manifest);
|
|
887
1002
|
const icons = [
|
|
888
1003
|
Object.values(
|
|
@@ -903,7 +1018,7 @@ async function manifestFiles(manifest, options = {}) {
|
|
|
903
1018
|
return r;
|
|
904
1019
|
})
|
|
905
1020
|
);
|
|
906
|
-
webAccessibleResources = resources.flat().filter(isString);
|
|
1021
|
+
webAccessibleResources = [...new Set(resources.flat())].filter(isString);
|
|
907
1022
|
}
|
|
908
1023
|
return {
|
|
909
1024
|
contentScripts: [...new Set(contentScripts)].filter(isString),
|
|
@@ -912,7 +1027,7 @@ async function manifestFiles(manifest, options = {}) {
|
|
|
912
1027
|
icons: [...new Set(icons)].filter(isString),
|
|
913
1028
|
locales: [...new Set(locales)].filter(isString),
|
|
914
1029
|
rulesets: [...new Set(rulesets)].filter(isString),
|
|
915
|
-
background
|
|
1030
|
+
background,
|
|
916
1031
|
webAccessibleResources
|
|
917
1032
|
};
|
|
918
1033
|
}
|
|
@@ -927,7 +1042,8 @@ function htmlFiles(manifest) {
|
|
|
927
1042
|
manifest.devtools_page,
|
|
928
1043
|
manifest.options_page,
|
|
929
1044
|
manifest.options_ui?.page,
|
|
930
|
-
manifest.sandbox?.pages
|
|
1045
|
+
manifest.sandbox?.pages,
|
|
1046
|
+
manifest.side_panel?.default_path
|
|
931
1047
|
].flat().filter(isString).map((s) => s.split("#")[0]).sort();
|
|
932
1048
|
return [...new Set(files)];
|
|
933
1049
|
}
|
|
@@ -952,11 +1068,13 @@ const pluginFileWriterPublic = () => {
|
|
|
952
1068
|
};
|
|
953
1069
|
};
|
|
954
1070
|
|
|
955
|
-
_debug("file-writer").extend("hmr");
|
|
956
|
-
const
|
|
1071
|
+
const debug$2 = _debug("file-writer").extend("hmr");
|
|
1072
|
+
const isCustomPayload = (p) => {
|
|
1073
|
+
return p.type === "custom";
|
|
1074
|
+
};
|
|
957
1075
|
const hmrPayload$ = new Subject();
|
|
958
1076
|
const crxHMRPayload$ = hmrPayload$.pipe(
|
|
959
|
-
filter((p) => !
|
|
1077
|
+
filter((p) => !isCustomPayload(p)),
|
|
960
1078
|
buffer(allFilesReady$),
|
|
961
1079
|
mergeMap((pps) => {
|
|
962
1080
|
let fullReload;
|
|
@@ -1015,6 +1133,7 @@ const crxHMRPayload$ = hmrPayload$.pipe(
|
|
|
1015
1133
|
}
|
|
1016
1134
|
}),
|
|
1017
1135
|
map((data) => {
|
|
1136
|
+
debug$2(`hmr payload`, data);
|
|
1018
1137
|
return {
|
|
1019
1138
|
type: "custom",
|
|
1020
1139
|
event: "crx:content-script-payload",
|
|
@@ -1054,6 +1173,7 @@ const pluginHMR = () => {
|
|
|
1054
1173
|
name: "crx:hmr",
|
|
1055
1174
|
apply: "serve",
|
|
1056
1175
|
enforce: "pre",
|
|
1176
|
+
// server hmr host should be localhost
|
|
1057
1177
|
async config({ server = {}, ...config2 }) {
|
|
1058
1178
|
if (server.hmr === false)
|
|
1059
1179
|
return;
|
|
@@ -1061,9 +1181,9 @@ const pluginHMR = () => {
|
|
|
1061
1181
|
server.hmr = {};
|
|
1062
1182
|
server.hmr = server.hmr ?? {};
|
|
1063
1183
|
server.hmr.host = "localhost";
|
|
1064
|
-
server.hmr.port = server.hmr.port ?? await getPort({ port: portNumbers(5200, 5300) });
|
|
1065
1184
|
return { server, ...config2 };
|
|
1066
1185
|
},
|
|
1186
|
+
// server should ignore outdir
|
|
1067
1187
|
configResolved(_config) {
|
|
1068
1188
|
config = _config;
|
|
1069
1189
|
const { watch = {} } = config.server;
|
|
@@ -1101,19 +1221,24 @@ const pluginHMR = () => {
|
|
|
1101
1221
|
closeBundle() {
|
|
1102
1222
|
subs.unsubscribe();
|
|
1103
1223
|
},
|
|
1224
|
+
// background changes require a full extension reload
|
|
1104
1225
|
handleHotUpdate({ modules, server }) {
|
|
1105
1226
|
const { root } = server.config;
|
|
1106
1227
|
const relFiles = /* @__PURE__ */ new Set();
|
|
1107
|
-
|
|
1228
|
+
const fsFiles = /* @__PURE__ */ new Set();
|
|
1229
|
+
for (const m of modules) {
|
|
1108
1230
|
if (m.id?.startsWith(root)) {
|
|
1109
1231
|
relFiles.add(m.id.slice(server.config.root.length));
|
|
1232
|
+
} else if (m.url?.startsWith("/@fs")) {
|
|
1233
|
+
fsFiles.add(m.url);
|
|
1110
1234
|
}
|
|
1235
|
+
}
|
|
1236
|
+
fsFiles.forEach((file) => update(file));
|
|
1111
1237
|
if (inputManifestFiles.background.length) {
|
|
1112
1238
|
const background = prefix$1("/", inputManifestFiles.background[0]);
|
|
1113
1239
|
if (relFiles.has(background) || modules.some(isImporter(join(server.config.root, background)))) {
|
|
1114
1240
|
debug$1("sending runtime reload");
|
|
1115
1241
|
server.ws.send(crxRuntimeReload);
|
|
1116
|
-
return [];
|
|
1117
1242
|
}
|
|
1118
1243
|
}
|
|
1119
1244
|
for (const [key, script] of contentScripts)
|
|
@@ -1128,6 +1253,7 @@ const pluginHMR = () => {
|
|
|
1128
1253
|
name: "crx:hmr",
|
|
1129
1254
|
apply: "serve",
|
|
1130
1255
|
enforce: "post",
|
|
1256
|
+
// get final output manifest for handleHotUpdate 👆
|
|
1131
1257
|
async transformCrxManifest(manifest) {
|
|
1132
1258
|
inputManifestFiles = await manifestFiles(manifest, { cwd: config.root });
|
|
1133
1259
|
return null;
|
|
@@ -1218,6 +1344,7 @@ const pluginHtmlInlineScripts = () => {
|
|
|
1218
1344
|
};
|
|
1219
1345
|
const postPlugin = {
|
|
1220
1346
|
name: "crx:html-auditor-post",
|
|
1347
|
+
// this hook isn't audited b/c we add it after we set up the auditors
|
|
1221
1348
|
transformIndexHtml(html, ctx) {
|
|
1222
1349
|
const key = toKey(ctx);
|
|
1223
1350
|
const p = pages.get(key);
|
|
@@ -1283,9 +1410,9 @@ const pluginHtmlInlineScripts = () => {
|
|
|
1283
1410
|
};
|
|
1284
1411
|
};
|
|
1285
1412
|
|
|
1286
|
-
var
|
|
1413
|
+
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";
|
|
1287
1414
|
|
|
1288
|
-
var
|
|
1415
|
+
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";
|
|
1289
1416
|
|
|
1290
1417
|
const { readFile } = promises;
|
|
1291
1418
|
const pluginManifest = () => {
|
|
@@ -1344,7 +1471,7 @@ const pluginManifest = () => {
|
|
|
1344
1471
|
name: "crx:manifest-loader",
|
|
1345
1472
|
enforce: "pre",
|
|
1346
1473
|
buildStart(options) {
|
|
1347
|
-
if (typeof options.input !== "undefined") {
|
|
1474
|
+
if (typeof options.input !== "undefined" && !("ssr" in this)) {
|
|
1348
1475
|
refId = this.emitFile({
|
|
1349
1476
|
type: "chunk",
|
|
1350
1477
|
id: manifestId,
|
|
@@ -1464,7 +1591,7 @@ const pluginManifest = () => {
|
|
|
1464
1591
|
})
|
|
1465
1592
|
);
|
|
1466
1593
|
}
|
|
1467
|
-
if (manifest2.background
|
|
1594
|
+
if (manifest2.background && "service_worker" in manifest2.background) {
|
|
1468
1595
|
const file = manifest2.background.service_worker;
|
|
1469
1596
|
const id2 = join(config.root, file);
|
|
1470
1597
|
const refId2 = this.emitFile({
|
|
@@ -1474,6 +1601,16 @@ const pluginManifest = () => {
|
|
|
1474
1601
|
});
|
|
1475
1602
|
manifest2.background.service_worker = refId2;
|
|
1476
1603
|
}
|
|
1604
|
+
if (manifest2.background && "scripts" in manifest2.background) {
|
|
1605
|
+
const file = manifest2.background.scripts[0];
|
|
1606
|
+
const id2 = join(config.root, file);
|
|
1607
|
+
const refId2 = this.emitFile({
|
|
1608
|
+
type: "chunk",
|
|
1609
|
+
id: id2,
|
|
1610
|
+
name: basename(file)
|
|
1611
|
+
});
|
|
1612
|
+
manifest2.background.scripts = [refId2];
|
|
1613
|
+
}
|
|
1477
1614
|
for (const file of htmlFiles(manifest2)) {
|
|
1478
1615
|
const id2 = join(config.root, file);
|
|
1479
1616
|
this.emitFile({
|
|
@@ -1484,7 +1621,7 @@ const pluginManifest = () => {
|
|
|
1484
1621
|
}
|
|
1485
1622
|
}
|
|
1486
1623
|
const encoded = encodeManifest(manifest2);
|
|
1487
|
-
return encoded;
|
|
1624
|
+
return { code: encoded, map: null };
|
|
1488
1625
|
},
|
|
1489
1626
|
async generateBundle(options, bundle) {
|
|
1490
1627
|
const manifestName = this.getFileName(refId);
|
|
@@ -1498,11 +1635,16 @@ const pluginManifest = () => {
|
|
|
1498
1635
|
);
|
|
1499
1636
|
}
|
|
1500
1637
|
} else {
|
|
1501
|
-
if (manifest2.background
|
|
1638
|
+
if (manifest2.background && "service_worker" in manifest2.background) {
|
|
1502
1639
|
const ref = manifest2.background.service_worker;
|
|
1503
1640
|
const name = this.getFileName(ref);
|
|
1504
1641
|
manifest2.background.service_worker = name;
|
|
1505
1642
|
}
|
|
1643
|
+
if (manifest2.background && "scripts" in manifest2.background) {
|
|
1644
|
+
const ref = manifest2.background.scripts[0];
|
|
1645
|
+
const name = this.getFileName(ref);
|
|
1646
|
+
manifest2.background.scripts = [name];
|
|
1647
|
+
}
|
|
1506
1648
|
manifest2.content_scripts = manifest2.content_scripts?.map(
|
|
1507
1649
|
({ js = [], ...rest }) => {
|
|
1508
1650
|
return {
|
|
@@ -1562,6 +1704,7 @@ Public dir: "${config.publicDir}"`
|
|
|
1562
1704
|
this.emitFile({
|
|
1563
1705
|
type: "asset",
|
|
1564
1706
|
fileName: f,
|
|
1707
|
+
// TODO: cache source buffer
|
|
1565
1708
|
source: await readFile(filename)
|
|
1566
1709
|
});
|
|
1567
1710
|
}
|
|
@@ -1570,17 +1713,20 @@ Public dir: "${config.publicDir}"`
|
|
|
1570
1713
|
if (config.command === "serve" && files.html.length) {
|
|
1571
1714
|
const refId2 = this.emitFile({
|
|
1572
1715
|
type: "asset",
|
|
1573
|
-
name: "
|
|
1574
|
-
source:
|
|
1716
|
+
name: "loading-page.js",
|
|
1717
|
+
source: loadingPageScript.replace(
|
|
1718
|
+
"%PORT%",
|
|
1719
|
+
`${config.server.port ?? 0}`
|
|
1720
|
+
)
|
|
1575
1721
|
});
|
|
1576
|
-
const
|
|
1722
|
+
const loadingPageScriptName = this.getFileName(refId2);
|
|
1577
1723
|
files.html.map(
|
|
1578
1724
|
(f) => this.emitFile({
|
|
1579
1725
|
type: "asset",
|
|
1580
1726
|
fileName: f,
|
|
1581
|
-
source:
|
|
1727
|
+
source: loadingPageHtml.replace(
|
|
1582
1728
|
"%SCRIPT%",
|
|
1583
|
-
`/${
|
|
1729
|
+
`/${loadingPageScriptName}`
|
|
1584
1730
|
)
|
|
1585
1731
|
})
|
|
1586
1732
|
);
|
|
@@ -1590,10 +1736,10 @@ Public dir: "${config.publicDir}"`
|
|
|
1590
1736
|
this.emitFile({
|
|
1591
1737
|
type: "asset",
|
|
1592
1738
|
fileName: "manifest.json",
|
|
1593
|
-
source: JSON.stringify(manifest2, null, 2)
|
|
1739
|
+
source: JSON.stringify(manifest2, null, 2) + "\n"
|
|
1594
1740
|
});
|
|
1595
1741
|
} else {
|
|
1596
|
-
manifestJson.source = JSON.stringify(manifest2, null, 2);
|
|
1742
|
+
manifestJson.source = JSON.stringify(manifest2, null, 2) + "\n";
|
|
1597
1743
|
}
|
|
1598
1744
|
delete bundle[manifestName];
|
|
1599
1745
|
}
|
|
@@ -1609,7 +1755,11 @@ function compileFileResources(fileName, {
|
|
|
1609
1755
|
assets: /* @__PURE__ */ new Set(),
|
|
1610
1756
|
css: /* @__PURE__ */ new Set(),
|
|
1611
1757
|
imports: /* @__PURE__ */ new Set()
|
|
1612
|
-
}) {
|
|
1758
|
+
}, processedFiles = /* @__PURE__ */ new Set()) {
|
|
1759
|
+
if (processedFiles.has(fileName)) {
|
|
1760
|
+
return resources;
|
|
1761
|
+
}
|
|
1762
|
+
processedFiles.add(fileName);
|
|
1613
1763
|
const chunk = chunks.get(fileName);
|
|
1614
1764
|
if (chunk) {
|
|
1615
1765
|
const { modules, facadeModuleId, imports, dynamicImports } = chunk;
|
|
@@ -1618,7 +1768,7 @@ function compileFileResources(fileName, {
|
|
|
1618
1768
|
for (const x of dynamicImports)
|
|
1619
1769
|
resources.imports.add(x);
|
|
1620
1770
|
for (const x of [...imports, ...dynamicImports])
|
|
1621
|
-
compileFileResources(x, { chunks, files, config }, resources);
|
|
1771
|
+
compileFileResources(x, { chunks, files, config }, resources, processedFiles);
|
|
1622
1772
|
for (const m of Object.keys(modules))
|
|
1623
1773
|
if (m !== facadeModuleId) {
|
|
1624
1774
|
const key = prefix$1("/", relative(config.root, m.split("?")[0]));
|
|
@@ -1631,7 +1781,8 @@ function compileFileResources(fileName, {
|
|
|
1631
1781
|
compileFileResources(
|
|
1632
1782
|
script.fileName,
|
|
1633
1783
|
{ chunks, files, config },
|
|
1634
|
-
resources
|
|
1784
|
+
resources,
|
|
1785
|
+
processedFiles
|
|
1635
1786
|
);
|
|
1636
1787
|
}
|
|
1637
1788
|
}
|
|
@@ -1650,7 +1801,7 @@ function compileFileResources(fileName, {
|
|
|
1650
1801
|
const defineManifest = (manifest) => manifest;
|
|
1651
1802
|
const defineDynamicResource = ({
|
|
1652
1803
|
matches = ["http://*/*", "https://*/*"],
|
|
1653
|
-
use_dynamic_url =
|
|
1804
|
+
use_dynamic_url = false
|
|
1654
1805
|
}) => ({
|
|
1655
1806
|
matches,
|
|
1656
1807
|
resources: [DYNAMIC_RESOURCE],
|
|
@@ -1662,22 +1813,34 @@ _debug("web-acc-res");
|
|
|
1662
1813
|
const pluginWebAccessibleResources = () => {
|
|
1663
1814
|
let config;
|
|
1664
1815
|
let injectCss;
|
|
1816
|
+
let browser;
|
|
1665
1817
|
return [
|
|
1666
1818
|
{
|
|
1667
1819
|
name: "crx:web-accessible-resources",
|
|
1668
1820
|
apply: "serve",
|
|
1669
1821
|
enforce: "post",
|
|
1822
|
+
async config(config2) {
|
|
1823
|
+
const opts = await getOptions(config2);
|
|
1824
|
+
browser = opts.browser || "chrome";
|
|
1825
|
+
},
|
|
1670
1826
|
renderCrxManifest(manifest) {
|
|
1671
1827
|
manifest.web_accessible_resources = manifest.web_accessible_resources ?? [];
|
|
1672
1828
|
manifest.web_accessible_resources = manifest.web_accessible_resources.map(({ resources, ...rest }) => ({
|
|
1673
1829
|
resources: resources.filter((r) => r !== DYNAMIC_RESOURCE),
|
|
1674
1830
|
...rest
|
|
1675
1831
|
})).filter(({ resources }) => resources.length);
|
|
1676
|
-
|
|
1677
|
-
|
|
1832
|
+
const war = {
|
|
1833
|
+
// all web origins can access
|
|
1678
1834
|
matches: ["<all_urls>"],
|
|
1679
|
-
resources
|
|
1680
|
-
|
|
1835
|
+
// all resources are web accessible
|
|
1836
|
+
resources: ["**/*", "*"],
|
|
1837
|
+
// change the extension origin on every reload
|
|
1838
|
+
use_dynamic_url: false
|
|
1839
|
+
};
|
|
1840
|
+
if (browser === "firefox") {
|
|
1841
|
+
delete war.use_dynamic_url;
|
|
1842
|
+
}
|
|
1843
|
+
manifest.web_accessible_resources.push(war);
|
|
1681
1844
|
return manifest;
|
|
1682
1845
|
}
|
|
1683
1846
|
},
|
|
@@ -1686,7 +1849,9 @@ const pluginWebAccessibleResources = () => {
|
|
|
1686
1849
|
apply: "build",
|
|
1687
1850
|
enforce: "post",
|
|
1688
1851
|
async config({ build, ...config2 }, { command }) {
|
|
1689
|
-
const
|
|
1852
|
+
const opts = await getOptions(config2);
|
|
1853
|
+
const contentScripts2 = opts.contentScripts || {};
|
|
1854
|
+
browser = opts.browser || "chrome";
|
|
1690
1855
|
injectCss = contentScripts2.injectCss ?? true;
|
|
1691
1856
|
return { ...config2, build: { ...build, manifest: command === "build" } };
|
|
1692
1857
|
},
|
|
@@ -1715,9 +1880,11 @@ const pluginWebAccessibleResources = () => {
|
|
|
1715
1880
|
dynamicScriptMatches.add("https://*/*");
|
|
1716
1881
|
}
|
|
1717
1882
|
if (contentScripts.size > 0) {
|
|
1883
|
+
const viteMajorVersion = parseInt(version.split(".")[0]);
|
|
1884
|
+
const manifestPath = viteMajorVersion > 4 ? ".vite/manifest.json" : "manifest.json";
|
|
1718
1885
|
const viteManifest = parseJsonAsset(
|
|
1719
1886
|
bundle,
|
|
1720
|
-
|
|
1887
|
+
manifestPath
|
|
1721
1888
|
);
|
|
1722
1889
|
const viteFiles = /* @__PURE__ */ new Map();
|
|
1723
1890
|
for (const [, file] of Object.entries(viteManifest))
|
|
@@ -1745,12 +1912,12 @@ const pluginWebAccessibleResources = () => {
|
|
|
1745
1912
|
{ chunks: bundleChunks, files: viteFiles, config }
|
|
1746
1913
|
);
|
|
1747
1914
|
contentScripts.get(key).css = [...css];
|
|
1748
|
-
if (type === "loader")
|
|
1915
|
+
if (type === "loader" || isDynamicScript)
|
|
1749
1916
|
imports.add(fileName);
|
|
1750
1917
|
const resource = {
|
|
1751
1918
|
matches: isDynamicScript ? [...dynamicScriptMatches] : matches,
|
|
1752
1919
|
resources: [...assets, ...imports],
|
|
1753
|
-
use_dynamic_url: isDynamicScript ? dynamicScriptDynamicUrl :
|
|
1920
|
+
use_dynamic_url: isDynamicScript ? dynamicScriptDynamicUrl : false
|
|
1754
1921
|
};
|
|
1755
1922
|
if (isDynamicScript || !injectCss) {
|
|
1756
1923
|
resource.resources.push(...css);
|
|
@@ -1794,6 +1961,11 @@ const pluginWebAccessibleResources = () => {
|
|
|
1794
1961
|
use_dynamic_url
|
|
1795
1962
|
});
|
|
1796
1963
|
}
|
|
1964
|
+
if (browser === "firefox") {
|
|
1965
|
+
for (const war of combinedResources) {
|
|
1966
|
+
delete war.use_dynamic_url;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1797
1969
|
if (combinedResources.length === 0)
|
|
1798
1970
|
delete manifest.web_accessible_resources;
|
|
1799
1971
|
else
|
|
@@ -1805,6 +1977,7 @@ const pluginWebAccessibleResources = () => {
|
|
|
1805
1977
|
};
|
|
1806
1978
|
|
|
1807
1979
|
const crx = (options) => {
|
|
1980
|
+
contentScripts.clear();
|
|
1808
1981
|
return [
|
|
1809
1982
|
pluginOptionsProvider(options),
|
|
1810
1983
|
pluginBackground(),
|