extension-develop 3.5.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
3
3
  return "u" < typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
4
4
  }();
5
5
  exports.ids = [
6
- "547"
6
+ "535"
7
7
  ];
8
8
  exports.modules = {
9
9
  "./webpack/webpack-config.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -47,13 +47,305 @@ exports.modules = {
47
47
  var dark_mode = __webpack_require__("./webpack/webpack-lib/dark-mode.ts");
48
48
  var messages = __webpack_require__("./webpack/webpack-lib/messages.ts");
49
49
  var extensions_to_load = __webpack_require__("./webpack/webpack-lib/extensions-to-load.ts");
50
- var companion_extensions = __webpack_require__("./webpack/webpack-lib/companion-extensions.ts");
50
+ var external_module_ = __webpack_require__("module");
51
+ function transpile_packages_normalizePath(filePath) {
52
+ return filePath.replace(/\\/g, '/');
53
+ }
54
+ function tryReadJson(filePath) {
55
+ try {
56
+ return JSON.parse(external_fs_.readFileSync(filePath, 'utf-8'));
57
+ } catch {
58
+ return;
59
+ }
60
+ }
61
+ function findPackageRootFromEntry(entryPath, packageName) {
62
+ let currentDir = external_path_.dirname(entryPath);
63
+ while(true){
64
+ const packageJsonPath = external_path_.join(currentDir, 'package.json');
65
+ const packageJson = tryReadJson(packageJsonPath);
66
+ if (packageJson?.name === packageName) return currentDir;
67
+ const parentDir = external_path_.dirname(currentDir);
68
+ if (parentDir === currentDir) return;
69
+ currentDir = parentDir;
70
+ }
71
+ }
72
+ function resolvePackageRoot(requireFromProject, projectRoot, packageName) {
73
+ try {
74
+ return external_path_.dirname(requireFromProject.resolve(`${packageName}/package.json`));
75
+ } catch {}
76
+ try {
77
+ const entryPath = requireFromProject.resolve(packageName);
78
+ const discovered = findPackageRootFromEntry(entryPath, packageName);
79
+ if (discovered) return discovered;
80
+ } catch {}
81
+ const guessedPackageDir = external_path_.join(projectRoot, 'node_modules', ...packageName.split('/'));
82
+ if (external_fs_.existsSync(external_path_.join(guessedPackageDir, 'package.json'))) return guessedPackageDir;
83
+ }
84
+ function getWorkspaceDependencyNames(projectRoot) {
85
+ const packageJsonPath = external_path_.join(projectRoot, 'package.json');
86
+ try {
87
+ const packageJson = JSON.parse(external_fs_.readFileSync(packageJsonPath, 'utf-8'));
88
+ const dependencySections = [
89
+ packageJson.dependencies,
90
+ packageJson.devDependencies,
91
+ packageJson.peerDependencies,
92
+ packageJson.optionalDependencies
93
+ ];
94
+ const names = new Set();
95
+ for (const section of dependencySections)if (section && 'object' == typeof section) {
96
+ for (const [name, version] of Object.entries(section))if ('string' == typeof version) {
97
+ if (version.startsWith('workspace:') || version.startsWith('link:') || version.startsWith('file:')) names.add(name);
98
+ }
99
+ }
100
+ return Array.from(names);
101
+ } catch {
102
+ return [];
103
+ }
104
+ }
105
+ function resolveTranspilePackageDirs(projectRoot, transpilePackages) {
106
+ const autoWorkspacePackages = getWorkspaceDependencyNames(projectRoot);
107
+ const packageNames = Array.from(new Set([
108
+ ...autoWorkspacePackages,
109
+ ...transpilePackages || []
110
+ ].map((entry)=>String(entry || '').trim()).filter(Boolean)));
111
+ if (0 === packageNames.length) return [];
112
+ const requireFromProject = (0, external_module_.createRequire)(external_path_.join(projectRoot, 'package.json'));
113
+ const resolvedDirs = new Set();
114
+ for (const packageName of packageNames){
115
+ const packageDir = resolvePackageRoot(requireFromProject, projectRoot, packageName);
116
+ if (packageDir) {
117
+ resolvedDirs.add(transpile_packages_normalizePath(packageDir));
118
+ try {
119
+ resolvedDirs.add(transpile_packages_normalizePath(external_fs_.realpathSync(packageDir)));
120
+ } catch {}
121
+ }
122
+ }
123
+ return Array.from(resolvedDirs);
124
+ }
125
+ function isSubPath(resourcePath, directoryPath) {
126
+ const resource = transpile_packages_normalizePath(resourcePath);
127
+ const dir = transpile_packages_normalizePath(directoryPath).replace(/\/+$/, '');
128
+ return resource === dir || resource.startsWith(`${dir}/`);
129
+ }
130
+ function isDir(p) {
131
+ try {
132
+ return external_fs_.existsSync(p) && external_fs_.statSync(p).isDirectory();
133
+ } catch {
134
+ return false;
135
+ }
136
+ }
137
+ function isFile(p) {
138
+ try {
139
+ return external_fs_.existsSync(p) && external_fs_.statSync(p).isFile();
140
+ } catch {
141
+ return false;
142
+ }
143
+ }
144
+ function toAbs(projectRoot, p) {
145
+ return external_path_.isAbsolute(p) ? p : external_path_.resolve(projectRoot, p);
146
+ }
147
+ function isValidExtensionRoot(dir) {
148
+ if (!isDir(dir)) return false;
149
+ return isFile(external_path_.join(dir, 'manifest.json'));
150
+ }
151
+ function resolveCompanionExtensionDirs(opts) {
152
+ const { projectRoot, config } = opts;
153
+ const explicitPaths = [];
154
+ let scanDir;
155
+ if (Array.isArray(config)) explicitPaths.push(...config.filter((p)=>'string' == typeof p));
156
+ else if (config && 'object' == typeof config) {
157
+ if (Array.isArray(config.paths)) explicitPaths.push(...config.paths.filter((p)=>'string' == typeof p));
158
+ if ('string' == typeof config.dir && config.dir.trim().length > 0) scanDir = config.dir.trim();
159
+ }
160
+ const found = [];
161
+ for (const p of explicitPaths){
162
+ const abs = toAbs(projectRoot, p);
163
+ if (isValidExtensionRoot(abs)) found.push(abs);
164
+ }
165
+ if (scanDir) {
166
+ const absScan = toAbs(projectRoot, scanDir);
167
+ if (isDir(absScan)) {
168
+ let entries = [];
169
+ try {
170
+ entries = external_fs_.readdirSync(absScan, {
171
+ withFileTypes: true
172
+ });
173
+ } catch {
174
+ entries = [];
175
+ }
176
+ for (const ent of entries){
177
+ if (!ent.isDirectory()) continue;
178
+ if (ent.name.startsWith('.')) continue;
179
+ const candidate = external_path_.join(absScan, ent.name);
180
+ if (isValidExtensionRoot(candidate)) found.push(candidate);
181
+ }
182
+ }
183
+ }
184
+ const unique = [];
185
+ const seen = new Set();
186
+ for (const p of found)if (!seen.has(p)) {
187
+ seen.add(p);
188
+ unique.push(p);
189
+ }
190
+ return unique;
191
+ }
51
192
  var core_ = __webpack_require__("@rspack/core");
52
193
  var core_default = /*#__PURE__*/ __webpack_require__.n(core_);
53
- var external_case_sensitive_paths_webpack_plugin_ = __webpack_require__("case-sensitive-paths-webpack-plugin");
54
- var external_case_sensitive_paths_webpack_plugin_default = /*#__PURE__*/ __webpack_require__.n(external_case_sensitive_paths_webpack_plugin_);
55
194
  var external_pintor_ = __webpack_require__("pintor");
56
195
  var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_);
196
+ function serverRestartRequiredFromSpecialFolderMessageOnly(addingOrRemoving, folder, typeOfAsset) {
197
+ return `${external_pintor_default().red('ERROR')} in ${external_pintor_default().yellow('manifest.json')} entrypoint: ${addingOrRemoving} ${external_pintor_default().yellow(typeOfAsset)} in ${external_pintor_default().underline(folder + '/')} requires a dev server restart to apply changes.`;
198
+ }
199
+ function specialFoldersSetupSummary(hasPublic, copyEnabled, ignoredCount) {
200
+ return `Special folders setup — public=${String(hasPublic)}, copy=${String(copyEnabled)}, ignored=${String(ignoredCount)}`;
201
+ }
202
+ function specialFolderChangeDetected(action, folder, relativePath) {
203
+ return `Special folders change — ${action} in ${folder}/: ${relativePath}`;
204
+ }
205
+ function _define_property(obj, key, value) {
206
+ if (key in obj) Object.defineProperty(obj, key, {
207
+ value: value,
208
+ enumerable: true,
209
+ configurable: true,
210
+ writable: true
211
+ });
212
+ else obj[key] = value;
213
+ return obj;
214
+ }
215
+ class WarnUponFolderChanges {
216
+ throwCompilationError(compilation, folder, filePath, isAddition) {
217
+ const addingOrRemoving = isAddition ? 'Adding' : 'Removing';
218
+ const typeOfAsset = 'pages' === folder ? 'HTML pages' : "script files";
219
+ const errorMessage = serverRestartRequiredFromSpecialFolderMessageOnly(addingOrRemoving, folder, typeOfAsset);
220
+ if (isAddition) {
221
+ const warn = new core_.WebpackError(errorMessage);
222
+ warn.name = 'SpecialFoldersChange';
223
+ warn.file = filePath;
224
+ warn.details = `Detected change in ${folder}/ affecting ${typeOfAsset}. Restart may be required for full effect.`;
225
+ compilation.warnings?.push(warn);
226
+ return;
227
+ }
228
+ const err = new core_.WebpackError(errorMessage);
229
+ err.name = 'SpecialFoldersRemoval';
230
+ err.file = filePath;
231
+ err.details = `Removing from ${folder}/ breaks current build. Restart the dev server to recompile.`;
232
+ compilation.errors?.push(err);
233
+ }
234
+ trackChange(projectPath, folder, change, filePath) {
235
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFolderChangeDetected('add' === change ? 'add' : 'remove', folder, external_path_.relative(projectPath, filePath)));
236
+ this.pendingChanges.push({
237
+ type: change,
238
+ folder,
239
+ filePath
240
+ });
241
+ }
242
+ collectChanges(compiler) {
243
+ const projectPath = compiler.options.context || process.cwd();
244
+ const pagesPath = external_path_.join(projectPath, 'pages') + external_path_.sep;
245
+ const scriptsPath = external_path_.join(projectPath, "scripts") + external_path_.sep;
246
+ const extensionsSupported = compiler.options.resolve?.extensions;
247
+ const supportedScripts = new Set((extensionsSupported || []).map((e)=>e.toLowerCase()));
248
+ const modifiedFiles = compiler.modifiedFiles || new Set();
249
+ const removedFiles = compiler.removedFiles || new Set();
250
+ for (const filePath of modifiedFiles){
251
+ if (filePath.startsWith(pagesPath) && filePath.endsWith('.html')) this.trackChange(projectPath, 'pages', 'add', filePath);
252
+ if (filePath.startsWith(scriptsPath)) {
253
+ const ext = external_path_.extname(filePath).toLowerCase();
254
+ if (supportedScripts.has(ext)) this.trackChange(projectPath, "scripts", 'add', filePath);
255
+ }
256
+ }
257
+ for (const filePath of removedFiles){
258
+ if (filePath.startsWith(pagesPath) && filePath.endsWith('.html')) this.trackChange(projectPath, 'pages', 'remove', filePath);
259
+ if (filePath.startsWith(scriptsPath)) {
260
+ const ext = external_path_.extname(filePath).toLowerCase();
261
+ if (supportedScripts.has(ext)) this.trackChange(projectPath, "scripts", 'remove', filePath);
262
+ }
263
+ }
264
+ }
265
+ applyPendingChanges(compilation) {
266
+ for (const change of this.pendingChanges)this.throwCompilationError(compilation, change.folder, change.filePath, 'add' === change.type);
267
+ this.pendingChanges = [];
268
+ }
269
+ apply(compiler) {
270
+ compiler.hooks.watchRun.tap('special-folders:warn-upon-folder-changes', ()=>{
271
+ this.collectChanges(compiler);
272
+ });
273
+ compiler.hooks.thisCompilation.tap('special-folders:warn-upon-folder-changes', (compilation)=>{
274
+ const projectPath = compiler.options.context || process.cwd();
275
+ const pagesPath = external_path_.join(projectPath, 'pages');
276
+ const scriptsPath = external_path_.join(projectPath, "scripts");
277
+ compilation.contextDependencies?.add(pagesPath);
278
+ compilation.contextDependencies?.add(scriptsPath);
279
+ this.applyPendingChanges(compilation);
280
+ });
281
+ }
282
+ constructor(){
283
+ _define_property(this, "pendingChanges", []);
284
+ }
285
+ }
286
+ function checkManifestInPublic(compilation, publicDir) {
287
+ try {
288
+ const manifestInPublic = external_path_.join(publicDir, 'manifest.json');
289
+ if (external_fs_.existsSync(manifestInPublic)) {
290
+ const ErrCtor = compilation.compiler.webpack?.WebpackError;
291
+ const err = new ErrCtor(`manifest.json must not be placed under public/: ${manifestInPublic}`);
292
+ err.file = 'manifest.json';
293
+ compilation.errors.push(err);
294
+ }
295
+ } catch {}
296
+ }
297
+ function feature_special_folders_define_property(obj, key, value) {
298
+ if (key in obj) Object.defineProperty(obj, key, {
299
+ value: value,
300
+ enumerable: true,
301
+ configurable: true,
302
+ writable: true
303
+ });
304
+ else obj[key] = value;
305
+ return obj;
306
+ }
307
+ class SpecialFoldersPlugin {
308
+ apply(compiler) {
309
+ const { manifestPath } = this.options;
310
+ const context = compiler.options.context || external_path_.dirname(manifestPath);
311
+ const publicDir = external_path_.join(context, 'public');
312
+ if (external_fs_.existsSync(publicDir) && external_fs_.statSync(publicDir).isDirectory()) {
313
+ compiler.hooks.thisCompilation.tap(SpecialFoldersPlugin.name, (compilation)=>{
314
+ compilation.hooks.processAssets.tap({
315
+ name: `${SpecialFoldersPlugin.name}:guards`,
316
+ stage: compilation.constructor.PROCESS_ASSETS_STAGE_PRE_PROCESS
317
+ }, ()=>{
318
+ checkManifestInPublic(compilation, publicDir);
319
+ });
320
+ });
321
+ new core_.rspack.CopyRspackPlugin({
322
+ patterns: [
323
+ {
324
+ from: publicDir,
325
+ to: '.',
326
+ noErrorOnMissing: true,
327
+ globOptions: {
328
+ ignore: [
329
+ 'manifest.json'
330
+ ]
331
+ }
332
+ }
333
+ ]
334
+ }).apply(compiler);
335
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFoldersSetupSummary(true, true, 1));
336
+ }
337
+ if ('development' === compiler.options.mode) {
338
+ if (compiler.options.watchOptions) new WarnUponFolderChanges().apply(compiler);
339
+ }
340
+ }
341
+ constructor(options){
342
+ feature_special_folders_define_property(this, "options", void 0);
343
+ this.options = options;
344
+ }
345
+ }
346
+ feature_special_folders_define_property(SpecialFoldersPlugin, "name", 'plugin-special-folders');
347
+ var external_case_sensitive_paths_webpack_plugin_ = __webpack_require__("case-sensitive-paths-webpack-plugin");
348
+ var external_case_sensitive_paths_webpack_plugin_default = /*#__PURE__*/ __webpack_require__.n(external_case_sensitive_paths_webpack_plugin_);
57
349
  function boring(manifestName, durationMs, stats) {
58
350
  const now = new Date();
59
351
  const hh = String(now.getHours()).padStart(2, '0');
@@ -98,7 +390,7 @@ exports.modules = {
98
390
  ].join('\n');
99
391
  }
100
392
  var external_dotenv_ = __webpack_require__("dotenv");
101
- function _define_property(obj, key, value) {
393
+ function env_define_property(obj, key, value) {
102
394
  if (key in obj) Object.defineProperty(obj, key, {
103
395
  value: value,
104
396
  enumerable: true,
@@ -203,8 +495,8 @@ exports.modules = {
203
495
  });
204
496
  }
205
497
  constructor(options){
206
- _define_property(this, "browser", void 0);
207
- _define_property(this, "manifestPath", void 0);
498
+ env_define_property(this, "browser", void 0);
499
+ env_define_property(this, "manifestPath", void 0);
208
500
  this.browser = options.browser || 'chrome';
209
501
  this.manifestPath = options.manifestPath;
210
502
  }
@@ -219,6 +511,7 @@ exports.modules = {
219
511
  else obj[key] = value;
220
512
  return obj;
221
513
  }
514
+ const rmdirSync = external_fs_.rmdirSync;
222
515
  class CleanDistFolderPlugin {
223
516
  apply(compiler) {
224
517
  const logger = compiler.getInfrastructureLogger('plugin-compilation:clean');
@@ -231,7 +524,7 @@ exports.modules = {
231
524
  recursive: true,
232
525
  force: true
233
526
  });
234
- else external_fs_.rmdirSync(distPath, {
527
+ else rmdirSync(distPath, {
235
528
  recursive: true
236
529
  });
237
530
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(cleanDistRemovedSummary(removedCount, distPath));
@@ -243,7 +536,7 @@ exports.modules = {
243
536
  recursive: true,
244
537
  force: true
245
538
  });
246
- else external_fs_.rmdirSync(distPath, {
539
+ else rmdirSync(distPath, {
247
540
  recursive: true
248
541
  });
249
542
  } catch {}
@@ -417,7 +710,29 @@ exports.modules = {
417
710
  return obj;
418
711
  }
419
712
  class CompilationPlugin {
713
+ applyIgnoreWarnings(compiler) {
714
+ const existing = compiler.options.ignoreWarnings;
715
+ const ignoreWarnings = Array.isArray(existing) ? [
716
+ ...existing
717
+ ] : existing ? [
718
+ existing
719
+ ] : [];
720
+ ignoreWarnings.push((warning)=>{
721
+ try {
722
+ const message = String(warning && (warning.message || warning) || '');
723
+ const modulePath = warning && warning.module && (warning.module.resource || warning.module.userRequest) || '';
724
+ if (message.includes('Critical dependency: the request of a dependency is an expression') && /[\\\/]@ffmpeg[\\\/]ffmpeg[\\\/]dist[\\\/]esm[\\\/](classes|worker)\.js$/.test(modulePath)) return true;
725
+ if (message.includes('Critical dependency: the request of a dependency is an expression') && /[\\\/]@techstark[\\\/]opencv-js[\\\/]dist[\\\/]opencv\.js$/.test(modulePath)) return true;
726
+ if (message.includes('Critical dependency: the request of a dependency is an expression') && /[\\\/]@sqlite\.org[\\\/]sqlite-wasm[\\\/]dist[\\\/]sqlite3-worker1\.mjs$/.test(modulePath)) return true;
727
+ return message.includes('Accessing import.meta directly is unsupported') && /[\\\/]@huggingface[\\\/]transformers[\\\/].*transformers\.web\.js$/.test(modulePath);
728
+ } catch {
729
+ return false;
730
+ }
731
+ });
732
+ compiler.options.ignoreWarnings = ignoreWarnings;
733
+ }
420
734
  apply(compiler) {
735
+ this.applyIgnoreWarnings(compiler);
421
736
  new (external_case_sensitive_paths_webpack_plugin_default())().apply(compiler);
422
737
  new EnvPlugin({
423
738
  manifestPath: this.manifestPath,
@@ -530,7 +845,7 @@ exports.modules = {
530
845
  var is_content_script = __webpack_require__("./webpack/plugin-css/css-lib/is-content-script.ts");
531
846
  async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage = {}) {
532
847
  const { useSass = true, useLess = true } = usage;
533
- const isContentScript = (issuer)=>(0, is_content_script.z)(issuer, manifestPath);
848
+ const isContentScript = (issuer)=>(0, is_content_script.z)(issuer, manifestPath, projectPath);
534
849
  const fileTypes = [
535
850
  {
536
851
  test: /\.css$/,
@@ -591,7 +906,7 @@ exports.modules = {
591
906
  }
592
907
  async function cssInHtmlLoader(projectPath, mode, manifestPath, usage = {}) {
593
908
  const { useSass = true, useLess = true } = usage;
594
- const isNotContentScript = (issuer)=>!(0, is_content_script.z)(issuer, manifestPath);
909
+ const isNotContentScript = (issuer)=>!(0, is_content_script.z)(issuer, manifestPath, projectPath);
595
910
  const fileTypes = [
596
911
  {
597
912
  test: /\.css$/,
@@ -691,7 +1006,7 @@ exports.modules = {
691
1006
  generator: {
692
1007
  filename: "content_scripts/[name].[contenthash:8].css"
693
1008
  },
694
- issuer: (issuer)=>(0, is_content_script.z)(issuer, manifestPath)
1009
+ issuer: (issuer)=>(0, is_content_script.z)(issuer, manifestPath, projectPath)
695
1010
  });
696
1011
  if (maybeInstallLess.length) loaders.push({
697
1012
  test: /\.less$/,
@@ -700,7 +1015,7 @@ exports.modules = {
700
1015
  generator: {
701
1016
  filename: "content_scripts/[name].[contenthash:8].css"
702
1017
  },
703
- issuer: (issuer)=>(0, is_content_script.z)(issuer, manifestPath)
1018
+ issuer: (issuer)=>(0, is_content_script.z)(issuer, manifestPath, projectPath)
704
1019
  });
705
1020
  compiler.options.plugins = [
706
1021
  ...compiler.options.plugins,
@@ -815,6 +1130,12 @@ exports.modules = {
815
1130
  }
816
1131
  };
817
1132
  const hasCustomSvgRule = compiler.options.module.rules.some((rule)=>rule && rule.test instanceof RegExp && rule.test.test('.svg') && void 0 !== rule.use);
1133
+ const hasUrlResourceQueryRule = compiler.options.module.rules.some((thisRule)=>{
1134
+ const rule = thisRule;
1135
+ const resourceQuery = rule?.resourceQuery;
1136
+ if (!(resourceQuery instanceof RegExp)) return false;
1137
+ return resourceQuery.test('url');
1138
+ });
818
1139
  const hasCustomFontsRule = compiler.options.module.rules.some((thisRule)=>{
819
1140
  const rule = thisRule;
820
1141
  if (!rule || !(rule.test instanceof RegExp)) return false;
@@ -822,6 +1143,12 @@ exports.modules = {
822
1143
  return void 0 !== rule.type || void 0 !== rule.use;
823
1144
  });
824
1145
  const loaders = [
1146
+ ...hasUrlResourceQueryRule ? [] : [
1147
+ {
1148
+ resourceQuery: /url/,
1149
+ type: 'asset/resource'
1150
+ }
1151
+ ],
825
1152
  ...hasCustomSvgRule ? [] : [
826
1153
  defaultSvgRule
827
1154
  ],
@@ -903,9 +1230,9 @@ exports.modules = {
903
1230
  var preact = __webpack_require__("./webpack/plugin-js-frameworks/js-tools/preact.ts");
904
1231
  var react = __webpack_require__("./webpack/plugin-js-frameworks/js-tools/react.ts");
905
1232
  var vue = __webpack_require__("./webpack/plugin-js-frameworks/js-tools/vue.ts");
906
- var typescript = __webpack_require__("./webpack/plugin-js-frameworks/js-tools/typescript.ts");
907
1233
  var svelte = __webpack_require__("./webpack/plugin-js-frameworks/js-tools/svelte.ts");
908
1234
  var js_frameworks_lib_messages = __webpack_require__("./webpack/plugin-js-frameworks/js-frameworks-lib/messages.ts");
1235
+ var typescript = __webpack_require__("./webpack/plugin-js-frameworks/js-tools/typescript.ts");
909
1236
  function plugin_js_frameworks_define_property(obj, key, value) {
910
1237
  if (key in obj) Object.defineProperty(obj, key, {
911
1238
  value: value,
@@ -978,6 +1305,7 @@ exports.modules = {
978
1305
  const tsConfigPath = (0, typescript.hB)(projectPath);
979
1306
  const manifestDir = external_path_.dirname(this.manifestPath);
980
1307
  const tsRoot = tsConfigPath ? external_path_.dirname(tsConfigPath) : manifestDir;
1308
+ const transpilePackageDirs = resolveTranspilePackageDirs(projectPath, this.transpilePackages);
981
1309
  const preferTypeScript = !!tsConfigPath || (0, typescript.eE)(projectPath);
982
1310
  let targets = [
983
1311
  'chrome >= 100'
@@ -1022,10 +1350,15 @@ exports.modules = {
1022
1350
  test: /\.(js|mjs|jsx|mjsx|ts|mts|tsx|mtsx)$/,
1023
1351
  include: Array.from(new Set([
1024
1352
  tsRoot,
1025
- manifestDir
1353
+ manifestDir,
1354
+ ...transpilePackageDirs
1026
1355
  ])),
1027
1356
  exclude: [
1028
- /[\\/]node_modules[\\/]/
1357
+ (resourcePath)=>{
1358
+ const isInNodeModules = /[\\/]node_modules[\\/]/.test(resourcePath);
1359
+ if (!isInNodeModules) return false;
1360
+ return !transpilePackageDirs.some((dir)=>isSubPath(resourcePath, dir));
1361
+ }
1029
1362
  ],
1030
1363
  use: {
1031
1364
  loader: 'builtin:swc-loader',
@@ -1102,8 +1435,10 @@ exports.modules = {
1102
1435
  constructor(options){
1103
1436
  plugin_js_frameworks_define_property(this, "manifestPath", void 0);
1104
1437
  plugin_js_frameworks_define_property(this, "mode", void 0);
1438
+ plugin_js_frameworks_define_property(this, "transpilePackages", void 0);
1105
1439
  this.manifestPath = options.manifestPath;
1106
1440
  this.mode = options.mode;
1441
+ this.transpilePackages = options.transpilePackages || [];
1107
1442
  }
1108
1443
  }
1109
1444
  plugin_js_frameworks_define_property(JsFrameworksPlugin, "name", 'plugin-js-frameworks');
@@ -1218,14 +1553,6 @@ exports.modules = {
1218
1553
  function unixify(filePath) {
1219
1554
  return filePath.replace(/\\/g, '/');
1220
1555
  }
1221
- function normalizeManifestOutputPath(originalPath) {
1222
- if (!originalPath) return originalPath;
1223
- const unixPath = originalPath.replace(/\\/g, '/');
1224
- if (/^\/public\//i.test(unixPath)) return unixPath.replace(/^\/public\//i, '');
1225
- if (/^(?:\.\/)?public\//i.test(unixPath)) return unixPath.replace(/^(?:\.\/)?public\//i, '');
1226
- if (/^\//.test(unixPath)) return unixPath.replace(/^\//, '');
1227
- return unixPath;
1228
- }
1229
1556
  function background_background(manifest) {
1230
1557
  return manifest.background && manifest.background.scripts && {
1231
1558
  background: {
@@ -1234,15 +1561,21 @@ exports.modules = {
1234
1561
  scripts: [
1235
1562
  ...manifest.background.scripts.map((script)=>(()=>{
1236
1563
  const raw = String(script);
1237
- const isPublic = /^(?:\/.+|(?:\.\/)?public\/)/i.test(raw);
1238
- const target = isPublic ? normalizeManifestOutputPath(raw) : "background/scripts.js";
1239
- return getFilename(target, raw);
1564
+ return getFilename("background/scripts.js", raw);
1240
1565
  })())
1241
1566
  ]
1242
1567
  }
1243
1568
  }
1244
1569
  };
1245
1570
  }
1571
+ function normalizeManifestOutputPath(originalPath) {
1572
+ if (!originalPath) return originalPath;
1573
+ const unixPath = originalPath.replace(/\\/g, '/');
1574
+ if (/^\/public\//i.test(unixPath)) return unixPath.replace(/^\/public\//i, '');
1575
+ if (/^(?:\.\/)?public\//i.test(unixPath)) return unixPath.replace(/^(?:\.\/)?public\//i, '');
1576
+ if (/^\//.test(unixPath)) return unixPath.replace(/^\//, '');
1577
+ return unixPath;
1578
+ }
1246
1579
  function browserAction(manifest) {
1247
1580
  return manifest.browser_action && {
1248
1581
  browser_action: {
@@ -1424,9 +1757,7 @@ exports.modules = {
1424
1757
  ...manifest.background.service_worker && {
1425
1758
  service_worker: (()=>{
1426
1759
  const raw = String(manifest.background.service_worker);
1427
- const isPublic = /^(?:\/.+|(?:\.\/)?public\/)/i.test(raw);
1428
- const target = isPublic ? normalizeManifestOutputPath(raw) : 'background/service_worker.js';
1429
- return getFilename(target, raw);
1760
+ return getFilename('background/service_worker.js', raw);
1430
1761
  })()
1431
1762
  }
1432
1763
  }
@@ -1455,9 +1786,7 @@ exports.modules = {
1455
1786
  ...manifest.side_panel.default_path && {
1456
1787
  default_path: (()=>{
1457
1788
  const raw = String(manifest.side_panel.default_path);
1458
- const isPublic = /^(?:\/.+|(?:\.\/)?public\/)/i.test(raw);
1459
- const target = isPublic ? normalizeManifestOutputPath(raw) : 'sidebar/index.html';
1460
- return getFilename(target, raw);
1789
+ return getFilename('sidebar/index.html', raw);
1461
1790
  })()
1462
1791
  }
1463
1792
  }
@@ -1479,9 +1808,7 @@ exports.modules = {
1479
1808
  ...manifest.background.page && {
1480
1809
  page: (()=>{
1481
1810
  const raw = String(manifest.background.page);
1482
- const isPublic = /^(?:\/.+|(?:\.\/)?public\/)/i.test(raw);
1483
- const target = isPublic ? normalizeManifestOutputPath(raw) : 'background/index.html';
1484
- return getFilename(target, raw);
1811
+ return getFilename('background/index.html', raw);
1485
1812
  })()
1486
1813
  }
1487
1814
  }
@@ -1517,11 +1844,12 @@ exports.modules = {
1517
1844
  }
1518
1845
  };
1519
1846
  }
1520
- function content_scripts_contentScripts(manifest) {
1847
+ function content_scripts_contentScripts(manifest, manifestPath) {
1521
1848
  if (!manifest.content_scripts) return;
1522
1849
  const original = manifest.content_scripts;
1523
1850
  const originalCount = original.length;
1524
1851
  const result = [];
1852
+ let bridgeOrdinal = 0;
1525
1853
  for(let index = 0; index < original.length; index++){
1526
1854
  const contentObj = original[index] || {};
1527
1855
  const contentJs = [
@@ -1530,24 +1858,25 @@ exports.modules = {
1530
1858
  const contentCss = [
1531
1859
  ...new Set(contentObj.css || [])
1532
1860
  ];
1861
+ if ('MAIN' === contentObj.world) {
1862
+ const bridgeIndex = originalCount + bridgeOrdinal++;
1863
+ const { world: _ignoredWorld, js: _ignoredJs, css: _ignoredCss, ...rest } = contentObj;
1864
+ result.push({
1865
+ ...rest,
1866
+ js: [
1867
+ getFilename(`content_scripts/content-${bridgeIndex}.js`, 'main-world-bridge.js')
1868
+ ],
1869
+ css: []
1870
+ });
1871
+ }
1533
1872
  result.push({
1534
1873
  ...original[index] || {},
1535
- js: contentJs.map((js)=>getFilename(`content_scripts/content-${index}.js`, js)),
1536
- css: contentCss.map((css)=>getFilename(`content_scripts/content-${index}.css`, css))
1537
- });
1538
- }
1539
- let bridgeOrdinal = 0;
1540
- for(let i = 0; i < original.length; i++){
1541
- const cs = original[i];
1542
- if (!cs || 'MAIN' !== cs.world) continue;
1543
- const bridgeIndex = originalCount + bridgeOrdinal++;
1544
- const { world: _ignoredWorld, js: _ignoredJs, css: _ignoredCss, ...rest } = cs;
1545
- result.push({
1546
- ...rest,
1547
1874
  js: [
1548
- getFilename(`content_scripts/content-${bridgeIndex}.js`, 'main-world-bridge.js')
1875
+ ...new Set(contentJs.map((js)=>getFilename(`content_scripts/content-${index}.js`, js)))
1549
1876
  ],
1550
- css: []
1877
+ css: [
1878
+ ...new Set(contentCss.map((css)=>getFilename(`content_scripts/content-${index}.css`, css)))
1879
+ ]
1551
1880
  });
1552
1881
  }
1553
1882
  return {
@@ -1696,11 +2025,11 @@ exports.modules = {
1696
2025
  }
1697
2026
  };
1698
2027
  }
1699
- function manifestCommon(manifest) {
2028
+ function manifestCommon(manifest, manifestPath) {
1700
2029
  return {
1701
2030
  ...backgroundPage(manifest),
1702
2031
  ...chromeUrlOverrides(manifest),
1703
- ...content_scripts_contentScripts(manifest),
2032
+ ...content_scripts_contentScripts(manifest, manifestPath),
1704
2033
  ...devtoolsPage(manifest),
1705
2034
  ...icons_icons(manifest),
1706
2035
  ...commands(manifest),
@@ -1723,7 +2052,7 @@ exports.modules = {
1723
2052
  const { [key]: _ignored, ...rest } = obj;
1724
2053
  return rest;
1725
2054
  };
1726
- const common = manifestCommon(manifestContent);
2055
+ const common = manifestCommon(manifestContent, manifestPath);
1727
2056
  const mv2 = manifestV2(manifestContent);
1728
2057
  const mv3 = manifestV3(manifestContent);
1729
2058
  const backgroundMerged = {
@@ -1742,10 +2071,30 @@ exports.modules = {
1742
2071
  return JSON.stringify(merged, null, 2);
1743
2072
  }
1744
2073
  function getManifestContent(compilation, manifestPath) {
1745
- if (compilation.getAsset?.('manifest.json') || compilation.assets?.['manifest.json']) {
1746
- const source = compilation.assets['manifest.json']?.source?.();
1747
- const manifest = 'function' == typeof source ? source().toString() : String(source || '');
1748
- return JSON.parse(manifest || '{}');
2074
+ const readAssetSource = (asset)=>{
2075
+ if (!asset) return '';
2076
+ const source = asset.source;
2077
+ if ('string' == typeof source) return source;
2078
+ if ('function' == typeof source) {
2079
+ const out = source();
2080
+ return 'string' == typeof out ? out : String(out || '');
2081
+ }
2082
+ if (source && 'function' == typeof source.source) {
2083
+ const out = source.source();
2084
+ return 'string' == typeof out ? out : String(out || '');
2085
+ }
2086
+ return '';
2087
+ };
2088
+ const getAsset = compilation.getAsset;
2089
+ if ('function' == typeof getAsset) {
2090
+ const manifestAsset = getAsset.call(compilation, 'manifest.json');
2091
+ const manifest = readAssetSource(manifestAsset);
2092
+ if (manifest) return JSON.parse(manifest);
2093
+ }
2094
+ const manifestAsset = compilation.assets?.['manifest.json'];
2095
+ if (manifestAsset) {
2096
+ const manifest = readAssetSource(manifestAsset);
2097
+ if (manifest) return JSON.parse(manifest);
1749
2098
  }
1750
2099
  try {
1751
2100
  const text = external_fs_.readFileSync(manifestPath, 'utf8');
@@ -2837,7 +3186,8 @@ exports.modules = {
2837
3186
  class AddScriptsAndStylesToCompilation {
2838
3187
  apply(compiler) {
2839
3188
  const htmlEntries = this.includeList || {};
2840
- const projectRoot = external_path_.dirname(this.manifestPath);
3189
+ const manifestDir = external_path_.dirname(this.manifestPath);
3190
+ const projectRoot = compiler.options.context || manifestDir;
2841
3191
  const publicDir = external_path_.join(projectRoot, 'public');
2842
3192
  const hasPublicDir = external_fs_.existsSync(publicDir);
2843
3193
  for (const field of Object.entries(htmlEntries)){
@@ -3248,24 +3598,27 @@ exports.modules = {
3248
3598
  }
3249
3599
  class HtmlPlugin {
3250
3600
  apply(compiler) {
3601
+ const includeList = {
3602
+ ...this.includeList || {}
3603
+ };
3251
3604
  new EmitHtmlFile({
3252
3605
  manifestPath: this.manifestPath,
3253
- includeList: this.includeList,
3606
+ includeList,
3254
3607
  browser: this.browser
3255
3608
  }).apply(compiler);
3256
3609
  new AddAssetsToCompilation({
3257
3610
  manifestPath: this.manifestPath,
3258
- includeList: this.includeList,
3611
+ includeList,
3259
3612
  browser: this.browser
3260
3613
  }).apply(compiler);
3261
3614
  new AddScriptsAndStylesToCompilation({
3262
3615
  manifestPath: this.manifestPath,
3263
- includeList: this.includeList,
3616
+ includeList,
3264
3617
  browser: this.browser
3265
3618
  }).apply(compiler);
3266
3619
  new UpdateHtmlFile({
3267
3620
  manifestPath: this.manifestPath,
3268
- includeList: this.includeList,
3621
+ includeList,
3269
3622
  browser: this.browser
3270
3623
  }).apply(compiler);
3271
3624
  if ('production' !== (compiler.options.mode || 'development')) compiler.options.module.rules.push({
@@ -3281,29 +3634,29 @@ exports.modules = {
3281
3634
  loader: external_path_.resolve(__dirname, "ensure-hmr-for-scripts"),
3282
3635
  options: {
3283
3636
  manifestPath: this.manifestPath,
3284
- includeList: this.includeList
3637
+ includeList
3285
3638
  }
3286
3639
  }
3287
3640
  ]
3288
3641
  });
3289
3642
  new AddToFileDependencies({
3290
3643
  manifestPath: this.manifestPath,
3291
- includeList: this.includeList,
3644
+ includeList,
3292
3645
  browser: this.browser
3293
3646
  }).apply(compiler);
3294
3647
  new throw_if_recompile_is_needed_ThrowIfRecompileIsNeeded({
3295
3648
  manifestPath: this.manifestPath,
3296
- includeList: this.includeList,
3649
+ includeList,
3297
3650
  browser: this.browser
3298
3651
  }).apply(compiler);
3299
3652
  new ThrowIfManifestEntryChange({
3300
3653
  manifestPath: this.manifestPath,
3301
- includeList: this.includeList,
3654
+ includeList,
3302
3655
  browser: this.browser
3303
3656
  }).apply(compiler);
3304
3657
  new HandleCommonErrors({
3305
3658
  manifestPath: this.manifestPath,
3306
- includeList: this.includeList,
3659
+ includeList,
3307
3660
  browser: this.browser
3308
3661
  }).apply(compiler);
3309
3662
  }
@@ -3349,17 +3702,29 @@ exports.modules = {
3349
3702
  });
3350
3703
  return fileAssets;
3351
3704
  }
3705
+ function findPackageRoot(startDir) {
3706
+ let current = startDir;
3707
+ for(let i = 0; i < 15; i++){
3708
+ if (external_fs_default().existsSync(external_path_default().join(current, 'package.json'))) return current;
3709
+ const parent = external_path_default().dirname(current);
3710
+ if (parent === current) break;
3711
+ current = parent;
3712
+ }
3713
+ }
3352
3714
  function getMainWorldBridgeScripts(manifestPath) {
3353
3715
  const bridgeScripts = {};
3354
3716
  try {
3355
3717
  const raw = JSON.parse(external_fs_default().readFileSync(manifestPath, 'utf-8'));
3356
3718
  const contentScripts = Array.isArray(raw?.content_scripts) ? raw.content_scripts : [];
3357
3719
  const originalCount = contentScripts.length;
3720
+ const packageRoot = findPackageRoot(__dirname);
3358
3721
  const bridgeSourceCandidates = [
3359
3722
  external_path_default().resolve(__dirname, 'main-world-bridge.js'),
3360
- external_path_default().resolve(__dirname, '../../../../../../main-world-bridge.js')
3361
- ];
3362
- const bridgeSource = bridgeSourceCandidates.find((p)=>external_fs_default().existsSync(p)) || bridgeSourceCandidates[0];
3723
+ packageRoot ? external_path_default().resolve(packageRoot, "webpack/plugin-extension/feature-scripts/steps/setup-reload-strategy/add-content-script-wrapper/main-world-bridge.js") : void 0,
3724
+ packageRoot ? external_path_default().resolve(packageRoot, 'main-world-bridge.js') : void 0
3725
+ ].filter((candidate)=>Boolean(candidate));
3726
+ const bridgeSource = bridgeSourceCandidates.find((p)=>external_fs_default().existsSync(p)) || void 0;
3727
+ if (!bridgeSource) return bridgeScripts;
3363
3728
  let bridgeOrdinal = 0;
3364
3729
  for(let i = 0; i < contentScripts.length; i++){
3365
3730
  const cs = contentScripts[i];
@@ -3370,6 +3735,7 @@ exports.modules = {
3370
3735
  } catch {}
3371
3736
  return bridgeScripts;
3372
3737
  }
3738
+ var package_json = __webpack_require__("./webpack/webpack-lib/package-json.ts");
3373
3739
  function add_content_script_wrapper_define_property(obj, key, value) {
3374
3740
  if (key in obj) Object.defineProperty(obj, key, {
3375
3741
  value: value,
@@ -3396,11 +3762,18 @@ exports.modules = {
3396
3762
  return base;
3397
3763
  }
3398
3764
  apply(compiler) {
3765
+ const manifestDir = external_path_.dirname(this.manifestPath);
3766
+ const packageJsonPath = (0, package_json.Pb)(this.manifestPath);
3767
+ const packageJsonDir = packageJsonPath ? external_path_.dirname(packageJsonPath) : manifestDir;
3768
+ const includeDirs = packageJsonDir === manifestDir ? [
3769
+ manifestDir
3770
+ ] : [
3771
+ manifestDir,
3772
+ packageJsonDir
3773
+ ];
3399
3774
  compiler.options.module.rules.push({
3400
3775
  test: /\.(js|mjs|jsx|mjsx|ts|mts|tsx|mtsx)$/,
3401
- include: [
3402
- external_path_.dirname(this.manifestPath)
3403
- ],
3776
+ include: includeDirs,
3404
3777
  exclude: [
3405
3778
  /([\\/])node_modules\1/
3406
3779
  ],
@@ -3417,9 +3790,7 @@ exports.modules = {
3417
3790
  if ('production' !== compiler.options.mode) {
3418
3791
  compiler.options.module.rules.push({
3419
3792
  test: /\.(js|mjs|jsx|mjsx|ts|mts|tsx|mtsx)$/,
3420
- include: [
3421
- external_path_.dirname(this.manifestPath)
3422
- ],
3793
+ include: includeDirs,
3423
3794
  exclude: [
3424
3795
  /([\\/])node_modules\1/
3425
3796
  ],
@@ -3436,9 +3807,7 @@ exports.modules = {
3436
3807
  });
3437
3808
  compiler.options.module.rules.push({
3438
3809
  test: /\.(js|mjs|jsx|mjsx|ts|mts|tsx|mtsx)$/,
3439
- include: [
3440
- external_path_.dirname(this.manifestPath)
3441
- ],
3810
+ include: includeDirs,
3442
3811
  exclude: [
3443
3812
  /([\\/])node_modules\1/
3444
3813
  ],
@@ -3504,7 +3873,7 @@ exports.modules = {
3504
3873
  if (!entry || 'string' != typeof entry) continue;
3505
3874
  if (add_scripts_isRemoteUrl(entry)) continue;
3506
3875
  let resolved = entry;
3507
- if (!external_fs_.existsSync(resolved)) resolved = entry.startsWith('/') ? external_path_.join(manifestDir, entry.slice(1)) : external_path_.isAbsolute(entry) ? entry : external_path_.join(manifestDir, entry);
3876
+ if (!external_fs_.existsSync(resolved)) resolved = external_path_.isAbsolute(entry) ? entry : entry.startsWith('/') ? external_path_.join(manifestDir, entry.slice(1)) : external_path_.join(manifestDir, entry);
3508
3877
  if (external_fs_.existsSync(resolved)) continue;
3509
3878
  const isPublicRoot = entry.startsWith('/') && !external_path_.isAbsolute(entry);
3510
3879
  const displayPath = isPublicRoot ? outputRoot ? external_path_.join(outputRoot, entry.slice(1)) : entry : resolved;
@@ -3525,11 +3894,10 @@ exports.modules = {
3525
3894
  const newEntries = {};
3526
3895
  const manifestDir = external_path_.dirname(this.manifestPath);
3527
3896
  const projectPath = compiler.options.context || manifestDir;
3528
- const publicDir = external_path_.join(projectPath, 'public');
3529
3897
  const resolveEntryPath = (entry)=>{
3530
3898
  if (!entry) return entry;
3531
3899
  if (add_scripts_isRemoteUrl(entry)) return entry;
3532
- if (entry.startsWith('/') && !external_path_.isAbsolute(entry)) return external_path_.join(publicDir, entry.slice(1));
3900
+ if (entry.startsWith('/') && !external_path_.isAbsolute(entry)) return external_path_.join(projectPath, entry.slice(1));
3533
3901
  if (external_path_.isAbsolute(entry)) return entry;
3534
3902
  return external_path_.join(manifestDir, entry);
3535
3903
  };
@@ -3546,11 +3914,7 @@ exports.modules = {
3546
3914
  ...scriptImports,
3547
3915
  ...cssImports
3548
3916
  ];
3549
- const entryImports = allImports.filter((filePath)=>{
3550
- const rel = external_path_.relative(publicDir, filePath);
3551
- const isUnderPublic = rel && !rel.startsWith('..') && !external_path_.isAbsolute(rel);
3552
- return !isUnderPublic;
3553
- });
3917
+ const entryImports = allImports;
3554
3918
  if (cssImports.length || scriptImports.length) {
3555
3919
  if ('background/service_worker' === feature) {
3556
3920
  const manifest = JSON.parse(external_fs_.readFileSync(this.manifestPath, 'utf8'));
@@ -3572,21 +3936,6 @@ exports.modules = {
3572
3936
  ...newEntries
3573
3937
  };
3574
3938
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(scriptsEntriesSummary(entriesAdded, publicTracked));
3575
- if (compiler?.hooks?.thisCompilation?.tap) compiler.hooks.thisCompilation.tap("scripts:add-public-deps", (compilation)=>{
3576
- try {
3577
- const allScriptFieldImports = Object.values(scriptFields).flatMap((scriptFieldEntry)=>[].concat(...Array.isArray(scriptFieldEntry) ? scriptFieldEntry : scriptFieldEntry ? [
3578
- scriptFieldEntry
3579
- ] : []));
3580
- const publicFilesOnly = allScriptFieldImports.filter((importPath)=>!add_scripts_isRemoteUrl(String(importPath))).map((importPath)=>resolveEntryPath(String(importPath))).filter((resolvedPath)=>{
3581
- const rel = external_path_.relative(publicDir, resolvedPath);
3582
- return rel && !rel.startsWith('..') && !external_path_.isAbsolute(rel);
3583
- });
3584
- for (const publicFilePath of publicFilesOnly)if (external_fs_.existsSync(publicFilePath)) {
3585
- compilation.fileDependencies.add(publicFilePath);
3586
- publicTracked++;
3587
- }
3588
- } catch {}
3589
- });
3590
3939
  }
3591
3940
  constructor(options){
3592
3941
  add_scripts_define_property(this, "manifestPath", void 0);
@@ -3712,6 +4061,7 @@ exports.modules = {
3712
4061
  const DOM_LOADER = "scriptLoader";
3713
4062
  const WORKER_LOADER = 'workerLoader';
3714
4063
  const CLASSIC_LOADER = 'classicLoader';
4064
+ const MAIN_CLASSIC_LOADER = 'classicLoaderMainWorld';
3715
4065
  const FALLBACK_LOADER = 'fallbackLoader';
3716
4066
  function LoadScriptRuntimeModule(webpack, supportDynamicImport, classicLoaderEnabled, contentScriptsMeta) {
3717
4067
  const { Template, RuntimeGlobals, RuntimeModule } = webpack;
@@ -3817,12 +4167,12 @@ exports.modules = {
3817
4167
  Template.indent([
3818
4168
  `${RuntimeGlobals.loadScript} = isWorker ? ${WORKER_LOADER} : ${DOM_LOADER};`
3819
4169
  ]),
3820
- "}",
3821
- isMainWorld ? Template.asString([
4170
+ "} else {",
4171
+ Template.indent(isMainWorld ? Template.asString([
3822
4172
  `${_const} __extjsMark = "__extjs__";`,
3823
4173
  `${_const} __extjsReqType = "EXTJS_WTW_LOAD";`,
3824
4174
  `${_const} __extjsResType = "EXTJS_WTW_LOADED";`,
3825
- `${_const} ${CLASSIC_LOADER} = ` + f('url, done', [
4175
+ `${_const} ${MAIN_CLASSIC_LOADER} = ` + f('url, done', [
3826
4176
  `${_const} requestId = String(Date.now()) + "-" + Math.random().toString(16).slice(2);`,
3827
4177
  `${_const} onMessage = ${f('event', [
3828
4178
  'try {',
@@ -3855,12 +4205,12 @@ exports.modules = {
3855
4205
  '}',
3856
4206
  'setTimeout(function(){ try { window.removeEventListener("message", onMessage); } catch(_){} done(Object.assign(new Error("Bridge timeout"), { type: "missing" })); }, 5000);'
3857
4207
  ]) + ';',
3858
- `else if (!isWorker) ${RuntimeGlobals.loadScript} = ${CLASSIC_LOADER};`
4208
+ `if (!isWorker) ${RuntimeGlobals.loadScript} = ${MAIN_CLASSIC_LOADER};`
3859
4209
  ]) : Template.asString([
3860
- `else if (!isWorker && hasExtensionRuntime) ${RuntimeGlobals.loadScript} = ${CLASSIC_LOADER};`,
4210
+ `if (!isWorker && hasExtensionRuntime) ${RuntimeGlobals.loadScript} = ${CLASSIC_LOADER};`,
3861
4211
  `else if (!isWorker) ${RuntimeGlobals.loadScript} = ${DOM_LOADER};`
3862
- ]),
3863
- "else { throw new TypeError('Unable to determinate the chunk loader: content script + Worker'); }",
4212
+ ])),
4213
+ "}",
3864
4214
  this.supportDynamicImport ? `${_const} ${FALLBACK_LOADER} = ${RuntimeGlobals.loadScript};` : '',
3865
4215
  this.supportDynamicImport ? `${RuntimeGlobals.loadScript} = ${DYNAMIC_IMPORT_LOADER};` : ''
3866
4216
  ].filter(Boolean));
@@ -3885,14 +4235,49 @@ exports.modules = {
3885
4235
  hash: compilation.hash || 'XXXX'
3886
4236
  }));
3887
4237
  return Template.asString([
4238
+ 'var __extjsBase = (typeof globalThis === "object" && globalThis && globalThis.__EXTJS_EXTENSION_BASE__) ? String(globalThis.__EXTJS_EXTENSION_BASE__) : "";',
4239
+ 'if (!__extjsBase && typeof document === "object" && document && document.documentElement) {',
4240
+ Template.indent([
4241
+ 'try { __extjsBase = document.documentElement.getAttribute("data-extjs-extension-base") || ""; } catch(_) { __extjsBase = ""; }'
4242
+ ]),
4243
+ "}",
3888
4244
  `if (${RuntimeGlobal} && ${RuntimeGlobal}.runtime && typeof ${RuntimeGlobal}.runtime.getURL === "function") {`,
3889
4245
  Template.indent([
3890
4246
  `${RuntimeGlobals.publicPath} = ${RuntimeGlobal}.runtime.getURL(${path});`
3891
4247
  ]),
4248
+ "} else if (__extjsBase) {",
4249
+ Template.indent([
4250
+ `${RuntimeGlobals.publicPath} = __extjsBase.replace(/\\/+$/, "/") + String(${path}).replace(/^\\/+/, "");`
4251
+ ]),
3892
4252
  "} else {",
3893
4253
  Template.indent([
3894
4254
  `${RuntimeGlobals.publicPath} = "";`
3895
4255
  ]),
4256
+ "}",
4257
+ 'if (!__extjsBase && typeof document === "object" && document && document.documentElement) {',
4258
+ Template.indent([
4259
+ "try {",
4260
+ Template.indent([
4261
+ "var __extjsRetries = 0;",
4262
+ "var __extjsUpdateBase = function(){",
4263
+ Template.indent([
4264
+ 'var base = "";',
4265
+ 'try { base = document.documentElement.getAttribute("data-extjs-extension-base") || ""; } catch(_) { base = ""; }',
4266
+ "if (base) {",
4267
+ Template.indent([
4268
+ `${RuntimeGlobals.publicPath} = base.replace(/\\/+$/, "/") + String(${path}).replace(/^\\/+/, "");`
4269
+ ]),
4270
+ "} else if (__extjsRetries++ < 50) {",
4271
+ Template.indent([
4272
+ "setTimeout(__extjsUpdateBase, 100);"
4273
+ ]),
4274
+ "}"
4275
+ ]),
4276
+ "};",
4277
+ "__extjsUpdateBase();"
4278
+ ]),
4279
+ "} catch (_) {}"
4280
+ ]),
3896
4281
  "}"
3897
4282
  ]);
3898
4283
  }
@@ -3936,17 +4321,54 @@ exports.modules = {
3936
4321
  ]),
3937
4322
  '// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration',
3938
4323
  '// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.',
4324
+ 'var __extjsBase = (typeof globalThis === "object" && globalThis && globalThis.__EXTJS_EXTENSION_BASE__) ? String(globalThis.__EXTJS_EXTENSION_BASE__) : "";',
4325
+ 'if (!__extjsBase && typeof document === "object" && document && document.documentElement) {',
4326
+ Template.indent([
4327
+ 'try { __extjsBase = document.documentElement.getAttribute("data-extjs-extension-base") || ""; } catch(_) { __extjsBase = ""; }'
4328
+ ]),
4329
+ "}",
4330
+ "if (__extjsBase && scriptUrl && !/^((chrome|moz)-extension):///.test(scriptUrl)) {",
4331
+ Template.indent([
4332
+ "scriptUrl = __extjsBase;"
4333
+ ]),
4334
+ "}",
3939
4335
  "if (!scriptUrl) {",
3940
4336
  Template.indent([
3941
4337
  `if (${RuntimeGlobal} && ${RuntimeGlobal}.runtime && typeof ${RuntimeGlobal}.runtime.getURL === "function") {`,
3942
4338
  Template.indent(`scriptUrl = ${RuntimeGlobal}.runtime.getURL("/");`),
3943
4339
  "} else {",
3944
- Template.indent('scriptUrl = "";'),
4340
+ Template.indent('scriptUrl = __extjsBase || "";'),
3945
4341
  "}"
3946
4342
  ]),
3947
4343
  '}',
3948
4344
  'scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\\?.*$/, "").replace(/\\/[^\\/]+$/, "/");',
3949
- undoPath ? `${RuntimeGlobals.publicPath} = scriptUrl + ${JSON.stringify(undoPath)};` : `${RuntimeGlobals.publicPath} = scriptUrl;`
4345
+ undoPath ? `${RuntimeGlobals.publicPath} = scriptUrl + ${JSON.stringify(undoPath)};` : `${RuntimeGlobals.publicPath} = scriptUrl;`,
4346
+ 'if (!scriptUrl && typeof document === "object" && document && document.documentElement) {',
4347
+ Template.indent([
4348
+ "try {",
4349
+ Template.indent([
4350
+ "var __extjsRetries = 0;",
4351
+ "var __extjsUpdateBase = function(){",
4352
+ Template.indent([
4353
+ 'var base = "";',
4354
+ 'try { base = document.documentElement.getAttribute("data-extjs-extension-base") || ""; } catch(_) { base = ""; }',
4355
+ "if (base) {",
4356
+ Template.indent([
4357
+ 'var normalized = base.replace(/\\/+$/, "/");',
4358
+ undoPath ? `${RuntimeGlobals.publicPath} = normalized + ${JSON.stringify(undoPath)};` : `${RuntimeGlobals.publicPath} = normalized;`
4359
+ ]),
4360
+ "} else if (__extjsRetries++ < 50) {",
4361
+ Template.indent([
4362
+ "setTimeout(__extjsUpdateBase, 100);"
4363
+ ]),
4364
+ "}"
4365
+ ]),
4366
+ "};",
4367
+ "__extjsUpdateBase();"
4368
+ ]),
4369
+ "} catch (_) {}"
4370
+ ]),
4371
+ "}"
3950
4372
  ]);
3951
4373
  }
3952
4374
  constructor(){
@@ -4479,10 +4901,30 @@ Set background.noDynamicEntryWarning to true to disable this warning.
4479
4901
  }
4480
4902
  const webpack_target_webextension_fork = WebExtensionPlugin;
4481
4903
  function manifest_getManifestContent(compilation, manifestPath) {
4482
- if (compilation.getAsset?.('manifest.json') || compilation.assets?.['manifest.json']) {
4483
- const source = compilation.assets['manifest.json']?.source?.();
4484
- const manifest = 'function' == typeof source ? source().toString() : String(source || '');
4485
- return JSON.parse(manifest || '{}');
4904
+ const readAssetSource = (asset)=>{
4905
+ if (!asset) return '';
4906
+ const source = asset.source;
4907
+ if ('string' == typeof source) return source;
4908
+ if ('function' == typeof source) {
4909
+ const out = source();
4910
+ return 'string' == typeof out ? out : String(out || '');
4911
+ }
4912
+ if (source && 'function' == typeof source.source) {
4913
+ const out = source.source();
4914
+ return 'string' == typeof out ? out : String(out || '');
4915
+ }
4916
+ return '';
4917
+ };
4918
+ const getAsset = compilation.getAsset;
4919
+ if ('function' == typeof getAsset) {
4920
+ const manifestAsset = getAsset.call(compilation, 'manifest.json');
4921
+ const manifest = readAssetSource(manifestAsset);
4922
+ if (manifest) return JSON.parse(manifest);
4923
+ }
4924
+ const manifestAsset = compilation.assets?.['manifest.json'];
4925
+ if (manifestAsset) {
4926
+ const manifest = readAssetSource(manifestAsset);
4927
+ if (manifest) return JSON.parse(manifest);
4486
4928
  }
4487
4929
  try {
4488
4930
  const text = external_fs_.readFileSync(manifestPath, 'utf8');
@@ -4687,7 +5129,18 @@ Set background.noDynamicEntryWarning to true to disable this warning.
4687
5129
  '/*.scss',
4688
5130
  '/*.sass',
4689
5131
  '/*.less',
4690
- '*.styl'
5132
+ '*.styl',
5133
+ "/scripts/*.js",
5134
+ "/scripts/*.css",
5135
+ '/hot/*',
5136
+ '/*.png',
5137
+ '/*.jpg',
5138
+ '/*.jpeg',
5139
+ '/*.svg',
5140
+ '/*.gif',
5141
+ '/*.webp',
5142
+ '/*.ico',
5143
+ '/*.avif'
4691
5144
  ];
4692
5145
  const resources = manifest.web_accessible_resources;
4693
5146
  if (!resources || 0 === resources.length) return defaultResources;
@@ -4703,7 +5156,18 @@ Set background.noDynamicEntryWarning to true to disable this warning.
4703
5156
  '/*.scss',
4704
5157
  '/*.sass',
4705
5158
  '/*.less',
4706
- '*.styl'
5159
+ '*.styl',
5160
+ "/scripts/*.js",
5161
+ "/scripts/*.css",
5162
+ '/hot/*',
5163
+ '/*.png',
5164
+ '/*.jpg',
5165
+ '/*.jpeg',
5166
+ '/*.svg',
5167
+ '/*.gif',
5168
+ '/*.webp',
5169
+ '/*.ico',
5170
+ '/*.avif'
4707
5171
  ];
4708
5172
  return [
4709
5173
  ...manifest.web_accessible_resources || [],
@@ -4812,7 +5276,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
4812
5276
  if (!compilation?.hooks?.processAssets) return;
4813
5277
  compilation.hooks.processAssets.tap({
4814
5278
  name: 'run-chromium:apply-manifest-dev-defaults',
4815
- stage: core_.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
5279
+ stage: core_.Compilation.PROCESS_ASSETS_STAGE_REPORT + 100
4816
5280
  }, (_assets)=>{
4817
5281
  if (!this.manifestPath) {
4818
5282
  const errorMessage = 'No manifest.json found in your extension bundle. Unable to patch manifest.json.';
@@ -5721,8 +6185,8 @@ Set background.noDynamicEntryWarning to true to disable this warning.
5721
6185
  }, ()=>{
5722
6186
  if (compilation.errors.length > 0) return;
5723
6187
  const iconFields = this.includeList || {};
5724
- external_path_.dirname(this.manifestPath);
5725
- const projectPath = compiler.options.context;
6188
+ const manifestDir = external_path_.dirname(this.manifestPath);
6189
+ const projectPath = compiler.options.context || manifestDir;
5726
6190
  const publicDir = external_path_.join(projectPath, 'public');
5727
6191
  for (const field of Object.entries(iconFields)){
5728
6192
  const [feature, resource] = field;
@@ -6701,108 +7165,8 @@ Set background.noDynamicEntryWarning to true to disable this warning.
6701
7165
  this.browser = options.browser || 'chrome';
6702
7166
  }
6703
7167
  }
6704
- function serverRestartRequiredFromSpecialFolderMessageOnly(addingOrRemoving, folder, typeOfAsset) {
6705
- return `${external_pintor_default().red('ERROR')} in ${external_pintor_default().yellow('manifest.json')} entrypoint: ${addingOrRemoving} ${external_pintor_default().yellow(typeOfAsset)} in ${external_pintor_default().underline(folder + '/')} requires a dev server restart to apply changes.`;
6706
- }
6707
- function specialFoldersSetupSummary(hasPublic, copyEnabled, ignoredCount) {
6708
- return `Special folders setup — public=${String(hasPublic)}, copy=${String(copyEnabled)}, ignored=${String(ignoredCount)}`;
6709
- }
6710
- function specialFolderChangeDetected(action, folder, relativePath) {
6711
- return `Special folders change — ${action} in ${folder}/: ${relativePath}`;
6712
- }
6713
- function warn_upon_folder_changes_define_property(obj, key, value) {
6714
- if (key in obj) Object.defineProperty(obj, key, {
6715
- value: value,
6716
- enumerable: true,
6717
- configurable: true,
6718
- writable: true
6719
- });
6720
- else obj[key] = value;
6721
- return obj;
6722
- }
6723
- class WarnUponFolderChanges {
6724
- throwCompilationError(compilation, folder, filePath, isAddition) {
6725
- const addingOrRemoving = isAddition ? 'Adding' : 'Removing';
6726
- const typeOfAsset = 'pages' === folder ? 'HTML pages' : "script files";
6727
- const errorMessage = serverRestartRequiredFromSpecialFolderMessageOnly(addingOrRemoving, folder, typeOfAsset);
6728
- if (isAddition) {
6729
- const warn = new core_.WebpackError(errorMessage);
6730
- warn.name = 'SpecialFoldersChange';
6731
- warn.file = filePath;
6732
- warn.details = `Detected change in ${folder}/ affecting ${typeOfAsset}. Restart may be required for full effect.`;
6733
- compilation.warnings?.push(warn);
6734
- return;
6735
- }
6736
- const err = new core_.WebpackError(errorMessage);
6737
- err.name = 'SpecialFoldersRemoval';
6738
- err.file = filePath;
6739
- err.details = `Removing from ${folder}/ breaks current build. Restart the dev server to recompile.`;
6740
- compilation.errors?.push(err);
6741
- }
6742
- trackChange(projectPath, folder, change, filePath) {
6743
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFolderChangeDetected('add' === change ? 'add' : 'remove', folder, external_path_.relative(projectPath, filePath)));
6744
- this.pendingChanges.push({
6745
- type: change,
6746
- folder,
6747
- filePath
6748
- });
6749
- }
6750
- collectChanges(compiler) {
6751
- const projectPath = compiler.options.context || process.cwd();
6752
- const pagesPath = external_path_.join(projectPath, 'pages') + external_path_.sep;
6753
- const scriptsPath = external_path_.join(projectPath, "scripts") + external_path_.sep;
6754
- const extensionsSupported = compiler.options.resolve?.extensions;
6755
- const supportedScripts = new Set((extensionsSupported || []).map((e)=>e.toLowerCase()));
6756
- const modifiedFiles = compiler.modifiedFiles || new Set();
6757
- const removedFiles = compiler.removedFiles || new Set();
6758
- for (const filePath of modifiedFiles){
6759
- if (filePath.startsWith(pagesPath) && filePath.endsWith('.html')) this.trackChange(projectPath, 'pages', 'add', filePath);
6760
- if (filePath.startsWith(scriptsPath)) {
6761
- const ext = external_path_.extname(filePath).toLowerCase();
6762
- if (supportedScripts.has(ext)) this.trackChange(projectPath, "scripts", 'add', filePath);
6763
- }
6764
- }
6765
- for (const filePath of removedFiles){
6766
- if (filePath.startsWith(pagesPath) && filePath.endsWith('.html')) this.trackChange(projectPath, 'pages', 'remove', filePath);
6767
- if (filePath.startsWith(scriptsPath)) {
6768
- const ext = external_path_.extname(filePath).toLowerCase();
6769
- if (supportedScripts.has(ext)) this.trackChange(projectPath, "scripts", 'remove', filePath);
6770
- }
6771
- }
6772
- }
6773
- applyPendingChanges(compilation) {
6774
- for (const change of this.pendingChanges)this.throwCompilationError(compilation, change.folder, change.filePath, 'add' === change.type);
6775
- this.pendingChanges = [];
6776
- }
6777
- apply(compiler) {
6778
- compiler.hooks.watchRun.tap('special-folders:warn-upon-folder-changes', ()=>{
6779
- this.collectChanges(compiler);
6780
- });
6781
- compiler.hooks.thisCompilation.tap('special-folders:warn-upon-folder-changes', (compilation)=>{
6782
- const projectPath = compiler.options.context || process.cwd();
6783
- const pagesPath = external_path_.join(projectPath, 'pages');
6784
- const scriptsPath = external_path_.join(projectPath, "scripts");
6785
- compilation.contextDependencies?.add(pagesPath);
6786
- compilation.contextDependencies?.add(scriptsPath);
6787
- this.applyPendingChanges(compilation);
6788
- });
6789
- }
6790
- constructor(){
6791
- warn_upon_folder_changes_define_property(this, "pendingChanges", []);
6792
- }
6793
- }
6794
- function checkManifestInPublic(compilation, publicDir) {
6795
- try {
6796
- const manifestInPublic = external_path_.join(publicDir, 'manifest.json');
6797
- if (external_fs_.existsSync(manifestInPublic)) {
6798
- const ErrCtor = compilation.compiler.webpack?.WebpackError;
6799
- const err = new ErrCtor(`manifest.json must not be placed under public/: ${manifestInPublic}`);
6800
- err.file = 'manifest.json';
6801
- compilation.errors.push(err);
6802
- }
6803
- } catch {}
6804
- }
6805
- function feature_special_folders_define_property(obj, key, value) {
7168
+ var get_data = __webpack_require__("./webpack/feature-special-folders/get-data.ts");
7169
+ function plugin_web_extension_define_property(obj, key, value) {
6806
7170
  if (key in obj) Object.defineProperty(obj, key, {
6807
7171
  value: value,
6808
7172
  enumerable: true,
@@ -6812,116 +7176,14 @@ Set background.noDynamicEntryWarning to true to disable this warning.
6812
7176
  else obj[key] = value;
6813
7177
  return obj;
6814
7178
  }
6815
- class SpecialFoldersPlugin {
6816
- apply(compiler) {
6817
- const { manifestPath } = this.options;
6818
- const context = compiler.options.context || external_path_.dirname(manifestPath);
6819
- const publicDir = external_path_.join(context, 'public');
6820
- if (external_fs_.existsSync(publicDir) && external_fs_.statSync(publicDir).isDirectory()) {
6821
- compiler.hooks.thisCompilation.tap(SpecialFoldersPlugin.name, (compilation)=>{
6822
- compilation.hooks.processAssets.tap({
6823
- name: `${SpecialFoldersPlugin.name}:guards`,
6824
- stage: compilation.constructor.PROCESS_ASSETS_STAGE_PRE_PROCESS
6825
- }, ()=>{
6826
- checkManifestInPublic(compilation, publicDir);
6827
- });
6828
- });
6829
- new core_.rspack.CopyRspackPlugin({
6830
- patterns: [
6831
- {
6832
- from: publicDir,
6833
- to: '.',
6834
- noErrorOnMissing: true,
6835
- globOptions: {
6836
- ignore: [
6837
- '**/manifest.json'
6838
- ]
6839
- }
6840
- }
6841
- ]
6842
- }).apply(compiler);
6843
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFoldersSetupSummary(true, true, 1));
6844
- }
6845
- if ('development' === compiler.options.mode) {
6846
- if (compiler.options.watchOptions) new WarnUponFolderChanges().apply(compiler);
6847
- }
6848
- }
6849
- constructor(options){
6850
- feature_special_folders_define_property(this, "options", void 0);
6851
- this.options = options;
6852
- }
6853
- }
6854
- feature_special_folders_define_property(SpecialFoldersPlugin, "name", 'plugin-special-folders');
6855
- function getSpecialFoldersDataForCompiler(compiler) {
6856
- return (0, external_browser_extension_manifest_fields_.getSpecialFoldersData)({
6857
- manifestPath: external_path_default().join(compiler.options.context || '', 'package.json')
6858
- });
6859
- }
6860
- function plugin_extension_define_property(obj, key, value) {
6861
- if (key in obj) Object.defineProperty(obj, key, {
6862
- value: value,
6863
- enumerable: true,
6864
- configurable: true,
6865
- writable: true
6866
- });
6867
- else obj[key] = value;
6868
- return obj;
6869
- }
6870
- class ExtensionPlugin {
7179
+ class plugin_web_extension_WebExtensionPlugin {
6871
7180
  apply(compiler) {
6872
7181
  const manifestPath = this.manifestPath;
6873
7182
  const manifestFieldsData = (0, external_browser_extension_manifest_fields_.getManifestFieldsData)({
6874
7183
  manifestPath,
6875
7184
  browser: this.browser
6876
7185
  });
6877
- const extraHtmlEntries = (()=>{
6878
- try {
6879
- const manifestDir = external_path_.dirname(manifestPath);
6880
- const raw = JSON.parse(external_fs_.readFileSync(manifestPath, 'utf-8'));
6881
- const browser = String(this.browser || '').toLowerCase();
6882
- const prefixes = 'chromium-based' === browser || 'chromium' === browser ? [
6883
- 'chromium',
6884
- 'chrome'
6885
- ] : 'edge' === browser ? [
6886
- 'edge'
6887
- ] : 'firefox' === browser || 'gecko-based' === browser ? [
6888
- 'firefox'
6889
- ] : [
6890
- 'chrome'
6891
- ];
6892
- const candidates = [
6893
- {
6894
- key: 'side_panel',
6895
- prop: 'default_path',
6896
- entry: 'sidebar/index'
6897
- },
6898
- {
6899
- key: 'sidebar_action',
6900
- prop: 'default_panel',
6901
- entry: 'sidebar/index'
6902
- }
6903
- ];
6904
- const entries = {};
6905
- for (const { key, prop, entry } of candidates){
6906
- const direct = raw?.[key];
6907
- if (direct && 'string' == typeof direct[prop]) {
6908
- const resolved = external_path_.resolve(manifestDir, direct[prop]);
6909
- if (external_fs_.existsSync(resolved)) entries[entry] = resolved;
6910
- }
6911
- for (const prefix of prefixes){
6912
- const prefixed = raw?.[`${prefix}:${key}`];
6913
- if (prefixed && 'string' == typeof prefixed[prop]) {
6914
- const resolved = external_path_.resolve(manifestDir, prefixed[prop]);
6915
- if (external_fs_.existsSync(resolved)) entries[entry] = resolved;
6916
- }
6917
- }
6918
- }
6919
- return entries;
6920
- } catch {
6921
- return {};
6922
- }
6923
- })();
6924
- const specialFoldersData = getSpecialFoldersDataForCompiler(compiler);
7186
+ const specialFoldersData = (0, get_data.B)(compiler);
6925
7187
  new ManifestPlugin({
6926
7188
  browser: this.browser,
6927
7189
  manifestPath,
@@ -6937,7 +7199,6 @@ Set background.noDynamicEntryWarning to true to disable this warning.
6937
7199
  browser: this.browser,
6938
7200
  includeList: {
6939
7201
  ...manifestFieldsData.html,
6940
- ...extraHtmlEntries,
6941
7202
  ...specialFoldersData.pages
6942
7203
  }
6943
7204
  }).apply(compiler);
@@ -6969,18 +7230,15 @@ Set background.noDynamicEntryWarning to true to disable this warning.
6969
7230
  ...specialFoldersData.scripts
6970
7231
  }
6971
7232
  }).apply(compiler);
6972
- new SpecialFoldersPlugin({
6973
- manifestPath
6974
- }).apply(compiler);
6975
7233
  }
6976
7234
  constructor(options){
6977
- plugin_extension_define_property(this, "manifestPath", void 0);
6978
- plugin_extension_define_property(this, "browser", void 0);
7235
+ plugin_web_extension_define_property(this, "manifestPath", void 0);
7236
+ plugin_web_extension_define_property(this, "browser", void 0);
6979
7237
  this.manifestPath = options.manifestPath;
6980
7238
  this.browser = options.browser || 'chrome';
6981
7239
  }
6982
7240
  }
6983
- plugin_extension_define_property(ExtensionPlugin, "name", 'plugin-extension');
7241
+ plugin_web_extension_define_property(plugin_web_extension_WebExtensionPlugin, "name", 'plugin-extension');
6984
7242
  function messages_getLoggingPrefix(type) {
6985
7243
  const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
6986
7244
  if (isAuthor) {
@@ -7059,10 +7317,30 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7059
7317
  return JSON.parse(s || '{}');
7060
7318
  }
7061
7319
  function compatibility_lib_manifest_getManifestContent(compilation, manifestPath) {
7062
- if (compilation.getAsset?.('manifest.json') || compilation.assets?.['manifest.json']) {
7063
- const source = compilation.assets['manifest.json']?.source?.();
7064
- const manifest = 'function' == typeof source ? source().toString() : String(source || '');
7065
- return manifest_parseJsonSafe(manifest);
7320
+ const readAssetSource = (asset)=>{
7321
+ if (!asset) return '';
7322
+ const source = asset.source;
7323
+ if ('string' == typeof source) return source;
7324
+ if ('function' == typeof source) {
7325
+ const out = source();
7326
+ return 'string' == typeof out ? out : String(out || '');
7327
+ }
7328
+ if (source && 'function' == typeof source.source) {
7329
+ const out = source.source();
7330
+ return 'string' == typeof out ? out : String(out || '');
7331
+ }
7332
+ return '';
7333
+ };
7334
+ const getAsset = compilation.getAsset;
7335
+ if ('function' == typeof getAsset) {
7336
+ const manifestAsset = getAsset.call(compilation, 'manifest.json');
7337
+ const manifest = readAssetSource(manifestAsset);
7338
+ if (manifest) return manifest_parseJsonSafe(manifest);
7339
+ }
7340
+ const manifestAsset = compilation.assets?.['manifest.json'];
7341
+ if (manifestAsset) {
7342
+ const manifest = readAssetSource(manifestAsset);
7343
+ if (manifest) return manifest_parseJsonSafe(manifest);
7066
7344
  }
7067
7345
  try {
7068
7346
  const text = external_fs_.readFileSync(manifestPath, 'utf8');
@@ -7383,6 +7661,310 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7383
7661
  this.ctx = ctx;
7384
7662
  }
7385
7663
  }
7664
+ function normalizeEnum(value, allowed) {
7665
+ if (null == value) return;
7666
+ const normalized = String(value).trim().toLowerCase();
7667
+ if (!normalized) return;
7668
+ return allowed.includes(normalized) ? normalized : void 0;
7669
+ }
7670
+ function resolveEnvMaxBytes() {
7671
+ const raw = String(process.env.EXTENSION_SOURCE_MAX_BYTES || '').trim();
7672
+ if (!raw) return;
7673
+ if (!/^\d+$/.test(raw)) return;
7674
+ return Math.max(0, parseInt(raw, 10));
7675
+ }
7676
+ function isRawEnvEnabled() {
7677
+ const raw = String(process.env.EXTENSION_SOURCE_RAW || '').trim();
7678
+ return '1' === raw || 'true' === raw.toLowerCase();
7679
+ }
7680
+ function normalizeSourceOutputConfig(input) {
7681
+ const allowedFormats = [
7682
+ 'pretty',
7683
+ 'json',
7684
+ 'ndjson'
7685
+ ];
7686
+ const allowedRedact = [
7687
+ 'off',
7688
+ 'safe',
7689
+ 'strict'
7690
+ ];
7691
+ const allowedShadow = [
7692
+ 'off',
7693
+ 'open-only',
7694
+ 'all'
7695
+ ];
7696
+ const format = normalizeEnum(input.format, allowedFormats) || normalizeEnum(input.logFormat, allowedFormats) || (input.sourceEnabled ? 'json' : 'pretty');
7697
+ const summary = Boolean(input.summary);
7698
+ let maxBytes = 'number' == typeof input.maxBytes && Number.isFinite(input.maxBytes) ? Math.max(0, Math.floor(input.maxBytes)) : void 0;
7699
+ if (void 0 === maxBytes) {
7700
+ const envMax = resolveEnvMaxBytes();
7701
+ if ('number' == typeof envMax) maxBytes = envMax;
7702
+ }
7703
+ if (void 0 === maxBytes) maxBytes = 262144;
7704
+ if (isRawEnvEnabled() && void 0 === input.maxBytes) maxBytes = 0;
7705
+ let redact = normalizeEnum(input.redact, allowedRedact) || ('pretty' !== format ? 'safe' : 'off');
7706
+ if (isRawEnvEnabled() && void 0 === input.redact) redact = 'off';
7707
+ const includeShadow = normalizeEnum(input.includeShadow, allowedShadow) || (input.sourceEnabled ? 'open-only' : 'off');
7708
+ return {
7709
+ format,
7710
+ summary,
7711
+ maxBytes,
7712
+ redact,
7713
+ includeShadow
7714
+ };
7715
+ }
7716
+ function applySourceRedaction(html, redact) {
7717
+ if (!html) return '';
7718
+ if ('off' === redact) return html;
7719
+ let output = html;
7720
+ output = stripTagBlocks(output, "script");
7721
+ output = stripTagBlocks(output, 'style');
7722
+ output = output.replace(/data:[^"'\s>]{1024,}/gi, 'data:[REDACTED_BASE64]');
7723
+ if ('strict' === redact) {
7724
+ output = stripInlineEventHandlers(output);
7725
+ output = output.replace(/="[^"]{257,}"/g, (match)=>`="${match.slice(2, 258)}..."`);
7726
+ output = output.replace(/='[^']{257,}'/g, (match)=>`='${match.slice(2, 258)}...'`);
7727
+ output = output.replace(/\b(?:javascript|data|vbscript)\s*:/gi, '');
7728
+ }
7729
+ return output;
7730
+ }
7731
+ function stripTagBlocks(input, tagName) {
7732
+ const lower = input.toLowerCase();
7733
+ const openToken = `<${tagName}`;
7734
+ const closeToken = `</${tagName}`;
7735
+ let cursor = 0;
7736
+ let output = '';
7737
+ while(cursor < input.length){
7738
+ const openIndex = lower.indexOf(openToken, cursor);
7739
+ if (-1 === openIndex) {
7740
+ output += input.slice(cursor);
7741
+ break;
7742
+ }
7743
+ output += input.slice(cursor, openIndex);
7744
+ const openEnd = lower.indexOf('>', openIndex + openToken.length);
7745
+ if (-1 === openEnd) break;
7746
+ const closeIndex = lower.indexOf(closeToken, openEnd + 1);
7747
+ if (-1 === closeIndex) {
7748
+ cursor = openEnd + 1;
7749
+ continue;
7750
+ }
7751
+ const closeEnd = lower.indexOf('>', closeIndex + closeToken.length);
7752
+ cursor = -1 === closeEnd ? closeIndex + closeToken.length : closeEnd + 1;
7753
+ }
7754
+ return output;
7755
+ }
7756
+ function stripInlineEventHandlers(input) {
7757
+ let output = '';
7758
+ let cursor = 0;
7759
+ while(cursor < input.length){
7760
+ const tagStart = input.indexOf('<', cursor);
7761
+ if (-1 === tagStart) {
7762
+ output += input.slice(cursor);
7763
+ break;
7764
+ }
7765
+ output += input.slice(cursor, tagStart);
7766
+ const tagEnd = input.indexOf('>', tagStart + 1);
7767
+ if (-1 === tagEnd) {
7768
+ output += input.slice(tagStart);
7769
+ break;
7770
+ }
7771
+ const tag = input.slice(tagStart, tagEnd + 1);
7772
+ output += stripInlineEventHandlersFromTag(tag);
7773
+ cursor = tagEnd + 1;
7774
+ }
7775
+ return output;
7776
+ }
7777
+ function stripInlineEventHandlersFromTag(tag) {
7778
+ if (tag.startsWith('</') || tag.startsWith('<!') || tag.startsWith('<?')) return tag;
7779
+ const withoutClose = tag.endsWith('/>') ? tag.slice(0, -2) : tag.slice(0, -1);
7780
+ const closeSuffix = tag.endsWith('/>') ? '/>' : '>';
7781
+ const firstSpace = withoutClose.search(/\s/);
7782
+ if (-1 === firstSpace) return tag;
7783
+ const prefix = withoutClose.slice(0, firstSpace);
7784
+ const attrs = withoutClose.slice(firstSpace);
7785
+ let rebuilt = prefix;
7786
+ let i = 0;
7787
+ while(i < attrs.length){
7788
+ while(i < attrs.length && /\s/.test(attrs[i]))i += 1;
7789
+ if (i >= attrs.length) break;
7790
+ const attrStart = i;
7791
+ while(i < attrs.length && !/[\s=>]/.test(attrs[i]))i += 1;
7792
+ const attrName = attrs.slice(attrStart, i);
7793
+ const attrNameLower = attrName.toLowerCase();
7794
+ while(i < attrs.length && /\s/.test(attrs[i]))i += 1;
7795
+ let value = '';
7796
+ if ('=' === attrs[i]) {
7797
+ value += '=';
7798
+ i += 1;
7799
+ while(i < attrs.length && /\s/.test(attrs[i])){
7800
+ value += attrs[i];
7801
+ i += 1;
7802
+ }
7803
+ const quote = attrs[i];
7804
+ if ('"' === quote || "'" === quote) {
7805
+ value += quote;
7806
+ i += 1;
7807
+ while(i < attrs.length && attrs[i] !== quote){
7808
+ value += attrs[i];
7809
+ i += 1;
7810
+ }
7811
+ if (i < attrs.length && attrs[i] === quote) {
7812
+ value += attrs[i];
7813
+ i += 1;
7814
+ }
7815
+ } else while(i < attrs.length && !/[\s>]/.test(attrs[i])){
7816
+ value += attrs[i];
7817
+ i += 1;
7818
+ }
7819
+ }
7820
+ if (!attrNameLower.startsWith('on')) rebuilt += ` ${attrName}${value}`;
7821
+ }
7822
+ return `${rebuilt}${closeSuffix}`;
7823
+ }
7824
+ function truncateByBytes(input, maxBytes) {
7825
+ const html = input || '';
7826
+ const byteLength = Buffer.byteLength(html, 'utf8');
7827
+ if (maxBytes <= 0 || byteLength <= maxBytes) return {
7828
+ output: html,
7829
+ truncated: false,
7830
+ byteLength
7831
+ };
7832
+ let acc = 0;
7833
+ let endIndex = 0;
7834
+ for(let i = 0; i < html.length; i++){
7835
+ const b = Buffer.byteLength(html[i], 'utf8');
7836
+ if (acc + b > maxBytes) break;
7837
+ acc += b;
7838
+ endIndex = i + 1;
7839
+ }
7840
+ return {
7841
+ output: html.slice(0, endIndex),
7842
+ truncated: true,
7843
+ byteLength
7844
+ };
7845
+ }
7846
+ function hashStringFNV1a(input) {
7847
+ let hash = 0x811c9dc5;
7848
+ for(let i = 0; i < input.length; i++){
7849
+ hash ^= input.charCodeAt(i);
7850
+ hash = 0x01000193 * hash >>> 0;
7851
+ }
7852
+ return hash.toString(16).padStart(8, '0');
7853
+ }
7854
+ function diffDomSnapshots(prev, next) {
7855
+ if (!prev) return {
7856
+ added: next.nodes.length,
7857
+ removed: 0,
7858
+ changed: 0,
7859
+ addedKeys: next.nodes.slice(0, 50).map((n)=>n.key),
7860
+ removedKeys: [],
7861
+ changedKeys: []
7862
+ };
7863
+ const prevMap = new Map(prev.nodes.map((n)=>[
7864
+ n.key,
7865
+ n
7866
+ ]));
7867
+ const nextMap = new Map(next.nodes.map((n)=>[
7868
+ n.key,
7869
+ n
7870
+ ]));
7871
+ let added = 0;
7872
+ let removed = 0;
7873
+ let changed = 0;
7874
+ const addedKeys = [];
7875
+ const removedKeys = [];
7876
+ const changedKeys = [];
7877
+ for (const [key, node] of nextMap.entries()){
7878
+ if (!prevMap.has(key)) {
7879
+ added += 1;
7880
+ if (addedKeys.length < 50) addedKeys.push(key);
7881
+ continue;
7882
+ }
7883
+ const prevNode = prevMap.get(key);
7884
+ const prevHash = hashStringFNV1a(JSON.stringify(prevNode));
7885
+ const nextHash = hashStringFNV1a(JSON.stringify(node));
7886
+ if (prevHash !== nextHash) {
7887
+ changed += 1;
7888
+ if (changedKeys.length < 50) changedKeys.push(key);
7889
+ }
7890
+ }
7891
+ for (const key of prevMap.keys())if (!nextMap.has(key)) {
7892
+ removed += 1;
7893
+ if (removedKeys.length < 50) removedKeys.push(key);
7894
+ }
7895
+ return {
7896
+ added,
7897
+ removed,
7898
+ changed,
7899
+ addedKeys,
7900
+ removedKeys,
7901
+ changedKeys
7902
+ };
7903
+ }
7904
+ function resolveActionFormat() {
7905
+ const raw = String(process.env.EXTENSION_SOURCE_FORMAT || '').trim();
7906
+ if ('json' === raw || 'ndjson' === raw) return raw;
7907
+ return 'pretty';
7908
+ }
7909
+ function emitActionEvent(action, payload = {}, format = resolveActionFormat()) {
7910
+ const base = {
7911
+ type: 'action_event',
7912
+ schema_version: '1.0',
7913
+ timestamp: new Date().toISOString(),
7914
+ action,
7915
+ ...payload
7916
+ };
7917
+ if ('pretty' === format) return void console.log(`${base.timestamp} [action] ${action} ${JSON.stringify(payload)}`);
7918
+ console.log(JSON.stringify(base));
7919
+ }
7920
+ function buildHtmlSummary(html) {
7921
+ const content = html || '';
7922
+ const extensionRootIdMatches = content.match(/id=(["'])extension-root\1/gi) || [];
7923
+ const extensionRootDataMatches = content.match(/data-extension-root=(["'])true\1/gi) || [];
7924
+ const shadowRootMatches = content.match(/shadowroot=/gi) || [];
7925
+ const scripts = content.match(/<script\b/gi) || [];
7926
+ const styles = content.match(/<style\b/gi) || [];
7927
+ const hasExtensionRootId = extensionRootIdMatches.length > 0;
7928
+ const hasContentScriptMarker = /(content_script|content_title|js-probe)/i.test(content);
7929
+ const markerIndex = content.search(/id=(["'])extension-root\1|data-extension-root=(["'])true\2/i);
7930
+ let snippet = '';
7931
+ if (markerIndex >= 0) {
7932
+ const start = Math.max(0, markerIndex - 200);
7933
+ const end = Math.min(content.length, markerIndex + 400);
7934
+ snippet = content.slice(start, end).replace(/\s+/g, ' ').trim();
7935
+ }
7936
+ return {
7937
+ counts: {
7938
+ extensionRoots: extensionRootIdMatches.length + extensionRootDataMatches.length,
7939
+ shadowRoots: shadowRootMatches.length,
7940
+ scripts: scripts.length,
7941
+ styles: styles.length
7942
+ },
7943
+ markers: {
7944
+ hasExtensionRootId,
7945
+ hasContentScriptMarker
7946
+ },
7947
+ snippet: snippet || void 0
7948
+ };
7949
+ }
7950
+ function sanitizeAttr(value) {
7951
+ if (null == value) return '';
7952
+ return String(value).replace(/"/g, "'").replace(/\s+/g, ' ').trim();
7953
+ }
7954
+ function formatHtmlSentinelBegin(meta) {
7955
+ const parts = [
7956
+ meta.url ? `url="${sanitizeAttr(meta.url)}"` : '',
7957
+ meta.title ? `title="${sanitizeAttr(meta.title)}"` : '',
7958
+ void 0 !== meta.tabId ? `tab="${sanitizeAttr(meta.tabId)}"` : '',
7959
+ meta.stage ? `stage="${sanitizeAttr(meta.stage)}"` : '',
7960
+ void 0 !== meta.truncated ? `truncated="${sanitizeAttr(meta.truncated.toString())}"` : ''
7961
+ ].filter(Boolean);
7962
+ const suffix = parts.length > 0 ? ` ${parts.join(' ')}` : '';
7963
+ return `<<<EXTJS_HTML_BEGIN${suffix}>>>`;
7964
+ }
7965
+ function formatHtmlSentinelEnd() {
7966
+ return '<<<EXTJS_HTML_END>>>';
7967
+ }
7386
7968
  function chromium_hard_reload_define_property(obj, key, value) {
7387
7969
  if (key in obj) Object.defineProperty(obj, key, {
7388
7970
  value: value,
@@ -7406,10 +7988,14 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7406
7988
  try {
7407
7989
  const modifiedFiles = compilerWithModifiedFiles?.modifiedFiles || new Set();
7408
7990
  const normalizedModifiedFilePaths = Array.from(modifiedFiles).map((filePath)=>String(filePath).replace(/\\/g, '/'));
7409
- const hitManifest = normalizedModifiedFilePaths.some((filePath)=>/(^|\/)manifest\.json$/i.test(filePath));
7410
- const localeChanged = normalizedModifiedFilePaths.some((filePath)=>/(^|\/)__?locales\/.+\.json$/i.test(filePath));
7991
+ const compilerContextRoot = String(compiler?.options?.context || '').replace(/\\/g, '/');
7992
+ const filesInCurrentCompilerContext = compilerContextRoot ? normalizedModifiedFilePaths.filter((filePath)=>filePath === compilerContextRoot || filePath.startsWith(`${compilerContextRoot}/`)) : normalizedModifiedFilePaths;
7993
+ const watchedModifiedFilePaths = filesInCurrentCompilerContext.length > 0 ? filesInCurrentCompilerContext : normalizedModifiedFilePaths;
7994
+ const hitManifest = watchedModifiedFilePaths.some((filePath)=>/(^|\/)manifest\.json$/i.test(filePath));
7995
+ const localeChanged = watchedModifiedFilePaths.some((filePath)=>/(^|\/)__?locales\/.+\.json$/i.test(filePath));
7411
7996
  let serviceWorkerChanged = false;
7412
- if (this.serviceWorkerSourceDependencyPaths.size > 0) serviceWorkerChanged = normalizedModifiedFilePaths.some((modifiedFilePath)=>{
7997
+ let contentScriptChanged = false;
7998
+ if (this.serviceWorkerSourceDependencyPaths.size > 0) serviceWorkerChanged = watchedModifiedFilePaths.some((modifiedFilePath)=>{
7413
7999
  if (this.serviceWorkerSourceDependencyPaths.has(modifiedFilePath)) return true;
7414
8000
  for (const serviceWorkerSourceDependencyPath of this.serviceWorkerSourceDependencyPaths)if (modifiedFilePath.endsWith(serviceWorkerSourceDependencyPath)) return true;
7415
8001
  return false;
@@ -7418,15 +8004,21 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7418
8004
  const { absolutePath: serviceWorkerAbsolutePath, relativePath: serviceWorkerRelativePath } = this.ctx.getServiceWorkerPaths() || {};
7419
8005
  if (serviceWorkerAbsolutePath) {
7420
8006
  const normalizedServiceWorkerAbsolutePath = serviceWorkerAbsolutePath.replace(/\\/g, '/');
7421
- serviceWorkerChanged = normalizedModifiedFilePaths.some((filePath)=>{
8007
+ serviceWorkerChanged = watchedModifiedFilePaths.some((filePath)=>{
7422
8008
  const normalizedPath = filePath.replace(/\\/g, '/');
7423
8009
  return normalizedPath === normalizedServiceWorkerAbsolutePath || normalizedPath.endsWith(normalizedServiceWorkerAbsolutePath) || (serviceWorkerRelativePath ? normalizedPath === serviceWorkerRelativePath.replace(/\\/g, '/') || normalizedPath.endsWith('/' + serviceWorkerRelativePath.replace(/\\/g, '/')) : false);
7424
8010
  });
7425
8011
  }
7426
8012
  }
8013
+ if (this.contentScriptSourceDependencyPaths.size > 0) contentScriptChanged = watchedModifiedFilePaths.some((modifiedFilePath)=>{
8014
+ if (this.contentScriptSourceDependencyPaths.has(modifiedFilePath)) return true;
8015
+ for (const contentPath of this.contentScriptSourceDependencyPaths)if (modifiedFilePath.endsWith(contentPath)) return true;
8016
+ return false;
8017
+ });
7427
8018
  if (hitManifest) this.ctx.setPendingReloadReason('manifest');
7428
8019
  else if (localeChanged) this.ctx.setPendingReloadReason('locales');
7429
8020
  else if (serviceWorkerChanged) this.ctx.setPendingReloadReason('sw');
8021
+ else if (contentScriptChanged) this.ctx.setPendingReloadReason('content');
7430
8022
  } catch (error) {
7431
8023
  this.logger?.warn?.('[reload-debug] watchRun inspect failed:', String(error));
7432
8024
  }
@@ -7437,13 +8029,29 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7437
8029
  if (hasErrors) return;
7438
8030
  this.refreshSWFromManifest(stats.compilation);
7439
8031
  this.refreshServiceWorkerSourceDependencyPaths(stats.compilation);
7440
- const reason = this.ctx.getPendingReloadReason();
8032
+ this.refreshContentScriptSourceDependencyPaths(stats.compilation);
8033
+ const pendingReason = this.ctx.getPendingReloadReason();
8034
+ const contentScriptEmitted = this.didEmitContentScripts(stats);
8035
+ const reason = pendingReason || (contentScriptEmitted ? 'content' : void 0);
7441
8036
  if (!reason) return;
7442
8037
  this.ctx.clearPendingReloadReason();
7443
8038
  const ctrl = this.ctx.getController();
7444
8039
  if (!ctrl) return;
7445
8040
  this.logger?.info?.(`[reload] reloading extension (reason:${reason})`);
7446
- const ok = await ctrl.hardReload();
8041
+ emitActionEvent('extension_reload', {
8042
+ reason: reason || 'unknown',
8043
+ browser: this.options?.browser
8044
+ });
8045
+ const reloadTimeoutMs = 8000;
8046
+ const ok = await Promise.race([
8047
+ ctrl.hardReload(),
8048
+ new Promise((resolve)=>{
8049
+ setTimeout(()=>{
8050
+ this.logger?.warn?.(`[reload] hardReload timed out after ${reloadTimeoutMs}ms; continuing with source inspection`);
8051
+ resolve(false);
8052
+ }, reloadTimeoutMs);
8053
+ })
8054
+ ]);
7447
8055
  if (!ok && !this.warnedDevMode) {
7448
8056
  this.warnedDevMode = true;
7449
8057
  this.logger?.warn?.(browsers_lib_messages.KE0(this.options?.browser));
@@ -7471,6 +8079,35 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7471
8079
  this.serviceWorkerSourceDependencyPaths = discovered;
7472
8080
  } catch {}
7473
8081
  }
8082
+ didEmitContentScripts(stats) {
8083
+ try {
8084
+ const json = 'function' == typeof stats?.toJson ? stats.toJson({
8085
+ assets: true
8086
+ }) : null;
8087
+ const assets = json?.assets || [];
8088
+ return assets.some((asset)=>{
8089
+ const name = String(asset?.name || '');
8090
+ if (!/(^|\/)content_scripts\/content-\d+\.(js|css)$/.test(name)) return false;
8091
+ if ('boolean' == typeof asset?.emitted) return asset.emitted;
8092
+ return true;
8093
+ });
8094
+ } catch {
8095
+ return false;
8096
+ }
8097
+ }
8098
+ refreshContentScriptSourceDependencyPaths(compilation) {
8099
+ try {
8100
+ const entrypoints = compilation?.entrypoints;
8101
+ if (!entrypoints) return;
8102
+ const discovered = new Set();
8103
+ for (const [name] of entrypoints){
8104
+ if (!String(name).startsWith("content_scripts/content-")) continue;
8105
+ const deps = this.collectEntrypointModuleResourcePaths(compilation, String(name));
8106
+ for (const dep of deps)discovered.add(dep);
8107
+ }
8108
+ this.contentScriptSourceDependencyPaths = discovered;
8109
+ } catch {}
8110
+ }
7474
8111
  collectEntrypointModuleResourcePaths(compilation, entrypointName) {
7475
8112
  const collectedResourcePaths = new Set();
7476
8113
  const entrypoints = compilation?.entrypoints;
@@ -7494,9 +8131,11 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7494
8131
  chromium_hard_reload_define_property(this, "logger", void 0);
7495
8132
  chromium_hard_reload_define_property(this, "warnedDevMode", void 0);
7496
8133
  chromium_hard_reload_define_property(this, "serviceWorkerSourceDependencyPaths", void 0);
8134
+ chromium_hard_reload_define_property(this, "contentScriptSourceDependencyPaths", void 0);
7497
8135
  this.options = options;
7498
8136
  this.ctx = ctx;
7499
8137
  this.serviceWorkerSourceDependencyPaths = new Set();
8138
+ this.contentScriptSourceDependencyPaths = new Set();
7500
8139
  }
7501
8140
  }
7502
8141
  var shared_utils = __webpack_require__("./webpack/plugin-browsers/browsers-lib/shared-utils.ts");
@@ -7528,13 +8167,23 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7528
8167
  }
7529
8168
  throw new Error(browsers_lib_messages.olb(port));
7530
8169
  }
7531
- async function ensureTargetAndSession(cdpClient, url) {
8170
+ async function ensureTargetAndSession(cdpClient, url, options) {
8171
+ const forceNavigate = Boolean(options?.forceNavigate);
7532
8172
  const targets = await cdpClient.getTargets();
7533
8173
  const existingTarget = (targets || []).find((t)=>String(t?.url || '') === url && 'page' === String(t?.type || ''));
7534
8174
  let targetId = '';
7535
8175
  if (existingTarget && existingTarget.targetId) {
7536
8176
  targetId = String(existingTarget.targetId);
7537
8177
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(browsers_lib_messages.dxi(existingTarget.targetId));
8178
+ if (forceNavigate) {
8179
+ const tempSession = await cdpClient.attachToTarget(targetId);
8180
+ if (tempSession) {
8181
+ try {
8182
+ await cdpClient.enableRuntimeAndLog(String(tempSession));
8183
+ } catch {}
8184
+ await cdpClient.navigate(String(tempSession), url);
8185
+ }
8186
+ }
7538
8187
  } else {
7539
8188
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(browsers_lib_messages.HSH());
7540
8189
  const created = await cdpClient.createTarget(url);
@@ -7566,15 +8215,15 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7566
8215
  sessionId: String(sessionId)
7567
8216
  };
7568
8217
  }
7569
- async function extractPageHtml(cdpClient, sessionId, logSamples = 'true' === process.env.EXTENSION_AUTHOR_MODE) {
7570
- let html = await cdpClient.getPageHTML(sessionId);
8218
+ async function extractPageHtml(cdpClient, sessionId, logSamples = 'true' === process.env.EXTENSION_AUTHOR_MODE, includeShadow = 'open-only') {
8219
+ let html = await cdpClient.getPageHTML(sessionId, includeShadow);
7571
8220
  if (!html) try {
7572
8221
  const targets = await cdpClient.getTargets();
7573
8222
  const fallbackTarget = targets.find((target)=>'page' === target.type && /example\.com|http/.test(String(target.url || '')));
7574
8223
  if (fallbackTarget && fallbackTarget.targetId) {
7575
8224
  const newSessionId = await cdpClient.attachToTarget(fallbackTarget.targetId);
7576
8225
  await cdpClient.waitForContentScriptInjection(newSessionId);
7577
- const retryHtml = await cdpClient.getPageHTML(newSessionId);
8226
+ const retryHtml = await cdpClient.getPageHTML(newSessionId, includeShadow);
7578
8227
  if (logSamples) {
7579
8228
  const sample2 = (retryHtml || '').slice(0, 200).replace(/\n/g, ' ');
7580
8229
  console.log(browsers_lib_messages.LcW(sample2));
@@ -7585,7 +8234,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7585
8234
  if (!html || !/(id=\"extension-root\"|content_script|content_title|js-probe)/.test(html)) for(let i = 0; i < 3; i++){
7586
8235
  await new Promise((r)=>setTimeout(r, 500));
7587
8236
  try {
7588
- const againHtml = await cdpClient.getPageHTML(sessionId);
8237
+ const againHtml = await cdpClient.getPageHTML(sessionId, includeShadow);
7589
8238
  if (logSamples) {
7590
8239
  const sample3 = (againHtml || '').slice(0, 200).replace(/\n/g, ' ');
7591
8240
  console.log(browsers_lib_messages.jUj(sample3));
@@ -7629,6 +8278,460 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7629
8278
  const isDevEnv = 'development' === String(process.env.EXTENSION_AUTHOR_MODE || '').trim().toLowerCase();
7630
8279
  return authorMode || isDevEnv;
7631
8280
  }
8281
+ getOutputConfig() {
8282
+ return normalizeSourceOutputConfig({
8283
+ format: this.devOptions.sourceFormat,
8284
+ summary: this.devOptions.sourceSummary,
8285
+ maxBytes: this.devOptions.sourceMaxBytes,
8286
+ redact: this.devOptions.sourceRedact,
8287
+ includeShadow: this.devOptions.sourceIncludeShadow,
8288
+ sourceEnabled: Boolean(this.devOptions.source || this.devOptions.watchSource),
8289
+ logFormat: this.devOptions.logFormat
8290
+ });
8291
+ }
8292
+ async getPageMetadata() {
8293
+ if (!this.cdpClient || !this.currentSessionId) return {};
8294
+ const meta = {};
8295
+ try {
8296
+ const url = await this.cdpClient.evaluate(this.currentSessionId, 'String(location.href)');
8297
+ if ('string' == typeof url) meta.url = url;
8298
+ } catch {}
8299
+ try {
8300
+ const title = await this.cdpClient.evaluate(this.currentSessionId, 'String(document.title)');
8301
+ if ('string' == typeof title) meta.title = title;
8302
+ } catch {}
8303
+ return meta;
8304
+ }
8305
+ async getFrameContext() {
8306
+ if (!this.cdpClient || !this.currentSessionId) return {};
8307
+ const context = {};
8308
+ try {
8309
+ const tree = await this.cdpClient.sendCommand('Page.getFrameTree', {}, this.currentSessionId);
8310
+ const frame = tree?.frameTree?.frame || tree?.frame;
8311
+ if (frame?.id) context.frameId = String(frame.id);
8312
+ if (frame?.url) context.frameUrl = String(frame.url);
8313
+ } catch {}
8314
+ try {
8315
+ const evalResp = await this.cdpClient.sendCommand('Runtime.evaluate', {
8316
+ expression: '1',
8317
+ returnByValue: true
8318
+ }, this.currentSessionId);
8319
+ if ('number' == typeof evalResp?.executionContextId) context.executionContextId = evalResp.executionContextId;
8320
+ } catch {}
8321
+ return context;
8322
+ }
8323
+ async getDomSnapshot() {
8324
+ if (!this.cdpClient || !this.currentSessionId) return;
8325
+ const includeShadow = 'off' !== this.devOptions.sourceIncludeShadow;
8326
+ try {
8327
+ const payload = await this.cdpClient.evaluate(this.currentSessionId, `(() => {
8328
+ const rootEl = document.querySelector('#extension-root,[data-extension-root="true"]');
8329
+ if (!rootEl) return null;
8330
+ const root = (${includeShadow ? 'rootEl.shadowRoot || rootEl' : 'rootEl'});
8331
+ const maxDepth = 6;
8332
+ const maxNodes = 500;
8333
+ let count = 0;
8334
+ let truncated = false;
8335
+ const nodes = [];
8336
+ const childIndex = (node) => {
8337
+ if (!node || !node.parentElement) return 0;
8338
+ const siblings = Array.from(node.parentElement.children || []);
8339
+ return siblings.indexOf(node);
8340
+ };
8341
+ const walk = (node, depth, path) => {
8342
+ if (!node || depth > maxDepth || count >= maxNodes) {
8343
+ truncated = truncated || count >= maxNodes;
8344
+ return;
8345
+ }
8346
+ if (node.nodeType !== 1) return;
8347
+ count++;
8348
+ const el = node;
8349
+ const text = el.textContent ? String(el.textContent).trim() : '';
8350
+ const key = path;
8351
+ nodes.push({
8352
+ key,
8353
+ tag: el.tagName ? String(el.tagName).toLowerCase() : 'unknown',
8354
+ id: el.id ? String(el.id) : undefined,
8355
+ classes: el.className ? String(el.className) : undefined,
8356
+ role: el.getAttribute ? el.getAttribute('role') : undefined,
8357
+ ariaLabel: el.getAttribute ? el.getAttribute('aria-label') : undefined,
8358
+ name: el.getAttribute ? el.getAttribute('name') : undefined,
8359
+ type: el.getAttribute ? el.getAttribute('type') : undefined,
8360
+ textLength: text.length,
8361
+ childCount: el.children ? el.children.length : 0
8362
+ });
8363
+ if (depth >= maxDepth) return;
8364
+ const children = el.children ? Array.from(el.children) : [];
8365
+ for (const child of children) {
8366
+ const idx = childIndex(child);
8367
+ const childPath =
8368
+ path +
8369
+ '/' +
8370
+ child.tagName.toLowerCase() +
8371
+ '[' +
8372
+ idx +
8373
+ ']';
8374
+ walk(child, depth + 1, childPath);
8375
+ }
8376
+ };
8377
+ const rootKey = root === rootEl
8378
+ ? rootEl.tagName.toLowerCase() + '[0]'
8379
+ : rootEl.tagName.toLowerCase() + '[0]/shadow-root[0]';
8380
+ walk(root, 0, rootKey);
8381
+ return {
8382
+ rootMode: root === rootEl ? 'element' : 'shadow',
8383
+ depthLimit: maxDepth,
8384
+ nodeLimit: maxNodes,
8385
+ truncated,
8386
+ nodes
8387
+ };
8388
+ })()`);
8389
+ if (payload && 'object' == typeof payload) return payload;
8390
+ } catch {}
8391
+ }
8392
+ async getPageMetaSnapshot() {
8393
+ if (!this.cdpClient || !this.currentSessionId) return {};
8394
+ try {
8395
+ const snapshot = await this.cdpClient.evaluate(this.currentSessionId, `(() => {
8396
+ try {
8397
+ return {
8398
+ readyState: document.readyState,
8399
+ viewport: {
8400
+ width: window.innerWidth,
8401
+ height: window.innerHeight,
8402
+ devicePixelRatio: window.devicePixelRatio
8403
+ },
8404
+ frameCount: (window.frames && window.frames.length) || 0
8405
+ };
8406
+ } catch (e) {
8407
+ return {};
8408
+ }
8409
+ })()`);
8410
+ if (snapshot && 'object' == typeof snapshot) return snapshot;
8411
+ } catch {}
8412
+ return {};
8413
+ }
8414
+ async getSelectorProbes(selectors) {
8415
+ if (!this.cdpClient || !this.currentSessionId) return [];
8416
+ if (!selectors.length) return [];
8417
+ try {
8418
+ const payload = await this.cdpClient.evaluate(this.currentSessionId, `(() => {
8419
+ const selectors = ${JSON.stringify(selectors)};
8420
+ const limit = 3;
8421
+ const snippetLen = 140;
8422
+ return selectors.map((selector) => {
8423
+ let nodes = [];
8424
+ try {
8425
+ nodes = Array.from(document.querySelectorAll(selector));
8426
+ } catch (e) {
8427
+ return {selector, count: 0, samples: []};
8428
+ }
8429
+ const samples = nodes.slice(0, limit).map((node) => {
8430
+ const text = (node && node.textContent) ? String(node.textContent) : '';
8431
+ return {
8432
+ tag: node && node.tagName ? String(node.tagName).toLowerCase() : 'unknown',
8433
+ id: node && node.id ? String(node.id) : undefined,
8434
+ classes: node && node.className ? String(node.className) : undefined,
8435
+ role: node && node.getAttribute ? node.getAttribute('role') : undefined,
8436
+ ariaLabel: node && node.getAttribute ? node.getAttribute('aria-label') : undefined,
8437
+ textLength: text.length,
8438
+ textSnippet: text.trim().slice(0, snippetLen)
8439
+ };
8440
+ });
8441
+ return {selector, count: nodes.length, samples};
8442
+ });
8443
+ })()`);
8444
+ if (Array.isArray(payload)) return payload;
8445
+ } catch {}
8446
+ return [];
8447
+ }
8448
+ async getExtensionRootTree() {
8449
+ if (!this.cdpClient || !this.currentSessionId) return;
8450
+ const includeShadow = 'off' !== this.devOptions.sourceIncludeShadow;
8451
+ try {
8452
+ const payload = await this.cdpClient.evaluate(this.currentSessionId, `(() => {
8453
+ const rootEl = document.querySelector('#extension-root,[data-extension-root="true"]');
8454
+ if (!rootEl) return null;
8455
+ const root = (${includeShadow ? 'rootEl.shadowRoot || rootEl' : 'rootEl'});
8456
+ const maxDepth = 4;
8457
+ const maxNodes = 200;
8458
+ let count = 0;
8459
+ let truncated = false;
8460
+ const nodeInfo = (node, depth) => {
8461
+ if (!node || depth > maxDepth || count >= maxNodes) {
8462
+ truncated = truncated || count >= maxNodes;
8463
+ return null;
8464
+ }
8465
+ if (node.nodeType !== 1) return null;
8466
+ count++;
8467
+ const el = node;
8468
+ const text = el.textContent ? String(el.textContent).trim() : '';
8469
+ const children = [];
8470
+ if (depth < maxDepth) {
8471
+ const nodes = el.children ? Array.from(el.children) : [];
8472
+ for (const child of nodes) {
8473
+ const childInfo = nodeInfo(child, depth + 1);
8474
+ if (childInfo) children.push(childInfo);
8475
+ }
8476
+ }
8477
+ return {
8478
+ tag: el.tagName ? String(el.tagName).toLowerCase() : 'unknown',
8479
+ id: el.id ? String(el.id) : undefined,
8480
+ classes: el.className ? String(el.className) : undefined,
8481
+ role: el.getAttribute ? el.getAttribute('role') : undefined,
8482
+ ariaLabel: el.getAttribute ? el.getAttribute('aria-label') : undefined,
8483
+ textLength: text.length,
8484
+ childCount: children.length,
8485
+ children
8486
+ };
8487
+ };
8488
+ const tree = nodeInfo(root, 0);
8489
+ return {
8490
+ rootMode: root === rootEl ? 'element' : 'shadow',
8491
+ depthLimit: maxDepth,
8492
+ nodeLimit: maxNodes,
8493
+ truncated,
8494
+ tree
8495
+ };
8496
+ })()`);
8497
+ if (payload && 'object' == typeof payload) return payload;
8498
+ } catch {}
8499
+ }
8500
+ setupConsoleCapture() {
8501
+ if (!this.cdpClient) return;
8502
+ const cdp = this.cdpClient;
8503
+ if ('function' != typeof cdp.onProtocolEvent) return;
8504
+ cdp.onProtocolEvent((message)=>{
8505
+ const method = String(message.method || '');
8506
+ const params = message.params || {};
8507
+ if ('Log.entryAdded' === method) {
8508
+ const entry = params.entry || {};
8509
+ const level = String(entry.level || 'log');
8510
+ const text = String(entry.text || '');
8511
+ const sourceUrl = entry.url ? String(entry.url) : void 0;
8512
+ this.recordConsoleEvent(level, text, sourceUrl);
8513
+ }
8514
+ if ('Runtime.consoleAPICalled' === method) {
8515
+ const type = String(params.type || 'log');
8516
+ const args = Array.isArray(params.args) ? params.args : [];
8517
+ const stack = params.stackTrace || {};
8518
+ const frame = Array.isArray(stack.callFrames) ? stack.callFrames[0] : null;
8519
+ const sourceUrl = frame && frame.url ? String(frame.url) : void 0;
8520
+ const text = args.map((arg)=>{
8521
+ if (void 0 !== arg?.value) return String(arg.value);
8522
+ if (void 0 !== arg?.description) return String(arg.description);
8523
+ return '';
8524
+ }).filter(Boolean).join(' ');
8525
+ this.recordConsoleEvent(type, text, sourceUrl);
8526
+ }
8527
+ });
8528
+ }
8529
+ recordConsoleEvent(level, text, sourceUrl) {
8530
+ const normalized = [
8531
+ 'error',
8532
+ 'warn',
8533
+ 'info',
8534
+ 'debug',
8535
+ 'log'
8536
+ ].includes(level) ? level : 'log';
8537
+ if (normalized in this.consoleCounts) this.consoleCounts[normalized] += 1;
8538
+ const hash = hashStringFNV1a(`${normalized}:${text}:${sourceUrl || ''}`);
8539
+ const existing = this.consoleTop.get(hash);
8540
+ if (existing) existing.count += 1;
8541
+ else this.consoleTop.set(hash, {
8542
+ level: normalized,
8543
+ text,
8544
+ count: 1,
8545
+ sourceUrl
8546
+ });
8547
+ }
8548
+ buildPrettyTitle(stage, url, title) {
8549
+ const parts = [];
8550
+ if ('updated' === stage) parts.push("UPDATED - after content script injection");
8551
+ else if ('pre_injection' === stage) parts.push("INITIAL - before content script injection");
8552
+ if (url || title) {
8553
+ const urlPart = url ? `URL: ${url}` : 'URL: unknown';
8554
+ const titlePart = title ? `TITLE: ${title}` : 'TITLE: unknown';
8555
+ parts.push(`${urlPart} | ${titlePart}`);
8556
+ }
8557
+ if (0 === parts.length) return 'HTML';
8558
+ return parts.join(' | ');
8559
+ }
8560
+ async emitSourceOutput(html, stage) {
8561
+ const outputConfig = this.getOutputConfig();
8562
+ const { url, title } = await this.getPageMetadata();
8563
+ const frameContext = await this.getFrameContext();
8564
+ const redacted = applySourceRedaction(html, outputConfig.redact);
8565
+ const summary = outputConfig.summary ? buildHtmlSummary(redacted) : void 0;
8566
+ const { output, truncated, byteLength } = truncateByBytes(redacted, outputConfig.maxBytes);
8567
+ const hash = hashStringFNV1a(output);
8568
+ const shouldDiff = Boolean(this.devOptions.sourceDiff) && 'updated' === stage;
8569
+ const diff = shouldDiff && this.lastOutputHash ? {
8570
+ changed: this.lastOutputHash !== hash,
8571
+ prevHash: this.lastOutputHash,
8572
+ hash,
8573
+ byteDelta: 'number' == typeof this.lastByteLength ? byteLength - this.lastByteLength : void 0,
8574
+ summaryDelta: summary && this.lastSummary ? {
8575
+ extensionRoots: summary.counts.extensionRoots - this.lastSummary.counts.extensionRoots,
8576
+ shadowRoots: summary.counts.shadowRoots - this.lastSummary.counts.shadowRoots,
8577
+ scripts: summary.counts.scripts - this.lastSummary.counts.scripts,
8578
+ styles: summary.counts.styles - this.lastSummary.counts.styles,
8579
+ snippetChanged: summary.snippet !== this.lastSummary.snippet
8580
+ } : void 0
8581
+ } : void 0;
8582
+ if ('pretty' === outputConfig.format) {
8583
+ console.log(browsers_lib_messages.Kq0());
8584
+ const heading = outputConfig.summary ? `SUMMARY - ${this.buildPrettyTitle(stage, url, title)}` : this.buildPrettyTitle(stage, url, title);
8585
+ console.log(browsers_lib_messages.BoR(heading));
8586
+ console.log(formatHtmlSentinelBegin({
8587
+ url,
8588
+ title,
8589
+ stage,
8590
+ truncated
8591
+ }));
8592
+ console.log(outputConfig.summary ? JSON.stringify(summary, null, 2) : output);
8593
+ if (diff && diff.changed) console.log(browsers_lib_messages.BoR(`DIFF - byteDelta=${diff.byteDelta ?? 'n/a'}`));
8594
+ console.log(formatHtmlSentinelEnd());
8595
+ if (truncated && outputConfig.maxBytes > 0) console.log(browsers_lib_messages.BoR(`TRUNCATED - showing first ${outputConfig.maxBytes} bytes (set --source-max-bytes or EXTENSION_SOURCE_MAX_BYTES to adjust)`));
8596
+ console.log(browsers_lib_messages.WVz());
8597
+ this.lastOutputHash = hash;
8598
+ this.lastByteLength = byteLength;
8599
+ this.lastSummary = summary;
8600
+ emitActionEvent('source_snapshot_captured', {
8601
+ stage
8602
+ });
8603
+ await this.emitExtraOutputs(stage, {
8604
+ url,
8605
+ title,
8606
+ frameContext
8607
+ });
8608
+ return;
8609
+ }
8610
+ const eventBase = {
8611
+ schema_version: '1.0',
8612
+ timestamp: new Date().toISOString(),
8613
+ stage,
8614
+ browser: this.devOptions.browser,
8615
+ mode: this.runtimeMode,
8616
+ url,
8617
+ title,
8618
+ frameId: frameContext.frameId,
8619
+ frameUrl: frameContext.frameUrl,
8620
+ executionContextId: frameContext.executionContextId,
8621
+ tabId: void 0,
8622
+ truncated,
8623
+ byteLength,
8624
+ maxBytes: outputConfig.maxBytes,
8625
+ redaction: outputConfig.redact,
8626
+ includeShadow: outputConfig.includeShadow,
8627
+ source: 'extension.js'
8628
+ };
8629
+ if (outputConfig.summary) {
8630
+ const payload = {
8631
+ type: 'page_html_summary',
8632
+ ...eventBase,
8633
+ summary,
8634
+ diff
8635
+ };
8636
+ console.log(JSON.stringify(payload));
8637
+ this.lastOutputHash = hash;
8638
+ this.lastByteLength = byteLength;
8639
+ this.lastSummary = summary;
8640
+ emitActionEvent('source_snapshot_captured', {
8641
+ stage
8642
+ });
8643
+ await this.emitExtraOutputs(stage, {
8644
+ url,
8645
+ title,
8646
+ frameContext
8647
+ });
8648
+ return;
8649
+ }
8650
+ const payload = {
8651
+ type: 'page_html',
8652
+ ...eventBase,
8653
+ html: output,
8654
+ diff
8655
+ };
8656
+ console.log(JSON.stringify(payload));
8657
+ this.lastOutputHash = hash;
8658
+ this.lastByteLength = byteLength;
8659
+ this.lastSummary = summary;
8660
+ emitActionEvent('source_snapshot_captured', {
8661
+ stage
8662
+ });
8663
+ await this.emitExtraOutputs(stage, {
8664
+ url,
8665
+ title,
8666
+ frameContext
8667
+ });
8668
+ }
8669
+ async emitExtraOutputs(stage, meta) {
8670
+ if (this.devOptions.sourceMeta) {
8671
+ const metaSnapshot = await this.getPageMetaSnapshot();
8672
+ this.emitEventPayload('page_meta', stage, meta, metaSnapshot);
8673
+ }
8674
+ if (Array.isArray(this.devOptions.sourceProbe)) {
8675
+ const probes = await this.getSelectorProbes(this.devOptions.sourceProbe);
8676
+ this.emitEventPayload('selector_probe', stage, meta, {
8677
+ probes
8678
+ });
8679
+ }
8680
+ if (this.devOptions.sourceTree && 'off' !== this.devOptions.sourceTree) {
8681
+ const tree = await this.getExtensionRootTree();
8682
+ if (tree) this.emitEventPayload('extension_root_tree', stage, meta, tree);
8683
+ }
8684
+ if (this.devOptions.sourceDom) {
8685
+ const snapshot = await this.getDomSnapshot();
8686
+ if (snapshot) {
8687
+ this.emitEventPayload('dom_snapshot', stage, meta, snapshot);
8688
+ if ('updated' === stage) {
8689
+ const diff = diffDomSnapshots(this.lastDomSnapshot, snapshot);
8690
+ this.emitEventPayload('dom_diff', stage, meta, diff);
8691
+ }
8692
+ this.lastDomSnapshot = snapshot;
8693
+ }
8694
+ }
8695
+ if (this.devOptions.sourceConsole) {
8696
+ const top = Array.from(this.consoleTop.values()).sort((a, b)=>b.count - a.count).slice(0, 5);
8697
+ this.emitEventPayload('console_summary', stage, meta, {
8698
+ counts: this.consoleCounts,
8699
+ top,
8700
+ supported: true
8701
+ });
8702
+ }
8703
+ }
8704
+ emitEventPayload(type, stage, meta, payload) {
8705
+ const outputConfig = this.getOutputConfig();
8706
+ const base = {
8707
+ type,
8708
+ schema_version: '1.0',
8709
+ timestamp: new Date().toISOString(),
8710
+ stage,
8711
+ browser: this.devOptions.browser,
8712
+ mode: this.runtimeMode,
8713
+ url: meta.url,
8714
+ title: meta.title,
8715
+ frameId: meta.frameContext?.frameId,
8716
+ frameUrl: meta.frameContext?.frameUrl,
8717
+ executionContextId: meta.frameContext?.executionContextId,
8718
+ source: 'extension.js'
8719
+ };
8720
+ if ('pretty' === outputConfig.format) {
8721
+ console.log(browsers_lib_messages.Kq0());
8722
+ console.log(browsers_lib_messages.BoR(type));
8723
+ console.log(JSON.stringify({
8724
+ ...base,
8725
+ ...payload
8726
+ }, null, 2));
8727
+ console.log(browsers_lib_messages.WVz());
8728
+ return;
8729
+ }
8730
+ console.log(JSON.stringify({
8731
+ ...base,
8732
+ ...payload
8733
+ }));
8734
+ }
7632
8735
  async getCdpPort() {
7633
8736
  const instanceId = this.devOptions.instanceId;
7634
8737
  return (0, shared_utils.jl)(this.devOptions.port, instanceId);
@@ -7640,6 +8743,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7640
8743
  await waitForChromeRemoteDebugging(port, instanceId);
7641
8744
  this.cdpClient = new cdp_client.n(port);
7642
8745
  await this.cdpClient.connect();
8746
+ this.setupConsoleCapture();
7643
8747
  if (this.isAuthorMode()) console.log(browsers_lib_messages.x_$());
7644
8748
  this.isInitialized = true;
7645
8749
  } catch (error) {
@@ -7647,24 +8751,34 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7647
8751
  throw error;
7648
8752
  }
7649
8753
  }
7650
- async inspectSource(url) {
8754
+ async inspectSource(url, options) {
7651
8755
  if (!this.cdpClient) throw new Error(browsers_lib_messages.Ib4());
7652
8756
  try {
7653
8757
  if (this.isAuthorMode()) {
7654
8758
  console.log(browsers_lib_messages.a66(url));
7655
8759
  console.log(browsers_lib_messages.Q0E());
7656
8760
  }
7657
- const { targetId, sessionId } = await ensureTargetAndSession(this.cdpClient, url);
8761
+ emitActionEvent('navigation_start', {
8762
+ url
8763
+ });
8764
+ const { targetId, sessionId } = await ensureTargetAndSession(this.cdpClient, url, options);
7658
8765
  this.currentTargetId = targetId;
7659
8766
  this.currentSessionId = sessionId;
7660
8767
  if (this.isAuthorMode()) console.log(browsers_lib_messages.C49());
7661
8768
  await this.cdpClient.waitForLoadEvent(this.currentSessionId);
8769
+ emitActionEvent('navigation_end', {
8770
+ url
8771
+ });
7662
8772
  try {
7663
- const initialHtml = await extractPageHtml(this.cdpClient, this.currentSessionId);
7664
- this.printHTML(String(initialHtml || ''));
8773
+ const outputConfig = this.getOutputConfig();
8774
+ const initialHtml = await extractPageHtml(this.cdpClient, this.currentSessionId, this.isAuthorMode(), outputConfig.includeShadow);
8775
+ await this.emitSourceOutput(String(initialHtml || ''), 'pre_injection');
7665
8776
  } catch {}
7666
8777
  if (this.isAuthorMode()) console.log(browsers_lib_messages.mOc());
7667
8778
  await this.cdpClient.waitForContentScriptInjection(this.currentSessionId);
8779
+ emitActionEvent("content_script_injected", {
8780
+ url
8781
+ });
7668
8782
  try {
7669
8783
  const deadline = Date.now() + 20000;
7670
8784
  const started = Date.now();
@@ -7686,7 +8800,8 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7686
8800
  await new Promise((r)=>setTimeout(r, delay));
7687
8801
  }
7688
8802
  } catch {}
7689
- const html = await extractPageHtml(this.cdpClient, this.currentSessionId);
8803
+ const outputConfig = this.getOutputConfig();
8804
+ const html = await extractPageHtml(this.cdpClient, this.currentSessionId, this.isAuthorMode(), outputConfig.includeShadow);
7690
8805
  return html;
7691
8806
  } catch (error) {
7692
8807
  if (this.isAuthorMode()) console.error(browsers_lib_messages._Jd(error.message));
@@ -7694,15 +8809,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7694
8809
  }
7695
8810
  }
7696
8811
  async startWatching(websocketServer) {
7697
- if (!this.isAuthorMode()) return;
7698
- if (this.isWatching) return void console.log(browsers_lib_messages.dWk());
8812
+ if (!this.devOptions.watchSource) return;
8813
+ if (this.isWatching) {
8814
+ if (this.isAuthorMode()) console.log(browsers_lib_messages.dWk());
8815
+ return;
8816
+ }
7699
8817
  this.isWatching = true;
7700
- console.log(browsers_lib_messages.RzV());
8818
+ if (this.isAuthorMode()) console.log(browsers_lib_messages.RzV());
7701
8819
  this.setupWebSocketHandler(websocketServer);
7702
- console.log(browsers_lib_messages.YKO());
8820
+ if (this.isAuthorMode()) console.log(browsers_lib_messages.YKO());
7703
8821
  }
7704
8822
  setupWebSocketHandler(websocketServer) {
7705
- if (!this.isAuthorMode()) return;
7706
8823
  if (!websocketServer || !websocketServer.clients) return void console.warn(browsers_lib_messages.cbf());
7707
8824
  websocketServer.clients.forEach((ws)=>{
7708
8825
  this.setupConnectionHandler(ws);
@@ -7712,7 +8829,6 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7712
8829
  });
7713
8830
  }
7714
8831
  setupConnectionHandler(ws) {
7715
- if (!this.isAuthorMode()) return;
7716
8832
  ws.on('message', async (data)=>{
7717
8833
  try {
7718
8834
  const message = JSON.parse(data);
@@ -7721,36 +8837,49 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7721
8837
  });
7722
8838
  }
7723
8839
  stopWatching() {
7724
- if (!this.isAuthorMode()) return;
7725
8840
  this.isWatching = false;
7726
- console.log(browsers_lib_messages.Qx1());
8841
+ if (this.isAuthorMode()) console.log(browsers_lib_messages.Qx1());
7727
8842
  }
7728
8843
  async handleFileChange() {
7729
- if (!this.isAuthorMode()) return;
7730
8844
  if (!this.cdpClient || !this.currentSessionId) return void console.warn(browsers_lib_messages.MfN());
7731
8845
  if (this.debounceTimer) clearTimeout(this.debounceTimer);
7732
8846
  this.debounceTimer = setTimeout(async ()=>{
7733
8847
  try {
7734
- console.log(browsers_lib_messages.$xt());
7735
- console.log(browsers_lib_messages.Tev());
8848
+ emitActionEvent('watch_rebuild_triggered', {});
8849
+ if (this.isAuthorMode()) {
8850
+ console.log(browsers_lib_messages.$xt());
8851
+ console.log(browsers_lib_messages.Tev());
8852
+ }
8853
+ const sourceUrl = 'string' == typeof this.devOptions.source && 'true' !== this.devOptions.source ? this.devOptions.source : '';
8854
+ if (sourceUrl) {
8855
+ emitActionEvent('watch_reinspect_source_url', {
8856
+ url: sourceUrl
8857
+ });
8858
+ const html = await this.inspectSource(sourceUrl, {
8859
+ forceNavigate: true
8860
+ });
8861
+ await this.emitSourceOutput(html || '', 'updated');
8862
+ return;
8863
+ }
7736
8864
  await this.cdpClient.waitForContentScriptInjection(this.currentSessionId);
7737
- console.log(browsers_lib_messages.Mcx());
8865
+ if (this.isAuthorMode()) console.log(browsers_lib_messages.Mcx());
7738
8866
  let html = '';
8867
+ const outputConfig = this.getOutputConfig();
7739
8868
  try {
7740
- html = await this.cdpClient.getPageHTML(this.currentSessionId);
8869
+ html = await this.cdpClient.getPageHTML(this.currentSessionId, outputConfig.includeShadow);
7741
8870
  } catch (e) {
7742
8871
  await new Promise((r)=>setTimeout(r, 250));
7743
8872
  try {
7744
- html = await this.cdpClient.getPageHTML(this.currentSessionId);
8873
+ html = await this.cdpClient.getPageHTML(this.currentSessionId, outputConfig.includeShadow);
7745
8874
  } catch {}
7746
8875
  }
7747
8876
  if (!html) {
7748
8877
  await new Promise((r)=>setTimeout(r, 300));
7749
8878
  try {
7750
- html = await this.cdpClient.getPageHTML(this.currentSessionId);
8879
+ html = await this.cdpClient.getPageHTML(this.currentSessionId, outputConfig.includeShadow);
7751
8880
  } catch {}
7752
8881
  }
7753
- this.printUpdatedHTML(html || '');
8882
+ await this.emitSourceOutput(html || '', 'updated');
7754
8883
  } catch (error) {
7755
8884
  console.error(browsers_lib_messages.acp(error.message));
7756
8885
  if (error.message.includes('session') || error.message.includes('target')) {
@@ -7771,64 +8900,11 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7771
8900
  console.error(browsers_lib_messages.pcF(error.message));
7772
8901
  }
7773
8902
  }
7774
- printHTML(html) {
7775
- const raw = String(process.env.EXTENSION_SOURCE_RAW || '').trim();
7776
- const maxBytesStr = String(process.env.EXTENSION_SOURCE_MAX_BYTES || '').trim();
7777
- const maxBytes = /^\d+$/.test(maxBytesStr) ? Math.max(0, parseInt(maxBytesStr, 10)) : 262144;
7778
- const shouldPrintRaw = '1' === raw || 'true' === raw.toLowerCase() || 0 === maxBytes;
7779
- const out = (()=>{
7780
- if (shouldPrintRaw) return html;
7781
- try {
7782
- const bytes = Buffer.byteLength(html || '', 'utf8');
7783
- if (bytes <= maxBytes) return html;
7784
- let acc = 0;
7785
- let endIndex = 0;
7786
- for(let i = 0; i < html.length; i++){
7787
- const b = Buffer.byteLength(html[i], 'utf8');
7788
- if (acc + b > maxBytes) break;
7789
- acc += b;
7790
- endIndex = i + 1;
7791
- }
7792
- return html.slice(0, endIndex);
7793
- } catch {
7794
- return html;
7795
- }
7796
- })();
7797
- console.log(browsers_lib_messages.Kq0());
7798
- console.log(out);
7799
- if (out.length < html.length && maxBytes > 0 && !('1' === raw || 'true' === raw.toLowerCase())) console.log(browsers_lib_messages.BoR(`TRUNCATED - showing first ${maxBytes} bytes (set EXTENSION_SOURCE_RAW=1 or EXTENSION_SOURCE_MAX_BYTES to adjust)`));
7800
- console.log(browsers_lib_messages.WVz());
8903
+ async printHTML(html) {
8904
+ await this.emitSourceOutput(html, 'post_injection');
7801
8905
  }
7802
- printUpdatedHTML(html) {
7803
- if (!this.isAuthorMode()) return;
7804
- const raw = String(process.env.EXTENSION_SOURCE_RAW || '').trim();
7805
- const maxBytesStr = String(process.env.EXTENSION_SOURCE_MAX_BYTES || '').trim();
7806
- const maxBytes = /^\d+$/.test(maxBytesStr) ? Math.max(0, parseInt(maxBytesStr, 10)) : 262144;
7807
- const shouldPrintRaw = '1' === raw || 'true' === raw.toLowerCase() || 0 === maxBytes;
7808
- const out = (()=>{
7809
- if (shouldPrintRaw) return html;
7810
- try {
7811
- const bytes = Buffer.byteLength(html || '', 'utf8');
7812
- if (bytes <= maxBytes) return html;
7813
- let acc = 0;
7814
- let endIndex = 0;
7815
- for(let i = 0; i < html.length; i++){
7816
- const b = Buffer.byteLength(html[i], 'utf8');
7817
- if (acc + b > maxBytes) break;
7818
- acc += b;
7819
- endIndex = i + 1;
7820
- }
7821
- return html.slice(0, endIndex);
7822
- } catch {
7823
- return html;
7824
- }
7825
- })();
7826
- console.log(browsers_lib_messages.Kq0());
7827
- console.log(browsers_lib_messages.BoR("UPDATED - after content script injection"));
7828
- console.log(browsers_lib_messages.Kq0());
7829
- console.log(out);
7830
- if (out.length < html.length && maxBytes > 0 && !('1' === raw || 'true' === raw.toLowerCase())) console.log(browsers_lib_messages.BoR(`TRUNCATED - showing first ${maxBytes} bytes (set EXTENSION_SOURCE_RAW=1 or EXTENSION_SOURCE_MAX_BYTES to adjust)`));
7831
- console.log(browsers_lib_messages.WVz());
8906
+ async printUpdatedHTML(html) {
8907
+ await this.emitSourceOutput(html, 'updated');
7832
8908
  }
7833
8909
  async cleanup() {
7834
8910
  try {
@@ -7842,6 +8918,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7842
8918
  }
7843
8919
  apply(compiler) {
7844
8920
  if (!this.devOptions.source && !this.devOptions.watchSource) return;
8921
+ this.runtimeMode = compiler.options.mode || this.runtimeMode;
7845
8922
  compiler.hooks.done.tapPromise('setup-chrome-inspection', async (stats)=>{
7846
8923
  try {
7847
8924
  if (!this.isInitialized) await this.initialize();
@@ -7849,13 +8926,18 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7849
8926
  if (this.devOptions.source && 'string' == typeof this.devOptions.source && 'true' !== this.devOptions.source) urlToInspect = this.devOptions.source;
7850
8927
  else if (this.devOptions.startingUrl) urlToInspect = this.devOptions.startingUrl;
7851
8928
  else throw new Error(browsers_lib_messages.Pu4());
7852
- const html = await this.inspectSource(urlToInspect);
7853
- this.printHTML(html);
8929
+ const html = await this.inspectSource(urlToInspect, {
8930
+ forceNavigate: this.devOptions.watchSource && this.hasInspectedSourceOnce
8931
+ });
8932
+ this.hasInspectedSourceOnce = true;
8933
+ await this.printHTML(html);
7854
8934
  const webSocketServer = compiler.options.webSocketServer;
7855
- if (this.devOptions.watchSource && this.isAuthorMode()) if (webSocketServer) await this.startWatching(webSocketServer);
8935
+ if (this.devOptions.watchSource) if (webSocketServer) await this.startWatching(webSocketServer);
7856
8936
  else try {
7857
- const updated = await this.cdpClient.getPageHTML(this.currentSessionId);
7858
- this.printUpdatedHTML(updated || '');
8937
+ const updated = await this.inspectSource(urlToInspect, {
8938
+ forceNavigate: true
8939
+ });
8940
+ await this.printUpdatedHTML(updated || '');
7859
8941
  } catch {}
7860
8942
  } catch (error) {
7861
8943
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.error(browsers_lib_messages.b82(error.message));
@@ -7869,7 +8951,21 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7869
8951
  chromium_source_inspection_define_property(this, "currentSessionId", null);
7870
8952
  chromium_source_inspection_define_property(this, "isInitialized", false);
7871
8953
  chromium_source_inspection_define_property(this, "isWatching", false);
8954
+ chromium_source_inspection_define_property(this, "hasInspectedSourceOnce", false);
7872
8955
  chromium_source_inspection_define_property(this, "debounceTimer", null);
8956
+ chromium_source_inspection_define_property(this, "runtimeMode", void 0);
8957
+ chromium_source_inspection_define_property(this, "lastOutputHash", void 0);
8958
+ chromium_source_inspection_define_property(this, "lastByteLength", void 0);
8959
+ chromium_source_inspection_define_property(this, "lastSummary", void 0);
8960
+ chromium_source_inspection_define_property(this, "lastDomSnapshot", void 0);
8961
+ chromium_source_inspection_define_property(this, "consoleCounts", {
8962
+ error: 0,
8963
+ warn: 0,
8964
+ info: 0,
8965
+ log: 0,
8966
+ debug: 0
8967
+ });
8968
+ chromium_source_inspection_define_property(this, "consoleTop", new Map());
7873
8969
  this.devOptions = devOptions;
7874
8970
  }
7875
8971
  }
@@ -7908,6 +9004,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7908
9004
  run_chromium_define_property(this, "instanceId", void 0);
7909
9005
  run_chromium_define_property(this, "source", void 0);
7910
9006
  run_chromium_define_property(this, "watchSource", void 0);
9007
+ run_chromium_define_property(this, "sourceFormat", void 0);
9008
+ run_chromium_define_property(this, "sourceSummary", void 0);
9009
+ run_chromium_define_property(this, "sourceMeta", void 0);
9010
+ run_chromium_define_property(this, "sourceProbe", void 0);
9011
+ run_chromium_define_property(this, "sourceTree", void 0);
9012
+ run_chromium_define_property(this, "sourceConsole", void 0);
9013
+ run_chromium_define_property(this, "sourceDom", void 0);
9014
+ run_chromium_define_property(this, "sourceMaxBytes", void 0);
9015
+ run_chromium_define_property(this, "sourceRedact", void 0);
9016
+ run_chromium_define_property(this, "sourceIncludeShadow", void 0);
9017
+ run_chromium_define_property(this, "sourceDiff", void 0);
7911
9018
  run_chromium_define_property(this, "dryRun", void 0);
7912
9019
  run_chromium_define_property(this, "logLevel", void 0);
7913
9020
  run_chromium_define_property(this, "logContexts", void 0);
@@ -7931,6 +9038,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7931
9038
  this.port = options.port;
7932
9039
  this.source = options.source;
7933
9040
  this.watchSource = options.watchSource;
9041
+ this.sourceFormat = options.sourceFormat;
9042
+ this.sourceSummary = options.sourceSummary;
9043
+ this.sourceMeta = options.sourceMeta;
9044
+ this.sourceProbe = options.sourceProbe;
9045
+ this.sourceTree = options.sourceTree;
9046
+ this.sourceConsole = options.sourceConsole;
9047
+ this.sourceDom = options.sourceDom;
9048
+ this.sourceMaxBytes = options.sourceMaxBytes;
9049
+ this.sourceRedact = options.sourceRedact;
9050
+ this.sourceIncludeShadow = options.sourceIncludeShadow;
9051
+ this.sourceDiff = options.sourceDiff;
7934
9052
  this.logLevel = options.logLevel;
7935
9053
  this.logContexts = options.logContexts;
7936
9054
  this.logFormat = options.logFormat;
@@ -8015,7 +9133,14 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8015
9133
  const assetsArr = Array.isArray(compilation?.getAssets?.()) ? compilation.getAssets() : [];
8016
9134
  const changed = assetsArr.filter((a)=>a?.emitted).map((a)=>String(a?.name || ''));
8017
9135
  const controller = this.host?.rdpController;
8018
- if (controller && 'function' == typeof controller.hardReload) await controller.hardReload(stats.compilation, changed);
9136
+ if (controller && 'function' == typeof controller.hardReload) {
9137
+ const reason = this.ctx.getPendingReloadReason?.();
9138
+ emitActionEvent('extension_reload', {
9139
+ reason: reason || 'unknown',
9140
+ browser: this.host.browser
9141
+ });
9142
+ await controller.hardReload(stats.compilation, changed);
9143
+ }
8019
9144
  } catch {}
8020
9145
  done();
8021
9146
  });
@@ -8028,6 +9153,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8028
9153
  }
8029
9154
  }
8030
9155
  var messaging_client = __webpack_require__("./webpack/plugin-browsers/run-firefox/firefox-source-inspection/remote-firefox/messaging-client.ts");
9156
+ var logging = __webpack_require__("./webpack/plugin-browsers/run-firefox/firefox-source-inspection/remote-firefox/logging.ts");
8031
9157
  const TARGET_SCAN_INTERVAL_MS = 250;
8032
9158
  async function selectActors(client, urlToInspect) {
8033
9159
  const deadline = Date.now() + 10000;
@@ -8139,8 +9265,428 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8139
9265
  watchSource: this.host.watchSource,
8140
9266
  startingUrl: this.host.startingUrl,
8141
9267
  port: this.host.port,
8142
- instanceId: this.host.instanceId
9268
+ instanceId: this.host.instanceId,
9269
+ sourceFormat: this.host.sourceFormat,
9270
+ sourceSummary: this.host.sourceSummary,
9271
+ sourceMeta: this.host.sourceMeta,
9272
+ sourceProbe: this.host.sourceProbe,
9273
+ sourceTree: this.host.sourceTree,
9274
+ sourceConsole: this.host.sourceConsole,
9275
+ sourceDom: this.host.sourceDom,
9276
+ sourceMaxBytes: this.host.sourceMaxBytes,
9277
+ sourceRedact: this.host.sourceRedact,
9278
+ sourceIncludeShadow: this.host.sourceIncludeShadow,
9279
+ sourceDiff: this.host.sourceDiff,
9280
+ logFormat: this.host.logFormat
9281
+ };
9282
+ }
9283
+ getOutputConfig() {
9284
+ return normalizeSourceOutputConfig({
9285
+ format: this.devOptions?.sourceFormat,
9286
+ summary: this.devOptions?.sourceSummary,
9287
+ maxBytes: this.devOptions?.sourceMaxBytes,
9288
+ redact: this.devOptions?.sourceRedact,
9289
+ includeShadow: this.devOptions?.sourceIncludeShadow,
9290
+ sourceEnabled: Boolean(this.devOptions?.source || this.devOptions?.watchSource),
9291
+ logFormat: this.devOptions?.logFormat
9292
+ });
9293
+ }
9294
+ buildPrettyTitle(stage, url, title) {
9295
+ const parts = [];
9296
+ if ('updated' === stage) parts.push("UPDATED - after content script injection");
9297
+ else if ('pre_injection' === stage) parts.push("INITIAL - before content script injection");
9298
+ if (url || title) {
9299
+ const urlPart = url ? `URL: ${url}` : 'URL: unknown';
9300
+ const titlePart = title ? `TITLE: ${title}` : 'TITLE: unknown';
9301
+ parts.push(`${urlPart} | ${titlePart}`);
9302
+ }
9303
+ if (0 === parts.length) return 'HTML';
9304
+ return parts.join(' | ');
9305
+ }
9306
+ getFrameContext(meta) {
9307
+ return {
9308
+ frameId: this.currentTabActor || this.currentConsoleActor || void 0,
9309
+ frameUrl: meta.url
9310
+ };
9311
+ }
9312
+ emitSourceOutput(html, stage, meta) {
9313
+ const outputConfig = this.getOutputConfig();
9314
+ const frameContext = this.getFrameContext(meta);
9315
+ const redacted = applySourceRedaction(html, outputConfig.redact);
9316
+ const summary = outputConfig.summary ? buildHtmlSummary(redacted) : void 0;
9317
+ const { output, truncated, byteLength } = truncateByBytes(redacted, outputConfig.maxBytes);
9318
+ const hash = hashStringFNV1a(output);
9319
+ const shouldDiff = Boolean(this.devOptions?.sourceDiff) && 'updated' === stage;
9320
+ const diff = shouldDiff && this.lastOutputHash ? {
9321
+ changed: this.lastOutputHash !== hash,
9322
+ prevHash: this.lastOutputHash,
9323
+ hash,
9324
+ byteDelta: 'number' == typeof this.lastByteLength ? byteLength - this.lastByteLength : void 0,
9325
+ summaryDelta: summary && this.lastSummary ? {
9326
+ extensionRoots: summary.counts.extensionRoots - this.lastSummary.counts.extensionRoots,
9327
+ shadowRoots: summary.counts.shadowRoots - this.lastSummary.counts.shadowRoots,
9328
+ scripts: summary.counts.scripts - this.lastSummary.counts.scripts,
9329
+ styles: summary.counts.styles - this.lastSummary.counts.styles,
9330
+ snippetChanged: summary.snippet !== this.lastSummary.snippet
9331
+ } : void 0
9332
+ } : void 0;
9333
+ if ('pretty' === outputConfig.format) {
9334
+ console.log(browsers_lib_messages.Kq0());
9335
+ const heading = outputConfig.summary ? `SUMMARY - ${this.buildPrettyTitle(stage, meta.url, meta.title)}` : this.buildPrettyTitle(stage, meta.url, meta.title);
9336
+ console.log(browsers_lib_messages.BoR(heading));
9337
+ console.log(formatHtmlSentinelBegin({
9338
+ url: meta.url,
9339
+ title: meta.title,
9340
+ stage,
9341
+ truncated
9342
+ }));
9343
+ console.log(outputConfig.summary ? JSON.stringify(summary, null, 2) : output);
9344
+ if (diff && diff.changed) console.log(browsers_lib_messages.BoR(`DIFF - byteDelta=${diff.byteDelta ?? 'n/a'}`));
9345
+ console.log(formatHtmlSentinelEnd());
9346
+ if (truncated && outputConfig.maxBytes > 0) console.log(browsers_lib_messages.BoR(`TRUNCATED - showing first ${outputConfig.maxBytes} bytes (set --source-max-bytes or EXTENSION_SOURCE_MAX_BYTES to adjust)`));
9347
+ console.log(browsers_lib_messages.WVz());
9348
+ this.lastOutputHash = hash;
9349
+ this.lastByteLength = byteLength;
9350
+ this.lastSummary = summary;
9351
+ emitActionEvent('source_snapshot_captured', {
9352
+ stage
9353
+ });
9354
+ this.emitExtraOutputs(stage, {
9355
+ ...meta,
9356
+ frameContext
9357
+ });
9358
+ return;
9359
+ }
9360
+ const eventBase = {
9361
+ schema_version: '1.0',
9362
+ timestamp: new Date().toISOString(),
9363
+ stage,
9364
+ browser: this.devOptions?.browser,
9365
+ mode: this.devOptions?.mode,
9366
+ url: meta.url,
9367
+ title: meta.title,
9368
+ frameId: frameContext.frameId,
9369
+ frameUrl: frameContext.frameUrl,
9370
+ tabId: void 0,
9371
+ truncated,
9372
+ byteLength,
9373
+ maxBytes: outputConfig.maxBytes,
9374
+ redaction: outputConfig.redact,
9375
+ includeShadow: outputConfig.includeShadow,
9376
+ source: 'extension.js'
8143
9377
  };
9378
+ if (outputConfig.summary) {
9379
+ console.log(JSON.stringify({
9380
+ type: 'page_html_summary',
9381
+ ...eventBase,
9382
+ summary,
9383
+ diff
9384
+ }));
9385
+ this.lastOutputHash = hash;
9386
+ this.lastByteLength = byteLength;
9387
+ this.lastSummary = summary;
9388
+ emitActionEvent('source_snapshot_captured', {
9389
+ stage
9390
+ });
9391
+ this.emitExtraOutputs(stage, {
9392
+ ...meta,
9393
+ frameContext
9394
+ });
9395
+ return;
9396
+ }
9397
+ console.log(JSON.stringify({
9398
+ type: 'page_html',
9399
+ ...eventBase,
9400
+ html: output,
9401
+ diff
9402
+ }));
9403
+ this.lastOutputHash = hash;
9404
+ this.lastByteLength = byteLength;
9405
+ this.lastSummary = summary;
9406
+ emitActionEvent('source_snapshot_captured', {
9407
+ stage
9408
+ });
9409
+ this.emitExtraOutputs(stage, {
9410
+ ...meta,
9411
+ frameContext
9412
+ });
9413
+ }
9414
+ setupConsoleCapture() {
9415
+ if (!this.client || this.consoleCaptureReady) return;
9416
+ this.consoleCaptureReady = true;
9417
+ this.client.on('message', (message)=>{
9418
+ try {
9419
+ const type = String(message?.type || '');
9420
+ if (!type) return;
9421
+ let level = 'info';
9422
+ let text = '';
9423
+ let sourceUrl;
9424
+ if ('consoleAPICall' === type || 'logMessage' === type) {
9425
+ const a = message?.message || message;
9426
+ level = String(a.level || a.category || 'log').toLowerCase();
9427
+ const arg = a.arguments && a.arguments[0] || a.message || a.text;
9428
+ text = String(arg && (arg.value || arg.text || arg.message || arg) || '');
9429
+ sourceUrl = a.filename || a.sourceName || void 0;
9430
+ } else {
9431
+ if ('pageError' !== type) return;
9432
+ level = 'error';
9433
+ text = String(message?.errorMessage || message?.cause || '');
9434
+ sourceUrl = message?.url || message?.sourceURL || void 0;
9435
+ }
9436
+ this.recordConsoleEvent(level, text, sourceUrl);
9437
+ } catch {}
9438
+ });
9439
+ }
9440
+ recordConsoleEvent(level, text, sourceUrl) {
9441
+ const normalized = [
9442
+ 'error',
9443
+ 'warn',
9444
+ 'info',
9445
+ 'debug',
9446
+ 'log'
9447
+ ].includes(level) ? level : 'log';
9448
+ if (normalized in this.consoleCounts) this.consoleCounts[normalized] += 1;
9449
+ const hash = hashStringFNV1a(`${normalized}:${text}:${sourceUrl || ''}`);
9450
+ const existing = this.consoleTop.get(hash);
9451
+ if (existing) existing.count += 1;
9452
+ else this.consoleTop.set(hash, {
9453
+ level: normalized,
9454
+ text,
9455
+ count: 1,
9456
+ sourceUrl
9457
+ });
9458
+ }
9459
+ async emitExtraOutputs(stage, meta) {
9460
+ if (!this.client || !this.currentConsoleActor) return;
9461
+ this.getOutputConfig();
9462
+ if (this.devOptions?.sourceMeta) {
9463
+ const metaSnapshot = await this.evaluateJson(this.currentConsoleActor, `(() => {
9464
+ try {
9465
+ return {
9466
+ readyState: document.readyState,
9467
+ viewport: {
9468
+ width: window.innerWidth,
9469
+ height: window.innerHeight,
9470
+ devicePixelRatio: window.devicePixelRatio
9471
+ },
9472
+ frameCount: (window.frames && window.frames.length) || 0
9473
+ };
9474
+ } catch (e) {
9475
+ return {};
9476
+ }
9477
+ })()`);
9478
+ this.emitEventPayload('page_meta', stage, meta, metaSnapshot || {});
9479
+ }
9480
+ if (Array.isArray(this.devOptions?.sourceProbe)) {
9481
+ const probes = await this.evaluateJson(this.currentConsoleActor, `(() => {
9482
+ const selectors = ${JSON.stringify(this.devOptions?.sourceProbe || [])};
9483
+ const limit = 3;
9484
+ const snippetLen = 140;
9485
+ return selectors.map((selector) => {
9486
+ let nodes = [];
9487
+ try {
9488
+ nodes = Array.from(document.querySelectorAll(selector));
9489
+ } catch (e) {
9490
+ return {selector, count: 0, samples: []};
9491
+ }
9492
+ const samples = nodes.slice(0, limit).map((node) => {
9493
+ const text = (node && node.textContent) ? String(node.textContent) : '';
9494
+ return {
9495
+ tag: node && node.tagName ? String(node.tagName).toLowerCase() : 'unknown',
9496
+ id: node && node.id ? String(node.id) : undefined,
9497
+ classes: node && node.className ? String(node.className) : undefined,
9498
+ role: node && node.getAttribute ? node.getAttribute('role') : undefined,
9499
+ ariaLabel: node && node.getAttribute ? node.getAttribute('aria-label') : undefined,
9500
+ textLength: text.length,
9501
+ textSnippet: text.trim().slice(0, snippetLen)
9502
+ };
9503
+ });
9504
+ return {selector, count: nodes.length, samples};
9505
+ });
9506
+ })()`);
9507
+ this.emitEventPayload('selector_probe', stage, meta, {
9508
+ probes: probes || []
9509
+ });
9510
+ }
9511
+ if (this.devOptions?.sourceTree && 'off' !== this.devOptions.sourceTree) {
9512
+ const tree = await this.evaluateJson(this.currentConsoleActor, `(() => {
9513
+ const rootEl = document.querySelector('#extension-root,[data-extension-root="true"]');
9514
+ if (!rootEl) return null;
9515
+ const root = (${'off' !== this.devOptions.sourceIncludeShadow ? 'rootEl.shadowRoot || rootEl' : 'rootEl'});
9516
+ const maxDepth = 4;
9517
+ const maxNodes = 200;
9518
+ let count = 0;
9519
+ let truncated = false;
9520
+ const nodeInfo = (node, depth) => {
9521
+ if (!node || depth > maxDepth || count >= maxNodes) {
9522
+ truncated = truncated || count >= maxNodes;
9523
+ return null;
9524
+ }
9525
+ if (node.nodeType !== 1) return null;
9526
+ count++;
9527
+ const el = node;
9528
+ const text = el.textContent ? String(el.textContent).trim() : '';
9529
+ const children = [];
9530
+ if (depth < maxDepth) {
9531
+ const nodes = el.children ? Array.from(el.children) : [];
9532
+ for (const child of nodes) {
9533
+ const childInfo = nodeInfo(child, depth + 1);
9534
+ if (childInfo) children.push(childInfo);
9535
+ }
9536
+ }
9537
+ return {
9538
+ tag: el.tagName ? String(el.tagName).toLowerCase() : 'unknown',
9539
+ id: el.id ? String(el.id) : undefined,
9540
+ classes: el.className ? String(el.className) : undefined,
9541
+ role: el.getAttribute ? el.getAttribute('role') : undefined,
9542
+ ariaLabel: el.getAttribute ? el.getAttribute('aria-label') : undefined,
9543
+ textLength: text.length,
9544
+ childCount: children.length,
9545
+ children
9546
+ };
9547
+ };
9548
+ const tree = nodeInfo(root, 0);
9549
+ return {
9550
+ rootMode: root === rootEl ? 'element' : 'shadow',
9551
+ depthLimit: maxDepth,
9552
+ nodeLimit: maxNodes,
9553
+ truncated,
9554
+ tree
9555
+ };
9556
+ })()`);
9557
+ if (tree) this.emitEventPayload('extension_root_tree', stage, meta, tree);
9558
+ }
9559
+ if (this.devOptions?.sourceDom) {
9560
+ const snapshot = await this.getDomSnapshot();
9561
+ if (snapshot) {
9562
+ this.emitEventPayload('dom_snapshot', stage, meta, snapshot);
9563
+ if ('updated' === stage) {
9564
+ const diff = diffDomSnapshots(this.lastDomSnapshot, snapshot);
9565
+ this.emitEventPayload('dom_diff', stage, meta, diff);
9566
+ }
9567
+ this.lastDomSnapshot = snapshot;
9568
+ }
9569
+ }
9570
+ if (this.devOptions?.sourceConsole) {
9571
+ const top = Array.from(this.consoleTop.values()).sort((a, b)=>b.count - a.count).slice(0, 5);
9572
+ this.emitEventPayload('console_summary', stage, meta, {
9573
+ counts: this.consoleCounts,
9574
+ top,
9575
+ supported: true
9576
+ });
9577
+ }
9578
+ }
9579
+ async evaluateJson(actor, expression) {
9580
+ if (!this.client) return;
9581
+ try {
9582
+ const serializedExpression = JSON.stringify(expression);
9583
+ const json = await this.client.evaluate(actor, `(() => {
9584
+ try {
9585
+ const __expr = ${serializedExpression};
9586
+ return JSON.stringify((0, eval)(__expr));
9587
+ } catch (e) {
9588
+ return '';
9589
+ }
9590
+ })()`);
9591
+ if ('string' == typeof json && json.length > 0) return JSON.parse(json);
9592
+ } catch {}
9593
+ }
9594
+ async getDomSnapshot() {
9595
+ if (!this.client || !this.currentConsoleActor) return;
9596
+ const includeShadow = this.devOptions?.sourceIncludeShadow !== 'off';
9597
+ const payload = await this.evaluateJson(this.currentConsoleActor, `(() => {
9598
+ const rootEl = document.querySelector('#extension-root,[data-extension-root="true"]');
9599
+ if (!rootEl) return null;
9600
+ const root = (${includeShadow ? 'rootEl.shadowRoot || rootEl' : 'rootEl'});
9601
+ const maxDepth = 6;
9602
+ const maxNodes = 500;
9603
+ let count = 0;
9604
+ let truncated = false;
9605
+ const nodes = [];
9606
+ const childIndex = (node) => {
9607
+ if (!node || !node.parentElement) return 0;
9608
+ const siblings = Array.from(node.parentElement.children || []);
9609
+ return siblings.indexOf(node);
9610
+ };
9611
+ const walk = (node, depth, path) => {
9612
+ if (!node || depth > maxDepth || count >= maxNodes) {
9613
+ truncated = truncated || count >= maxNodes;
9614
+ return;
9615
+ }
9616
+ if (node.nodeType !== 1) return;
9617
+ count++;
9618
+ const el = node;
9619
+ const text = el.textContent ? String(el.textContent).trim() : '';
9620
+ const key = path;
9621
+ nodes.push({
9622
+ key,
9623
+ tag: el.tagName ? String(el.tagName).toLowerCase() : 'unknown',
9624
+ id: el.id ? String(el.id) : undefined,
9625
+ classes: el.className ? String(el.className) : undefined,
9626
+ role: el.getAttribute ? el.getAttribute('role') : undefined,
9627
+ ariaLabel: el.getAttribute ? el.getAttribute('aria-label') : undefined,
9628
+ name: el.getAttribute ? el.getAttribute('name') : undefined,
9629
+ type: el.getAttribute ? el.getAttribute('type') : undefined,
9630
+ textLength: text.length,
9631
+ childCount: el.children ? el.children.length : 0
9632
+ });
9633
+ if (depth >= maxDepth) return;
9634
+ const children = el.children ? Array.from(el.children) : [];
9635
+ for (const child of children) {
9636
+ const idx = childIndex(child);
9637
+ const childPath =
9638
+ path +
9639
+ '/' +
9640
+ child.tagName.toLowerCase() +
9641
+ '[' +
9642
+ idx +
9643
+ ']';
9644
+ walk(child, depth + 1, childPath);
9645
+ }
9646
+ };
9647
+ const rootKey = root === rootEl
9648
+ ? rootEl.tagName.toLowerCase() + '[0]'
9649
+ : rootEl.tagName.toLowerCase() + '[0]/shadow-root[0]';
9650
+ walk(root, 0, rootKey);
9651
+ return {
9652
+ rootMode: root === rootEl ? 'element' : 'shadow',
9653
+ depthLimit: maxDepth,
9654
+ nodeLimit: maxNodes,
9655
+ truncated,
9656
+ nodes
9657
+ };
9658
+ })()`);
9659
+ if (payload && 'object' == typeof payload) return payload;
9660
+ }
9661
+ emitEventPayload(type, stage, meta, payload) {
9662
+ const outputConfig = this.getOutputConfig();
9663
+ const base = {
9664
+ type,
9665
+ schema_version: '1.0',
9666
+ timestamp: new Date().toISOString(),
9667
+ stage,
9668
+ browser: this.devOptions?.browser,
9669
+ mode: this.devOptions?.mode,
9670
+ url: meta.url,
9671
+ title: meta.title,
9672
+ frameId: meta.frameContext?.frameId,
9673
+ frameUrl: meta.frameContext?.frameUrl,
9674
+ source: 'extension.js'
9675
+ };
9676
+ if ('pretty' === outputConfig.format) {
9677
+ console.log(browsers_lib_messages.Kq0());
9678
+ console.log(browsers_lib_messages.BoR(type));
9679
+ console.log(JSON.stringify({
9680
+ ...base,
9681
+ ...payload
9682
+ }, null, 2));
9683
+ console.log(browsers_lib_messages.WVz());
9684
+ return;
9685
+ }
9686
+ console.log(JSON.stringify({
9687
+ ...base,
9688
+ ...payload
9689
+ }));
8144
9690
  }
8145
9691
  async getRdpPort() {
8146
9692
  const instanceId = this.devOptions?.instanceId;
@@ -8155,6 +9701,8 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8155
9701
  while(retries < MAX_CONNECT_RETRIES)try {
8156
9702
  await client.connect(port);
8157
9703
  this.client = client;
9704
+ this.setupConsoleCapture();
9705
+ if (this.devOptions?.sourceConsole) await (0, logging.c)(client);
8158
9706
  this.initialized = true;
8159
9707
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
8160
9708
  console.log(browsers_lib_messages.X6h());
@@ -8214,15 +9762,15 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8214
9762
  try {
8215
9763
  const descriptor = this.currentTabActor || actorToUse;
8216
9764
  if (this.lastUrlToInspect) await this.ensureUrlAndReady(actorToUse, this.lastUrlToInspect);
9765
+ const meta = {};
8217
9766
  try {
8218
9767
  const currentUrl = await this.client.evaluate(actorToUse, 'String(location.href)');
9768
+ if ('string' == typeof currentUrl) meta.url = currentUrl;
8219
9769
  const currentTitle = await this.client.evaluate(actorToUse, 'String(document.title)');
8220
- console.log(browsers_lib_messages.Kq0());
8221
- console.log(browsers_lib_messages.BoR(`URL: ${currentUrl} | TITLE: ${currentTitle}`));
9770
+ if ('string' == typeof currentTitle) meta.title = currentTitle;
8222
9771
  } catch {}
8223
9772
  const html = await (0, source_inspect.Lj)(this.client, descriptor, actorToUse) || '';
8224
- console.log(html);
8225
- console.log(browsers_lib_messages.WVz());
9773
+ this.emitSourceOutput(html, 'post_injection', meta);
8226
9774
  return;
8227
9775
  } catch (err) {
8228
9776
  lastError = err;
@@ -8240,6 +9788,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8240
9788
  if (this.debounceTimer) clearTimeout(this.debounceTimer);
8241
9789
  this.debounceTimer = setTimeout(async ()=>{
8242
9790
  try {
9791
+ emitActionEvent('watch_rebuild_triggered', {});
8243
9792
  if (this.currentTabActor && this.lastUrlToInspect) {
8244
9793
  const freshConsole = await this.resolveConsoleActor(this.currentTabActor, this.lastUrlToInspect);
8245
9794
  if (freshConsole) this.currentConsoleActor = freshConsole;
@@ -8251,10 +9800,14 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8251
9800
  try {
8252
9801
  const descriptor = this.currentTabActor || this.currentConsoleActor;
8253
9802
  const html = await (0, source_inspect.Lj)(this.client, descriptor, this.currentConsoleActor);
8254
- console.log(browsers_lib_messages.Kq0());
8255
- console.log(browsers_lib_messages.BoR("UPDATED - after content script injection"));
8256
- console.log(html);
8257
- console.log(browsers_lib_messages.WVz());
9803
+ const meta = {};
9804
+ try {
9805
+ const currentUrl = await this.client.evaluate(this.currentConsoleActor, 'String(location.href)');
9806
+ if ('string' == typeof currentUrl) meta.url = currentUrl;
9807
+ const currentTitle = await this.client.evaluate(this.currentConsoleActor, 'String(document.title)');
9808
+ if ('string' == typeof currentTitle) meta.title = currentTitle;
9809
+ } catch {}
9810
+ this.emitSourceOutput(html, 'updated', meta);
8258
9811
  return;
8259
9812
  } catch (err) {
8260
9813
  lastError = err;
@@ -8280,11 +9833,20 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8280
9833
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(browsers_lib_messages.rCC(urlToInspect));
8281
9834
  const { tabActor, consoleActor } = await this.selectActors(urlToInspect);
8282
9835
  this.currentTabActor = tabActor;
9836
+ emitActionEvent('navigation_start', {
9837
+ url: urlToInspect
9838
+ });
8283
9839
  await this.ensureNavigatedAndLoaded(urlToInspect, tabActor);
9840
+ emitActionEvent('navigation_end', {
9841
+ url: urlToInspect
9842
+ });
8284
9843
  const resolvedConsoleActor = await this.resolveConsoleActor(tabActor, urlToInspect);
8285
9844
  this.currentConsoleActor = resolvedConsoleActor || consoleActor;
8286
9845
  if (this.currentConsoleActor) {
8287
9846
  await this.waitForContentScriptInjection(this.currentConsoleActor);
9847
+ emitActionEvent("content_script_injected", {
9848
+ url: urlToInspect
9849
+ });
8288
9850
  await this.printHTML(this.currentConsoleActor);
8289
9851
  }
8290
9852
  if (this.devOptions?.watchSource) {
@@ -8308,6 +9870,19 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8308
9870
  firefox_source_inspection_define_property(this, "debounceTimer", null);
8309
9871
  firefox_source_inspection_define_property(this, "initialized", false);
8310
9872
  firefox_source_inspection_define_property(this, "lastUrlToInspect", null);
9873
+ firefox_source_inspection_define_property(this, "lastOutputHash", void 0);
9874
+ firefox_source_inspection_define_property(this, "lastByteLength", void 0);
9875
+ firefox_source_inspection_define_property(this, "lastSummary", void 0);
9876
+ firefox_source_inspection_define_property(this, "lastDomSnapshot", void 0);
9877
+ firefox_source_inspection_define_property(this, "consoleCounts", {
9878
+ error: 0,
9879
+ warn: 0,
9880
+ info: 0,
9881
+ log: 0,
9882
+ debug: 0
9883
+ });
9884
+ firefox_source_inspection_define_property(this, "consoleTop", new Map());
9885
+ firefox_source_inspection_define_property(this, "consoleCaptureReady", false);
8311
9886
  this.host = host;
8312
9887
  this._ctx = ctx;
8313
9888
  }
@@ -8349,6 +9924,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8349
9924
  run_firefox_define_property(this, "copyFromProfile", void 0);
8350
9925
  run_firefox_define_property(this, "source", void 0);
8351
9926
  run_firefox_define_property(this, "watchSource", void 0);
9927
+ run_firefox_define_property(this, "sourceFormat", void 0);
9928
+ run_firefox_define_property(this, "sourceSummary", void 0);
9929
+ run_firefox_define_property(this, "sourceMeta", void 0);
9930
+ run_firefox_define_property(this, "sourceProbe", void 0);
9931
+ run_firefox_define_property(this, "sourceTree", void 0);
9932
+ run_firefox_define_property(this, "sourceConsole", void 0);
9933
+ run_firefox_define_property(this, "sourceDom", void 0);
9934
+ run_firefox_define_property(this, "sourceMaxBytes", void 0);
9935
+ run_firefox_define_property(this, "sourceRedact", void 0);
9936
+ run_firefox_define_property(this, "sourceIncludeShadow", void 0);
9937
+ run_firefox_define_property(this, "sourceDiff", void 0);
8352
9938
  run_firefox_define_property(this, "dryRun", void 0);
8353
9939
  run_firefox_define_property(this, "logLevel", void 0);
8354
9940
  run_firefox_define_property(this, "logContexts", void 0);
@@ -8373,6 +9959,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8373
9959
  this.port = options.port;
8374
9960
  this.source = options.source;
8375
9961
  this.watchSource = options.watchSource;
9962
+ this.sourceFormat = options.sourceFormat;
9963
+ this.sourceSummary = options.sourceSummary;
9964
+ this.sourceMeta = options.sourceMeta;
9965
+ this.sourceProbe = options.sourceProbe;
9966
+ this.sourceTree = options.sourceTree;
9967
+ this.sourceConsole = options.sourceConsole;
9968
+ this.sourceDom = options.sourceDom;
9969
+ this.sourceMaxBytes = options.sourceMaxBytes;
9970
+ this.sourceRedact = options.sourceRedact;
9971
+ this.sourceIncludeShadow = options.sourceIncludeShadow;
9972
+ this.sourceDiff = options.sourceDiff;
8376
9973
  this.logLevel = options.logLevel;
8377
9974
  this.logContexts = options.logContexts;
8378
9975
  this.logFormat = options.logFormat;
@@ -8425,6 +10022,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8425
10022
  plugin_browsers_define_property(this, "port", void 0);
8426
10023
  plugin_browsers_define_property(this, "source", void 0);
8427
10024
  plugin_browsers_define_property(this, "watchSource", void 0);
10025
+ plugin_browsers_define_property(this, "sourceFormat", void 0);
10026
+ plugin_browsers_define_property(this, "sourceSummary", void 0);
10027
+ plugin_browsers_define_property(this, "sourceMeta", void 0);
10028
+ plugin_browsers_define_property(this, "sourceProbe", void 0);
10029
+ plugin_browsers_define_property(this, "sourceTree", void 0);
10030
+ plugin_browsers_define_property(this, "sourceConsole", void 0);
10031
+ plugin_browsers_define_property(this, "sourceDom", void 0);
10032
+ plugin_browsers_define_property(this, "sourceMaxBytes", void 0);
10033
+ plugin_browsers_define_property(this, "sourceRedact", void 0);
10034
+ plugin_browsers_define_property(this, "sourceIncludeShadow", void 0);
10035
+ plugin_browsers_define_property(this, "sourceDiff", void 0);
8428
10036
  plugin_browsers_define_property(this, "dryRun", void 0);
8429
10037
  plugin_browsers_define_property(this, "logLevel", void 0);
8430
10038
  plugin_browsers_define_property(this, "logContexts", void 0);
@@ -8448,6 +10056,17 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8448
10056
  this.port = normalized.port;
8449
10057
  this.source = normalized.source;
8450
10058
  this.watchSource = normalized.watchSource;
10059
+ this.sourceFormat = normalized.sourceFormat;
10060
+ this.sourceSummary = normalized.sourceSummary;
10061
+ this.sourceMeta = normalized.sourceMeta;
10062
+ this.sourceProbe = normalized.sourceProbe;
10063
+ this.sourceTree = normalized.sourceTree;
10064
+ this.sourceConsole = normalized.sourceConsole;
10065
+ this.sourceDom = normalized.sourceDom;
10066
+ this.sourceMaxBytes = normalized.sourceMaxBytes;
10067
+ this.sourceRedact = normalized.sourceRedact;
10068
+ this.sourceIncludeShadow = normalized.sourceIncludeShadow;
10069
+ this.sourceDiff = normalized.sourceDiff;
8451
10070
  this.logLevel = normalized.logLevel;
8452
10071
  this.logContexts = normalized.logContexts;
8453
10072
  this.logFormat = normalized.logFormat;
@@ -8468,17 +10087,85 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8468
10087
  }
8469
10088
  }
8470
10089
  plugin_browsers_define_property(BrowsersPlugin, "name", 'plugin-browsers');
10090
+ function plugin_wasm_define_property(obj, key, value) {
10091
+ if (key in obj) Object.defineProperty(obj, key, {
10092
+ value: value,
10093
+ enumerable: true,
10094
+ configurable: true,
10095
+ writable: true
10096
+ });
10097
+ else obj[key] = value;
10098
+ return obj;
10099
+ }
10100
+ class WasmPlugin {
10101
+ resolveAssetPath(projectRoot, relativePath) {
10102
+ const candidates = [
10103
+ external_path_.join(projectRoot, 'node_modules', relativePath),
10104
+ external_path_.join(process.cwd(), 'node_modules', relativePath)
10105
+ ];
10106
+ for (const candidate of candidates)if (external_fs_.existsSync(candidate)) return candidate;
10107
+ return null;
10108
+ }
10109
+ buildAssetAliases(projectRoot) {
10110
+ const aliases = {};
10111
+ const addAlias = (request, relativePath)=>{
10112
+ const resolved = this.resolveAssetPath(projectRoot, relativePath);
10113
+ if (resolved) aliases[request] = resolved;
10114
+ };
10115
+ addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.js', '@ffmpeg/core/dist/esm/ffmpeg-core.js');
10116
+ addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.wasm', '@ffmpeg/core/dist/esm/ffmpeg-core.wasm');
10117
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.js', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.js');
10118
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm');
10119
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js');
10120
+ addAlias('@imagemagick/magick-wasm/magick.wasm', '@imagemagick/magick-wasm/magick.wasm');
10121
+ addAlias('tesseract-wasm/dist/tesseract-worker.js', 'tesseract-wasm/dist/tesseract-worker.js');
10122
+ addAlias('tesseract-wasm/dist/tesseract-core.wasm', 'tesseract-wasm/dist/tesseract-core.wasm');
10123
+ return aliases;
10124
+ }
10125
+ ensureWasmResolution(compiler, projectRoot) {
10126
+ compiler.options.resolve = compiler.options.resolve || {};
10127
+ const extensions = compiler.options.resolve.extensions || [];
10128
+ if (!extensions.includes('.wasm')) compiler.options.resolve.extensions = [
10129
+ ...extensions,
10130
+ '.wasm'
10131
+ ];
10132
+ const assetAliases = this.buildAssetAliases(projectRoot);
10133
+ compiler.options.resolve.alias = {
10134
+ ...assetAliases,
10135
+ ...compiler.options.resolve.alias
10136
+ };
10137
+ }
10138
+ ensureWasmExperiments(compiler) {
10139
+ compiler.options.experiments = {
10140
+ ...compiler.options.experiments,
10141
+ asyncWebAssembly: true
10142
+ };
10143
+ }
10144
+ apply(compiler) {
10145
+ const projectRoot = String(compiler.options.context || process.cwd());
10146
+ this.ensureWasmExperiments(compiler);
10147
+ this.ensureWasmResolution(compiler, projectRoot);
10148
+ }
10149
+ constructor(options){
10150
+ plugin_wasm_define_property(this, "manifestPath", void 0);
10151
+ plugin_wasm_define_property(this, "mode", void 0);
10152
+ this.manifestPath = options.manifestPath;
10153
+ this.mode = options.mode;
10154
+ }
10155
+ }
10156
+ plugin_wasm_define_property(WasmPlugin, "name", 'plugin-wasm');
8471
10157
  function webpackConfig(projectStructure, devOptions) {
8472
10158
  const { manifestPath } = projectStructure;
8473
10159
  const { packageJsonDir } = (0, webpack_lib_paths.fu)(projectStructure);
8474
10160
  const manifest = filterKeysForThisBrowser(JSON.parse(external_fs_.readFileSync(manifestPath, 'utf-8')), devOptions.browser);
8475
10161
  const primaryExtensionOutputDir = (0, webpack_lib_paths.G6)(external_path_.isAbsolute(devOptions.output.path) ? devOptions.output.path : external_path_.resolve(packageJsonDir, devOptions.output.path));
8476
- const companionUnpackedExtensionDirs = (0, companion_extensions.A)({
10162
+ const companionUnpackedExtensionDirs = resolveCompanionExtensionDirs({
8477
10163
  projectRoot: packageJsonDir,
8478
10164
  config: devOptions.extensions
8479
10165
  });
8480
10166
  const unpackedExtensionDirsToLoad = (0, extensions_to_load.n)(external_path_.resolve(__dirname, '..'), devOptions.mode, devOptions.browser, primaryExtensionOutputDir, companionUnpackedExtensionDirs);
8481
10167
  const debug = 'true' === process.env.EXTENSION_AUTHOR_MODE;
10168
+ const transpilePackageDirs = resolveTranspilePackageDirs(packageJsonDir, devOptions.transpilePackages);
8482
10169
  if (debug) {
8483
10170
  console.log(messages._A(devOptions.browser, devOptions.chromiumBinary, devOptions.geckoBinary));
8484
10171
  console.log(messages.aw(packageJsonDir));
@@ -8507,18 +10194,26 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8507
10194
  new CssPlugin({
8508
10195
  manifestPath
8509
10196
  }),
8510
- new JsFrameworksPlugin({
10197
+ new WasmPlugin({
8511
10198
  manifestPath,
8512
10199
  mode: devOptions.mode
8513
10200
  }),
10201
+ new JsFrameworksPlugin({
10202
+ manifestPath,
10203
+ mode: devOptions.mode,
10204
+ transpilePackages: devOptions.transpilePackages
10205
+ }),
8514
10206
  new CompatibilityPlugin({
8515
10207
  manifestPath,
8516
10208
  browser: devOptions.browser,
8517
10209
  polyfill: devOptions.polyfill
8518
10210
  }),
8519
- new ExtensionPlugin({
10211
+ new plugin_web_extension_WebExtensionPlugin({
8520
10212
  manifestPath,
8521
10213
  browser: devOptions.browser
10214
+ }),
10215
+ new SpecialFoldersPlugin({
10216
+ manifestPath
8522
10217
  })
8523
10218
  ];
8524
10219
  if (!devOptions.noRunner) plugins.push(new BrowsersPlugin({
@@ -8536,6 +10231,12 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8536
10231
  port: devOptions.port,
8537
10232
  source: devOptions.source,
8538
10233
  watchSource: devOptions.watchSource,
10234
+ sourceFormat: devOptions.sourceFormat,
10235
+ sourceSummary: devOptions.sourceSummary,
10236
+ sourceMaxBytes: devOptions.sourceMaxBytes,
10237
+ sourceRedact: devOptions.sourceRedact,
10238
+ sourceIncludeShadow: devOptions.sourceIncludeShadow,
10239
+ sourceDiff: devOptions.sourceDiff,
8539
10240
  dryRun: '1' === process.env.EXTENSION_DEV_NO_BROWSER,
8540
10241
  logLevel: devOptions.logLevel,
8541
10242
  logContexts: devOptions.logContexts,
@@ -8564,7 +10265,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8564
10265
  }
8565
10266
  },
8566
10267
  watchOptions: {
8567
- ignored: /node_modules|dist|extension-js\/profiles/,
10268
+ ignored: transpilePackageDirs.length > 0 ? /dist|extension-js\/profiles/ : /node_modules|dist|extension-js\/profiles/,
8568
10269
  poll: 1000,
8569
10270
  aggregateTimeout: 200
8570
10271
  },
@@ -8583,6 +10284,11 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8583
10284
  aliasFields: [
8584
10285
  'browser'
8585
10286
  ],
10287
+ fallback: {
10288
+ crypto: false,
10289
+ fs: false,
10290
+ path: false
10291
+ },
8586
10292
  modules: projectStructure.packageJsonPath ? [
8587
10293
  'node_modules',
8588
10294
  external_path_.join(packageJsonDir, 'node_modules'),
@@ -8600,10 +10306,12 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8600
10306
  '.mts',
8601
10307
  '.tsx',
8602
10308
  '.json',
8603
- '.wasm',
8604
10309
  '.svelte'
8605
10310
  ]
8606
10311
  },
10312
+ node: {
10313
+ __dirname: false
10314
+ },
8607
10315
  resolveLoader: {
8608
10316
  extensions: [
8609
10317
  '.js',
@@ -8617,7 +10325,6 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8617
10325
  ]
8618
10326
  },
8619
10327
  module: {
8620
- rules: [],
8621
10328
  parser: {
8622
10329
  'css/auto': {
8623
10330
  namedExports: false
@@ -8638,17 +10345,6 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8638
10345
  level: 'development' === String(devOptions.mode) && '1' === String(process.env.EXTENSION_VERBOSE || '').trim() ? 'info' : 'error',
8639
10346
  console: (0, branding.P)('Extension.js')
8640
10347
  },
8641
- ignoreWarnings: [
8642
- (warning)=>{
8643
- try {
8644
- const message = String(warning && (warning.message || warning) || '');
8645
- const modulePath = warning && warning.module && (warning.module.resource || warning.module.userRequest) || '';
8646
- return message.includes('Accessing import.meta directly is unsupported') && /[\\\/]@huggingface[\\\/]transformers[\\\/].*transformers\.web\.js$/.test(modulePath);
8647
- } catch {
8648
- return false;
8649
- }
8650
- }
8651
- ],
8652
10348
  performance: {
8653
10349
  hints: 'production' === devOptions.mode ? 'warning' : false
8654
10350
  },
@@ -8663,8 +10359,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8663
10359
  chunkIds: 'deterministic'
8664
10360
  },
8665
10361
  experiments: {
8666
- css: true,
8667
- asyncWebAssembly: true
10362
+ css: true
8668
10363
  }
8669
10364
  };
8670
10365
  }