@crxjs/vite-plugin 1.0.0 → 1.0.3
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/CHANGELOG.md +20 -0
- package/dist/index.cjs +218 -220
- package/dist/index.mjs +215 -218
- package/package.json +11 -14
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @crxjs/vite-plugin
|
|
2
|
+
|
|
3
|
+
## 1.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8b2e587: check service worker on interval from extension page
|
|
8
|
+
|
|
9
|
+
## 1.0.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- be8a1de: Remove unused code that throws when web accessible resources contains
|
|
14
|
+
an HTML file.
|
|
15
|
+
|
|
16
|
+
## 1.0.1
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- d2b4f9e: feat: allow hash in manifest html urls
|
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,7 @@ function _interopNamespace(e) {
|
|
|
42
42
|
var debug__default = /*#__PURE__*/_interopDefaultLegacy(debug$5);
|
|
43
43
|
var fg__default = /*#__PURE__*/_interopDefaultLegacy(fg);
|
|
44
44
|
var v8__default = /*#__PURE__*/_interopDefaultLegacy(v8);
|
|
45
|
+
var fsExtra__default = /*#__PURE__*/_interopDefaultLegacy(fsExtra);
|
|
45
46
|
var MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString);
|
|
46
47
|
var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
|
|
47
48
|
var jsesc__default = /*#__PURE__*/_interopDefaultLegacy(jsesc);
|
|
@@ -101,7 +102,7 @@ function htmlFiles(manifest) {
|
|
|
101
102
|
manifest.options_page,
|
|
102
103
|
manifest.options_ui?.page,
|
|
103
104
|
manifest.sandbox?.pages
|
|
104
|
-
].flat().filter(isString).sort();
|
|
105
|
+
].flat().filter(isString).map((s) => s.split("#")[0]).sort();
|
|
105
106
|
return [...new Set(files)];
|
|
106
107
|
}
|
|
107
108
|
function decodeManifest(code) {
|
|
@@ -1981,6 +1982,7 @@ function withLatestFrom() {
|
|
|
1981
1982
|
});
|
|
1982
1983
|
}
|
|
1983
1984
|
|
|
1985
|
+
const { pathExistsSync, outputFile, statSync } = fsExtra__default["default"];
|
|
1984
1986
|
const debug$3 = _debug("file-writer").extend("events");
|
|
1985
1987
|
const writerEvent$ = new BehaviorSubject({
|
|
1986
1988
|
type: "init"
|
|
@@ -2002,7 +2004,7 @@ const filesReady$ = writerEvent$.pipe(filter((x) => {
|
|
|
2002
2004
|
return x.type === "writeBundle";
|
|
2003
2005
|
}), switchMap((event) => interval(100).pipe(mapTo(event), first(({ bundle, options, timestamp }) => {
|
|
2004
2006
|
const result = Object.keys(bundle).every((p) => {
|
|
2005
|
-
const stats =
|
|
2007
|
+
const stats = statSync(join(options.dir, p));
|
|
2006
2008
|
return stats.mtimeMs > timestamp;
|
|
2007
2009
|
});
|
|
2008
2010
|
return result;
|
|
@@ -2014,7 +2016,7 @@ const rebuildFiles = async () => {
|
|
|
2014
2016
|
debug$3("rebuildFiles start");
|
|
2015
2017
|
await filesReady();
|
|
2016
2018
|
await Promise.all([
|
|
2017
|
-
|
|
2019
|
+
outputFile(await triggerName, Date.now().toString()),
|
|
2018
2020
|
filesStart()
|
|
2019
2021
|
]);
|
|
2020
2022
|
await filesReady();
|
|
@@ -2063,8 +2065,8 @@ const pluginFileWriterEvents = () => {
|
|
|
2063
2065
|
async buildStart(options) {
|
|
2064
2066
|
start = perf_hooks.performance.now();
|
|
2065
2067
|
const filename = await triggerName;
|
|
2066
|
-
if (!
|
|
2067
|
-
await
|
|
2068
|
+
if (!pathExistsSync(filename)) {
|
|
2069
|
+
await outputFile(filename, Date.now().toString());
|
|
2068
2070
|
}
|
|
2069
2071
|
this.addWatchFile(filename);
|
|
2070
2072
|
writerEvent$.next({ type: "buildStart", options });
|
|
@@ -2091,7 +2093,7 @@ const pluginFileWriterEvents = () => {
|
|
|
2091
2093
|
};
|
|
2092
2094
|
};
|
|
2093
2095
|
|
|
2094
|
-
var preControllerScript = "
|
|
2096
|
+
var preControllerScript = "const id = setInterval(() => location.reload(), 100);\nsetTimeout(() => clearInterval(id), 5e3);\n";
|
|
2095
2097
|
|
|
2096
2098
|
var preControllerHtml = "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <title>Waiting for the extension service worker...</title>\n <script src=\"%PATH%\"></script>\n </head>\n <body>\n <h1>Waiting for service worker</h1>\n\n <p>\n If you see this message, it means the service worker has not loaded fully.\n </p>\n\n <p>\n During development, the service worker reroutes HTML requests to the dev\n server, so this file isn't used unless the extension service worker opens\n a page immediately after a full extension reload, and before the service\n worker takes control of fetch (e.g., in the onInstalled event). In that\n case, this page will continuously reload until the service worker is\n ready, always less than 100 ms.\n </p>\n\n <p>This page is never added in production.</p>\n </body>\n</html>\n";
|
|
2097
2099
|
|
|
@@ -2543,6 +2545,216 @@ const pluginHtmlAuditor = () => {
|
|
|
2543
2545
|
};
|
|
2544
2546
|
};
|
|
2545
2547
|
|
|
2548
|
+
const pluginManifest = (_manifest) => () => {
|
|
2549
|
+
let manifest;
|
|
2550
|
+
let plugins;
|
|
2551
|
+
let refId;
|
|
2552
|
+
let config;
|
|
2553
|
+
return [
|
|
2554
|
+
{
|
|
2555
|
+
name: "crx:manifest-init",
|
|
2556
|
+
enforce: "pre",
|
|
2557
|
+
async config(config2, env) {
|
|
2558
|
+
manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
|
|
2559
|
+
if (manifest.manifest_version !== 3)
|
|
2560
|
+
throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
|
|
2561
|
+
if (env.command === "serve") {
|
|
2562
|
+
const {
|
|
2563
|
+
contentScripts: js,
|
|
2564
|
+
background: sw,
|
|
2565
|
+
html
|
|
2566
|
+
} = await manifestFiles(manifest);
|
|
2567
|
+
let { entries = [] } = config2.optimizeDeps ?? {};
|
|
2568
|
+
entries = [entries].flat();
|
|
2569
|
+
const set = new Set(entries);
|
|
2570
|
+
for (const x of [...js, ...sw, ...html])
|
|
2571
|
+
set.add(x);
|
|
2572
|
+
return {
|
|
2573
|
+
...config2,
|
|
2574
|
+
optimizeDeps: {
|
|
2575
|
+
...config2.optimizeDeps,
|
|
2576
|
+
entries: [...set]
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2579
|
+
}
|
|
2580
|
+
},
|
|
2581
|
+
buildStart(options) {
|
|
2582
|
+
if (options.plugins)
|
|
2583
|
+
plugins = options.plugins;
|
|
2584
|
+
}
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
name: "crx:manifest-loader",
|
|
2588
|
+
apply: "build",
|
|
2589
|
+
enforce: "pre",
|
|
2590
|
+
buildStart() {
|
|
2591
|
+
refId = this.emitFile({
|
|
2592
|
+
type: "chunk",
|
|
2593
|
+
id: manifestId,
|
|
2594
|
+
name: "crx-manifest.js",
|
|
2595
|
+
preserveSignature: "strict"
|
|
2596
|
+
});
|
|
2597
|
+
},
|
|
2598
|
+
resolveId(source) {
|
|
2599
|
+
if (source === manifestId)
|
|
2600
|
+
return manifestId;
|
|
2601
|
+
return null;
|
|
2602
|
+
},
|
|
2603
|
+
load(id) {
|
|
2604
|
+
if (id === manifestId)
|
|
2605
|
+
return encodeManifest(manifest);
|
|
2606
|
+
return null;
|
|
2607
|
+
}
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
name: "crx:stub-input",
|
|
2611
|
+
apply: "build",
|
|
2612
|
+
enforce: "pre",
|
|
2613
|
+
options({ input, ...options }) {
|
|
2614
|
+
return {
|
|
2615
|
+
input: isString(input) && input.endsWith("index.html") ? stubId : input,
|
|
2616
|
+
...options
|
|
2617
|
+
};
|
|
2618
|
+
},
|
|
2619
|
+
resolveId(source) {
|
|
2620
|
+
if (source === stubId)
|
|
2621
|
+
return stubId;
|
|
2622
|
+
return null;
|
|
2623
|
+
},
|
|
2624
|
+
load(id) {
|
|
2625
|
+
if (id === stubId)
|
|
2626
|
+
return `console.log('stub')`;
|
|
2627
|
+
return null;
|
|
2628
|
+
},
|
|
2629
|
+
generateBundle(options, bundle) {
|
|
2630
|
+
for (const [key, chunk] of Object.entries(bundle)) {
|
|
2631
|
+
if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
|
|
2632
|
+
delete bundle[key];
|
|
2633
|
+
break;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
},
|
|
2638
|
+
{
|
|
2639
|
+
name: "crx:manifest-post",
|
|
2640
|
+
apply: "build",
|
|
2641
|
+
enforce: "post",
|
|
2642
|
+
configResolved(_config) {
|
|
2643
|
+
config = _config;
|
|
2644
|
+
const plugins2 = config.plugins;
|
|
2645
|
+
const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
|
|
2646
|
+
const [plugin] = plugins2.splice(crx, 1);
|
|
2647
|
+
plugins2.push(plugin);
|
|
2648
|
+
},
|
|
2649
|
+
async transform(code, id) {
|
|
2650
|
+
if (id !== manifestId)
|
|
2651
|
+
return;
|
|
2652
|
+
let manifest2 = decodeManifest.call(this, code);
|
|
2653
|
+
for (const plugin of plugins) {
|
|
2654
|
+
try {
|
|
2655
|
+
const m = structuredClone(manifest2);
|
|
2656
|
+
const result = await plugin.transformCrxManifest?.call(this, m);
|
|
2657
|
+
manifest2 = result ?? manifest2;
|
|
2658
|
+
} catch (error) {
|
|
2659
|
+
if (error instanceof Error)
|
|
2660
|
+
error.message = `[${plugin.name}] ${error.message}`;
|
|
2661
|
+
throw error;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
if (manifest2.content_scripts?.length) {
|
|
2665
|
+
manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
|
|
2666
|
+
const refJS = js.map((file) => this.emitFile({
|
|
2667
|
+
type: "chunk",
|
|
2668
|
+
id: file,
|
|
2669
|
+
name: basename(file)
|
|
2670
|
+
}));
|
|
2671
|
+
return { js: refJS, ...rest };
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
if (!this.meta.watchMode) {
|
|
2675
|
+
if (manifest2.background?.service_worker) {
|
|
2676
|
+
const file = manifest2.background.service_worker;
|
|
2677
|
+
const refId2 = this.emitFile({
|
|
2678
|
+
type: "chunk",
|
|
2679
|
+
id: file,
|
|
2680
|
+
name: basename(file)
|
|
2681
|
+
});
|
|
2682
|
+
manifest2.background.service_worker = refId2;
|
|
2683
|
+
}
|
|
2684
|
+
for (const file of htmlFiles(manifest2)) {
|
|
2685
|
+
this.emitFile({
|
|
2686
|
+
type: "chunk",
|
|
2687
|
+
id: file,
|
|
2688
|
+
name: basename(file)
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
const encoded = encodeManifest(manifest2);
|
|
2693
|
+
return encoded;
|
|
2694
|
+
},
|
|
2695
|
+
async generateBundle(options, bundle) {
|
|
2696
|
+
const manifestName = this.getFileName(refId);
|
|
2697
|
+
const manifestJs = bundle[manifestName];
|
|
2698
|
+
let manifest2 = decodeManifest.call(this, manifestJs.code);
|
|
2699
|
+
if (manifest2.background?.service_worker && !this.meta.watchMode) {
|
|
2700
|
+
const ref = manifest2.background.service_worker;
|
|
2701
|
+
const name = this.getFileName(ref);
|
|
2702
|
+
manifest2.background.service_worker = name;
|
|
2703
|
+
}
|
|
2704
|
+
manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
|
|
2705
|
+
const refJS = js.map((ref) => this.getFileName(ref));
|
|
2706
|
+
return { js: refJS, ...rest };
|
|
2707
|
+
});
|
|
2708
|
+
for (const plugin of plugins) {
|
|
2709
|
+
try {
|
|
2710
|
+
const m = structuredClone(manifest2);
|
|
2711
|
+
const result = await plugin.renderCrxManifest?.call(this, m, bundle);
|
|
2712
|
+
manifest2 = result ?? manifest2;
|
|
2713
|
+
} catch (error) {
|
|
2714
|
+
const name = `[${plugin.name}]`;
|
|
2715
|
+
let message = error;
|
|
2716
|
+
if (error instanceof Error) {
|
|
2717
|
+
message = colors__default["default"].red(`${name} ${error.stack ? error.stack : error.message}`);
|
|
2718
|
+
} else if (typeof error === "string") {
|
|
2719
|
+
message = colors__default["default"].red(`${name} ${error}`);
|
|
2720
|
+
}
|
|
2721
|
+
console.log(message);
|
|
2722
|
+
throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
const assetTypes = [
|
|
2726
|
+
"icons",
|
|
2727
|
+
"locales",
|
|
2728
|
+
"rulesets",
|
|
2729
|
+
"webAccessibleResources"
|
|
2730
|
+
];
|
|
2731
|
+
const files = await manifestFiles(manifest2);
|
|
2732
|
+
await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
|
|
2733
|
+
if (typeof bundle[f] === "undefined") {
|
|
2734
|
+
const filename = join(config.root, f);
|
|
2735
|
+
this.emitFile({
|
|
2736
|
+
type: "asset",
|
|
2737
|
+
fileName: f,
|
|
2738
|
+
source: await fsExtra.readFile(filename)
|
|
2739
|
+
});
|
|
2740
|
+
}
|
|
2741
|
+
}));
|
|
2742
|
+
const manifestJson = bundle["manifest.json"];
|
|
2743
|
+
if (typeof manifestJson === "undefined") {
|
|
2744
|
+
this.emitFile({
|
|
2745
|
+
type: "asset",
|
|
2746
|
+
fileName: "manifest.json",
|
|
2747
|
+
source: JSON.stringify(manifest2, null, 2)
|
|
2748
|
+
});
|
|
2749
|
+
} else {
|
|
2750
|
+
manifestJson.source = JSON.stringify(manifest2, null, 2);
|
|
2751
|
+
}
|
|
2752
|
+
delete bundle[manifestName];
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
];
|
|
2756
|
+
};
|
|
2757
|
+
|
|
2546
2758
|
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";
|
|
2547
2759
|
|
|
2548
2760
|
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";
|
|
@@ -2981,220 +3193,6 @@ const pluginResources = ({ contentScripts = {} }) => {
|
|
|
2981
3193
|
];
|
|
2982
3194
|
};
|
|
2983
3195
|
|
|
2984
|
-
const pluginManifest = (_manifest) => () => {
|
|
2985
|
-
let manifest;
|
|
2986
|
-
let plugins;
|
|
2987
|
-
let refId;
|
|
2988
|
-
let config;
|
|
2989
|
-
return [
|
|
2990
|
-
{
|
|
2991
|
-
name: "crx:manifest-init",
|
|
2992
|
-
enforce: "pre",
|
|
2993
|
-
async config(config2, env) {
|
|
2994
|
-
manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
|
|
2995
|
-
if (manifest.manifest_version !== 3)
|
|
2996
|
-
throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
|
|
2997
|
-
if (env.command === "serve") {
|
|
2998
|
-
const {
|
|
2999
|
-
contentScripts: js,
|
|
3000
|
-
background: sw,
|
|
3001
|
-
html
|
|
3002
|
-
} = await manifestFiles(manifest);
|
|
3003
|
-
let { entries = [] } = config2.optimizeDeps ?? {};
|
|
3004
|
-
entries = [entries].flat();
|
|
3005
|
-
const set = new Set(entries);
|
|
3006
|
-
for (const x of [...js, ...sw, ...html])
|
|
3007
|
-
set.add(x);
|
|
3008
|
-
return {
|
|
3009
|
-
...config2,
|
|
3010
|
-
optimizeDeps: {
|
|
3011
|
-
...config2.optimizeDeps,
|
|
3012
|
-
entries: [...set]
|
|
3013
|
-
}
|
|
3014
|
-
};
|
|
3015
|
-
}
|
|
3016
|
-
},
|
|
3017
|
-
buildStart(options) {
|
|
3018
|
-
if (options.plugins)
|
|
3019
|
-
plugins = options.plugins;
|
|
3020
|
-
}
|
|
3021
|
-
},
|
|
3022
|
-
{
|
|
3023
|
-
name: "crx:manifest-loader",
|
|
3024
|
-
apply: "build",
|
|
3025
|
-
enforce: "pre",
|
|
3026
|
-
buildStart() {
|
|
3027
|
-
refId = this.emitFile({
|
|
3028
|
-
type: "chunk",
|
|
3029
|
-
id: manifestId,
|
|
3030
|
-
name: "crx-manifest.js",
|
|
3031
|
-
preserveSignature: "strict"
|
|
3032
|
-
});
|
|
3033
|
-
},
|
|
3034
|
-
resolveId(source) {
|
|
3035
|
-
if (source === manifestId)
|
|
3036
|
-
return manifestId;
|
|
3037
|
-
return null;
|
|
3038
|
-
},
|
|
3039
|
-
load(id) {
|
|
3040
|
-
if (id === manifestId)
|
|
3041
|
-
return encodeManifest(manifest);
|
|
3042
|
-
return null;
|
|
3043
|
-
}
|
|
3044
|
-
},
|
|
3045
|
-
{
|
|
3046
|
-
name: "crx:stub-input",
|
|
3047
|
-
apply: "build",
|
|
3048
|
-
enforce: "pre",
|
|
3049
|
-
options({ input, ...options }) {
|
|
3050
|
-
return {
|
|
3051
|
-
input: isString(input) && input.endsWith("index.html") ? stubId : input,
|
|
3052
|
-
...options
|
|
3053
|
-
};
|
|
3054
|
-
},
|
|
3055
|
-
resolveId(source) {
|
|
3056
|
-
if (source === stubId)
|
|
3057
|
-
return stubId;
|
|
3058
|
-
return null;
|
|
3059
|
-
},
|
|
3060
|
-
load(id) {
|
|
3061
|
-
if (id === stubId)
|
|
3062
|
-
return `console.log('stub')`;
|
|
3063
|
-
return null;
|
|
3064
|
-
},
|
|
3065
|
-
generateBundle(options, bundle) {
|
|
3066
|
-
for (const [key, chunk] of Object.entries(bundle)) {
|
|
3067
|
-
if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
|
|
3068
|
-
delete bundle[key];
|
|
3069
|
-
break;
|
|
3070
|
-
}
|
|
3071
|
-
}
|
|
3072
|
-
}
|
|
3073
|
-
},
|
|
3074
|
-
{
|
|
3075
|
-
name: "crx:manifest-post",
|
|
3076
|
-
apply: "build",
|
|
3077
|
-
enforce: "post",
|
|
3078
|
-
configResolved(_config) {
|
|
3079
|
-
config = _config;
|
|
3080
|
-
const plugins2 = config.plugins;
|
|
3081
|
-
const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
|
|
3082
|
-
const [plugin] = plugins2.splice(crx, 1);
|
|
3083
|
-
plugins2.push(plugin);
|
|
3084
|
-
},
|
|
3085
|
-
async transform(code, id) {
|
|
3086
|
-
if (id !== manifestId)
|
|
3087
|
-
return;
|
|
3088
|
-
let manifest2 = decodeManifest.call(this, code);
|
|
3089
|
-
for (const plugin of plugins) {
|
|
3090
|
-
try {
|
|
3091
|
-
const m = structuredClone(manifest2);
|
|
3092
|
-
const result = await plugin.transformCrxManifest?.call(this, m);
|
|
3093
|
-
manifest2 = result ?? manifest2;
|
|
3094
|
-
} catch (error) {
|
|
3095
|
-
if (error instanceof Error)
|
|
3096
|
-
error.message = `[${plugin.name}] ${error.message}`;
|
|
3097
|
-
throw error;
|
|
3098
|
-
}
|
|
3099
|
-
}
|
|
3100
|
-
if (manifest2.content_scripts?.length) {
|
|
3101
|
-
manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
|
|
3102
|
-
const refJS = js.map((file) => this.emitFile({
|
|
3103
|
-
type: "chunk",
|
|
3104
|
-
id: file,
|
|
3105
|
-
name: basename(file)
|
|
3106
|
-
}));
|
|
3107
|
-
return { js: refJS, ...rest };
|
|
3108
|
-
});
|
|
3109
|
-
}
|
|
3110
|
-
if (!this.meta.watchMode) {
|
|
3111
|
-
if (manifest2.background?.service_worker) {
|
|
3112
|
-
const file = manifest2.background.service_worker;
|
|
3113
|
-
const refId2 = this.emitFile({
|
|
3114
|
-
type: "chunk",
|
|
3115
|
-
id: file,
|
|
3116
|
-
name: basename(file)
|
|
3117
|
-
});
|
|
3118
|
-
manifest2.background.service_worker = refId2;
|
|
3119
|
-
}
|
|
3120
|
-
for (const file of htmlFiles(manifest2)) {
|
|
3121
|
-
this.emitFile({
|
|
3122
|
-
type: "chunk",
|
|
3123
|
-
id: file,
|
|
3124
|
-
name: basename(file)
|
|
3125
|
-
});
|
|
3126
|
-
}
|
|
3127
|
-
}
|
|
3128
|
-
const encoded = encodeManifest(manifest2);
|
|
3129
|
-
return encoded;
|
|
3130
|
-
},
|
|
3131
|
-
async generateBundle(options, bundle) {
|
|
3132
|
-
const manifestName = this.getFileName(refId);
|
|
3133
|
-
const manifestJs = bundle[manifestName];
|
|
3134
|
-
let manifest2 = decodeManifest.call(this, manifestJs.code);
|
|
3135
|
-
if (manifest2.background?.service_worker && !this.meta.watchMode) {
|
|
3136
|
-
const ref = manifest2.background.service_worker;
|
|
3137
|
-
const name = this.getFileName(ref);
|
|
3138
|
-
manifest2.background.service_worker = name;
|
|
3139
|
-
}
|
|
3140
|
-
manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
|
|
3141
|
-
const refJS = js.map((ref) => this.getFileName(ref));
|
|
3142
|
-
return { js: refJS, ...rest };
|
|
3143
|
-
});
|
|
3144
|
-
manifest2.web_accessible_resources = manifest2.web_accessible_resources?.map(({ resources, ...rest }) => ({
|
|
3145
|
-
resources: resources.map((r) => fg__default["default"].isDynamicPattern(r) || r === dynamicResourcesName ? r : this.getFileName(r)),
|
|
3146
|
-
...rest
|
|
3147
|
-
}));
|
|
3148
|
-
for (const plugin of plugins) {
|
|
3149
|
-
try {
|
|
3150
|
-
const m = structuredClone(manifest2);
|
|
3151
|
-
const result = await plugin.renderCrxManifest?.call(this, m, bundle);
|
|
3152
|
-
manifest2 = result ?? manifest2;
|
|
3153
|
-
} catch (error) {
|
|
3154
|
-
const name = `[${plugin.name}]`;
|
|
3155
|
-
let message = error;
|
|
3156
|
-
if (error instanceof Error) {
|
|
3157
|
-
message = colors__default["default"].red(`${name} ${error.stack ? error.stack : error.message}`);
|
|
3158
|
-
} else if (typeof error === "string") {
|
|
3159
|
-
message = colors__default["default"].red(`${name} ${error}`);
|
|
3160
|
-
}
|
|
3161
|
-
console.log(message);
|
|
3162
|
-
throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
|
|
3163
|
-
}
|
|
3164
|
-
}
|
|
3165
|
-
const assetTypes = [
|
|
3166
|
-
"icons",
|
|
3167
|
-
"locales",
|
|
3168
|
-
"rulesets",
|
|
3169
|
-
"webAccessibleResources"
|
|
3170
|
-
];
|
|
3171
|
-
const files = await manifestFiles(manifest2);
|
|
3172
|
-
await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
|
|
3173
|
-
if (typeof bundle[f] === "undefined") {
|
|
3174
|
-
const filename = join(config.root, f);
|
|
3175
|
-
this.emitFile({
|
|
3176
|
-
type: "asset",
|
|
3177
|
-
fileName: f,
|
|
3178
|
-
source: await fsExtra.readFile(filename)
|
|
3179
|
-
});
|
|
3180
|
-
}
|
|
3181
|
-
}));
|
|
3182
|
-
const manifestJson = bundle["manifest.json"];
|
|
3183
|
-
if (typeof manifestJson === "undefined") {
|
|
3184
|
-
this.emitFile({
|
|
3185
|
-
type: "asset",
|
|
3186
|
-
fileName: "manifest.json",
|
|
3187
|
-
source: JSON.stringify(manifest2, null, 2)
|
|
3188
|
-
});
|
|
3189
|
-
} else {
|
|
3190
|
-
manifestJson.source = JSON.stringify(manifest2, null, 2);
|
|
3191
|
-
}
|
|
3192
|
-
delete bundle[manifestName];
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3195
|
-
];
|
|
3196
|
-
};
|
|
3197
|
-
|
|
3198
3196
|
var workerHmrClient = "const ownOrigin = new URL(chrome.runtime.getURL(\"/\")).origin;\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 }\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 chrome.runtime.reload();\n});\n";
|
|
3199
3197
|
|
|
3200
3198
|
function defineClientValues(code, config) {
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { createHash as createHash$1 } from 'crypto';
|
|
|
4
4
|
import debug$5 from 'debug';
|
|
5
5
|
import fg from 'fast-glob';
|
|
6
6
|
import v8 from 'v8';
|
|
7
|
-
import { readFile,
|
|
7
|
+
import fsExtra, { readFile, readFileSync } from 'fs-extra';
|
|
8
8
|
import MagicString from 'magic-string';
|
|
9
9
|
import { posix } from 'path';
|
|
10
10
|
import { performance } from 'perf_hooks';
|
|
@@ -69,7 +69,7 @@ function htmlFiles(manifest) {
|
|
|
69
69
|
manifest.options_page,
|
|
70
70
|
manifest.options_ui?.page,
|
|
71
71
|
manifest.sandbox?.pages
|
|
72
|
-
].flat().filter(isString).sort();
|
|
72
|
+
].flat().filter(isString).map((s) => s.split("#")[0]).sort();
|
|
73
73
|
return [...new Set(files)];
|
|
74
74
|
}
|
|
75
75
|
function decodeManifest(code) {
|
|
@@ -1949,6 +1949,7 @@ function withLatestFrom() {
|
|
|
1949
1949
|
});
|
|
1950
1950
|
}
|
|
1951
1951
|
|
|
1952
|
+
const { pathExistsSync, outputFile, statSync } = fsExtra;
|
|
1952
1953
|
const debug$3 = _debug("file-writer").extend("events");
|
|
1953
1954
|
const writerEvent$ = new BehaviorSubject({
|
|
1954
1955
|
type: "init"
|
|
@@ -2031,7 +2032,7 @@ const pluginFileWriterEvents = () => {
|
|
|
2031
2032
|
async buildStart(options) {
|
|
2032
2033
|
start = performance.now();
|
|
2033
2034
|
const filename = await triggerName;
|
|
2034
|
-
if (!
|
|
2035
|
+
if (!pathExistsSync(filename)) {
|
|
2035
2036
|
await outputFile(filename, Date.now().toString());
|
|
2036
2037
|
}
|
|
2037
2038
|
this.addWatchFile(filename);
|
|
@@ -2059,7 +2060,7 @@ const pluginFileWriterEvents = () => {
|
|
|
2059
2060
|
};
|
|
2060
2061
|
};
|
|
2061
2062
|
|
|
2062
|
-
var preControllerScript = "
|
|
2063
|
+
var preControllerScript = "const id = setInterval(() => location.reload(), 100);\nsetTimeout(() => clearInterval(id), 5e3);\n";
|
|
2063
2064
|
|
|
2064
2065
|
var preControllerHtml = "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <title>Waiting for the extension service worker...</title>\n <script src=\"%PATH%\"></script>\n </head>\n <body>\n <h1>Waiting for service worker</h1>\n\n <p>\n If you see this message, it means the service worker has not loaded fully.\n </p>\n\n <p>\n During development, the service worker reroutes HTML requests to the dev\n server, so this file isn't used unless the extension service worker opens\n a page immediately after a full extension reload, and before the service\n worker takes control of fetch (e.g., in the onInstalled event). In that\n case, this page will continuously reload until the service worker is\n ready, always less than 100 ms.\n </p>\n\n <p>This page is never added in production.</p>\n </body>\n</html>\n";
|
|
2065
2066
|
|
|
@@ -2511,6 +2512,216 @@ const pluginHtmlAuditor = () => {
|
|
|
2511
2512
|
};
|
|
2512
2513
|
};
|
|
2513
2514
|
|
|
2515
|
+
const pluginManifest = (_manifest) => () => {
|
|
2516
|
+
let manifest;
|
|
2517
|
+
let plugins;
|
|
2518
|
+
let refId;
|
|
2519
|
+
let config;
|
|
2520
|
+
return [
|
|
2521
|
+
{
|
|
2522
|
+
name: "crx:manifest-init",
|
|
2523
|
+
enforce: "pre",
|
|
2524
|
+
async config(config2, env) {
|
|
2525
|
+
manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
|
|
2526
|
+
if (manifest.manifest_version !== 3)
|
|
2527
|
+
throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
|
|
2528
|
+
if (env.command === "serve") {
|
|
2529
|
+
const {
|
|
2530
|
+
contentScripts: js,
|
|
2531
|
+
background: sw,
|
|
2532
|
+
html
|
|
2533
|
+
} = await manifestFiles(manifest);
|
|
2534
|
+
let { entries = [] } = config2.optimizeDeps ?? {};
|
|
2535
|
+
entries = [entries].flat();
|
|
2536
|
+
const set = new Set(entries);
|
|
2537
|
+
for (const x of [...js, ...sw, ...html])
|
|
2538
|
+
set.add(x);
|
|
2539
|
+
return {
|
|
2540
|
+
...config2,
|
|
2541
|
+
optimizeDeps: {
|
|
2542
|
+
...config2.optimizeDeps,
|
|
2543
|
+
entries: [...set]
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2546
|
+
}
|
|
2547
|
+
},
|
|
2548
|
+
buildStart(options) {
|
|
2549
|
+
if (options.plugins)
|
|
2550
|
+
plugins = options.plugins;
|
|
2551
|
+
}
|
|
2552
|
+
},
|
|
2553
|
+
{
|
|
2554
|
+
name: "crx:manifest-loader",
|
|
2555
|
+
apply: "build",
|
|
2556
|
+
enforce: "pre",
|
|
2557
|
+
buildStart() {
|
|
2558
|
+
refId = this.emitFile({
|
|
2559
|
+
type: "chunk",
|
|
2560
|
+
id: manifestId,
|
|
2561
|
+
name: "crx-manifest.js",
|
|
2562
|
+
preserveSignature: "strict"
|
|
2563
|
+
});
|
|
2564
|
+
},
|
|
2565
|
+
resolveId(source) {
|
|
2566
|
+
if (source === manifestId)
|
|
2567
|
+
return manifestId;
|
|
2568
|
+
return null;
|
|
2569
|
+
},
|
|
2570
|
+
load(id) {
|
|
2571
|
+
if (id === manifestId)
|
|
2572
|
+
return encodeManifest(manifest);
|
|
2573
|
+
return null;
|
|
2574
|
+
}
|
|
2575
|
+
},
|
|
2576
|
+
{
|
|
2577
|
+
name: "crx:stub-input",
|
|
2578
|
+
apply: "build",
|
|
2579
|
+
enforce: "pre",
|
|
2580
|
+
options({ input, ...options }) {
|
|
2581
|
+
return {
|
|
2582
|
+
input: isString(input) && input.endsWith("index.html") ? stubId : input,
|
|
2583
|
+
...options
|
|
2584
|
+
};
|
|
2585
|
+
},
|
|
2586
|
+
resolveId(source) {
|
|
2587
|
+
if (source === stubId)
|
|
2588
|
+
return stubId;
|
|
2589
|
+
return null;
|
|
2590
|
+
},
|
|
2591
|
+
load(id) {
|
|
2592
|
+
if (id === stubId)
|
|
2593
|
+
return `console.log('stub')`;
|
|
2594
|
+
return null;
|
|
2595
|
+
},
|
|
2596
|
+
generateBundle(options, bundle) {
|
|
2597
|
+
for (const [key, chunk] of Object.entries(bundle)) {
|
|
2598
|
+
if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
|
|
2599
|
+
delete bundle[key];
|
|
2600
|
+
break;
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
},
|
|
2605
|
+
{
|
|
2606
|
+
name: "crx:manifest-post",
|
|
2607
|
+
apply: "build",
|
|
2608
|
+
enforce: "post",
|
|
2609
|
+
configResolved(_config) {
|
|
2610
|
+
config = _config;
|
|
2611
|
+
const plugins2 = config.plugins;
|
|
2612
|
+
const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
|
|
2613
|
+
const [plugin] = plugins2.splice(crx, 1);
|
|
2614
|
+
plugins2.push(plugin);
|
|
2615
|
+
},
|
|
2616
|
+
async transform(code, id) {
|
|
2617
|
+
if (id !== manifestId)
|
|
2618
|
+
return;
|
|
2619
|
+
let manifest2 = decodeManifest.call(this, code);
|
|
2620
|
+
for (const plugin of plugins) {
|
|
2621
|
+
try {
|
|
2622
|
+
const m = structuredClone(manifest2);
|
|
2623
|
+
const result = await plugin.transformCrxManifest?.call(this, m);
|
|
2624
|
+
manifest2 = result ?? manifest2;
|
|
2625
|
+
} catch (error) {
|
|
2626
|
+
if (error instanceof Error)
|
|
2627
|
+
error.message = `[${plugin.name}] ${error.message}`;
|
|
2628
|
+
throw error;
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
if (manifest2.content_scripts?.length) {
|
|
2632
|
+
manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
|
|
2633
|
+
const refJS = js.map((file) => this.emitFile({
|
|
2634
|
+
type: "chunk",
|
|
2635
|
+
id: file,
|
|
2636
|
+
name: basename(file)
|
|
2637
|
+
}));
|
|
2638
|
+
return { js: refJS, ...rest };
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
if (!this.meta.watchMode) {
|
|
2642
|
+
if (manifest2.background?.service_worker) {
|
|
2643
|
+
const file = manifest2.background.service_worker;
|
|
2644
|
+
const refId2 = this.emitFile({
|
|
2645
|
+
type: "chunk",
|
|
2646
|
+
id: file,
|
|
2647
|
+
name: basename(file)
|
|
2648
|
+
});
|
|
2649
|
+
manifest2.background.service_worker = refId2;
|
|
2650
|
+
}
|
|
2651
|
+
for (const file of htmlFiles(manifest2)) {
|
|
2652
|
+
this.emitFile({
|
|
2653
|
+
type: "chunk",
|
|
2654
|
+
id: file,
|
|
2655
|
+
name: basename(file)
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
const encoded = encodeManifest(manifest2);
|
|
2660
|
+
return encoded;
|
|
2661
|
+
},
|
|
2662
|
+
async generateBundle(options, bundle) {
|
|
2663
|
+
const manifestName = this.getFileName(refId);
|
|
2664
|
+
const manifestJs = bundle[manifestName];
|
|
2665
|
+
let manifest2 = decodeManifest.call(this, manifestJs.code);
|
|
2666
|
+
if (manifest2.background?.service_worker && !this.meta.watchMode) {
|
|
2667
|
+
const ref = manifest2.background.service_worker;
|
|
2668
|
+
const name = this.getFileName(ref);
|
|
2669
|
+
manifest2.background.service_worker = name;
|
|
2670
|
+
}
|
|
2671
|
+
manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
|
|
2672
|
+
const refJS = js.map((ref) => this.getFileName(ref));
|
|
2673
|
+
return { js: refJS, ...rest };
|
|
2674
|
+
});
|
|
2675
|
+
for (const plugin of plugins) {
|
|
2676
|
+
try {
|
|
2677
|
+
const m = structuredClone(manifest2);
|
|
2678
|
+
const result = await plugin.renderCrxManifest?.call(this, m, bundle);
|
|
2679
|
+
manifest2 = result ?? manifest2;
|
|
2680
|
+
} catch (error) {
|
|
2681
|
+
const name = `[${plugin.name}]`;
|
|
2682
|
+
let message = error;
|
|
2683
|
+
if (error instanceof Error) {
|
|
2684
|
+
message = colors.red(`${name} ${error.stack ? error.stack : error.message}`);
|
|
2685
|
+
} else if (typeof error === "string") {
|
|
2686
|
+
message = colors.red(`${name} ${error}`);
|
|
2687
|
+
}
|
|
2688
|
+
console.log(message);
|
|
2689
|
+
throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
const assetTypes = [
|
|
2693
|
+
"icons",
|
|
2694
|
+
"locales",
|
|
2695
|
+
"rulesets",
|
|
2696
|
+
"webAccessibleResources"
|
|
2697
|
+
];
|
|
2698
|
+
const files = await manifestFiles(manifest2);
|
|
2699
|
+
await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
|
|
2700
|
+
if (typeof bundle[f] === "undefined") {
|
|
2701
|
+
const filename = join(config.root, f);
|
|
2702
|
+
this.emitFile({
|
|
2703
|
+
type: "asset",
|
|
2704
|
+
fileName: f,
|
|
2705
|
+
source: await readFile(filename)
|
|
2706
|
+
});
|
|
2707
|
+
}
|
|
2708
|
+
}));
|
|
2709
|
+
const manifestJson = bundle["manifest.json"];
|
|
2710
|
+
if (typeof manifestJson === "undefined") {
|
|
2711
|
+
this.emitFile({
|
|
2712
|
+
type: "asset",
|
|
2713
|
+
fileName: "manifest.json",
|
|
2714
|
+
source: JSON.stringify(manifest2, null, 2)
|
|
2715
|
+
});
|
|
2716
|
+
} else {
|
|
2717
|
+
manifestJson.source = JSON.stringify(manifest2, null, 2);
|
|
2718
|
+
}
|
|
2719
|
+
delete bundle[manifestName];
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
];
|
|
2723
|
+
};
|
|
2724
|
+
|
|
2514
2725
|
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";
|
|
2515
2726
|
|
|
2516
2727
|
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";
|
|
@@ -2949,220 +3160,6 @@ const pluginResources = ({ contentScripts = {} }) => {
|
|
|
2949
3160
|
];
|
|
2950
3161
|
};
|
|
2951
3162
|
|
|
2952
|
-
const pluginManifest = (_manifest) => () => {
|
|
2953
|
-
let manifest;
|
|
2954
|
-
let plugins;
|
|
2955
|
-
let refId;
|
|
2956
|
-
let config;
|
|
2957
|
-
return [
|
|
2958
|
-
{
|
|
2959
|
-
name: "crx:manifest-init",
|
|
2960
|
-
enforce: "pre",
|
|
2961
|
-
async config(config2, env) {
|
|
2962
|
-
manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
|
|
2963
|
-
if (manifest.manifest_version !== 3)
|
|
2964
|
-
throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
|
|
2965
|
-
if (env.command === "serve") {
|
|
2966
|
-
const {
|
|
2967
|
-
contentScripts: js,
|
|
2968
|
-
background: sw,
|
|
2969
|
-
html
|
|
2970
|
-
} = await manifestFiles(manifest);
|
|
2971
|
-
let { entries = [] } = config2.optimizeDeps ?? {};
|
|
2972
|
-
entries = [entries].flat();
|
|
2973
|
-
const set = new Set(entries);
|
|
2974
|
-
for (const x of [...js, ...sw, ...html])
|
|
2975
|
-
set.add(x);
|
|
2976
|
-
return {
|
|
2977
|
-
...config2,
|
|
2978
|
-
optimizeDeps: {
|
|
2979
|
-
...config2.optimizeDeps,
|
|
2980
|
-
entries: [...set]
|
|
2981
|
-
}
|
|
2982
|
-
};
|
|
2983
|
-
}
|
|
2984
|
-
},
|
|
2985
|
-
buildStart(options) {
|
|
2986
|
-
if (options.plugins)
|
|
2987
|
-
plugins = options.plugins;
|
|
2988
|
-
}
|
|
2989
|
-
},
|
|
2990
|
-
{
|
|
2991
|
-
name: "crx:manifest-loader",
|
|
2992
|
-
apply: "build",
|
|
2993
|
-
enforce: "pre",
|
|
2994
|
-
buildStart() {
|
|
2995
|
-
refId = this.emitFile({
|
|
2996
|
-
type: "chunk",
|
|
2997
|
-
id: manifestId,
|
|
2998
|
-
name: "crx-manifest.js",
|
|
2999
|
-
preserveSignature: "strict"
|
|
3000
|
-
});
|
|
3001
|
-
},
|
|
3002
|
-
resolveId(source) {
|
|
3003
|
-
if (source === manifestId)
|
|
3004
|
-
return manifestId;
|
|
3005
|
-
return null;
|
|
3006
|
-
},
|
|
3007
|
-
load(id) {
|
|
3008
|
-
if (id === manifestId)
|
|
3009
|
-
return encodeManifest(manifest);
|
|
3010
|
-
return null;
|
|
3011
|
-
}
|
|
3012
|
-
},
|
|
3013
|
-
{
|
|
3014
|
-
name: "crx:stub-input",
|
|
3015
|
-
apply: "build",
|
|
3016
|
-
enforce: "pre",
|
|
3017
|
-
options({ input, ...options }) {
|
|
3018
|
-
return {
|
|
3019
|
-
input: isString(input) && input.endsWith("index.html") ? stubId : input,
|
|
3020
|
-
...options
|
|
3021
|
-
};
|
|
3022
|
-
},
|
|
3023
|
-
resolveId(source) {
|
|
3024
|
-
if (source === stubId)
|
|
3025
|
-
return stubId;
|
|
3026
|
-
return null;
|
|
3027
|
-
},
|
|
3028
|
-
load(id) {
|
|
3029
|
-
if (id === stubId)
|
|
3030
|
-
return `console.log('stub')`;
|
|
3031
|
-
return null;
|
|
3032
|
-
},
|
|
3033
|
-
generateBundle(options, bundle) {
|
|
3034
|
-
for (const [key, chunk] of Object.entries(bundle)) {
|
|
3035
|
-
if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
|
|
3036
|
-
delete bundle[key];
|
|
3037
|
-
break;
|
|
3038
|
-
}
|
|
3039
|
-
}
|
|
3040
|
-
}
|
|
3041
|
-
},
|
|
3042
|
-
{
|
|
3043
|
-
name: "crx:manifest-post",
|
|
3044
|
-
apply: "build",
|
|
3045
|
-
enforce: "post",
|
|
3046
|
-
configResolved(_config) {
|
|
3047
|
-
config = _config;
|
|
3048
|
-
const plugins2 = config.plugins;
|
|
3049
|
-
const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
|
|
3050
|
-
const [plugin] = plugins2.splice(crx, 1);
|
|
3051
|
-
plugins2.push(plugin);
|
|
3052
|
-
},
|
|
3053
|
-
async transform(code, id) {
|
|
3054
|
-
if (id !== manifestId)
|
|
3055
|
-
return;
|
|
3056
|
-
let manifest2 = decodeManifest.call(this, code);
|
|
3057
|
-
for (const plugin of plugins) {
|
|
3058
|
-
try {
|
|
3059
|
-
const m = structuredClone(manifest2);
|
|
3060
|
-
const result = await plugin.transformCrxManifest?.call(this, m);
|
|
3061
|
-
manifest2 = result ?? manifest2;
|
|
3062
|
-
} catch (error) {
|
|
3063
|
-
if (error instanceof Error)
|
|
3064
|
-
error.message = `[${plugin.name}] ${error.message}`;
|
|
3065
|
-
throw error;
|
|
3066
|
-
}
|
|
3067
|
-
}
|
|
3068
|
-
if (manifest2.content_scripts?.length) {
|
|
3069
|
-
manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
|
|
3070
|
-
const refJS = js.map((file) => this.emitFile({
|
|
3071
|
-
type: "chunk",
|
|
3072
|
-
id: file,
|
|
3073
|
-
name: basename(file)
|
|
3074
|
-
}));
|
|
3075
|
-
return { js: refJS, ...rest };
|
|
3076
|
-
});
|
|
3077
|
-
}
|
|
3078
|
-
if (!this.meta.watchMode) {
|
|
3079
|
-
if (manifest2.background?.service_worker) {
|
|
3080
|
-
const file = manifest2.background.service_worker;
|
|
3081
|
-
const refId2 = this.emitFile({
|
|
3082
|
-
type: "chunk",
|
|
3083
|
-
id: file,
|
|
3084
|
-
name: basename(file)
|
|
3085
|
-
});
|
|
3086
|
-
manifest2.background.service_worker = refId2;
|
|
3087
|
-
}
|
|
3088
|
-
for (const file of htmlFiles(manifest2)) {
|
|
3089
|
-
this.emitFile({
|
|
3090
|
-
type: "chunk",
|
|
3091
|
-
id: file,
|
|
3092
|
-
name: basename(file)
|
|
3093
|
-
});
|
|
3094
|
-
}
|
|
3095
|
-
}
|
|
3096
|
-
const encoded = encodeManifest(manifest2);
|
|
3097
|
-
return encoded;
|
|
3098
|
-
},
|
|
3099
|
-
async generateBundle(options, bundle) {
|
|
3100
|
-
const manifestName = this.getFileName(refId);
|
|
3101
|
-
const manifestJs = bundle[manifestName];
|
|
3102
|
-
let manifest2 = decodeManifest.call(this, manifestJs.code);
|
|
3103
|
-
if (manifest2.background?.service_worker && !this.meta.watchMode) {
|
|
3104
|
-
const ref = manifest2.background.service_worker;
|
|
3105
|
-
const name = this.getFileName(ref);
|
|
3106
|
-
manifest2.background.service_worker = name;
|
|
3107
|
-
}
|
|
3108
|
-
manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
|
|
3109
|
-
const refJS = js.map((ref) => this.getFileName(ref));
|
|
3110
|
-
return { js: refJS, ...rest };
|
|
3111
|
-
});
|
|
3112
|
-
manifest2.web_accessible_resources = manifest2.web_accessible_resources?.map(({ resources, ...rest }) => ({
|
|
3113
|
-
resources: resources.map((r) => fg.isDynamicPattern(r) || r === dynamicResourcesName ? r : this.getFileName(r)),
|
|
3114
|
-
...rest
|
|
3115
|
-
}));
|
|
3116
|
-
for (const plugin of plugins) {
|
|
3117
|
-
try {
|
|
3118
|
-
const m = structuredClone(manifest2);
|
|
3119
|
-
const result = await plugin.renderCrxManifest?.call(this, m, bundle);
|
|
3120
|
-
manifest2 = result ?? manifest2;
|
|
3121
|
-
} catch (error) {
|
|
3122
|
-
const name = `[${plugin.name}]`;
|
|
3123
|
-
let message = error;
|
|
3124
|
-
if (error instanceof Error) {
|
|
3125
|
-
message = colors.red(`${name} ${error.stack ? error.stack : error.message}`);
|
|
3126
|
-
} else if (typeof error === "string") {
|
|
3127
|
-
message = colors.red(`${name} ${error}`);
|
|
3128
|
-
}
|
|
3129
|
-
console.log(message);
|
|
3130
|
-
throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
|
|
3131
|
-
}
|
|
3132
|
-
}
|
|
3133
|
-
const assetTypes = [
|
|
3134
|
-
"icons",
|
|
3135
|
-
"locales",
|
|
3136
|
-
"rulesets",
|
|
3137
|
-
"webAccessibleResources"
|
|
3138
|
-
];
|
|
3139
|
-
const files = await manifestFiles(manifest2);
|
|
3140
|
-
await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
|
|
3141
|
-
if (typeof bundle[f] === "undefined") {
|
|
3142
|
-
const filename = join(config.root, f);
|
|
3143
|
-
this.emitFile({
|
|
3144
|
-
type: "asset",
|
|
3145
|
-
fileName: f,
|
|
3146
|
-
source: await readFile(filename)
|
|
3147
|
-
});
|
|
3148
|
-
}
|
|
3149
|
-
}));
|
|
3150
|
-
const manifestJson = bundle["manifest.json"];
|
|
3151
|
-
if (typeof manifestJson === "undefined") {
|
|
3152
|
-
this.emitFile({
|
|
3153
|
-
type: "asset",
|
|
3154
|
-
fileName: "manifest.json",
|
|
3155
|
-
source: JSON.stringify(manifest2, null, 2)
|
|
3156
|
-
});
|
|
3157
|
-
} else {
|
|
3158
|
-
manifestJson.source = JSON.stringify(manifest2, null, 2);
|
|
3159
|
-
}
|
|
3160
|
-
delete bundle[manifestName];
|
|
3161
|
-
}
|
|
3162
|
-
}
|
|
3163
|
-
];
|
|
3164
|
-
};
|
|
3165
|
-
|
|
3166
3163
|
var workerHmrClient = "const ownOrigin = new URL(chrome.runtime.getURL(\"/\")).origin;\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 }\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 chrome.runtime.reload();\n});\n";
|
|
3167
3164
|
|
|
3168
3165
|
function defineClientValues(code, config) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crxjs/vite-plugin",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Build Chrome Extensions with this Vite plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rollup-plugin",
|
|
@@ -72,17 +72,17 @@
|
|
|
72
72
|
"jsesc": "^3.0.2",
|
|
73
73
|
"magic-string": "^0.26.0",
|
|
74
74
|
"picocolors": "^1.0.0",
|
|
75
|
-
"react-refresh": "^0.
|
|
75
|
+
"react-refresh": "^0.13.0",
|
|
76
76
|
"rollup": "^2.70.2"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@extend-chrome/messages": "1.2.2",
|
|
80
80
|
"@extend-chrome/storage": "1.5.0",
|
|
81
81
|
"@rollup/plugin-alias": "3.1.9",
|
|
82
|
-
"@rollup/plugin-commonjs": "21.0
|
|
82
|
+
"@rollup/plugin-commonjs": "21.1.0",
|
|
83
83
|
"@rollup/plugin-node-resolve": "13.2.0",
|
|
84
84
|
"@types/acorn": "4.0.6",
|
|
85
|
-
"@types/chrome": "0.0.
|
|
85
|
+
"@types/chrome": "0.0.183",
|
|
86
86
|
"@types/debug": "4.1.7",
|
|
87
87
|
"@types/fs-extra": "9.0.13",
|
|
88
88
|
"@types/jest": "27.4.1",
|
|
@@ -90,28 +90,25 @@
|
|
|
90
90
|
"@types/jsesc": "3.0.1",
|
|
91
91
|
"@types/node": "17.0.18",
|
|
92
92
|
"@types/react": "17.0.44",
|
|
93
|
-
"@types/react-dom": "17.0.
|
|
94
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
95
|
-
"@typescript-eslint/parser": "5.
|
|
93
|
+
"@types/react-dom": "17.0.16",
|
|
94
|
+
"@typescript-eslint/eslint-plugin": "5.21.0",
|
|
95
|
+
"@typescript-eslint/parser": "5.21.0",
|
|
96
96
|
"@vitejs/plugin-react": "1.3.1",
|
|
97
97
|
"@vitejs/plugin-vue": "2.3.1",
|
|
98
|
-
"
|
|
99
|
-
"@vueuse/core": "7.6.2",
|
|
100
|
-
"@vueuse/router": "8.2.6",
|
|
101
|
-
"esbuild": "0.14.23",
|
|
98
|
+
"esbuild": "0.14.38",
|
|
102
99
|
"esbuild-runner": "2.2.1",
|
|
100
|
+
"eslint": "^8.14.0",
|
|
103
101
|
"jest": "27.5.1",
|
|
104
102
|
"jest-image-snapshot": "4.5.1",
|
|
105
|
-
"playwright-chromium": "1.21.
|
|
103
|
+
"playwright-chromium": "1.21.1",
|
|
106
104
|
"react": "17.0.2",
|
|
107
105
|
"react-dom": "17.0.2",
|
|
108
106
|
"rimraf": "3.0.2",
|
|
109
107
|
"rollup-plugin-dts": "^4.2.0",
|
|
110
108
|
"rollup-plugin-esbuild": "4.9.1",
|
|
111
109
|
"rxjs": "7.5.5",
|
|
112
|
-
"typescript": "4.6.3",
|
|
113
110
|
"vite": "^2.9.5",
|
|
114
|
-
"vite-plugin-inspect": "0.
|
|
111
|
+
"vite-plugin-inspect": "0.5.0",
|
|
115
112
|
"vue": "3.2.33"
|
|
116
113
|
},
|
|
117
114
|
"peerDependencies": {
|