extension-develop 4.1.31 → 4.1.32
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 +2 -0
- package/dist/105~0.mjs +1 -1
- package/dist/177~0.mjs +87 -19
- package/dist/273~0.mjs +13 -3
- package/dist/363~0.mjs +1874 -0
- package/dist/{896~0.mjs → 469~0.mjs} +116 -586
- package/dist/519~0.mjs +21 -8
- package/dist/616~0.mjs +1 -1
- package/dist/771~0.mjs +103 -0
- package/dist/832~0.mjs +229 -463
- package/dist/840~0.mjs +1189 -54
- package/dist/846~0.mjs +453 -0
- package/dist/852~0.mjs +8 -6
- package/dist/bridge.mjs +3 -2
- package/dist/command-preview.d.ts +1 -0
- package/dist/contract/codes.json +39 -29
- package/dist/contract/envelope.schema.json +16 -0
- package/dist/contract/golden.build.compile.json +20 -3
- package/dist/contract/golden.eval.csp-blocks-eval.page.json +15 -0
- package/dist/css-parse-guard-loader.mjs +3 -1
- package/dist/dead-css-url-loader.mjs +129 -13
- package/dist/dev-server/cleanup.d.ts +1 -1
- package/dist/dev-server/lifecycle-stream.d.ts +14 -3
- package/dist/dev-server/session-start-prune.d.ts +13 -0
- package/dist/dev-server~0.mjs +91 -14
- package/dist/ensure-hmr-for-scripts.js +4 -8
- package/dist/ensure-hmr-for-scripts.mjs +4 -8
- package/dist/extension-js-devtools/build-stamp.json +2 -2
- package/dist/extension-js-theme/build-stamp.json +2 -2
- package/dist/feature-scripts-content-script-wrapper.js +7 -4
- package/dist/feature-scripts-content-script-wrapper.mjs +7 -4
- package/dist/lib/build-summary.d.ts +4 -1
- package/dist/lib/coded-warnings.d.ts +3 -0
- package/dist/lib/compilation-diagnostics.d.ts +23 -0
- package/dist/lib/config-loader.d.ts +2 -2
- package/dist/lib/config-resolved-plugin.d.ts +3 -2
- package/dist/lib/corepack-registry.d.ts +3 -0
- package/dist/lib/diagnostic-code.d.ts +6 -0
- package/dist/lib/merge-options.d.ts +1 -0
- package/dist/lib/messages.d.ts +4 -1
- package/dist/lib/messaging.d.ts +12 -4
- package/dist/lib/output-files.d.ts +11 -0
- package/dist/lib/package-manager.d.ts +2 -2
- package/dist/module.mjs +2 -1
- package/dist/plugin-browsers/index.d.ts +1 -0
- package/dist/plugin-compatibility/compatibility-lib/free-browser-references.d.ts +9 -0
- package/dist/plugin-css/css-lib/dead-url-refs.d.ts +5 -1
- package/dist/plugin-css/css-lib/inline-content-script-css.d.ts +4 -2
- package/dist/plugin-css/css-lib/line-rewrite-source-map.d.ts +8 -0
- package/dist/plugin-css/dead-css-url-loader.d.ts +0 -2
- package/dist/plugin-css/public-css-url-loader.d.ts +8 -3
- package/dist/plugin-playwright/index.d.ts +9 -4
- package/dist/plugin-reload/classify-reload.d.ts +2 -0
- package/dist/plugin-reload/messages.d.ts +1 -0
- package/dist/plugin-reload/reload-lib/dev-content-scripts.d.ts +4 -0
- package/dist/plugin-reload/steps/prune-unreachable-chunks.d.ts +5 -0
- package/dist/plugin-special-folders/messages.d.ts +1 -1
- package/dist/plugin-special-folders/prune-removed-public-files.d.ts +7 -0
- package/dist/plugin-static-assets/check-namespace-imports.d.ts +4 -0
- package/dist/plugin-static-assets/static-assets-lib/asset-output-name.d.ts +8 -0
- package/dist/plugin-static-assets/static-assets-lib/messages.d.ts +1 -0
- package/dist/plugin-web-extension/feature-html/html-lib/utils.d.ts +2 -1
- package/dist/plugin-web-extension/feature-icons/messages.d.ts +1 -4
- package/dist/plugin-web-extension/feature-locales/get-locales.d.ts +2 -0
- package/dist/plugin-web-extension/feature-locales/messages.d.ts +3 -1
- package/dist/plugin-web-extension/feature-locales/validation.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/manifest-lib/filter-keys-safari.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/manifest-overrides/common/content_scripts.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/messages.d.ts +1 -0
- package/dist/plugin-web-extension/feature-scripts/index.d.ts +2 -0
- package/dist/plugin-web-extension/feature-scripts/messages.d.ts +4 -3
- package/dist/plugin-web-extension/feature-scripts/scripts-lib/load-time-constants.d.ts +11 -0
- package/dist/plugin-web-extension/feature-scripts/steps/trace-runtime-loaded-files.d.ts +4 -0
- package/dist/plugin-web-extension/feature-scripts/steps/warn-missing-build-constants.d.ts +24 -0
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/declared-pages.d.ts +2 -0
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/resolve-war.d.ts +5 -0
- package/dist/plugin-web-extension/index.d.ts +1 -0
- package/dist/plugin-web-extension/shared/classic-concat.d.ts +1 -0
- package/dist/plugin-web-extension/shared/compilation-issues.d.ts +1 -1
- package/dist/preprocessor-passthrough-loader.mjs +3 -1
- package/dist/public-css-url-loader.mjs +1 -1
- package/dist/rspack-config~0.mjs +4925 -5885
- package/dist/stats-handler~0.mjs +12 -4
- package/dist/types.d.ts +19 -2
- package/dist/zip~0.mjs +20 -2
- package/package.json +4 -4
- package/dist/300~0.mjs +0 -394
- package/dist/747~0.mjs +0 -90
package/dist/363~0.mjs
ADDED
|
@@ -0,0 +1,1874 @@
|
|
|
1
|
+
import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
|
|
2
|
+
import { Compilation, DefinePlugin, ProvidePlugin, WebpackError, sources } from "@rspack/core";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import pintor from "pintor";
|
|
5
|
+
import { publicRelativePath, findPublicFile, inspectPublicFolders } from "./105~0.mjs";
|
|
6
|
+
import { isChromiumBasedBrowser, CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, isWebkitBasedBrowser, stripBom, parseJsonSafe, isGeckoBasedBrowser } from "./937~0.mjs";
|
|
7
|
+
import { parseCanonicalContentScriptAsset, getCanonicalContentScriptJsAssetName, getCanonicalContentScriptCssAssetName } from "./640~0.mjs";
|
|
8
|
+
import { debugLine, isDebug, humanLine, prefix as messaging_prefix } from "./852~0.mjs";
|
|
9
|
+
import { filterKeysForThisBrowser } from "./143~0.mjs";
|
|
10
|
+
import { displayPath } from "./469~0.mjs";
|
|
11
|
+
import { getPreloadedEnvKeys } from "./846~0.mjs";
|
|
12
|
+
import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
|
|
13
|
+
import { dirname as __rspack_dirname } from "node:path";
|
|
14
|
+
var __rspack_import_meta_dirname__ = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
|
|
15
|
+
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
16
|
+
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
17
|
+
import * as __rspack_external_dotenv from "dotenv";
|
|
18
|
+
const ACTION_HTML_FEATURE = 'action/index';
|
|
19
|
+
const BROWSER_ACTION_HTML_FEATURE = 'browser_action/index';
|
|
20
|
+
const PAGE_ACTION_HTML_FEATURE = 'page_action/index';
|
|
21
|
+
const OPTIONS_HTML_FEATURE = 'options/index';
|
|
22
|
+
const SIDEBAR_HTML_FEATURE = 'sidebar/index';
|
|
23
|
+
const SIDEBAR_ACTION_HTML_FEATURE = 'sidebar_action/index';
|
|
24
|
+
const ACTION_HTML_OUTPUT = 'action/index.html';
|
|
25
|
+
const BROWSER_ACTION_HTML_OUTPUT = 'browser_action/index.html';
|
|
26
|
+
const PAGE_ACTION_HTML_OUTPUT = 'page_action/index.html';
|
|
27
|
+
const SIDEBAR_HTML_OUTPUT = 'sidebar/index.html';
|
|
28
|
+
const SIDEBAR_ACTION_HTML_OUTPUT = 'sidebar_action/index.html';
|
|
29
|
+
function readPageRef(value, key) {
|
|
30
|
+
if (!value || 'object' != typeof value || Array.isArray(value)) return;
|
|
31
|
+
const page = value[key];
|
|
32
|
+
if ('string' != typeof page) return;
|
|
33
|
+
const trimmed = page.trim();
|
|
34
|
+
return trimmed || void 0;
|
|
35
|
+
}
|
|
36
|
+
function readDefaultPopup(value) {
|
|
37
|
+
return readPageRef(value, 'default_popup');
|
|
38
|
+
}
|
|
39
|
+
function normalizePopupRef(ref) {
|
|
40
|
+
return String(ref || '').replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\/+/, '');
|
|
41
|
+
}
|
|
42
|
+
function popupRefsShareSource(a, b) {
|
|
43
|
+
if ('string' != typeof a || 'string' != typeof b) return false;
|
|
44
|
+
const left = normalizePopupRef(a);
|
|
45
|
+
const right = normalizePopupRef(b);
|
|
46
|
+
return Boolean(left) && left === right;
|
|
47
|
+
}
|
|
48
|
+
function resolveManifestHtmlPath(context, relativePath, projectPath) {
|
|
49
|
+
const unix = relativePath.replace(/\\/g, '/');
|
|
50
|
+
const manifestPath = __rspack_external_node_path_806ed179.join(context, 'manifest.json');
|
|
51
|
+
const hosted = findPublicFile(manifestPath, projectPath, unix);
|
|
52
|
+
if (/^(?:\/public\/|(?:\.\/)?public\/)/i.test(unix)) return hosted || __rspack_external_node_path_806ed179.join(context, 'public', publicRelativePath(unix));
|
|
53
|
+
const beside = /^\//.test(unix) ? __rspack_external_node_path_806ed179.join(context, unix.slice(1)) : __rspack_external_node_path_806ed179.join(context, unix);
|
|
54
|
+
if (hosted && !__rspack_external_node_fs_1b05aee1.existsSync(beside)) return hosted;
|
|
55
|
+
return beside;
|
|
56
|
+
}
|
|
57
|
+
function actionPopupRef(manifest) {
|
|
58
|
+
if (!manifest) return;
|
|
59
|
+
return readDefaultPopup(manifest.action) || readDefaultPopup(manifest.browser_action);
|
|
60
|
+
}
|
|
61
|
+
function browserActionOwnPopupRef(manifest) {
|
|
62
|
+
if (!manifest) return;
|
|
63
|
+
const action = readDefaultPopup(manifest.action);
|
|
64
|
+
const browserAction = readDefaultPopup(manifest.browser_action);
|
|
65
|
+
if (!action || !browserAction) return;
|
|
66
|
+
if (popupRefsShareSource(action, browserAction)) return;
|
|
67
|
+
return browserAction;
|
|
68
|
+
}
|
|
69
|
+
function browserActionOutputTarget(manifest) {
|
|
70
|
+
return browserActionOwnPopupRef(manifest) ? BROWSER_ACTION_HTML_OUTPUT : ACTION_HTML_OUTPUT;
|
|
71
|
+
}
|
|
72
|
+
function pageActionPopupRef(manifest) {
|
|
73
|
+
if (!manifest) return;
|
|
74
|
+
return readDefaultPopup(manifest.page_action);
|
|
75
|
+
}
|
|
76
|
+
function sidebarPanelRef(manifest) {
|
|
77
|
+
if (!manifest) return;
|
|
78
|
+
return readPageRef(manifest.side_panel, 'default_path') || readPageRef(manifest.sidebar_action, 'default_panel');
|
|
79
|
+
}
|
|
80
|
+
function sidebarActionOwnPanelRef(manifest) {
|
|
81
|
+
if (!manifest) return;
|
|
82
|
+
const sidePanel = readPageRef(manifest.side_panel, 'default_path');
|
|
83
|
+
const sidebarAction = readPageRef(manifest.sidebar_action, 'default_panel');
|
|
84
|
+
if (!sidePanel || !sidebarAction) return;
|
|
85
|
+
if (popupRefsShareSource(sidePanel, sidebarAction)) return;
|
|
86
|
+
return sidebarAction;
|
|
87
|
+
}
|
|
88
|
+
function sidebarActionOutputTarget(manifest) {
|
|
89
|
+
return sidebarActionOwnPanelRef(manifest) ? SIDEBAR_ACTION_HTML_OUTPUT : SIDEBAR_HTML_OUTPUT;
|
|
90
|
+
}
|
|
91
|
+
function optionsPageRef(manifest) {
|
|
92
|
+
if (!manifest) return;
|
|
93
|
+
const modern = manifest.options_ui?.page;
|
|
94
|
+
if ('string' == typeof modern && modern.trim()) return modern.trim();
|
|
95
|
+
const legacy = manifest.options_page;
|
|
96
|
+
if ('string' == typeof legacy && legacy.trim()) return legacy.trim();
|
|
97
|
+
}
|
|
98
|
+
function isPageActionLiveSurface(manifest, browser) {
|
|
99
|
+
if (isGeckoBasedBrowser(String(browser || ''))) return true;
|
|
100
|
+
const version = Number(manifest?.manifest_version);
|
|
101
|
+
return Number.isFinite(version) && version < 3;
|
|
102
|
+
}
|
|
103
|
+
function pageActionDropReason(manifest, browser) {
|
|
104
|
+
if (!manifest || 'object' != typeof manifest) return;
|
|
105
|
+
if (!('page_action' in manifest) || null == manifest.page_action) return;
|
|
106
|
+
if (!isPageActionLiveSurface(manifest, browser)) return 'unsupported';
|
|
107
|
+
if (isChromiumBasedBrowser(String(browser || '')) && (null != manifest.browser_action || shouldFoldActionIntoBrowserAction(manifest))) return 'conflicts';
|
|
108
|
+
}
|
|
109
|
+
function shouldDropPageAction(manifest, browser) {
|
|
110
|
+
return void 0 !== pageActionDropReason(manifest, browser);
|
|
111
|
+
}
|
|
112
|
+
function dropPageAction(manifest) {
|
|
113
|
+
if (!manifest || !('page_action' in manifest)) return manifest;
|
|
114
|
+
const rest = {
|
|
115
|
+
...manifest
|
|
116
|
+
};
|
|
117
|
+
delete rest.page_action;
|
|
118
|
+
return rest;
|
|
119
|
+
}
|
|
120
|
+
function isBrowserActionLiveSurface(manifest) {
|
|
121
|
+
const version = Number(manifest?.manifest_version);
|
|
122
|
+
return !Number.isFinite(version) || version < 3;
|
|
123
|
+
}
|
|
124
|
+
function shouldFoldBrowserActionIntoAction(manifest) {
|
|
125
|
+
if (!manifest || 'object' != typeof manifest) return false;
|
|
126
|
+
if (!('browser_action' in manifest) || null == manifest.browser_action) return false;
|
|
127
|
+
if (isBrowserActionLiveSurface(manifest)) return false;
|
|
128
|
+
return null == manifest.action;
|
|
129
|
+
}
|
|
130
|
+
function foldBrowserActionIntoAction(manifest) {
|
|
131
|
+
if (!shouldFoldBrowserActionIntoAction(manifest)) return manifest;
|
|
132
|
+
const { browser_action: folded, ...rest } = manifest;
|
|
133
|
+
return {
|
|
134
|
+
...rest,
|
|
135
|
+
action: folded
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function shouldFoldActionIntoBrowserAction(manifest) {
|
|
139
|
+
if (!manifest || 'object' != typeof manifest) return false;
|
|
140
|
+
if (!('action' in manifest) || null == manifest.action) return false;
|
|
141
|
+
const version = Number(manifest.manifest_version);
|
|
142
|
+
if (2 !== version) return false;
|
|
143
|
+
return null == manifest.browser_action;
|
|
144
|
+
}
|
|
145
|
+
function foldActionIntoBrowserAction(manifest) {
|
|
146
|
+
if (!shouldFoldActionIntoBrowserAction(manifest)) return manifest;
|
|
147
|
+
const { action: folded, ...rest } = manifest;
|
|
148
|
+
return {
|
|
149
|
+
...rest,
|
|
150
|
+
browser_action: folded,
|
|
151
|
+
...renameExecuteActionCommand(manifest)
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function renameExecuteActionCommand(manifest) {
|
|
155
|
+
const commands = manifest.commands;
|
|
156
|
+
if (!commands || 'object' != typeof commands) return {};
|
|
157
|
+
if (!('_execute_action' in commands)) return {};
|
|
158
|
+
if ('_execute_browser_action' in commands) return {};
|
|
159
|
+
const { _execute_action: shortcut, ...others } = commands;
|
|
160
|
+
return {
|
|
161
|
+
commands: {
|
|
162
|
+
...others,
|
|
163
|
+
_execute_browser_action: shortcut
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function sidebarFoldTarget(manifest, browser) {
|
|
168
|
+
if (!manifest || 'object' != typeof manifest) return;
|
|
169
|
+
const hasSidePanel = null != manifest.side_panel;
|
|
170
|
+
const hasSidebarAction = null != manifest.sidebar_action;
|
|
171
|
+
if (hasSidePanel === hasSidebarAction) return;
|
|
172
|
+
const target = String(browser || '');
|
|
173
|
+
if (hasSidebarAction) {
|
|
174
|
+
if (!readPageRef(manifest.sidebar_action, 'default_panel')) return;
|
|
175
|
+
if (!isChromiumBasedBrowser(target)) return;
|
|
176
|
+
if ('opera' === target) return;
|
|
177
|
+
const version = Number(manifest.manifest_version);
|
|
178
|
+
return version >= 3 ? 'side_panel' : void 0;
|
|
179
|
+
}
|
|
180
|
+
if (!readPageRef(manifest.side_panel, 'default_path')) return;
|
|
181
|
+
return isGeckoBasedBrowser(target) ? 'sidebar_action' : void 0;
|
|
182
|
+
}
|
|
183
|
+
const SIDE_PANEL_PERMISSION = 'sidePanel';
|
|
184
|
+
function withSidePanelPermission(manifest) {
|
|
185
|
+
const current = Array.isArray(manifest.permissions) ? manifest.permissions : [];
|
|
186
|
+
return current.includes(SIDE_PANEL_PERMISSION) ? current : [
|
|
187
|
+
...current,
|
|
188
|
+
SIDE_PANEL_PERMISSION
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
function foldSidebarKeyForBrowser(manifest, browser) {
|
|
192
|
+
const target = sidebarFoldTarget(manifest, browser);
|
|
193
|
+
if (!target) return manifest;
|
|
194
|
+
if ('side_panel' === target) {
|
|
195
|
+
const panel = readPageRef(manifest.sidebar_action, 'default_panel');
|
|
196
|
+
const { sidebar_action: _folded, ...rest } = manifest;
|
|
197
|
+
return {
|
|
198
|
+
...rest,
|
|
199
|
+
side_panel: {
|
|
200
|
+
default_path: panel
|
|
201
|
+
},
|
|
202
|
+
permissions: withSidePanelPermission(manifest)
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const panel = readPageRef(manifest.side_panel, 'default_path');
|
|
206
|
+
const { side_panel: _folded, ...rest } = manifest;
|
|
207
|
+
return {
|
|
208
|
+
...rest,
|
|
209
|
+
sidebar_action: {
|
|
210
|
+
default_panel: panel,
|
|
211
|
+
...sidebarActionStyle(manifest)
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function sidebarActionStyle(manifest) {
|
|
216
|
+
const version = Number(manifest.manifest_version);
|
|
217
|
+
if (2 !== version) return {};
|
|
218
|
+
const source = manifest.side_panel;
|
|
219
|
+
const own = source?.browser_style;
|
|
220
|
+
return {
|
|
221
|
+
browser_style: 'boolean' == typeof own ? own : false
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function pageActionOutputTarget(manifest) {
|
|
225
|
+
const actionRef = actionPopupRef(manifest);
|
|
226
|
+
const browserActionRef = browserActionOwnPopupRef(manifest);
|
|
227
|
+
const pageRef = pageActionPopupRef(manifest);
|
|
228
|
+
if (actionRef && pageRef && popupRefsShareSource(actionRef, pageRef)) return ACTION_HTML_OUTPUT;
|
|
229
|
+
if (browserActionRef && pageRef && popupRefsShareSource(browserActionRef, pageRef)) return BROWSER_ACTION_HTML_OUTPUT;
|
|
230
|
+
return PAGE_ACTION_HTML_OUTPUT;
|
|
231
|
+
}
|
|
232
|
+
function applyIndependentHtmlSurfaces(html, manifest, context, browser, projectPath) {
|
|
233
|
+
const next = {
|
|
234
|
+
...html || {}
|
|
235
|
+
};
|
|
236
|
+
const optionsRef = optionsPageRef(manifest);
|
|
237
|
+
if (optionsRef) next[OPTIONS_HTML_FEATURE] = resolveManifestHtmlPath(context, optionsRef, projectPath);
|
|
238
|
+
const resolve = (ref)=>ref ? resolveManifestHtmlPath(context, ref, projectPath) : void 0;
|
|
239
|
+
const assign = (feature, resolved)=>{
|
|
240
|
+
if (resolved) next[feature] = resolved;
|
|
241
|
+
else delete next[feature];
|
|
242
|
+
};
|
|
243
|
+
assign(SIDEBAR_HTML_FEATURE, resolve(sidebarPanelRef(manifest)));
|
|
244
|
+
assign(SIDEBAR_ACTION_HTML_FEATURE, resolve(sidebarActionOwnPanelRef(manifest)));
|
|
245
|
+
const actionRef = actionPopupRef(manifest);
|
|
246
|
+
const pageRef = pageActionPopupRef(manifest);
|
|
247
|
+
assign(ACTION_HTML_FEATURE, resolve(actionRef));
|
|
248
|
+
assign(BROWSER_ACTION_HTML_FEATURE, resolve(browserActionOwnPopupRef(manifest)));
|
|
249
|
+
const pageOwnsItsPage = pageRef && !pageActionDropReason(manifest, browser) && pageActionOutputTarget(manifest) === PAGE_ACTION_HTML_OUTPUT;
|
|
250
|
+
assign(PAGE_ACTION_HTML_FEATURE, pageOwnsItsPage ? resolve(pageRef) : void 0);
|
|
251
|
+
return leavePublicPagesToCopier(next, context, projectPath);
|
|
252
|
+
}
|
|
253
|
+
function leavePublicPagesToCopier(html, context, projectPath) {
|
|
254
|
+
const manifestPath = __rspack_external_node_path_806ed179.join(context, 'manifest.json');
|
|
255
|
+
const { fromRoot, fromManifest } = inspectPublicFolders(manifestPath, projectPath);
|
|
256
|
+
const roots = [
|
|
257
|
+
fromRoot,
|
|
258
|
+
fromManifest
|
|
259
|
+
].map((root)=>__rspack_external_node_path_806ed179.resolve(root));
|
|
260
|
+
for (const [feature, resolved] of Object.entries(html)){
|
|
261
|
+
if ('string' != typeof resolved) continue;
|
|
262
|
+
const hosted = roots.some((root)=>{
|
|
263
|
+
const rel = __rspack_external_node_path_806ed179.relative(root, __rspack_external_node_path_806ed179.resolve(resolved));
|
|
264
|
+
return Boolean(rel) && !rel.startsWith('..') && !__rspack_external_node_path_806ed179.isAbsolute(rel);
|
|
265
|
+
});
|
|
266
|
+
if (hosted) delete html[feature];
|
|
267
|
+
}
|
|
268
|
+
return html;
|
|
269
|
+
}
|
|
270
|
+
function isFromFilepathList(filePath, filepathList) {
|
|
271
|
+
return Object.values(filepathList || {}).some((value)=>value === filePath);
|
|
272
|
+
}
|
|
273
|
+
function isFolder(filePath) {
|
|
274
|
+
try {
|
|
275
|
+
return __rspack_external_node_fs_1b05aee1.statSync(filePath).isDirectory();
|
|
276
|
+
} catch {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function getFilename(feature, filePath) {
|
|
281
|
+
const entryExt = __rspack_external_node_path_806ed179.extname(filePath);
|
|
282
|
+
let fileOutputpath = feature;
|
|
283
|
+
if ([
|
|
284
|
+
'.js',
|
|
285
|
+
'.jsx',
|
|
286
|
+
'.tsx',
|
|
287
|
+
'.ts',
|
|
288
|
+
'.vue',
|
|
289
|
+
'.svelte'
|
|
290
|
+
].includes(entryExt)) fileOutputpath = fileOutputpath.replace(entryExt, '.js');
|
|
291
|
+
if ([
|
|
292
|
+
'.html',
|
|
293
|
+
'.njk',
|
|
294
|
+
'.nunjucks'
|
|
295
|
+
].includes(entryExt)) fileOutputpath = fileOutputpath.replace(entryExt, '.html');
|
|
296
|
+
if ([
|
|
297
|
+
'.css',
|
|
298
|
+
'.scss',
|
|
299
|
+
'.sass',
|
|
300
|
+
'.less'
|
|
301
|
+
].includes(entryExt)) fileOutputpath = fileOutputpath.replace(entryExt, '.css');
|
|
302
|
+
return unixify(fileOutputpath || '');
|
|
303
|
+
}
|
|
304
|
+
function unixify(filePath) {
|
|
305
|
+
return filePath.replace(/\\/g, '/');
|
|
306
|
+
}
|
|
307
|
+
function resolveRootAbsoluteRef(ref, projectRoot, publicRoot) {
|
|
308
|
+
if (!ref || !ref.startsWith('/')) return;
|
|
309
|
+
if (projectRoot && ref.startsWith(projectRoot)) return;
|
|
310
|
+
if (ref.startsWith('//')) return;
|
|
311
|
+
const trimmed = ref.replace(/^\/+/, '');
|
|
312
|
+
if (!trimmed) return;
|
|
313
|
+
if (publicRoot && __rspack_external_node_fs_1b05aee1.existsSync(__rspack_external_node_path_806ed179.join(publicRoot, trimmed))) return;
|
|
314
|
+
const candidate = __rspack_external_node_path_806ed179.resolve(projectRoot, trimmed);
|
|
315
|
+
const rel = __rspack_external_node_path_806ed179.relative(projectRoot, candidate);
|
|
316
|
+
if (rel.startsWith('..') || __rspack_external_node_path_806ed179.isAbsolute(rel)) return;
|
|
317
|
+
if (!__rspack_external_node_fs_1b05aee1.existsSync(candidate) || !__rspack_external_node_fs_1b05aee1.statSync(candidate).isFile()) return;
|
|
318
|
+
return candidate;
|
|
319
|
+
}
|
|
320
|
+
function collectRootAbsoluteRefs(source) {
|
|
321
|
+
const refs = new Set();
|
|
322
|
+
const attrRe = /(?:src|href)\s*=\s*["'](\/[^"'#?]*)["']/gi;
|
|
323
|
+
const urlRe = /url\(\s*["']?(\/[^"')#?]+)["']?\s*\)/gi;
|
|
324
|
+
let m;
|
|
325
|
+
while(m = attrRe.exec(source))refs.add(m[1]);
|
|
326
|
+
while(m = urlRe.exec(source))refs.add(m[1]);
|
|
327
|
+
return refs;
|
|
328
|
+
}
|
|
329
|
+
function isManifestAddress(value) {
|
|
330
|
+
if ('string' != typeof value) return false;
|
|
331
|
+
const trimmed = value.trim();
|
|
332
|
+
return /^[a-z][a-z0-9+.-]+:/i.test(trimmed) || trimmed.startsWith('//');
|
|
333
|
+
}
|
|
334
|
+
function backgroundPage(manifest) {
|
|
335
|
+
return manifest.background?.page && {
|
|
336
|
+
background: {
|
|
337
|
+
page: (()=>{
|
|
338
|
+
const raw = String(manifest.background.page);
|
|
339
|
+
return getFilename('background/index.html', raw);
|
|
340
|
+
})()
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function normalizeManifestOutputPath(originalPath) {
|
|
345
|
+
if (!originalPath) return originalPath;
|
|
346
|
+
const unixPath = originalPath.replace(/\\/g, '/');
|
|
347
|
+
if (/^\/public\//i.test(unixPath)) return unixPath.replace(/^\/public\//i, '');
|
|
348
|
+
if (/^(?:\.\/)?public\//i.test(unixPath)) return unixPath.replace(/^(?:\.\/)?public\//i, '');
|
|
349
|
+
if (/^\//.test(unixPath)) return unixPath.replace(/^\//, '');
|
|
350
|
+
return unixPath;
|
|
351
|
+
}
|
|
352
|
+
function manifestPageOutputTarget(raw, compiledTarget, manifestPath, projectPath) {
|
|
353
|
+
const unixPath = raw.replace(/\\/g, '/');
|
|
354
|
+
if (/^(?:\/public\/|(?:\.\/)?public\/)/i.test(unixPath)) return normalizeManifestOutputPath(unixPath);
|
|
355
|
+
if (/^\//.test(unixPath)) {
|
|
356
|
+
const rest = unixPath.replace(/^\/+/, '');
|
|
357
|
+
if (manifestPath && rest) {
|
|
358
|
+
const manifestDir = __rspack_external_node_path_806ed179.dirname(manifestPath);
|
|
359
|
+
const inPublic = Boolean(findPublicFile(manifestPath, projectPath, rest));
|
|
360
|
+
const inRoot = __rspack_external_node_fs_1b05aee1.existsSync(__rspack_external_node_path_806ed179.join(manifestDir, rest));
|
|
361
|
+
if (inRoot && !inPublic) return compiledTarget;
|
|
362
|
+
}
|
|
363
|
+
return normalizeManifestOutputPath(unixPath);
|
|
364
|
+
}
|
|
365
|
+
const rest = unixPath.replace(/^\.\//, '');
|
|
366
|
+
if (!manifestPath || !rest || rest.split('/').includes('..')) return compiledTarget;
|
|
367
|
+
if (__rspack_external_node_fs_1b05aee1.existsSync(__rspack_external_node_path_806ed179.join(__rspack_external_node_path_806ed179.dirname(manifestPath), rest))) return compiledTarget;
|
|
368
|
+
if (findPublicFile(manifestPath, projectPath, rest)) return rest;
|
|
369
|
+
return compiledTarget;
|
|
370
|
+
}
|
|
371
|
+
function manifestJsonOutputTarget(raw, compiledTarget, manifestPath, projectPath) {
|
|
372
|
+
return manifestPageOutputTarget(raw, compiledTarget, manifestPath, projectPath);
|
|
373
|
+
}
|
|
374
|
+
function pathEscapesExtensionRoot(normalized) {
|
|
375
|
+
return !normalized || normalized.split('/').includes('..') || /^[A-Za-z]:/.test(normalized);
|
|
376
|
+
}
|
|
377
|
+
function externalAssetOutputPath(normalized, root) {
|
|
378
|
+
const unix = normalized.replace(/\\/g, '/');
|
|
379
|
+
const noDrive = unix.replace(/^([A-Za-z]):(?:\/|$)/, '_drive_$1/');
|
|
380
|
+
const safe = noDrive.split('/').map((segment)=>{
|
|
381
|
+
if ('..' === segment) return '_';
|
|
382
|
+
if ('.' === segment || !segment) return '';
|
|
383
|
+
return segment.replace(/[<>:"|?*\x00-\x1F]/g, '_');
|
|
384
|
+
}).filter(Boolean).join('/');
|
|
385
|
+
return safe ? `${root}/${safe}` : `${root}/external`;
|
|
386
|
+
}
|
|
387
|
+
function iconOutputPath(raw) {
|
|
388
|
+
if (/^(?:\/public\/|(?:\.\/)?public\/)/i.test(raw)) return normalizeManifestOutputPath(raw);
|
|
389
|
+
const normalized = normalizeManifestOutputPath(raw).replace(/^\.\//, '');
|
|
390
|
+
if (!pathEscapesExtensionRoot(normalized)) return normalized;
|
|
391
|
+
return externalAssetOutputPath(normalized, 'icons');
|
|
392
|
+
}
|
|
393
|
+
function themeIconOutputPath(raw, folder) {
|
|
394
|
+
return featureAssetOutputPath(raw, folder);
|
|
395
|
+
}
|
|
396
|
+
function themeImageOutputPath(raw) {
|
|
397
|
+
return featureAssetOutputPath(raw, 'theme/images');
|
|
398
|
+
}
|
|
399
|
+
function featureAssetOutputPath(raw, folder) {
|
|
400
|
+
if (/^(?:\/public\/|(?:\.\/)?public\/)/i.test(raw)) return normalizeManifestOutputPath(raw);
|
|
401
|
+
const normalized = normalizeManifestOutputPath(raw).replace(/^\.\//, '');
|
|
402
|
+
if (!pathEscapesExtensionRoot(normalized)) return `${folder}/${normalized}`;
|
|
403
|
+
return externalAssetOutputPath(normalized, folder);
|
|
404
|
+
}
|
|
405
|
+
function chromeUrlOverrides(manifest, manifestPath, projectPath) {
|
|
406
|
+
return manifest.chrome_url_overrides && {
|
|
407
|
+
chrome_url_overrides: {
|
|
408
|
+
...manifest.chrome_url_overrides.bookmarks && {
|
|
409
|
+
bookmarks: (()=>{
|
|
410
|
+
const raw = String(manifest.chrome_url_overrides.bookmarks);
|
|
411
|
+
return getFilename(manifestPageOutputTarget(raw, 'chrome_url_overrides/bookmarks.html', manifestPath, projectPath), raw);
|
|
412
|
+
})()
|
|
413
|
+
},
|
|
414
|
+
...manifest.chrome_url_overrides.history && {
|
|
415
|
+
history: (()=>{
|
|
416
|
+
const raw = String(manifest.chrome_url_overrides.history);
|
|
417
|
+
return getFilename(manifestPageOutputTarget(raw, 'chrome_url_overrides/history.html', manifestPath, projectPath), raw);
|
|
418
|
+
})()
|
|
419
|
+
},
|
|
420
|
+
...manifest.chrome_url_overrides.newtab && {
|
|
421
|
+
newtab: (()=>{
|
|
422
|
+
const raw = String(manifest.chrome_url_overrides.newtab);
|
|
423
|
+
return getFilename(manifestPageOutputTarget(raw, 'chrome_url_overrides/newtab.html', manifestPath, projectPath), raw);
|
|
424
|
+
})()
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
function commands_commands(manifest) {
|
|
430
|
+
return manifest.commands && {
|
|
431
|
+
commands: manifest.commands
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function isBundledContentPath(filePath, ext) {
|
|
435
|
+
const normalized = String(filePath || '').replace(/\\/g, '/');
|
|
436
|
+
const bundledAsset = parseCanonicalContentScriptAsset(normalized);
|
|
437
|
+
return bundledAsset?.extension === ext;
|
|
438
|
+
}
|
|
439
|
+
function isHollowContentScript(entry) {
|
|
440
|
+
const contentObj = entry || {};
|
|
441
|
+
const js = Array.isArray(contentObj.js) ? contentObj.js : [];
|
|
442
|
+
const css = Array.isArray(contentObj.css) ? contentObj.css : [];
|
|
443
|
+
return 0 === js.length && 0 === css.length;
|
|
444
|
+
}
|
|
445
|
+
function isAlreadyBundledContentScripts(contentScripts) {
|
|
446
|
+
if (!Array.isArray(contentScripts)) return false;
|
|
447
|
+
const filled = contentScripts.filter((contentObj)=>!isHollowContentScript(contentObj));
|
|
448
|
+
if (0 === filled.length) return false;
|
|
449
|
+
return filled.every((contentObj)=>{
|
|
450
|
+
const js = Array.isArray(contentObj?.js) ? contentObj.js : [];
|
|
451
|
+
const css = Array.isArray(contentObj?.css) ? contentObj.css : [];
|
|
452
|
+
return js.every((filePath)=>isBundledContentPath(filePath, 'js')) && css.every((filePath)=>isBundledContentPath(filePath, 'css'));
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
function content_scripts_contentScripts(manifest, manifestPath) {
|
|
456
|
+
if (!manifest.content_scripts) return;
|
|
457
|
+
const original = manifest.content_scripts;
|
|
458
|
+
if (isAlreadyBundledContentScripts(original)) return {
|
|
459
|
+
content_scripts: original
|
|
460
|
+
};
|
|
461
|
+
const originalCount = original.length;
|
|
462
|
+
const result = [];
|
|
463
|
+
let bridgeOrdinal = 0;
|
|
464
|
+
for(let index = 0; index < original.length; index++){
|
|
465
|
+
const contentObj = original[index] || {};
|
|
466
|
+
if (isHollowContentScript(contentObj)) continue;
|
|
467
|
+
const contentJs = [
|
|
468
|
+
...new Set(contentObj.js || [])
|
|
469
|
+
];
|
|
470
|
+
const contentCss = [
|
|
471
|
+
...new Set(contentObj.css || [])
|
|
472
|
+
];
|
|
473
|
+
if ('MAIN' === contentObj.world) {
|
|
474
|
+
const bridgeIndex = originalCount + bridgeOrdinal++;
|
|
475
|
+
const { world: _ignoredWorld, js: _ignoredJs, css: _ignoredCss, ...rest } = contentObj;
|
|
476
|
+
result.push({
|
|
477
|
+
...rest,
|
|
478
|
+
js: [
|
|
479
|
+
getFilename(getCanonicalContentScriptJsAssetName(bridgeIndex), 'main-world-bridge.js')
|
|
480
|
+
],
|
|
481
|
+
css: []
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
result.push({
|
|
485
|
+
...original[index] || {},
|
|
486
|
+
js: [
|
|
487
|
+
...new Set(contentJs.map((js)=>getFilename(getCanonicalContentScriptJsAssetName(index), js)))
|
|
488
|
+
],
|
|
489
|
+
css: [
|
|
490
|
+
...new Set(contentCss.map((css)=>getFilename(getCanonicalContentScriptCssAssetName(index), css)))
|
|
491
|
+
]
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
content_scripts: result
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function hasMv3StringPolicy(manifest) {
|
|
499
|
+
if (3 !== Number(manifest.manifest_version)) return false;
|
|
500
|
+
return 'string' == typeof manifest.content_security_policy;
|
|
501
|
+
}
|
|
502
|
+
function contentSecurityPolicy(manifest) {
|
|
503
|
+
if (!manifest.content_security_policy) return;
|
|
504
|
+
if (hasMv3StringPolicy(manifest)) return {
|
|
505
|
+
content_security_policy: {
|
|
506
|
+
extension_pages: manifest.content_security_policy
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
return {
|
|
510
|
+
content_security_policy: manifest.content_security_policy
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function devtoolsPage(manifest, manifestPath, projectPath) {
|
|
514
|
+
return manifest.devtools_page && {
|
|
515
|
+
devtools_page: (()=>{
|
|
516
|
+
const raw = String(manifest.devtools_page);
|
|
517
|
+
return getFilename(manifestPageOutputTarget(raw, 'devtools/index.html', manifestPath, projectPath), raw);
|
|
518
|
+
})()
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function icons(manifest) {
|
|
522
|
+
return manifest.icons && {
|
|
523
|
+
icons: Object.fromEntries(Object.entries(manifest.icons).map(([size, icon])=>{
|
|
524
|
+
const raw = String(icon);
|
|
525
|
+
return [
|
|
526
|
+
size,
|
|
527
|
+
getFilename(iconOutputPath(raw), raw)
|
|
528
|
+
];
|
|
529
|
+
}))
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function omnibox_omnibox(manifest) {
|
|
533
|
+
const omnibox = manifest.omnibox;
|
|
534
|
+
return omnibox && {
|
|
535
|
+
omnibox: {
|
|
536
|
+
...omnibox,
|
|
537
|
+
...omnibox.default_icon && {
|
|
538
|
+
default_icon: 'string' == typeof omnibox.default_icon ? getFilename(iconOutputPath(omnibox.default_icon), omnibox.default_icon) : Object.fromEntries(Object.entries(omnibox.default_icon).map(([size, icon])=>[
|
|
539
|
+
size,
|
|
540
|
+
getFilename(iconOutputPath(icon), icon)
|
|
541
|
+
]))
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function optionsPage(manifest, manifestPath, projectPath) {
|
|
547
|
+
return manifest.options_page && {
|
|
548
|
+
options_page: (()=>{
|
|
549
|
+
const raw = String(manifest.options_page);
|
|
550
|
+
return getFilename(manifestPageOutputTarget(raw, 'options/index.html', manifestPath, projectPath), raw);
|
|
551
|
+
})()
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
function options_ui_optionsUi(manifest, manifestPath, projectPath) {
|
|
555
|
+
return manifest.options_ui && {
|
|
556
|
+
options_ui: {
|
|
557
|
+
...manifest.options_ui,
|
|
558
|
+
...manifest.options_ui.page && {
|
|
559
|
+
page: (()=>{
|
|
560
|
+
const raw = String(manifest.options_ui.page);
|
|
561
|
+
return getFilename(manifestPageOutputTarget(raw, 'options/index.html', manifestPath, projectPath), raw);
|
|
562
|
+
})()
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
function permissions(manifest) {
|
|
568
|
+
return manifest.permissions && {
|
|
569
|
+
permissions: manifest.permissions
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function sandbox(manifest, manifestPath, projectPath) {
|
|
573
|
+
return manifest.sandbox && {
|
|
574
|
+
sandbox: {
|
|
575
|
+
...manifest.sandbox,
|
|
576
|
+
...manifest.sandbox.pages && {
|
|
577
|
+
pages: manifest.sandbox.pages.map((page, index)=>getFilename(manifestPageOutputTarget(page, `sandbox/page-${index}.html`, manifestPath, projectPath), page))
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function storage(manifest, manifestPath, projectPath) {
|
|
583
|
+
return manifest.storage && {
|
|
584
|
+
storage: {
|
|
585
|
+
...manifest.storage.managed_schema && {
|
|
586
|
+
managed_schema: (()=>{
|
|
587
|
+
const raw = String(manifest.storage.managed_schema);
|
|
588
|
+
return getFilename(manifestJsonOutputTarget(raw, 'storage/managed_schema.json', manifestPath, projectPath), raw);
|
|
589
|
+
})()
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
const rewriteThemeImage = (value, manifestPath, projectPath)=>getFilename(manifestPageOutputTarget(value, themeImageOutputPath(value), manifestPath, projectPath), value);
|
|
595
|
+
function theme(manifest, manifestPath, projectPath) {
|
|
596
|
+
return manifest.theme && {
|
|
597
|
+
theme: {
|
|
598
|
+
...manifest.theme,
|
|
599
|
+
...manifest.theme.images && {
|
|
600
|
+
images: Object.fromEntries(Object.entries(manifest.theme.images).map(([key, value])=>[
|
|
601
|
+
key,
|
|
602
|
+
Array.isArray(value) ? value.map((entry)=>rewriteThemeImage(entry, manifestPath, projectPath)) : rewriteThemeImage(value, manifestPath, projectPath)
|
|
603
|
+
]))
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
function userScripts(manifest) {
|
|
609
|
+
return manifest.user_scripts && {
|
|
610
|
+
user_scripts: {
|
|
611
|
+
...manifest.user_scripts,
|
|
612
|
+
...manifest.user_scripts.api_script && {
|
|
613
|
+
api_script: getFilename("user_scripts/api_script.js", manifest.user_scripts.api_script)
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
function normalizeOutputPath(originalPath) {
|
|
619
|
+
if (!originalPath) return originalPath;
|
|
620
|
+
const unix = originalPath.replace(/\\/g, '/');
|
|
621
|
+
if (/[*?[\]{}]/.test(unix)) return unix;
|
|
622
|
+
if (/^\/public\//i.test(unix)) return unix.replace(/^\/public\//i, '');
|
|
623
|
+
if (/^(?:\.\/)?public\//i.test(unix)) return unix.replace(/^(?:\.\/)?public\//i, '');
|
|
624
|
+
if (/^\//.test(unix)) return unix.replace(/^\//, '');
|
|
625
|
+
return unix;
|
|
626
|
+
}
|
|
627
|
+
function webAccessibleResources(manifest) {
|
|
628
|
+
if (!manifest.web_accessible_resources || !manifest.web_accessible_resources.length) return;
|
|
629
|
+
const mapResource = (resource)=>getFilename(normalizeOutputPath(resource), resource);
|
|
630
|
+
const entries = manifest.web_accessible_resources.map((entry)=>{
|
|
631
|
+
if ('string' == typeof entry) return mapResource(entry);
|
|
632
|
+
if (!entry || !Array.isArray(entry.resources)) return;
|
|
633
|
+
return {
|
|
634
|
+
...entry,
|
|
635
|
+
resources: entry.resources.map(mapResource)
|
|
636
|
+
};
|
|
637
|
+
}).filter((entry)=>void 0 !== entry);
|
|
638
|
+
if (0 === entries.length) return;
|
|
639
|
+
return {
|
|
640
|
+
web_accessible_resources: entries
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
function manifestCommon(manifest, manifestPath, projectPath) {
|
|
644
|
+
return {
|
|
645
|
+
...backgroundPage(manifest),
|
|
646
|
+
...chromeUrlOverrides(manifest, manifestPath, projectPath),
|
|
647
|
+
...content_scripts_contentScripts(manifest, manifestPath),
|
|
648
|
+
...devtoolsPage(manifest, manifestPath, projectPath),
|
|
649
|
+
...icons(manifest),
|
|
650
|
+
...commands_commands(manifest),
|
|
651
|
+
...permissions(manifest),
|
|
652
|
+
...optionsPage(manifest, manifestPath, projectPath),
|
|
653
|
+
...options_ui_optionsUi(manifest, manifestPath, projectPath),
|
|
654
|
+
...sandbox(manifest, manifestPath, projectPath),
|
|
655
|
+
...storage(manifest, manifestPath, projectPath),
|
|
656
|
+
...theme(manifest, manifestPath, projectPath),
|
|
657
|
+
...userScripts(manifest),
|
|
658
|
+
...webAccessibleResources(manifest),
|
|
659
|
+
...contentSecurityPolicy(manifest),
|
|
660
|
+
...omnibox_omnibox(manifest)
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
function pageAction(manifest, manifestPath, projectPath) {
|
|
664
|
+
return manifest.page_action && {
|
|
665
|
+
page_action: {
|
|
666
|
+
...manifest.page_action,
|
|
667
|
+
...manifest.page_action.default_popup && {
|
|
668
|
+
default_popup: getFilename(manifestPageOutputTarget(String(manifest.page_action.default_popup), pageActionOutputTarget(manifest), manifestPath, projectPath), String(manifest.page_action.default_popup))
|
|
669
|
+
},
|
|
670
|
+
...manifest.page_action.default_icon && {
|
|
671
|
+
default_icon: 'string' == typeof manifest.page_action.default_icon ? (()=>{
|
|
672
|
+
const raw = String(manifest.page_action.default_icon);
|
|
673
|
+
return getFilename(iconOutputPath(raw), raw);
|
|
674
|
+
})() : Object.fromEntries(Object.entries(manifest.page_action.default_icon).map(([size, icon])=>{
|
|
675
|
+
const raw = String(icon);
|
|
676
|
+
return [
|
|
677
|
+
size,
|
|
678
|
+
getFilename(iconOutputPath(raw), raw)
|
|
679
|
+
];
|
|
680
|
+
}))
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
function sidebar_action_sidebarAction(manifest, manifestPath, projectPath) {
|
|
686
|
+
return manifest.sidebar_action && {
|
|
687
|
+
sidebar_action: {
|
|
688
|
+
...manifest.sidebar_action,
|
|
689
|
+
...manifest.sidebar_action.default_panel && {
|
|
690
|
+
default_panel: (()=>{
|
|
691
|
+
const raw = String(manifest.sidebar_action.default_panel);
|
|
692
|
+
return getFilename(manifestPageOutputTarget(raw, sidebarActionOutputTarget(manifest), manifestPath, projectPath), raw);
|
|
693
|
+
})()
|
|
694
|
+
},
|
|
695
|
+
...manifest.sidebar_action.default_icon && {
|
|
696
|
+
default_icon: 'string' == typeof manifest.sidebar_action.default_icon ? (()=>{
|
|
697
|
+
const raw = String(manifest.sidebar_action.default_icon);
|
|
698
|
+
return getFilename(iconOutputPath(raw), raw);
|
|
699
|
+
})() : Object.fromEntries(Object.entries(manifest.sidebar_action.default_icon).map(([size, icon])=>{
|
|
700
|
+
const raw = String(icon);
|
|
701
|
+
return [
|
|
702
|
+
size,
|
|
703
|
+
getFilename(iconOutputPath(raw), raw)
|
|
704
|
+
];
|
|
705
|
+
}))
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
function background(manifest) {
|
|
711
|
+
return manifest.background?.scripts && {
|
|
712
|
+
background: {
|
|
713
|
+
scripts: [
|
|
714
|
+
...new Set(manifest.background.scripts.map((script)=>getFilename("background/scripts.js", String(script))))
|
|
715
|
+
]
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function browser_action_browserAction(manifest, manifestPath, projectPath) {
|
|
720
|
+
return manifest.browser_action && {
|
|
721
|
+
browser_action: {
|
|
722
|
+
...manifest.browser_action,
|
|
723
|
+
...manifest.browser_action.default_popup && {
|
|
724
|
+
default_popup: getFilename(manifestPageOutputTarget(String(manifest.browser_action.default_popup), browserActionOutputTarget(manifest), manifestPath, projectPath), String(manifest.browser_action.default_popup))
|
|
725
|
+
},
|
|
726
|
+
...manifest.browser_action.default_icon && {
|
|
727
|
+
default_icon: 'string' == typeof manifest.browser_action.default_icon ? (()=>{
|
|
728
|
+
const raw = String(manifest.browser_action.default_icon);
|
|
729
|
+
return getFilename(iconOutputPath(raw), raw);
|
|
730
|
+
})() : Object.fromEntries(Object.entries(manifest.browser_action.default_icon).map(([size, icon])=>{
|
|
731
|
+
const raw = String(icon);
|
|
732
|
+
return [
|
|
733
|
+
size,
|
|
734
|
+
getFilename(iconOutputPath(raw), raw)
|
|
735
|
+
];
|
|
736
|
+
}))
|
|
737
|
+
},
|
|
738
|
+
...manifest.browser_action.theme_icons && {
|
|
739
|
+
theme_icons: manifest.browser_action.theme_icons.map((themeIcon)=>({
|
|
740
|
+
...themeIcon,
|
|
741
|
+
...themeIcon.light && {
|
|
742
|
+
light: getFilename(themeIconOutputPath(String(themeIcon.light), 'browser_action'), String(themeIcon.light))
|
|
743
|
+
},
|
|
744
|
+
...themeIcon.dark && {
|
|
745
|
+
dark: getFilename(themeIconOutputPath(String(themeIcon.dark), 'browser_action'), String(themeIcon.dark))
|
|
746
|
+
}
|
|
747
|
+
}))
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function chromeSettingsOverrides(manifest, manifestPath, projectPath) {
|
|
753
|
+
const overrides = manifest.chrome_settings_overrides;
|
|
754
|
+
return overrides && {
|
|
755
|
+
chrome_settings_overrides: {
|
|
756
|
+
...overrides.homepage && {
|
|
757
|
+
homepage: overrides.homepage
|
|
758
|
+
},
|
|
759
|
+
...overrides.search_provider && {
|
|
760
|
+
search_provider: {
|
|
761
|
+
...overrides.search_provider,
|
|
762
|
+
...overrides.search_provider.favicon_url && {
|
|
763
|
+
favicon_url: (()=>{
|
|
764
|
+
const fav = String(overrides.search_provider.favicon_url);
|
|
765
|
+
if (isManifestAddress(fav)) return fav;
|
|
766
|
+
return getFilename(manifestPageOutputTarget(fav, `chrome_settings_overrides/${__rspack_external_node_path_806ed179.basename(fav)}`, manifestPath, projectPath), fav);
|
|
767
|
+
})()
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
},
|
|
771
|
+
...overrides.startup_pages && {
|
|
772
|
+
startup_pages: overrides.startup_pages.map((page, index)=>isManifestAddress(page) ? page : getFilename(manifestPageOutputTarget(page, `chrome_settings_overrides/startup-${index}.html`, manifestPath, projectPath), page))
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
function asPolicyObject(policy) {
|
|
778
|
+
if (!policy || 'object' != typeof policy || Array.isArray(policy)) return;
|
|
779
|
+
return policy;
|
|
780
|
+
}
|
|
781
|
+
function content_security_policy_contentSecurityPolicy(manifest) {
|
|
782
|
+
if (2 !== manifest.manifest_version) return;
|
|
783
|
+
const policy = asPolicyObject(manifest.content_security_policy);
|
|
784
|
+
if (!policy) return;
|
|
785
|
+
if ('string' != typeof policy.extension_pages) return;
|
|
786
|
+
return {
|
|
787
|
+
content_security_policy: policy.extension_pages
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
function hasMv2SandboxPolicy(manifest) {
|
|
791
|
+
if (2 !== manifest.manifest_version) return false;
|
|
792
|
+
const policy = asPolicyObject(manifest.content_security_policy);
|
|
793
|
+
return 'string' == typeof policy?.sandbox;
|
|
794
|
+
}
|
|
795
|
+
function dropMv2ObjectPolicy(manifest) {
|
|
796
|
+
if (2 !== manifest.manifest_version) return manifest;
|
|
797
|
+
if (!asPolicyObject(manifest.content_security_policy)) return manifest;
|
|
798
|
+
const { content_security_policy: _dropped, ...rest } = manifest;
|
|
799
|
+
return rest;
|
|
800
|
+
}
|
|
801
|
+
const MV2_HOST_KEYS = [
|
|
802
|
+
'host_permissions',
|
|
803
|
+
'optional_host_permissions'
|
|
804
|
+
];
|
|
805
|
+
function appendUnique(base, extra) {
|
|
806
|
+
const list = [
|
|
807
|
+
...Array.isArray(base) ? base : [],
|
|
808
|
+
...Array.isArray(extra) ? extra : []
|
|
809
|
+
].filter((entry)=>'string' == typeof entry);
|
|
810
|
+
return [
|
|
811
|
+
...new Set(list)
|
|
812
|
+
];
|
|
813
|
+
}
|
|
814
|
+
function hostPermissions(manifest) {
|
|
815
|
+
if (2 !== manifest.manifest_version) return;
|
|
816
|
+
const result = {};
|
|
817
|
+
if (Array.isArray(manifest.host_permissions)) result.permissions = appendUnique(manifest.permissions, manifest.host_permissions);
|
|
818
|
+
if (Array.isArray(manifest.optional_host_permissions)) result.optional_permissions = appendUnique(manifest.optional_permissions, manifest.optional_host_permissions);
|
|
819
|
+
return Object.keys(result).length ? result : void 0;
|
|
820
|
+
}
|
|
821
|
+
function dropMv2HostKeys(manifest) {
|
|
822
|
+
if (2 !== manifest.manifest_version) return manifest;
|
|
823
|
+
const rest = {
|
|
824
|
+
...manifest
|
|
825
|
+
};
|
|
826
|
+
for (const key of MV2_HOST_KEYS)delete rest[key];
|
|
827
|
+
return rest;
|
|
828
|
+
}
|
|
829
|
+
const getBasename = (filepath)=>__rspack_external_node_path_806ed179.basename(filepath);
|
|
830
|
+
function themeExperiment(manifest, manifestPath, projectPath) {
|
|
831
|
+
const te = manifest.theme_experiment;
|
|
832
|
+
return te && {
|
|
833
|
+
theme_experiment: {
|
|
834
|
+
...te,
|
|
835
|
+
...'string' == typeof te.stylesheet && {
|
|
836
|
+
stylesheet: getFilename(manifestPageOutputTarget(te.stylesheet, `theme_experiment/${getBasename(te.stylesheet)}`, manifestPath, projectPath), te.stylesheet)
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
function manifestV2(manifest, manifestPath, projectPath) {
|
|
842
|
+
return {
|
|
843
|
+
...background(manifest),
|
|
844
|
+
...browser_action_browserAction(manifest, manifestPath, projectPath),
|
|
845
|
+
...pageAction(manifest, manifestPath, projectPath),
|
|
846
|
+
...sidebar_action_sidebarAction(manifest, manifestPath, projectPath),
|
|
847
|
+
...chromeSettingsOverrides(manifest, manifestPath, projectPath),
|
|
848
|
+
...hostPermissions(manifest),
|
|
849
|
+
...content_security_policy_contentSecurityPolicy(manifest),
|
|
850
|
+
...themeExperiment(manifest, manifestPath, projectPath)
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function action_action(manifest, manifestPath, projectPath) {
|
|
854
|
+
return manifest.action && {
|
|
855
|
+
action: {
|
|
856
|
+
...manifest.action,
|
|
857
|
+
...manifest.action.default_popup && {
|
|
858
|
+
default_popup: getFilename(manifestPageOutputTarget(String(manifest.action.default_popup), 'action/index.html', manifestPath, projectPath), String(manifest.action.default_popup))
|
|
859
|
+
},
|
|
860
|
+
...manifest.action.default_icon && {
|
|
861
|
+
default_icon: 'string' == typeof manifest.action.default_icon ? (()=>{
|
|
862
|
+
const raw = String(manifest.action.default_icon);
|
|
863
|
+
return getFilename(iconOutputPath(raw), raw);
|
|
864
|
+
})() : Object.fromEntries(Object.entries(manifest.action.default_icon).map(([size, icon])=>{
|
|
865
|
+
const raw = String(icon);
|
|
866
|
+
return [
|
|
867
|
+
size,
|
|
868
|
+
getFilename(iconOutputPath(raw), raw)
|
|
869
|
+
];
|
|
870
|
+
}))
|
|
871
|
+
},
|
|
872
|
+
...manifest.action.theme_icons && {
|
|
873
|
+
theme_icons: manifest.action.theme_icons.map((themeIcon)=>({
|
|
874
|
+
...themeIcon,
|
|
875
|
+
...themeIcon.light && {
|
|
876
|
+
light: getFilename(themeIconOutputPath(String(themeIcon.light), 'action'), String(themeIcon.light))
|
|
877
|
+
},
|
|
878
|
+
...themeIcon.dark && {
|
|
879
|
+
dark: getFilename(themeIconOutputPath(String(themeIcon.dark), 'action'), String(themeIcon.dark))
|
|
880
|
+
}
|
|
881
|
+
}))
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
function backgroundServiceWorker(manifest) {
|
|
887
|
+
return manifest.background?.service_worker && {
|
|
888
|
+
background: {
|
|
889
|
+
service_worker: (()=>{
|
|
890
|
+
const raw = String(manifest.background.service_worker);
|
|
891
|
+
return getFilename('background/service_worker.js', raw);
|
|
892
|
+
})()
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
function declarativeNetRequest(manifest, manifestPath, projectPath) {
|
|
897
|
+
return manifest.declarative_net_request && {
|
|
898
|
+
declarative_net_request: {
|
|
899
|
+
...manifest.declarative_net_request,
|
|
900
|
+
...Array.isArray(manifest.declarative_net_request.rule_resources) && {
|
|
901
|
+
rule_resources: manifest.declarative_net_request.rule_resources.map((resourceObj)=>({
|
|
902
|
+
...resourceObj,
|
|
903
|
+
path: resourceObj.path && getFilename(manifestJsonOutputTarget(resourceObj.path, `declarative_net_request/${resourceObj.id}.json`, manifestPath, projectPath), resourceObj.path)
|
|
904
|
+
}))
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
function host_permissions_hostPermissions(manifest) {
|
|
910
|
+
return manifest.host_permissions && {
|
|
911
|
+
host_permissions: manifest.host_permissions
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
function side_panel_sidePanel(manifest, manifestPath, projectPath) {
|
|
915
|
+
return manifest.side_panel && {
|
|
916
|
+
side_panel: {
|
|
917
|
+
...manifest.side_panel,
|
|
918
|
+
...manifest.side_panel.default_path && {
|
|
919
|
+
default_path: (()=>{
|
|
920
|
+
const raw = String(manifest.side_panel.default_path);
|
|
921
|
+
return getFilename(manifestPageOutputTarget(raw, 'sidebar/index.html', manifestPath, projectPath), raw);
|
|
922
|
+
})()
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
function manifestV3(manifest, manifestPath, projectPath) {
|
|
928
|
+
return {
|
|
929
|
+
...action_action(manifest, manifestPath, projectPath),
|
|
930
|
+
...pageAction(manifest, manifestPath, projectPath),
|
|
931
|
+
...backgroundServiceWorker(manifest),
|
|
932
|
+
...declarativeNetRequest(manifest, manifestPath, projectPath),
|
|
933
|
+
...host_permissions_hostPermissions(manifest),
|
|
934
|
+
...side_panel_sidePanel(manifest, manifestPath, projectPath)
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
function getManifestOverrides(manifestPath, manifest, projectPath) {
|
|
938
|
+
const manifestContent = manifest || JSON.parse(stripBom(__rspack_external_node_fs_1b05aee1.readFileSync(manifestPath, 'utf8')));
|
|
939
|
+
const omit = (obj, key)=>{
|
|
940
|
+
if (!obj) return {};
|
|
941
|
+
const { [key]: _ignored, ...rest } = obj;
|
|
942
|
+
return rest;
|
|
943
|
+
};
|
|
944
|
+
const pickBackground = (obj)=>{
|
|
945
|
+
const value = obj.background;
|
|
946
|
+
return value && 'object' == typeof value ? value : {};
|
|
947
|
+
};
|
|
948
|
+
const common = manifestCommon(manifestContent, manifestPath, projectPath);
|
|
949
|
+
const mv2 = manifestV2(manifestContent, manifestPath, projectPath);
|
|
950
|
+
const mv3 = manifestV3(manifestContent, manifestPath, projectPath);
|
|
951
|
+
const backgroundMerged = {
|
|
952
|
+
...manifestContent.background || {},
|
|
953
|
+
...pickBackground(common),
|
|
954
|
+
...pickBackground(mv2),
|
|
955
|
+
...pickBackground(mv3)
|
|
956
|
+
};
|
|
957
|
+
const merged = {
|
|
958
|
+
...manifestContent,
|
|
959
|
+
...omit(common, 'background'),
|
|
960
|
+
...omit(mv2, 'background'),
|
|
961
|
+
...omit(mv3, 'background')
|
|
962
|
+
};
|
|
963
|
+
if (Object.keys(backgroundMerged).length) merged.background = backgroundMerged;
|
|
964
|
+
return JSON.stringify(dropMv2ObjectPolicy(dropMv2HostKeys(merged)), null, 2);
|
|
965
|
+
}
|
|
966
|
+
function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
|
|
967
|
+
const lines = [];
|
|
968
|
+
lines.push("Entrypoint references changed.");
|
|
969
|
+
if (fileRemoved) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(fileRemoved)}`);
|
|
970
|
+
if (fileAdded) lines.push(`${pintor.gray('GOT')} ${pintor.underline(fileAdded)}`);
|
|
971
|
+
lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
|
|
972
|
+
return lines.join('\n');
|
|
973
|
+
}
|
|
974
|
+
function manifestFilesInTurnedOffPublic(files) {
|
|
975
|
+
return [
|
|
976
|
+
'manifest.json names files that the build did not emit:',
|
|
977
|
+
...files.map((file)=>` - ${pintor.underline(file)}`),
|
|
978
|
+
`The public folder is turned off, ${pintor.blue('folders.public')} is ${pintor.blue('false')} in extension.config.js, so nothing inside public/ ships.`,
|
|
979
|
+
'Turn the folder back on, or move these files out of public/ and name them by their path in the project.'
|
|
980
|
+
].join('\n');
|
|
981
|
+
}
|
|
982
|
+
function legacyManifestPathWarning(field, legacyPath, modernPath) {
|
|
983
|
+
const lines = [];
|
|
984
|
+
lines.push(`${messaging_prefix('warn')} The ${pintor.blue(field)} field uses a deprecated scaffold path.`);
|
|
985
|
+
lines.push(`${pintor.gray('PATH')} ${pintor.underline(legacyPath)}`);
|
|
986
|
+
lines.push(`Point it at ${pintor.underline(modernPath)}, Extension.js already emits the page there.`);
|
|
987
|
+
return lines.join('\n');
|
|
988
|
+
}
|
|
989
|
+
function fatalManifestShapeFixed(field, detail) {
|
|
990
|
+
const lines = [];
|
|
991
|
+
lines.push(`${messaging_prefix('warn')} Repaired the ${pintor.blue(field)} field, which Chrome refuses to load the extension over.`);
|
|
992
|
+
lines.push(`${pintor.gray('REASON')} ${pintor.underline(detail)}`);
|
|
993
|
+
lines.push(`Fix the field in your ${pintor.blue('manifest.json')} file.`);
|
|
994
|
+
return lines.join('\n');
|
|
995
|
+
}
|
|
996
|
+
function manifestFieldMistyped(field, expected, received) {
|
|
997
|
+
const lines = [];
|
|
998
|
+
lines.push(`The ${pintor.blue(field)} field in your ${pintor.blue('manifest.json')} must be ${expected}.`);
|
|
999
|
+
lines.push(`${pintor.gray('GOT')} ${pintor.underline(received)}`);
|
|
1000
|
+
lines.push(`No browser loads the extension with it written this way, so the build stops here. Rewrite the field as ${expected} and try again.`);
|
|
1001
|
+
return lines.join('\n');
|
|
1002
|
+
}
|
|
1003
|
+
function invalidThemeValue(field, detail, value) {
|
|
1004
|
+
const lines = [];
|
|
1005
|
+
lines.push(`Check the ${pintor.yellow(field)} field in your ${pintor.yellow('manifest.json')} file.`);
|
|
1006
|
+
lines.push(detail);
|
|
1007
|
+
lines.push(`Chrome rejects the whole extension when this value is malformed.\nThe build stops here to protect you.`);
|
|
1008
|
+
lines.push('');
|
|
1009
|
+
lines.push(`${pintor.red('INVALID VALUE')} ${value}`);
|
|
1010
|
+
return lines.join('\n');
|
|
1011
|
+
}
|
|
1012
|
+
function themeNotSupportedByBrowser(browser) {
|
|
1013
|
+
const lines = [];
|
|
1014
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.blue(browser)} does not support the ${pintor.yellow('theme')} field.`);
|
|
1015
|
+
lines.push("The field ships unchanged in the manifest and Safari ignores it.");
|
|
1016
|
+
return lines.join('\n');
|
|
1017
|
+
}
|
|
1018
|
+
function missingGeckoDataCollectionPermissions() {
|
|
1019
|
+
const lines = [];
|
|
1020
|
+
lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.blue('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
|
|
1021
|
+
lines.push(`Declare ${pintor.blue('{"required": ["none"]}')} if this extension transmits no data.`);
|
|
1022
|
+
lines.push(`See ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')} for details.`);
|
|
1023
|
+
return lines.join('\n');
|
|
1024
|
+
}
|
|
1025
|
+
function manifestInvalidError(error) {
|
|
1026
|
+
const lines = [];
|
|
1027
|
+
lines.push(`Can't read your ${pintor.blue('manifest.json')} file.`);
|
|
1028
|
+
lines.push(`${pintor.gray('REASON')} ${pintor.underline(String(error))}`);
|
|
1029
|
+
lines.push("Update your manifest and try again.");
|
|
1030
|
+
return lines.join('\n');
|
|
1031
|
+
}
|
|
1032
|
+
function manifestIncludeSummary(browser, manifestPath) {
|
|
1033
|
+
return `${messaging_prefix('debug')} manifest include browser=${browser} path=${manifestPath}`;
|
|
1034
|
+
}
|
|
1035
|
+
function manifestEmitSuccess() {
|
|
1036
|
+
return `${messaging_prefix('debug')} manifest emitted=true schemaStripped=true`;
|
|
1037
|
+
}
|
|
1038
|
+
function manifestOverridesSummary(overrideKeys, devCssStubsAdded) {
|
|
1039
|
+
return `${messaging_prefix('debug')} manifest overrides keys=${String(overrideKeys)} devCssStubs=${String(devCssStubsAdded)}`;
|
|
1040
|
+
}
|
|
1041
|
+
function manifestDepsTracked(addedCount) {
|
|
1042
|
+
return `${messaging_prefix('debug')} manifest deps=${String(addedCount)}`;
|
|
1043
|
+
}
|
|
1044
|
+
function manifestLegacyWarningsSummary(count) {
|
|
1045
|
+
return `${messaging_prefix('debug')} manifest legacyWarnings=${String(count)}`;
|
|
1046
|
+
}
|
|
1047
|
+
function pageActionNotSupportedByBrowser(browser) {
|
|
1048
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} does not show the ${pintor.yellow('page_action')} address bar surface.\nThe field was dropped from the built manifest and its page was not emitted.`;
|
|
1049
|
+
}
|
|
1050
|
+
function pageActionDroppedForBrowserAction(browser) {
|
|
1051
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} refuses a Manifest V2 manifest that declares both ${pintor.yellow('browser_action')} and ${pintor.yellow('page_action')}.\nThe build kept ${pintor.yellow('browser_action')} and dropped ${pintor.yellow('page_action')} from the built manifest, so its page was not emitted. Remove one of the two keys, or scope page_action with the firefox: prefix.`;
|
|
1052
|
+
}
|
|
1053
|
+
function vendorPrefixedKeyDropped(key, familyKey, vendor, browser) {
|
|
1054
|
+
const vendorName = 'edge' === vendor ? 'Edge' : 'Chrome';
|
|
1055
|
+
return `${messaging_prefix('warn')} ${pintor.yellow(key)} now applies only to ${vendorName} builds, so the ${pintor.blue(browser)} build dropped it.\nRename it to ${pintor.yellow(familyKey)} to keep it on every Chromium-based browser. Leave it as is if it's meant for ${vendorName} only.`;
|
|
1056
|
+
}
|
|
1057
|
+
function prefixScope(prefix) {
|
|
1058
|
+
if ('chrome' === prefix) return 'Chrome';
|
|
1059
|
+
if ('edge' === prefix) return 'Edge';
|
|
1060
|
+
if ('chromium' === prefix) return 'Chromium-based';
|
|
1061
|
+
if ('firefox' === prefix || 'gecko' === prefix) return 'Firefox-based';
|
|
1062
|
+
if ('safari' === prefix || 'webkit' === prefix) return 'Safari';
|
|
1063
|
+
return prefix;
|
|
1064
|
+
}
|
|
1065
|
+
function manifestVersionLostForBrowser(browser, prefixedKeys, resolved) {
|
|
1066
|
+
const target = pintor.blue(browser);
|
|
1067
|
+
const field = pintor.yellow('manifest_version');
|
|
1068
|
+
const scoped = prefixedKeys.map((key)=>{
|
|
1069
|
+
const scope = prefixScope(key.substring(0, key.indexOf(':')));
|
|
1070
|
+
return `${pintor.yellow(key)} applies only to ${scope} builds`;
|
|
1071
|
+
});
|
|
1072
|
+
const lead = void 0 === resolved ? scoped.length ? `${scoped.join(', ')}, so the ${target} build has no ${field}.` : `The ${target} build has no ${field}.` : `The ${target} build resolved ${field} to ${pintor.yellow(JSON.stringify(resolved))}, and browsers load only 2 or 3.`;
|
|
1073
|
+
return `${messaging_prefix('error')} ${lead}\nNo browser loads a manifest without it, so the build was refused. Add a plain ${field}, or scope one to this browser: ${pintor.yellow('chromium:manifest_version')} for every Chromium-based browser, ${pintor.yellow('firefox:manifest_version')} for Firefox.`;
|
|
1074
|
+
}
|
|
1075
|
+
function edgeStoreKeyDropped(browser) {
|
|
1076
|
+
return `${messaging_prefix('warn')} Edge Add-ons refuses a package whose manifest carries ${pintor.yellow('key')}, so the ${pintor.blue(browser)} production build dropped it.\nPartner Center assigns the id that ${pintor.yellow('key')} pins everywhere else, so the field has no use in this package. Write it as ${pintor.yellow('chrome:key')} if it is meant for the Chrome Web Store build only.`;
|
|
1077
|
+
}
|
|
1078
|
+
function mv2SandboxPolicyDropped(browser) {
|
|
1079
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} reads a Manifest V2 ${pintor.yellow('content_security_policy')} as one string, so the ${pintor.yellow('sandbox')} slot has nowhere to go.\nThe build wrote the ${pintor.yellow('extension_pages')} policy as that string and dropped the sandbox policy from the built manifest. Scope the object form with the chromium: prefix, or declare a Manifest V3 build for this browser.`;
|
|
1080
|
+
}
|
|
1081
|
+
function mv3StringPolicyRewritten(browser) {
|
|
1082
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} reads a Manifest V3 ${pintor.yellow('content_security_policy')} as an object, and the manifest wrote the Manifest V2 string form.\nThe build moved that string into the ${pintor.yellow('extension_pages')} slot, which is what the browser refuses to install the extension without. Write the object form in manifest.json, or scope the string with the firefox: prefix for a Manifest V2 build.`;
|
|
1083
|
+
}
|
|
1084
|
+
function mv3BrowserActionFoldedIntoAction(browser) {
|
|
1085
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} replaced ${pintor.yellow('browser_action')} with ${pintor.yellow('action')} in Manifest V3, so the toolbar button never opens under the old key.\nThe build wrote the key as ${pintor.yellow('action')} in the built manifest. Rename it in manifest.json, or scope it with the firefox: prefix for a Manifest V2 build.`;
|
|
1086
|
+
}
|
|
1087
|
+
function mv2ActionFoldedIntoBrowserAction(browser) {
|
|
1088
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} resolved ${pintor.yellow('manifest_version')} to 2, and Manifest V2 has no ${pintor.yellow('action')} key, so the toolbar button and its popup never load.\nThe build wrote the key as ${pintor.yellow('browser_action')} in the built manifest, pointing at the same compiled popup. Scope the Manifest V3 key with the chromium: prefix, or declare ${pintor.yellow('firefox:manifest_version')} 3 to keep it.`;
|
|
1089
|
+
}
|
|
1090
|
+
function sidebarKeyTranslatedForBrowser(browser, from, to) {
|
|
1091
|
+
const permission = 'side_panel' === to ? `, and added the ${pintor.yellow('sidePanel')} permission the panel needs to appear` : '';
|
|
1092
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} reads a sidebar only from ${pintor.yellow(to)}, and the manifest declared ${pintor.yellow(from)} alone, so the panel never opens.\nThe build wrote the key as ${pintor.yellow(to)} in the built manifest${permission}, pointing at the same compiled page. Declare both keys to ship a panel of its own per vendor, or scope ${pintor.yellow(from)} with a prefix to keep it off this build.`;
|
|
1093
|
+
}
|
|
1094
|
+
function mv3BackgroundPageUnsupported(browser) {
|
|
1095
|
+
return `${messaging_prefix('warn')} ${pintor.blue(browser)} has no ${pintor.yellow('background.page')} in Manifest V3, and the extension installs with no background context at all.\nNothing reports that at load time: the background code, the reload bridge and the control channel all go missing silently. The build kept the page as written, so the rest of the extension still loads. Declare ${pintor.yellow('background.service_worker')} instead, or scope the page with the firefox: prefix for a Manifest V2 build.`;
|
|
1096
|
+
}
|
|
1097
|
+
function geckoSidePanelUnsupported(file) {
|
|
1098
|
+
const lines = [];
|
|
1099
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.sidePanel, which is Chromium only.`);
|
|
1100
|
+
lines.push(`Firefox opens a sidebar through the ${pintor.yellow('sidebar_action')} manifest key on every manifest version, and addons-linter flags the call as UNSUPPORTED_API.`);
|
|
1101
|
+
lines.push(`Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')} so the Firefox bundle drops it.`);
|
|
1102
|
+
return lines.join('\n');
|
|
1103
|
+
}
|
|
1104
|
+
function safariUnsupportedApi(file, api, detail) {
|
|
1105
|
+
const lines = [];
|
|
1106
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} calls chrome.${api}, which Safari does not have.`);
|
|
1107
|
+
lines.push(detail);
|
|
1108
|
+
lines.push(`Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or guard it with ${pintor.yellow(`chrome.${api}?.`)}.`);
|
|
1109
|
+
return lines.join('\n');
|
|
1110
|
+
}
|
|
1111
|
+
const safariBackgroundDies = "The call throws when the script runs, Safari drops the background, and nothing reports an error.";
|
|
1112
|
+
function safariSidePanelUnsupported(file) {
|
|
1113
|
+
return safariUnsupportedApi(file, 'sidePanel', "The call throws when the script runs. In a background service worker, Safari then never starts the worker, and nothing reports an error.");
|
|
1114
|
+
}
|
|
1115
|
+
function safariOffscreenUnsupported(file) {
|
|
1116
|
+
return safariUnsupportedApi(file, 'offscreen', `Safari has no offscreen documents, so that DOM work has no place to run. ${safariBackgroundDies}`);
|
|
1117
|
+
}
|
|
1118
|
+
function safariTabGroupsUnsupported(file) {
|
|
1119
|
+
return safariUnsupportedApi(file, 'tabGroups', `Safari has no tab groups, and its tabs carry no group id. ${safariBackgroundDies}`);
|
|
1120
|
+
}
|
|
1121
|
+
function safariManagementUnsupported(file) {
|
|
1122
|
+
return safariUnsupportedApi(file, 'management', `Safari exposes no management namespace at all, not even getSelf. ${safariBackgroundDies}`);
|
|
1123
|
+
}
|
|
1124
|
+
function safariUserScriptsUnsupported(file) {
|
|
1125
|
+
return safariUnsupportedApi(file, 'userScripts', `Safari has no userScripts namespace, and scripting.registerContentScripts is the closest it offers. ${safariBackgroundDies}`);
|
|
1126
|
+
}
|
|
1127
|
+
function safariIdentityUnsupported(file) {
|
|
1128
|
+
return safariUnsupportedApi(file, 'identity', `Safari has no identity namespace, and Apple points OAuth flows at a normal tab instead. ${safariBackgroundDies}`);
|
|
1129
|
+
}
|
|
1130
|
+
function safariNotificationsUnsupported(file) {
|
|
1131
|
+
return safariUnsupportedApi(file, 'notifications', `Safari has no notifications namespace, so a page has to raise the web Notification instead. ${safariBackgroundDies}`);
|
|
1132
|
+
}
|
|
1133
|
+
function safariOmniboxUnsupported(file) {
|
|
1134
|
+
return safariUnsupportedApi(file, 'omnibox', `Safari has no omnibox keyword API. ${safariBackgroundDies}`);
|
|
1135
|
+
}
|
|
1136
|
+
function safariBookmarksUnsupported(file) {
|
|
1137
|
+
return safariUnsupportedApi(file, 'bookmarks', `Safari does not expose bookmarks to extensions on any version. ${safariBackgroundDies}`);
|
|
1138
|
+
}
|
|
1139
|
+
function safariHistoryUnsupported(file) {
|
|
1140
|
+
return safariUnsupportedApi(file, 'history', `Safari does not expose browsing history to extensions on any version. ${safariBackgroundDies}`);
|
|
1141
|
+
}
|
|
1142
|
+
function safariDownloadsUnsupported(file) {
|
|
1143
|
+
return safariUnsupportedApi(file, 'downloads', `Safari has no downloads namespace. ${safariBackgroundDies}`);
|
|
1144
|
+
}
|
|
1145
|
+
function safariIdleUnsupported(file) {
|
|
1146
|
+
return safariUnsupportedApi(file, 'idle', `Safari has no idle namespace. ${safariBackgroundDies}`);
|
|
1147
|
+
}
|
|
1148
|
+
const safariMissingMemberDetails = {
|
|
1149
|
+
'action.getUserSettings': `Safari has no pinned-state query for the toolbar button, so there is no function to call. ${safariBackgroundDies}`,
|
|
1150
|
+
'action.getBadgeTextColor': `Safari draws the badge in its own colors and offers no badge text color call. ${safariBackgroundDies}`,
|
|
1151
|
+
'action.setBadgeTextColor': `Safari draws the badge in its own colors and offers no badge text color call. ${safariBackgroundDies}`,
|
|
1152
|
+
'action.onUserSettingsChanged': `Safari raises no event when the toolbar button settings change, so the listener attaches to nothing. ${safariBackgroundDies}`,
|
|
1153
|
+
'storage.managed': `Safari has no managed storage area, since it carries no enterprise policy channel for web extensions. ${safariBackgroundDies}`,
|
|
1154
|
+
'runtime.getContexts': `Safari keeps no inventory of extension contexts to hand back. ${safariBackgroundDies}`,
|
|
1155
|
+
'runtime.onSuspend': `Safari tears a background down without announcing it, so this lifecycle event does not exist. ${safariBackgroundDies}`,
|
|
1156
|
+
'runtime.onSuspendCanceled': `Safari tears a background down without announcing it, so this lifecycle event does not exist. ${safariBackgroundDies}`,
|
|
1157
|
+
'runtime.onUpdateAvailable': `Safari ships an extension inside its host app, so the browser raises no update event for it. ${safariBackgroundDies}`,
|
|
1158
|
+
'declarativeNetRequest.getAvailableStaticRuleCount': `Safari implements the blocking core of declarativeNetRequest and not its rule-budget queries. ${safariBackgroundDies}`,
|
|
1159
|
+
'declarativeNetRequest.getDisabledRuleIds': `Safari cannot disable individual static rules, so it has nothing to report here. ${safariBackgroundDies}`,
|
|
1160
|
+
'declarativeNetRequest.updateStaticRules': `Safari cannot toggle individual static rules, only whole rulesets through updateEnabledRulesets. ${safariBackgroundDies}`,
|
|
1161
|
+
'declarativeNetRequest.testMatchOutcome': `Safari has no rule-matching test harness, which is a Chrome debugging aid. ${safariBackgroundDies}`,
|
|
1162
|
+
'declarativeNetRequest.onRuleMatchedDebug': `Safari raises no rule-match debug event, which Chrome offers to unpacked extensions only. ${safariBackgroundDies}`,
|
|
1163
|
+
'tabs.group': `Safari has no tab groups at all, so there is no group to move a tab into. ${safariBackgroundDies}`,
|
|
1164
|
+
'tabs.ungroup': `Safari has no tab groups at all, so there is no group to take a tab out of. ${safariBackgroundDies}`,
|
|
1165
|
+
'webNavigation.onCreatedNavigationTarget': `Safari reports the main navigation events only, and this one is not among them. ${safariBackgroundDies}`,
|
|
1166
|
+
'webNavigation.onHistoryStateUpdated': `Safari reports the main navigation events only, so a History API navigation goes unannounced. ${safariBackgroundDies}`,
|
|
1167
|
+
'webNavigation.onReferenceFragmentUpdated': `Safari reports the main navigation events only, so a fragment change goes unannounced. ${safariBackgroundDies}`,
|
|
1168
|
+
'webNavigation.onTabReplaced': `Safari reports the main navigation events only, and this one is not among them. ${safariBackgroundDies}`,
|
|
1169
|
+
'windows.onBoundsChanged': `Safari raises no event when a window is moved or resized. ${safariBackgroundDies}`
|
|
1170
|
+
};
|
|
1171
|
+
function safariMemberUnsupported(file, api, member, kind) {
|
|
1172
|
+
const guard = 'call' === kind ? `chrome.${api}.${member}?.()` : `chrome.${api}.${member}?.`;
|
|
1173
|
+
const lines = [];
|
|
1174
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} calls chrome.${api}.${member}, which Safari does not have.`);
|
|
1175
|
+
lines.push(safariMissingMemberDetails[`${api}.${member}`] || `Safari ships chrome.${api} without this member. ${safariBackgroundDies}`);
|
|
1176
|
+
lines.push(`Safari has ${pintor.blue(`chrome.${api}`)} itself, so a guard on the namespace does not help. Move the call behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or guard it with ${pintor.yellow(guard)}.`);
|
|
1177
|
+
return lines.join('\n');
|
|
1178
|
+
}
|
|
1179
|
+
function geckoActionUnsupportedOnMv2(file) {
|
|
1180
|
+
const lines = [];
|
|
1181
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.underline(file)} uses chrome.action, which Manifest V2 does not have on Firefox.`);
|
|
1182
|
+
lines.push("Firefox Manifest V2 exposes the toolbar button as browserAction, and addons-linter flags the call as UNSUPPORTED_API.");
|
|
1183
|
+
lines.push(`Use browserAction behind a build-time branch on ${pintor.blue('import.meta.env.EXTENSION_PUBLIC_BROWSER')}, or declare Manifest V3 for Firefox with ${pintor.yellow('firefox:manifest_version')}.`);
|
|
1184
|
+
return lines.join('\n');
|
|
1185
|
+
}
|
|
1186
|
+
function contentScriptEntryDroppedForBrowser(index, browser, prefixedKeys) {
|
|
1187
|
+
const lines = [];
|
|
1188
|
+
lines.push(`${messaging_prefix('warn')} ${pintor.yellow(`content_scripts[${String(index)}]`)} has no js and no css in the ${pintor.blue(browser)} build, so the build left it out.`);
|
|
1189
|
+
if (prefixedKeys.length > 0) lines.push(`${prefixedKeys.map((key)=>pintor.yellow(key)).join(', ')} ${1 === prefixedKeys.length ? 'applies' : 'apply'} to another browser. Add ${pintor.yellow(`${browser}:js`)} or a plain ${pintor.yellow('js')} to keep the entry here.`);
|
|
1190
|
+
return lines.join('\n');
|
|
1191
|
+
}
|
|
1192
|
+
function webkitUnsupportedKeysDropped(browser, dropped) {
|
|
1193
|
+
const count = dropped.length;
|
|
1194
|
+
const lines = [];
|
|
1195
|
+
lines.push(`${messaging_prefix('warn')} Safari has no support for ${String(count)} manifest ${1 === count ? 'key' : 'keys'} this project declares, so the ${pintor.blue(browser)} build dropped ${1 === count ? 'it' : 'them'}.`);
|
|
1196
|
+
for (const entry of dropped)lines.push(`${pintor.yellow(entry.path)} ${pintor.gray(entry.reason)}`);
|
|
1197
|
+
lines.push(`Every key above is inert on Safari, so the built app lost nothing it could have run. Declare a Safari-only replacement with the ${pintor.yellow('safari:')} prefix if you have one.`);
|
|
1198
|
+
return lines.join('\n');
|
|
1199
|
+
}
|
|
1200
|
+
const UNSUPPORTED_TOP_LEVEL_KEYS = {
|
|
1201
|
+
side_panel: 'Safari has no side panel surface',
|
|
1202
|
+
sidebar_action: 'Safari has no sidebar surface',
|
|
1203
|
+
sandbox: 'Safari cannot run sandboxed extension pages',
|
|
1204
|
+
user_scripts: 'Safari has no userScripts API',
|
|
1205
|
+
omnibox: 'Safari has no omnibox keyword API',
|
|
1206
|
+
chrome_settings_overrides: 'Safari lets no extension override these settings',
|
|
1207
|
+
tts_engine: 'Safari has no speech engine API',
|
|
1208
|
+
file_browser_handlers: 'ChromeOS only',
|
|
1209
|
+
input_components: 'ChromeOS only',
|
|
1210
|
+
cross_origin_embedder_policy: 'Safari reads no COEP key from a manifest',
|
|
1211
|
+
cross_origin_opener_policy: 'Safari reads no COOP key from a manifest',
|
|
1212
|
+
requirements: 'Chrome Web Store only',
|
|
1213
|
+
oauth2: 'Safari has no identity API to consume it',
|
|
1214
|
+
nacl_modules: 'Native Client is Chrome only',
|
|
1215
|
+
replacement_web_app: 'Chrome Web Store only',
|
|
1216
|
+
offline_enabled: 'Chrome Web Store only',
|
|
1217
|
+
differential_fingerprint: 'Chrome Web Store only',
|
|
1218
|
+
incognito: 'Safari always runs extensions in spanning mode and ignores the declared value'
|
|
1219
|
+
};
|
|
1220
|
+
const UNSUPPORTED_PERMISSIONS = new Set([
|
|
1221
|
+
'accessibilityFeatures.modify',
|
|
1222
|
+
'accessibilityFeatures.read',
|
|
1223
|
+
'audio',
|
|
1224
|
+
'background',
|
|
1225
|
+
'bookmarks',
|
|
1226
|
+
'browsingData',
|
|
1227
|
+
'certificateProvider',
|
|
1228
|
+
'clipboardRead',
|
|
1229
|
+
'contentSettings',
|
|
1230
|
+
'debugger',
|
|
1231
|
+
'declarativeContent',
|
|
1232
|
+
'desktopCapture',
|
|
1233
|
+
'documentScan',
|
|
1234
|
+
'downloads',
|
|
1235
|
+
'enterprise.deviceAttributes',
|
|
1236
|
+
'enterprise.platformKeys',
|
|
1237
|
+
'experimental',
|
|
1238
|
+
'favicon',
|
|
1239
|
+
'fileSystemProvider',
|
|
1240
|
+
'fontSettings',
|
|
1241
|
+
'gcm',
|
|
1242
|
+
'geolocation',
|
|
1243
|
+
'history',
|
|
1244
|
+
'identity',
|
|
1245
|
+
'identity.email',
|
|
1246
|
+
'idle',
|
|
1247
|
+
'management',
|
|
1248
|
+
'notifications',
|
|
1249
|
+
'offscreen',
|
|
1250
|
+
'pageCapture',
|
|
1251
|
+
'platformKeys',
|
|
1252
|
+
'power',
|
|
1253
|
+
'printerProvider',
|
|
1254
|
+
'privacy',
|
|
1255
|
+
'processes',
|
|
1256
|
+
'proxy',
|
|
1257
|
+
'readingList',
|
|
1258
|
+
'search',
|
|
1259
|
+
'sessions',
|
|
1260
|
+
'sidePanel',
|
|
1261
|
+
'system.cpu',
|
|
1262
|
+
'system.display',
|
|
1263
|
+
'system.memory',
|
|
1264
|
+
'system.storage',
|
|
1265
|
+
'systemLog',
|
|
1266
|
+
'tabCapture',
|
|
1267
|
+
'tabGroups',
|
|
1268
|
+
'topSites',
|
|
1269
|
+
'tts',
|
|
1270
|
+
'ttsEngine',
|
|
1271
|
+
'userScripts',
|
|
1272
|
+
'vpnProvider',
|
|
1273
|
+
'wallpaper',
|
|
1274
|
+
'webAuthenticationProxy',
|
|
1275
|
+
'webRequestBlocking'
|
|
1276
|
+
]);
|
|
1277
|
+
const PERMISSION_LISTS = [
|
|
1278
|
+
'permissions',
|
|
1279
|
+
'optional_permissions'
|
|
1280
|
+
];
|
|
1281
|
+
function isWebkitUnsupportedPermission(permission, browser) {
|
|
1282
|
+
return isWebkitBasedBrowser(String(browser)) && UNSUPPORTED_PERMISSIONS.has(permission);
|
|
1283
|
+
}
|
|
1284
|
+
const UNSUPPORTED_OPTIONS_UI_KEYS = {
|
|
1285
|
+
open_in_tab: 'Safari always opens the options page in a tab'
|
|
1286
|
+
};
|
|
1287
|
+
function isPlainObject(value) {
|
|
1288
|
+
return !!value && 'object' == typeof value && !Array.isArray(value);
|
|
1289
|
+
}
|
|
1290
|
+
function dropWebkitUnsupportedKeys(manifest, browser) {
|
|
1291
|
+
const dropped = [];
|
|
1292
|
+
if (!isWebkitBasedBrowser(String(browser))) return {
|
|
1293
|
+
manifest,
|
|
1294
|
+
dropped
|
|
1295
|
+
};
|
|
1296
|
+
const next = {
|
|
1297
|
+
...manifest
|
|
1298
|
+
};
|
|
1299
|
+
for (const [key, reason] of Object.entries(UNSUPPORTED_TOP_LEVEL_KEYS))if (key in next) {
|
|
1300
|
+
delete next[key];
|
|
1301
|
+
dropped.push({
|
|
1302
|
+
path: key,
|
|
1303
|
+
reason
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
for (const listName of PERMISSION_LISTS){
|
|
1307
|
+
const list = next[listName];
|
|
1308
|
+
if (!Array.isArray(list)) continue;
|
|
1309
|
+
const kept = list.filter((entry)=>{
|
|
1310
|
+
if ('string' != typeof entry || !UNSUPPORTED_PERMISSIONS.has(entry)) return true;
|
|
1311
|
+
dropped.push({
|
|
1312
|
+
path: `${listName}.${entry}`,
|
|
1313
|
+
reason: `Safari has no ${entry} API`
|
|
1314
|
+
});
|
|
1315
|
+
return false;
|
|
1316
|
+
});
|
|
1317
|
+
if (kept.length !== list.length) if (0 === kept.length) delete next[listName];
|
|
1318
|
+
else next[listName] = kept;
|
|
1319
|
+
}
|
|
1320
|
+
const optionsUi = next.options_ui;
|
|
1321
|
+
if (isPlainObject(optionsUi)) {
|
|
1322
|
+
const patched = {
|
|
1323
|
+
...optionsUi
|
|
1324
|
+
};
|
|
1325
|
+
let changed = false;
|
|
1326
|
+
for (const [key, reason] of Object.entries(UNSUPPORTED_OPTIONS_UI_KEYS))if (key in patched) {
|
|
1327
|
+
delete patched[key];
|
|
1328
|
+
changed = true;
|
|
1329
|
+
dropped.push({
|
|
1330
|
+
path: `options_ui.${key}`,
|
|
1331
|
+
reason
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
if (changed) next.options_ui = patched;
|
|
1335
|
+
}
|
|
1336
|
+
return {
|
|
1337
|
+
manifest: next,
|
|
1338
|
+
dropped
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
function omitWebkitDroppedEntries(entries, dropped) {
|
|
1342
|
+
const owners = new Set(dropped.map((entry)=>entry.path));
|
|
1343
|
+
if (0 === owners.size) return entries;
|
|
1344
|
+
return Object.fromEntries(Object.entries(entries).filter(([feature])=>!owners.has(feature.split('/')[0])));
|
|
1345
|
+
}
|
|
1346
|
+
const reportedDrops = new Set();
|
|
1347
|
+
function reportWebkitDroppedKeys(dropped, browser) {
|
|
1348
|
+
if (0 === dropped.length) return;
|
|
1349
|
+
const signature = `${String(browser)}\0${dropped.map((entry)=>entry.path).join(',')}`;
|
|
1350
|
+
if (reportedDrops.has(signature)) return;
|
|
1351
|
+
reportedDrops.add(signature);
|
|
1352
|
+
humanLine(webkitUnsupportedKeysDropped(String(browser), dropped));
|
|
1353
|
+
}
|
|
1354
|
+
const cjsRequire = createRequire(import.meta.url);
|
|
1355
|
+
const manifestSourceStore = new WeakMap();
|
|
1356
|
+
function manifestSourceEntry(compilation) {
|
|
1357
|
+
let entry = manifestSourceStore.get(compilation);
|
|
1358
|
+
if (!entry) {
|
|
1359
|
+
entry = {};
|
|
1360
|
+
manifestSourceStore.set(compilation, entry);
|
|
1361
|
+
}
|
|
1362
|
+
return entry;
|
|
1363
|
+
}
|
|
1364
|
+
function readAssetSource(asset) {
|
|
1365
|
+
if (!asset) return '';
|
|
1366
|
+
const source = asset.source;
|
|
1367
|
+
if ('string' == typeof source) return source;
|
|
1368
|
+
if ('function' == typeof source) {
|
|
1369
|
+
const out = source();
|
|
1370
|
+
return 'string' == typeof out ? out : String(out || '');
|
|
1371
|
+
}
|
|
1372
|
+
if (source && 'function' == typeof source.source) {
|
|
1373
|
+
const out = source.source();
|
|
1374
|
+
return 'string' == typeof out ? out : String(out || '');
|
|
1375
|
+
}
|
|
1376
|
+
return '';
|
|
1377
|
+
}
|
|
1378
|
+
function setOriginalManifestContent(compilation, source) {
|
|
1379
|
+
manifestSourceEntry(compilation).original = source;
|
|
1380
|
+
}
|
|
1381
|
+
function getOriginalManifestContent(compilation) {
|
|
1382
|
+
return manifestSourceStore.get(compilation)?.original;
|
|
1383
|
+
}
|
|
1384
|
+
function setCurrentManifestContent(compilation, source) {
|
|
1385
|
+
manifestSourceEntry(compilation).current = source;
|
|
1386
|
+
}
|
|
1387
|
+
function getCurrentManifestContent(compilation) {
|
|
1388
|
+
return manifestSourceStore.get(compilation)?.current;
|
|
1389
|
+
}
|
|
1390
|
+
function getManifestContent(compilation, manifestPath) {
|
|
1391
|
+
const currentManifest = getCurrentManifestContent(compilation);
|
|
1392
|
+
if (currentManifest) return parseJsonSafe(currentManifest);
|
|
1393
|
+
const getAsset = compilation.getAsset;
|
|
1394
|
+
if ('function' == typeof getAsset) {
|
|
1395
|
+
const manifestAsset = getAsset.call(compilation, 'manifest.json');
|
|
1396
|
+
const manifest = readAssetSource(manifestAsset);
|
|
1397
|
+
if (manifest) return parseJsonSafe(manifest);
|
|
1398
|
+
}
|
|
1399
|
+
const manifestAsset = compilation.assets?.['manifest.json'];
|
|
1400
|
+
if (manifestAsset) {
|
|
1401
|
+
const manifest = readAssetSource(manifestAsset);
|
|
1402
|
+
if (manifest) return parseJsonSafe(manifest);
|
|
1403
|
+
}
|
|
1404
|
+
const originalManifest = getOriginalManifestContent(compilation);
|
|
1405
|
+
if (originalManifest) return parseJsonSafe(originalManifest);
|
|
1406
|
+
try {
|
|
1407
|
+
const text = __rspack_external_node_fs_1b05aee1.readFileSync(manifestPath, 'utf8');
|
|
1408
|
+
return parseJsonSafe(text);
|
|
1409
|
+
} catch {
|
|
1410
|
+
try {
|
|
1411
|
+
const resolved = cjsRequire.resolve(manifestPath);
|
|
1412
|
+
delete cjsRequire.cache[resolved];
|
|
1413
|
+
} catch {}
|
|
1414
|
+
return cjsRequire(manifestPath);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
function buildCanonicalManifestWithOverrides(manifestPath, manifest, browser, projectPath) {
|
|
1418
|
+
const filteredManifest = filterKeysForThisBrowser(manifest, browser);
|
|
1419
|
+
const withoutPageAction = shouldDropPageAction(filteredManifest, browser) ? dropPageAction(filteredManifest) : filteredManifest;
|
|
1420
|
+
const forOverrides = foldBrowserActionIntoAction(withoutPageAction);
|
|
1421
|
+
const overrides = getManifestOverrides(manifestPath, forOverrides, projectPath);
|
|
1422
|
+
const canonical = dropMv2ObjectPolicy(dropMv2HostKeys({
|
|
1423
|
+
...forOverrides,
|
|
1424
|
+
...JSON.parse(overrides)
|
|
1425
|
+
}));
|
|
1426
|
+
const translated = foldActionIntoBrowserAction(foldSidebarKeyForBrowser(canonical, browser));
|
|
1427
|
+
const webkit = dropWebkitUnsupportedKeys(translated, browser);
|
|
1428
|
+
reportWebkitDroppedKeys(webkit.dropped, browser);
|
|
1429
|
+
return {
|
|
1430
|
+
manifest: webkit.manifest,
|
|
1431
|
+
overrides
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
function boring(manifestName, durationMs, stats) {
|
|
1435
|
+
const now = new Date();
|
|
1436
|
+
const hh = String(now.getHours()).padStart(2, '0');
|
|
1437
|
+
const mm = String(now.getMinutes()).padStart(2, '0');
|
|
1438
|
+
const ss = String(now.getSeconds()).padStart(2, '0');
|
|
1439
|
+
const timestamp = pintor.gray(`[${hh}:${mm}:${ss}]`);
|
|
1440
|
+
const hasErrors = stats.hasErrors();
|
|
1441
|
+
const hasWarnings = stats.hasWarnings();
|
|
1442
|
+
const arrow = hasErrors ? messaging_prefix('error') : hasWarnings ? messaging_prefix('warn') : messaging_prefix('info');
|
|
1443
|
+
const status = hasErrors ? `compiled ${pintor.red('with errors')}` : hasWarnings ? `compiled ${pintor.yellow('with warnings')}` : 'compiled';
|
|
1444
|
+
const app = manifestName;
|
|
1445
|
+
const time = `${durationMs} ms`;
|
|
1446
|
+
return `${arrow} ${timestamp} ${app} ${status} in ${time}.`;
|
|
1447
|
+
}
|
|
1448
|
+
function cleanDistStarting(distPath) {
|
|
1449
|
+
return `${messaging_prefix('debug')} clean start path=${distPath}`;
|
|
1450
|
+
}
|
|
1451
|
+
function cleanDistRemovedSummary(removedCount, distPath) {
|
|
1452
|
+
return `${messaging_prefix('debug')} clean removed=${removedCount} path=${distPath}`;
|
|
1453
|
+
}
|
|
1454
|
+
function cleanDistSkippedNotFound(distPath) {
|
|
1455
|
+
return `${messaging_prefix('debug')} clean skipped=not-found path=${distPath}`;
|
|
1456
|
+
}
|
|
1457
|
+
function zipPackagingSkipped(reason) {
|
|
1458
|
+
return `${messaging_prefix('debug')} zip skipped=true reason="${reason}"`;
|
|
1459
|
+
}
|
|
1460
|
+
function envSelectedFile(envPath) {
|
|
1461
|
+
return `${messaging_prefix('debug')} env file=${envPath || 'none'}`;
|
|
1462
|
+
}
|
|
1463
|
+
function envInjectedPublicVars(count) {
|
|
1464
|
+
return `${messaging_prefix('debug')} env injected=${count} prefix=EXTENSION_PUBLIC_`;
|
|
1465
|
+
}
|
|
1466
|
+
function envValueBreaksJsonAsset(asset, names) {
|
|
1467
|
+
return `${pintor.yellow(asset)} is not valid JSON after substituting ${names.map((name)=>pintor.yellow(`$${name}`)).join(', ')}.\nQuote the placeholder to get a JSON string: ${pintor.gray(`"$${names[0]}"`)}. An unquoted placeholder takes the value as written, so the value must be JSON itself.`;
|
|
1468
|
+
}
|
|
1469
|
+
function projectConfigChangedRestartRequired(configPath) {
|
|
1470
|
+
return `${pintor.yellow(displayPath(configPath))} changed. This session keeps running the config it read at startup.\nStop it and run ${pintor.blue('extension dev')} again to apply the change.`;
|
|
1471
|
+
}
|
|
1472
|
+
function envChangedRestartRequired(envPath) {
|
|
1473
|
+
return `${pintor.yellow(displayPath(envPath))} changed. The values this build inlined are the ones read when the compiler started.\nRestart the dev server to apply the change.`;
|
|
1474
|
+
}
|
|
1475
|
+
function envNoMatchingFile(browser, mode, presentFiles, expectedCandidates) {
|
|
1476
|
+
return `Found ${presentFiles.map((file)=>pintor.yellow(file)).join(', ')}, but none match browser ${pintor.yellow(browser)} in mode ${pintor.yellow(mode)}.\nEXTENSION_PUBLIC_* variables read from code are ${pintor.yellow('undefined')} in this build.\nRename the file to one of these, in priority order: ${expectedCandidates.map((file)=>pintor.gray(file)).join(', ')}.\nFamily names apply to every family member, so ${pintor.yellow('.env.chrome')} also matches ${pintor.yellow('chromium')} and ${pintor.yellow('edge')} targets.`;
|
|
1477
|
+
}
|
|
1478
|
+
const DEV_SESSION_RESTART_DEBOUNCE_MS = 300;
|
|
1479
|
+
class DevSessionRestartScheduler {
|
|
1480
|
+
debounceMs;
|
|
1481
|
+
handler = null;
|
|
1482
|
+
timer;
|
|
1483
|
+
latest = null;
|
|
1484
|
+
inFlight = false;
|
|
1485
|
+
constructor(debounceMs = DEV_SESSION_RESTART_DEBOUNCE_MS){
|
|
1486
|
+
this.debounceMs = Math.max(0, debounceMs);
|
|
1487
|
+
}
|
|
1488
|
+
setHandler(handler) {
|
|
1489
|
+
this.handler = handler;
|
|
1490
|
+
}
|
|
1491
|
+
request(request) {
|
|
1492
|
+
this.latest = request;
|
|
1493
|
+
if (this.inFlight) return;
|
|
1494
|
+
this.schedule();
|
|
1495
|
+
}
|
|
1496
|
+
isPending() {
|
|
1497
|
+
return null != this.latest || this.inFlight;
|
|
1498
|
+
}
|
|
1499
|
+
dispose() {
|
|
1500
|
+
if (this.timer) clearTimeout(this.timer);
|
|
1501
|
+
this.timer = void 0;
|
|
1502
|
+
this.latest = null;
|
|
1503
|
+
this.handler = null;
|
|
1504
|
+
}
|
|
1505
|
+
schedule() {
|
|
1506
|
+
if (this.timer) clearTimeout(this.timer);
|
|
1507
|
+
if (0 === this.debounceMs) return void this.flush();
|
|
1508
|
+
this.timer = setTimeout(()=>{
|
|
1509
|
+
this.timer = void 0;
|
|
1510
|
+
this.flush();
|
|
1511
|
+
}, this.debounceMs);
|
|
1512
|
+
this.timer.unref?.();
|
|
1513
|
+
}
|
|
1514
|
+
async flush() {
|
|
1515
|
+
if (this.inFlight) return;
|
|
1516
|
+
const request = this.latest;
|
|
1517
|
+
const handler = this.handler;
|
|
1518
|
+
if (!request || !handler) return;
|
|
1519
|
+
this.latest = null;
|
|
1520
|
+
this.inFlight = true;
|
|
1521
|
+
try {
|
|
1522
|
+
await handler(request);
|
|
1523
|
+
} catch {} finally{
|
|
1524
|
+
this.inFlight = false;
|
|
1525
|
+
if (this.latest) this.schedule();
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
let boundScheduler = null;
|
|
1530
|
+
const restartingCompilers = new WeakSet();
|
|
1531
|
+
function bindDevSessionRestart(scheduler) {
|
|
1532
|
+
boundScheduler = scheduler;
|
|
1533
|
+
}
|
|
1534
|
+
function unbindDevSessionRestart() {
|
|
1535
|
+
boundScheduler = null;
|
|
1536
|
+
}
|
|
1537
|
+
function requestDevSessionRestart(compiler, request) {
|
|
1538
|
+
if (!boundScheduler) return false;
|
|
1539
|
+
if (compiler) restartingCompilers.add(compiler);
|
|
1540
|
+
boundScheduler.request(request);
|
|
1541
|
+
return true;
|
|
1542
|
+
}
|
|
1543
|
+
function isCompilerRestarting(compiler) {
|
|
1544
|
+
return null != compiler && restartingCompilers.has(compiler);
|
|
1545
|
+
}
|
|
1546
|
+
class WatchEnvFilesPlugin {
|
|
1547
|
+
static name = 'plugin-compilation:watch-env-files';
|
|
1548
|
+
candidates;
|
|
1549
|
+
watched;
|
|
1550
|
+
changedPath = null;
|
|
1551
|
+
constructor(paths){
|
|
1552
|
+
this.candidates = Array.from(new Set(paths.filter((file)=>Boolean(file)).map((file)=>__rspack_external_node_path_806ed179.resolve(file))));
|
|
1553
|
+
this.watched = new Set(this.candidates);
|
|
1554
|
+
}
|
|
1555
|
+
collectChange(compiler) {
|
|
1556
|
+
const touched = [
|
|
1557
|
+
...compiler.modifiedFiles || [],
|
|
1558
|
+
...compiler.removedFiles || []
|
|
1559
|
+
];
|
|
1560
|
+
for (const file of touched){
|
|
1561
|
+
const resolved = __rspack_external_node_path_806ed179.resolve(file);
|
|
1562
|
+
if (this.watched.has(resolved)) {
|
|
1563
|
+
this.changedPath = resolved;
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
addDependencies(compilation) {
|
|
1569
|
+
for (const candidate of this.candidates)if (__rspack_external_node_fs_1b05aee1.existsSync(candidate)) compilation.fileDependencies?.add(candidate);
|
|
1570
|
+
else compilation.missingDependencies?.add(candidate);
|
|
1571
|
+
}
|
|
1572
|
+
apply(compiler) {
|
|
1573
|
+
if (0 === this.candidates.length) return;
|
|
1574
|
+
compiler.hooks.watchRun.tap(WatchEnvFilesPlugin.name, ()=>{
|
|
1575
|
+
this.collectChange(compiler);
|
|
1576
|
+
});
|
|
1577
|
+
compiler.hooks.thisCompilation.tap(WatchEnvFilesPlugin.name, (compilation)=>{
|
|
1578
|
+
this.addDependencies(compilation);
|
|
1579
|
+
const changedPath = this.changedPath;
|
|
1580
|
+
if (!changedPath) return;
|
|
1581
|
+
this.changedPath = null;
|
|
1582
|
+
if (requestDevSessionRestart(compiler, {
|
|
1583
|
+
reason: 'env',
|
|
1584
|
+
pathChanged: changedPath
|
|
1585
|
+
})) return;
|
|
1586
|
+
const warning = new WebpackError(envChangedRestartRequired(changedPath));
|
|
1587
|
+
warning.name = 'EnvFileChange';
|
|
1588
|
+
warning.file = __rspack_external_node_path_806ed179.basename(changedPath);
|
|
1589
|
+
compilation.warnings?.push(warning);
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
const IMPORT_META_URL_RUNTIME = '(function(){var h=typeof document!=="undefined"&&document.baseURI||self.location.href;try{var g=globalThis,r=(g.browser||g.chrome).runtime.getURL("/");return h.indexOf(r)===0?h:r}catch(_){return h}})()';
|
|
1594
|
+
function importMetaUrlForEmitPath(emitPath) {
|
|
1595
|
+
const request = emitPath.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
1596
|
+
return `(function(){try{var g=globalThis;return (g.browser||g.chrome).runtime.getURL(${toJsStringLiteral(request)})}catch(_){return ${IMPORT_META_URL_RUNTIME}}})()`;
|
|
1597
|
+
}
|
|
1598
|
+
function toJsStringLiteral(value) {
|
|
1599
|
+
return JSON.stringify(value).replace(/[<>\u007f-\uffff]/g, (char)=>`\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
|
1600
|
+
}
|
|
1601
|
+
function escapeForJsonAsset(value) {
|
|
1602
|
+
return JSON.stringify(value).slice(1, -1);
|
|
1603
|
+
}
|
|
1604
|
+
const HTML_ENTITIES = {
|
|
1605
|
+
'&': '&',
|
|
1606
|
+
'<': '<',
|
|
1607
|
+
'>': '>',
|
|
1608
|
+
'"': '"',
|
|
1609
|
+
"'": '''
|
|
1610
|
+
};
|
|
1611
|
+
function rawTextElementAt(content, offset) {
|
|
1612
|
+
const before = content.slice(0, offset).toLowerCase();
|
|
1613
|
+
for (const tag of [
|
|
1614
|
+
"script",
|
|
1615
|
+
'style'
|
|
1616
|
+
]){
|
|
1617
|
+
const open = before.lastIndexOf(`<${tag}`);
|
|
1618
|
+
const openEnd = before.indexOf('>', open);
|
|
1619
|
+
if (-1 !== open && open > before.lastIndexOf(`</${tag}`) && -1 !== openEnd) return {
|
|
1620
|
+
tag,
|
|
1621
|
+
textStart: openEnd + 1
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
function insideStringLiteral(text, quotes, templates) {
|
|
1626
|
+
let quote = '';
|
|
1627
|
+
const expressions = [];
|
|
1628
|
+
for(let i = 0; i < text.length; i++){
|
|
1629
|
+
const char = text[i];
|
|
1630
|
+
if (quote) {
|
|
1631
|
+
if ('\\' === char) i++;
|
|
1632
|
+
else if ('`' === quote && '$' === char && '{' === text[i + 1]) {
|
|
1633
|
+
expressions.push(0);
|
|
1634
|
+
quote = '';
|
|
1635
|
+
i++;
|
|
1636
|
+
} else if (char === quote) quote = '';
|
|
1637
|
+
continue;
|
|
1638
|
+
}
|
|
1639
|
+
if ('/' === char && '/' === text[i + 1]) {
|
|
1640
|
+
const end = text.indexOf('\n', i);
|
|
1641
|
+
if (-1 === end) return false;
|
|
1642
|
+
i = end;
|
|
1643
|
+
} else if ('/' === char && '*' === text[i + 1]) {
|
|
1644
|
+
const end = text.indexOf('*/', i + 2);
|
|
1645
|
+
if (-1 === end) return false;
|
|
1646
|
+
i = end + 1;
|
|
1647
|
+
} else if (quotes.includes(char) || templates && '`' === char) quote = char;
|
|
1648
|
+
else if (expressions.length && '{' === char) expressions[expressions.length - 1]++;
|
|
1649
|
+
else if (expressions.length && '}' === char) if (0 === expressions[expressions.length - 1]) {
|
|
1650
|
+
expressions.pop();
|
|
1651
|
+
quote = '`';
|
|
1652
|
+
} else expressions[expressions.length - 1]--;
|
|
1653
|
+
}
|
|
1654
|
+
return '' !== quote;
|
|
1655
|
+
}
|
|
1656
|
+
function isInsideJsonString(content, offset) {
|
|
1657
|
+
return insideStringLiteral(content.slice(0, offset), '"', false);
|
|
1658
|
+
}
|
|
1659
|
+
function substituteForJsonAsset(content, offset, value) {
|
|
1660
|
+
return isInsideJsonString(content, offset) ? escapeForJsonAsset(value) : value;
|
|
1661
|
+
}
|
|
1662
|
+
function escapeForHtmlAsset(content, offset, value) {
|
|
1663
|
+
const element = rawTextElementAt(content, offset);
|
|
1664
|
+
if (element?.tag === "script") {
|
|
1665
|
+
const script = content.slice(element.textStart, offset);
|
|
1666
|
+
if (!insideStringLiteral(script, '"\'', true)) return value.replace(/<\/(script)/gi, '<\\/$1').replace(/<!--/g, '<\\!--');
|
|
1667
|
+
return toJsStringLiteral(value).slice(1, -1).replace(/'/g, '\\u0027').replace(/`/g, '\\u0060').replace(/\$\{/g, '\\u0024{');
|
|
1668
|
+
}
|
|
1669
|
+
if (element?.tag === 'style') return value;
|
|
1670
|
+
return value.replace(/[&<>"']/g, (char)=>HTML_ENTITIES[char]);
|
|
1671
|
+
}
|
|
1672
|
+
function parsesAsJson(text) {
|
|
1673
|
+
try {
|
|
1674
|
+
JSON.parse(text);
|
|
1675
|
+
return true;
|
|
1676
|
+
} catch {
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
function resolveProcessShim() {
|
|
1681
|
+
const candidate = __rspack_external_node_path_806ed179.join(__rspack_import_meta_dirname__, '..', 'runtime', 'process-shim.cjs');
|
|
1682
|
+
try {
|
|
1683
|
+
return __rspack_external_node_fs_1b05aee1.existsSync(candidate) ? candidate : void 0;
|
|
1684
|
+
} catch {
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
function findNearestWorkspaceRoot(startDir) {
|
|
1689
|
+
let current = __rspack_external_node_path_806ed179.isAbsolute(startDir) ? __rspack_external_node_path_806ed179.normalize(startDir) : __rspack_external_node_path_806ed179.resolve(startDir);
|
|
1690
|
+
while(true){
|
|
1691
|
+
if (__rspack_external_node_fs_1b05aee1.existsSync(__rspack_external_node_path_806ed179.join(current, 'pnpm-workspace.yaml'))) return current;
|
|
1692
|
+
const parent = __rspack_external_node_path_806ed179.dirname(current);
|
|
1693
|
+
if (parent === current) return;
|
|
1694
|
+
current = parent;
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
function resolveEnvPaths(projectPath, envFiles) {
|
|
1698
|
+
const localEnvPath = envFiles.map((file)=>__rspack_external_node_path_806ed179.join(projectPath, file)).find((filePath)=>__rspack_external_node_fs_1b05aee1.existsSync(filePath)) || '';
|
|
1699
|
+
const localDefaultsPath = __rspack_external_node_path_806ed179.join(projectPath, '.env.defaults');
|
|
1700
|
+
if (localEnvPath) return {
|
|
1701
|
+
envPath: localEnvPath,
|
|
1702
|
+
defaultsPath: localDefaultsPath
|
|
1703
|
+
};
|
|
1704
|
+
const workspaceRoot = findNearestWorkspaceRoot(projectPath);
|
|
1705
|
+
if (workspaceRoot && workspaceRoot !== projectPath) {
|
|
1706
|
+
const workspaceEnvPath = envFiles.map((file)=>__rspack_external_node_path_806ed179.join(workspaceRoot, file)).find((filePath)=>__rspack_external_node_fs_1b05aee1.existsSync(filePath)) || '';
|
|
1707
|
+
const workspaceDefaultsPath = __rspack_external_node_path_806ed179.join(workspaceRoot, '.env.defaults');
|
|
1708
|
+
if (workspaceEnvPath || __rspack_external_node_fs_1b05aee1.existsSync(workspaceDefaultsPath)) return {
|
|
1709
|
+
envPath: workspaceEnvPath,
|
|
1710
|
+
defaultsPath: __rspack_external_node_fs_1b05aee1.existsSync(localDefaultsPath) ? localDefaultsPath : workspaceDefaultsPath,
|
|
1711
|
+
fallbackDefaultsPath: __rspack_external_node_fs_1b05aee1.existsSync(localDefaultsPath) ? workspaceDefaultsPath : void 0
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1714
|
+
if (__rspack_external_node_fs_1b05aee1.existsSync(localDefaultsPath)) return {
|
|
1715
|
+
envPath: localEnvPath,
|
|
1716
|
+
defaultsPath: localDefaultsPath
|
|
1717
|
+
};
|
|
1718
|
+
return {
|
|
1719
|
+
envPath: '',
|
|
1720
|
+
defaultsPath: localDefaultsPath
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
function getEnvFileCandidates(browser, mode) {
|
|
1724
|
+
const browserName = String(browser);
|
|
1725
|
+
const isChromiumTarget = isChromiumBasedBrowser(browserName) || 'safari' === browserName || browserName.includes('webkit');
|
|
1726
|
+
const familyNames = isChromiumTarget ? CHROMIUM_FAMILY_ALIASES : isGeckoBasedBrowser(browserName) ? GECKO_FAMILY_ALIASES : [];
|
|
1727
|
+
const names = [
|
|
1728
|
+
browserName,
|
|
1729
|
+
...familyNames.filter((name)=>name !== browserName)
|
|
1730
|
+
];
|
|
1731
|
+
return [
|
|
1732
|
+
...names.flatMap((name)=>[
|
|
1733
|
+
`.env.${name}.${mode}`,
|
|
1734
|
+
`.env.${name}`
|
|
1735
|
+
]),
|
|
1736
|
+
`.env.${mode}`,
|
|
1737
|
+
'.env.local',
|
|
1738
|
+
'.env'
|
|
1739
|
+
];
|
|
1740
|
+
}
|
|
1741
|
+
class EnvPlugin {
|
|
1742
|
+
browser;
|
|
1743
|
+
manifestPath;
|
|
1744
|
+
define;
|
|
1745
|
+
constructor(options){
|
|
1746
|
+
this.browser = options.browser || 'chrome';
|
|
1747
|
+
this.manifestPath = options.manifestPath;
|
|
1748
|
+
this.define = options.define;
|
|
1749
|
+
}
|
|
1750
|
+
apply(compiler) {
|
|
1751
|
+
const projectPath = compiler.options.context || (this.manifestPath ? __rspack_external_node_path_806ed179.dirname(this.manifestPath) : '');
|
|
1752
|
+
const mode = compiler.options.mode || 'development';
|
|
1753
|
+
const envFiles = getEnvFileCandidates(this.browser, mode);
|
|
1754
|
+
const { envPath, defaultsPath, fallbackDefaultsPath } = resolveEnvPaths(projectPath, envFiles);
|
|
1755
|
+
if (isDebug()) debugLine(envSelectedFile(envPath));
|
|
1756
|
+
if (projectPath && compiler.options.watchOptions) new WatchEnvFilesPlugin([
|
|
1757
|
+
...envFiles.map((file)=>__rspack_external_node_path_806ed179.join(projectPath, file)),
|
|
1758
|
+
__rspack_external_node_path_806ed179.join(projectPath, '.env.defaults'),
|
|
1759
|
+
envPath,
|
|
1760
|
+
defaultsPath,
|
|
1761
|
+
fallbackDefaultsPath
|
|
1762
|
+
]).apply(compiler);
|
|
1763
|
+
if (!envPath && projectPath) {
|
|
1764
|
+
let unmatchedEnvFiles = [];
|
|
1765
|
+
try {
|
|
1766
|
+
unmatchedEnvFiles = __rspack_external_node_fs_1b05aee1.readdirSync(projectPath).filter((file)=>file.startsWith('.env') && '.env.defaults' !== file && '.env.example' !== file).sort();
|
|
1767
|
+
} catch {}
|
|
1768
|
+
if (unmatchedEnvFiles.length > 0) compiler.hooks.thisCompilation.tap('env:warn-unmatched', (compilation)=>{
|
|
1769
|
+
const warn = new WebpackError(envNoMatchingFile(String(this.browser), String(mode), unmatchedEnvFiles, envFiles));
|
|
1770
|
+
warn.name = 'EnvNoMatchingFile';
|
|
1771
|
+
compilation.warnings.push(warn);
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1774
|
+
const envVars = envPath ? __rspack_external_dotenv.parse(__rspack_external_node_fs_1b05aee1.readFileSync(envPath)) : {};
|
|
1775
|
+
const readDefaults = (filePath)=>filePath && __rspack_external_node_fs_1b05aee1.existsSync(filePath) ? __rspack_external_dotenv.parse(__rspack_external_node_fs_1b05aee1.readFileSync(filePath)) : {};
|
|
1776
|
+
const defaultsVars = {
|
|
1777
|
+
...readDefaults(fallbackDefaultsPath),
|
|
1778
|
+
...readDefaults(defaultsPath)
|
|
1779
|
+
};
|
|
1780
|
+
const preloadedKeys = getPreloadedEnvKeys();
|
|
1781
|
+
const systemEnv = Object.fromEntries(Object.entries(process.env).filter(([key])=>!preloadedKeys.has(key)));
|
|
1782
|
+
const combinedVars = {
|
|
1783
|
+
...defaultsVars,
|
|
1784
|
+
...envVars,
|
|
1785
|
+
...systemEnv
|
|
1786
|
+
};
|
|
1787
|
+
const filteredEnvVars = Object.keys(combinedVars).filter((key)=>key.startsWith('EXTENSION_PUBLIC_')).reduce((obj, key)=>{
|
|
1788
|
+
obj[`process.env.${key}`] = JSON.stringify(combinedVars[key]);
|
|
1789
|
+
obj[`import.meta.env.${key}`] = JSON.stringify(combinedVars[key]);
|
|
1790
|
+
return obj;
|
|
1791
|
+
}, {});
|
|
1792
|
+
filteredEnvVars['process.env.EXTENSION_PUBLIC_BROWSER'] = JSON.stringify(this.browser);
|
|
1793
|
+
filteredEnvVars['import.meta.env.EXTENSION_PUBLIC_BROWSER'] = JSON.stringify(this.browser);
|
|
1794
|
+
filteredEnvVars['process.env.EXTENSION_PUBLIC_MODE'] = JSON.stringify(mode);
|
|
1795
|
+
filteredEnvVars['import.meta.env.EXTENSION_PUBLIC_MODE'] = JSON.stringify(mode);
|
|
1796
|
+
filteredEnvVars['process.env.EXTENSION_BROWSER'] = JSON.stringify(this.browser);
|
|
1797
|
+
filteredEnvVars['import.meta.env.EXTENSION_BROWSER'] = JSON.stringify(this.browser);
|
|
1798
|
+
filteredEnvVars['process.env.EXTENSION_MODE'] = JSON.stringify(mode);
|
|
1799
|
+
filteredEnvVars['import.meta.env.EXTENSION_MODE'] = JSON.stringify(mode);
|
|
1800
|
+
filteredEnvVars['process.env.BROWSER'] = JSON.stringify(this.browser);
|
|
1801
|
+
filteredEnvVars['import.meta.env.BROWSER'] = JSON.stringify(this.browser);
|
|
1802
|
+
filteredEnvVars['process.env.MODE'] = JSON.stringify(mode);
|
|
1803
|
+
filteredEnvVars['import.meta.env.MODE'] = JSON.stringify(mode);
|
|
1804
|
+
const importMetaEnvObject = {};
|
|
1805
|
+
for (const [key, value] of Object.entries(filteredEnvVars))if (key.startsWith('import.meta.env.')) importMetaEnvObject[key.slice(16)] = JSON.parse(value);
|
|
1806
|
+
filteredEnvVars['import.meta.env'] = JSON.stringify(importMetaEnvObject);
|
|
1807
|
+
filteredEnvVars['import.meta.dirname'] = 'undefined';
|
|
1808
|
+
filteredEnvVars['import.meta.filename'] = 'undefined';
|
|
1809
|
+
filteredEnvVars.global = 'globalThis';
|
|
1810
|
+
for (const [key, value] of Object.entries(this.define || {}))filteredEnvVars[key] = JSON.stringify(value);
|
|
1811
|
+
const injectedCount = Object.keys(filteredEnvVars).filter((k)=>k.startsWith('process.env.EXTENSION_PUBLIC_')).length;
|
|
1812
|
+
if (isDebug()) debugLine(envInjectedPublicVars(injectedCount));
|
|
1813
|
+
const processShim = resolveProcessShim();
|
|
1814
|
+
if (!processShim) {
|
|
1815
|
+
filteredEnvVars['process.env'] = '{}';
|
|
1816
|
+
filteredEnvVars.process = '({env:{},argv:[],platform:"browser",browser:true,versions:{},nextTick:function(cb){Promise.resolve().then(function(){cb()})}})';
|
|
1817
|
+
}
|
|
1818
|
+
new DefinePlugin(filteredEnvVars).apply(compiler);
|
|
1819
|
+
const importMetaUrl = new DefinePlugin({
|
|
1820
|
+
'import.meta.url': IMPORT_META_URL_RUNTIME
|
|
1821
|
+
});
|
|
1822
|
+
importMetaUrl.affectedHooks = 'thisCompilation';
|
|
1823
|
+
importMetaUrl.apply(compiler);
|
|
1824
|
+
if (processShim) new ProvidePlugin({
|
|
1825
|
+
process: processShim
|
|
1826
|
+
}).apply(compiler);
|
|
1827
|
+
const templateVars = buildTemplateVars(combinedVars, this.browser, mode);
|
|
1828
|
+
compiler.hooks.thisCompilation.tap('manifest:update-manifest', (compilation)=>{
|
|
1829
|
+
compilation.hooks.processAssets.tap({
|
|
1830
|
+
name: 'env:module',
|
|
1831
|
+
stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
|
|
1832
|
+
}, (assets)=>{
|
|
1833
|
+
const files = Object.keys(compilation.assets || assets);
|
|
1834
|
+
files.forEach((filename)=>{
|
|
1835
|
+
if (filename.endsWith('.json') || filename.endsWith('.html')) {
|
|
1836
|
+
const isJsonAsset = filename.endsWith('.json');
|
|
1837
|
+
const original = String(compilation.assets[filename]?.source() ?? '');
|
|
1838
|
+
const substituted = new Set();
|
|
1839
|
+
const resolveVar = (name, offset)=>{
|
|
1840
|
+
if (!Object.prototype.hasOwnProperty.call(templateVars, name)) return `$${name}`;
|
|
1841
|
+
substituted.add(name);
|
|
1842
|
+
return isJsonAsset ? substituteForJsonAsset(original, offset, templateVars[name]) : escapeForHtmlAsset(original, offset, templateVars[name]);
|
|
1843
|
+
};
|
|
1844
|
+
const placeholder = /\$EXTENSION_[A-Z0-9_]+/g;
|
|
1845
|
+
const fileContent = original.replace(placeholder, (match, offset)=>resolveVar(match.slice(1), offset));
|
|
1846
|
+
const parsedBefore = ()=>parsesAsJson(original.replace(placeholder, (match, offset)=>substituted.has(match.slice(1)) ? isInsideJsonString(original, offset) ? '' : 'null' : match));
|
|
1847
|
+
if (isJsonAsset && substituted.size > 0 && !parsesAsJson(fileContent) && parsedBefore()) {
|
|
1848
|
+
const error = new WebpackError(envValueBreaksJsonAsset(filename, [
|
|
1849
|
+
...substituted
|
|
1850
|
+
]));
|
|
1851
|
+
error.name = 'EnvValueBreaksJsonAsset';
|
|
1852
|
+
error.file = filename;
|
|
1853
|
+
compilation.errors.push(error);
|
|
1854
|
+
}
|
|
1855
|
+
compilation.updateAsset(filename, new sources.RawSource(fileContent));
|
|
1856
|
+
if ('manifest.json' === filename) setCurrentManifestContent(compilation, fileContent);
|
|
1857
|
+
}
|
|
1858
|
+
});
|
|
1859
|
+
});
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
function buildTemplateVars(combinedVars, browser, mode) {
|
|
1864
|
+
const vars = {};
|
|
1865
|
+
for (const [key, value] of Object.entries(combinedVars))if ('string' == typeof value && key.startsWith('EXTENSION_')) vars[key] = value;
|
|
1866
|
+
const browserValue = String(browser);
|
|
1867
|
+
const modeValue = String(mode);
|
|
1868
|
+
vars.EXTENSION_BROWSER = browserValue;
|
|
1869
|
+
vars.EXTENSION_PUBLIC_BROWSER = browserValue;
|
|
1870
|
+
vars.EXTENSION_MODE = modeValue;
|
|
1871
|
+
vars.EXTENSION_PUBLIC_MODE = modeValue;
|
|
1872
|
+
return vars;
|
|
1873
|
+
}
|
|
1874
|
+
export { DevSessionRestartScheduler, EnvPlugin, applyIndependentHtmlSurfaces, bindDevSessionRestart, boring, buildCanonicalManifestWithOverrides, cleanDistRemovedSummary, cleanDistSkippedNotFound, cleanDistStarting, collectRootAbsoluteRefs, contentScriptEntryDroppedForBrowser, dropWebkitUnsupportedKeys, edgeStoreKeyDropped, externalAssetOutputPath, fatalManifestShapeFixed, geckoActionUnsupportedOnMv2, geckoSidePanelUnsupported, getCurrentManifestContent, getManifestContent, getOriginalManifestContent, hasMv2SandboxPolicy, hasMv3StringPolicy, iconOutputPath, importMetaUrlForEmitPath, invalidThemeValue, isCompilerRestarting, isFolder, isFromFilepathList, isHollowContentScript, isManifestAddress, isWebkitUnsupportedPermission, legacyManifestPathWarning, manifestDepsTracked, manifestEmitSuccess, manifestFieldMistyped, manifestFilesInTurnedOffPublic, manifestIncludeSummary, manifestInvalidError, manifestLegacyWarningsSummary, manifestOverridesSummary, manifestVersionLostForBrowser, missingGeckoDataCollectionPermissions, mv2ActionFoldedIntoBrowserAction, mv2SandboxPolicyDropped, mv3BackgroundPageUnsupported, mv3BrowserActionFoldedIntoAction, mv3StringPolicyRewritten, normalizeManifestOutputPath, omitWebkitDroppedEntries, pageActionDropReason, pageActionDroppedForBrowserAction, pageActionNotSupportedByBrowser, projectConfigChangedRestartRequired, requestDevSessionRestart, resolveRootAbsoluteRef, safariBookmarksUnsupported, safariDownloadsUnsupported, safariHistoryUnsupported, safariIdentityUnsupported, safariIdleUnsupported, safariManagementUnsupported, safariMemberUnsupported, safariNotificationsUnsupported, safariOffscreenUnsupported, safariOmniboxUnsupported, safariSidePanelUnsupported, safariTabGroupsUnsupported, safariUserScriptsUnsupported, serverRestartRequiredFromManifestError, setCurrentManifestContent, setOriginalManifestContent, shouldFoldActionIntoBrowserAction, shouldFoldBrowserActionIntoAction, sidebarFoldTarget, sidebarKeyTranslatedForBrowser, themeIconOutputPath, themeImageOutputPath, themeNotSupportedByBrowser, toJsStringLiteral, unbindDevSessionRestart, unixify, vendorPrefixedKeyDropped, zipPackagingSkipped };
|