extension-develop 4.0.16 → 4.0.17

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.
@@ -13,10 +13,11 @@ import content_security_policy_parser from "content-security-policy-parser";
13
13
  import node_fs from "node:fs";
14
14
  import node_path from "node:path";
15
15
  import { isResourceUnderDirs, canonicalizeDir, toResourceKey } from "./93.mjs";
16
- import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, packagingDistributionFiles, PlaywrightPlugin, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, spacerLine, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, treeWithDistFilesbrowser, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, constants_isGeckoBasedBrowser, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
16
+ import { prefix as messaging_prefix, isDebug } from "./349.mjs";
17
+ import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, packagingDistributionFiles, PlaywrightPlugin, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, isGeckoBasedBrowser, spacerLine, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, treeWithDistFilesbrowser, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
18
+ import { unixify as paths_unixify, getManifestOverrides, isUsingTypeScript, resolvePackageManager, jsFrameworksIntegrationsEnabled, resolveRootAbsoluteRef, isStaticThemeSource, buildCanonicalManifest, getCurrentManifestContent, ensureTypeScriptConfig, resolveDevelopInstallRoot, filterKeysForThisBrowser as manifest_utils_filterKeysForThisBrowser, isUsingCustomLoader, getUserTypeScriptConfigFile, isUsingIntegration as messages_isUsingIntegration, reportToCompilation, normalizeManifestOutputPath, jsFrameworksHmrSummary, ReloadPlugin, humanLine, jsFrameworksConfigsDetected, collectRootAbsoluteRefs, getManifestContent, resolveDevelopDistFile, hasDependency, setOriginalManifestContent, isFromFilepathList, setCurrentManifestContent } from "./839.mjs";
17
19
  import { scrubBrand, makeSanitizedConsole } from "./0~branding.mjs";
18
20
  import { stripBom, parseJsonSafe } from "./23.mjs";
19
- import { unixify as paths_unixify, getManifestOverrides, isUsingTypeScript, resolvePackageManager, jsFrameworksIntegrationsEnabled, resolveRootAbsoluteRef, isStaticThemeSource, getCurrentManifestContent, buildCanonicalManifest, ensureTypeScriptConfig, resolveDevelopInstallRoot, filterKeysForThisBrowser as manifest_utils_filterKeysForThisBrowser, isUsingCustomLoader, getUserTypeScriptConfigFile, isUsingIntegration as messages_isUsingIntegration, reportToCompilation, normalizeManifestOutputPath, jsFrameworksHmrSummary, ReloadPlugin, jsFrameworksConfigsDetected, collectRootAbsoluteRefs, getManifestContent, resolveDevelopDistFile, hasDependency, setOriginalManifestContent, isFromFilepathList, setCurrentManifestContent } from "./839.mjs";
20
21
  import { hasProjectDependency, findNearestProjectManifestSync, PROJECT_MANIFEST_FILENAMES, readProjectDependencies } from "./80.mjs";
21
22
  import { cssIntegrationsEnabled, cssConfigsDetected, deadCssUrlRef, missingSassDependency, isUsingIntegration, postCssPluginNotResolved } from "./845.mjs";
22
23
  import { getCanonicalContentScriptEntryName, parseCanonicalContentScriptAsset, getCanonicalContentScriptJsAssetName, isCanonicalContentScriptAsset, EXTENSIONJS_CONTENT_SCRIPT_LAYER } from "./291.mjs";
@@ -116,33 +117,23 @@ function isSubPath(resourcePath, directoryPath) {
116
117
  ]);
117
118
  }
118
119
  function getLoggingPrefix(type) {
119
- const isAuthor = 'true' === process.env.EXTENSION_AUTHOR_MODE;
120
- if (isAuthor) {
121
- const base = 'error' === type ? 'ERROR Author says' : '⏵⏵⏵ Author says';
122
- return pintor.brightMagenta(base);
123
- }
124
- if ('error' === type) return pintor.red('ERROR');
125
- if ('warn' === type) return pintor.brightYellow('⏵⏵⏵');
126
- if ('info' === type) return pintor.gray('⏵⏵⏵');
127
- return pintor.green('⏵⏵⏵');
120
+ return messaging_prefix(type);
128
121
  }
129
122
  const messages_code = (text)=>pintor.blue(text);
130
123
  function webextensionPolyfillNotFound() {
131
- return `${getLoggingPrefix('warn')} webextension-polyfill not found.\nInstall it to enable the browser API polyfill:\n${messages_code('npm install webextension-polyfill')}`;
124
+ return `${getLoggingPrefix('warn')} webextension-polyfill is not installed.\nThe browser API polyfill is disabled for this build.\nInstall it with ${messages_code('npm install webextension-polyfill')}.`;
132
125
  }
133
- function capitalizedBrowserName(browser) {
134
- const b = String(browser || '');
135
- const cap = b.charAt(0).toUpperCase() + b.slice(1);
136
- return pintor.yellow(`${cap}`);
126
+ function browserKey(browser) {
127
+ return String(browser || 'unknown');
137
128
  }
138
129
  function compatibilityPolyfillEnabled(browser, polyfillPath) {
139
- return `${pintor.gray('⏵⏵⏵')} Compatibility: Polyfill enabled for ${capitalizedBrowserName(browser)}\n${pintor.gray('ALIAS')} ${pintor.underline(polyfillPath)}`;
130
+ return `${messaging_prefix('debug')} compat polyfill=enabled browser=${browserKey(browser)} alias=${polyfillPath}`;
140
131
  }
141
132
  function compatibilityPolyfillSkipped(reason, browser) {
142
- return `${pintor.gray('⏵⏵⏵')} Compatibility: Polyfill ${pintor.gray('skipped')} for ${capitalizedBrowserName(browser)} (${pintor.gray(reason)})`;
133
+ return `${messaging_prefix('debug')} compat polyfill=skipped browser=${browserKey(browser)} reason="${reason}"`;
143
134
  }
144
135
  function compatibilityPolyfillDisabled(browser) {
145
- return `${pintor.gray('⏵⏵⏵')} Compatibility: Polyfill ${pintor.gray('disabled')} for ${capitalizedBrowserName(browser)}`;
136
+ return `${messaging_prefix('debug')} compat polyfill=disabled browser=${browserKey(browser)}`;
146
137
  }
147
138
  const cjsRequire = createRequire(import.meta.url);
148
139
  class PolyfillPlugin {
@@ -170,7 +161,7 @@ class PolyfillPlugin {
170
161
  new core.ProvidePlugin({
171
162
  browser: 'webextension-polyfill'
172
163
  }).apply(compiler);
173
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillEnabled(this.browser, polyfillPath));
164
+ if (isDebug()) console.log(compatibilityPolyfillEnabled(this.browser, polyfillPath));
174
165
  } catch (error) {
175
166
  console.warn(webextensionPolyfillNotFound());
176
167
  }
@@ -187,23 +178,23 @@ class CompatibilityPlugin {
187
178
  this.polyfill = options.polyfill || false;
188
179
  }
189
180
  apply(compiler) {
190
- const isGeckoFamily = constants_isGeckoBasedBrowser(String(this.browser));
181
+ const isGeckoFamily = isGeckoBasedBrowser(String(this.browser));
191
182
  if (this.polyfill) if (isGeckoFamily) {
192
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
183
+ if (isDebug()) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
193
184
  } else {
194
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
185
+ if (isDebug()) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
195
186
  new PolyfillPlugin({
196
187
  manifestPath: this.manifestPath,
197
188
  browser: this.browser || 'chrome'
198
189
  }).apply(compiler);
199
190
  }
200
- else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillDisabled(this.browser));
191
+ else if (isDebug()) console.log(compatibilityPolyfillDisabled(this.browser));
201
192
  }
202
193
  }
203
194
  function setupCompilerLifecycleHooks(compiler) {
204
195
  const verbose = '1' === String(process.env.EXTENSION_VERBOSE || '').trim();
205
196
  compiler.hooks.invalid.tap('extension.js:invalid', ()=>{
206
- if (verbose) console.log(bundlerRecompiling());
197
+ if (verbose) humanLine(bundlerRecompiling());
207
198
  });
208
199
  compiler.hooks.failed.tap('extension.js:failed', (error)=>{
209
200
  console.error(bundlerFatalError(error));
@@ -215,14 +206,14 @@ function setupNoBrowserBannerOnFirstDone(opts) {
215
206
  if (printed) return;
216
207
  if (stats?.hasErrors?.()) return;
217
208
  printed = true;
218
- console.log(messages_ready('development', opts.browser));
219
- console.log(spacerLine());
220
- console.log(browserRunnerDisabled({
209
+ humanLine(spacerLine());
210
+ humanLine(browserRunnerDisabled({
221
211
  browser: opts.browser,
222
212
  manifestPath: opts.manifestPath,
223
213
  readyPath: opts.readyPath
224
214
  }));
225
- console.log(spacerLine());
215
+ humanLine(spacerLine());
216
+ humanLine(messages_ready('development', opts.browser));
226
217
  });
227
218
  }
228
219
  function setupCompilerDoneDiagnostics(compiler, port) {
@@ -286,58 +277,37 @@ function boring(manifestName, durationMs, stats) {
286
277
  return `${arrow} ${timestamp} ${app} compiled ${label} in ${time}.`;
287
278
  }
288
279
  function cleanDistStarting(distPath) {
289
- return `${pintor.gray('⏵⏵⏵')} Clean dist: ${pintor.gray('starting')}\n${pintor.gray('PATH')} ${pintor.underline(distPath)}`;
280
+ return `${messaging_prefix('debug')} clean start path=${distPath}`;
290
281
  }
291
282
  function cleanDistRemovedSummary(removedCount, distPath) {
292
- return [
293
- `${pintor.underline('Clean dist (completed)')}`,
294
- `${pintor.gray('REMOVED')} ${pintor.gray(String(removedCount))}`,
295
- `${pintor.gray('PATH')} ${pintor.underline(distPath)}`
296
- ].join('\n');
283
+ return `${messaging_prefix('debug')} clean removed=${removedCount} path=${distPath}`;
297
284
  }
298
285
  function cleanDistSkippedNotFound(distPath) {
299
- return `${pintor.gray('⏵⏵⏵')} Clean dist: ${pintor.gray('skipped')} (path not found)\n${pintor.gray('PATH')} ${pintor.underline(distPath)}`;
286
+ return `${messaging_prefix('debug')} clean skipped=not-found path=${distPath}`;
300
287
  }
301
288
  function zipPackagingSkipped(reason) {
302
- return `${pintor.gray('⏵⏵⏵')} Packaging: ${pintor.gray('skipped')} (${pintor.gray(reason)})`;
289
+ return `${messaging_prefix('debug')} zip skipped=true reason="${reason}"`;
303
290
  }
304
291
  function envSelectedFile(envPath) {
305
- const label = envPath ? pintor.underline(envPath) : pintor.gray('none');
306
- return [
307
- `${pintor.underline('Environment')}`,
308
- `${pintor.gray('PATH')} ${label}`
309
- ].join('\n');
292
+ return `${messaging_prefix('debug')} env file=${envPath || 'none'}`;
310
293
  }
311
294
  function envInjectedPublicVars(count) {
312
- return [
313
- `${pintor.underline('Environment')}`,
314
- `${pintor.gray('INJECTED')} ${pintor.gray(String(count))} EXTENSION_PUBLIC_*`
315
- ].join('\n');
295
+ return `${messaging_prefix('debug')} env injected=${count} prefix=EXTENSION_PUBLIC_`;
316
296
  }
317
297
  function envNoMatchingFile(browser, mode, presentFiles, expectedCandidates) {
318
- return `Found ${presentFiles.map((file)=>pintor.yellow(file)).join(', ')} but none match browser ${pintor.yellow(browser)} (mode ${pintor.yellow(mode)}), so EXTENSION_PUBLIC_* variables read from code will be ${pintor.yellow('undefined')} in this build.\nMatching names, in priority order: ${expectedCandidates.map((file)=>pintor.gray(file)).join(', ')}.\nFamily names apply to every family member, e.g. ${pintor.yellow('.env.chrome')} also matches ${pintor.yellow('chromium')} and ${pintor.yellow('edge')} targets.`;
298
+ return `Found ${presentFiles.map((file)=>pintor.yellow(file)).join(', ')}, but none match browser ${pintor.yellow(browser)} in mode ${pintor.yellow(mode)}.\nEXTENSION_PUBLIC_* variables read from code are ${pintor.yellow('undefined')} in this build.\nRename the file to one of these, in priority order: ${expectedCandidates.map((file)=>pintor.gray(file)).join(', ')}.\nFamily names apply to every family member, so ${pintor.yellow('.env.chrome')} also matches ${pintor.yellow('chromium')} and ${pintor.yellow('edge')} targets.`;
319
299
  }
320
300
  const sharedState = {
321
301
  bannerPrinted: false,
322
302
  pendingCompilationLine: ''
323
303
  };
324
- const BANNER_PRINTED_EVENT = 'extensionjs:banner-printed';
325
304
  function markBannerPrinted() {
326
305
  sharedState.bannerPrinted = true;
327
306
  if (sharedState.pendingCompilationLine) {
328
- console.log(sharedState.pendingCompilationLine);
307
+ humanLine(sharedState.pendingCompilationLine);
329
308
  sharedState.pendingCompilationLine = '';
330
309
  }
331
310
  }
332
- let listenerInstalled = false;
333
- function ensureBannerListener() {
334
- if (listenerInstalled) return;
335
- listenerInstalled = true;
336
- process.on(BANNER_PRINTED_EVENT, ()=>{
337
- markBannerPrinted();
338
- });
339
- }
340
- ensureBannerListener();
341
311
  function isBannerPrinted() {
342
312
  if (sharedState.bannerPrinted) return true;
343
313
  if ('true' === process.env.EXTENSION_CLI_BANNER_PRINTED) {
@@ -365,6 +335,9 @@ class BoringPlugin {
365
335
  this.sawUserInvalidation = false;
366
336
  this.printedPostBannerStartupSuccess = false;
367
337
  });
338
+ compiler.hooks.afterDone?.tap('develop:brand:flush', ()=>{
339
+ isBannerPrinted();
340
+ });
368
341
  compiler.hooks.done.tap('develop:brand', (stats)=>{
369
342
  const hasErrors = Boolean(stats?.hasErrors?.());
370
343
  const hasWarnings = Boolean(stats?.hasWarnings?.());
@@ -407,7 +380,7 @@ class BoringPlugin {
407
380
  if (!this.sawUserInvalidation) if (this.printedPostBannerStartupSuccess) return;
408
381
  else this.printedPostBannerStartupSuccess = true;
409
382
  }
410
- console.log(line);
383
+ humanLine(line);
411
384
  } catch {}
412
385
  });
413
386
  }
@@ -422,13 +395,13 @@ class CleanDistFolderPlugin {
422
395
  const distPath = __rspack_external_node_path_c5b9b54f.join(compiler.options.context, 'dist', this.options.browser);
423
396
  if (__rspack_external_node_fs_5ea92f0c.existsSync(distPath)) {
424
397
  const removedCount = countFilesRecursively(distPath);
425
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(cleanDistStarting(distPath));
398
+ if (isDebug()) console.log(cleanDistStarting(distPath));
426
399
  try {
427
400
  __rspack_external_node_fs_5ea92f0c.rmSync(distPath, {
428
401
  recursive: true,
429
402
  force: true
430
403
  });
431
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
404
+ if (isDebug()) {
432
405
  console.log(cleanDistRemovedSummary(removedCount, distPath));
433
406
  logger.info('[CleanDistFolderPlugin] Removed old hot-update files before compilation.');
434
407
  }
@@ -444,7 +417,7 @@ class CleanDistFolderPlugin {
444
417
  }, 100);
445
418
  logger.error(`[CleanDistFolderPlugin] Failed to remove hot-update files: ${error.message}`);
446
419
  }
447
- } else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(cleanDistSkippedNotFound(distPath));
420
+ } else if (isDebug()) console.log(cleanDistSkippedNotFound(distPath));
448
421
  }
449
422
  }
450
423
  function countFilesRecursively(dir) {
@@ -504,7 +477,7 @@ function resolveEnvPaths(projectPath, envFiles) {
504
477
  function getEnvFileCandidates(browser, mode) {
505
478
  const browserName = String(browser);
506
479
  const isChromiumTarget = isChromiumBasedBrowser(browserName) || 'safari' === browserName || browserName.includes('webkit');
507
- const familyNames = isChromiumTarget ? CHROMIUM_FAMILY_ALIASES : constants_isGeckoBasedBrowser(browserName) ? GECKO_FAMILY_ALIASES : [];
480
+ const familyNames = isChromiumTarget ? CHROMIUM_FAMILY_ALIASES : isGeckoBasedBrowser(browserName) ? GECKO_FAMILY_ALIASES : [];
508
481
  const names = [
509
482
  browserName,
510
483
  ...familyNames.filter((name)=>name !== browserName)
@@ -531,7 +504,7 @@ class EnvPlugin {
531
504
  const mode = compiler.options.mode || 'development';
532
505
  const envFiles = getEnvFileCandidates(this.browser, mode);
533
506
  const { envPath, defaultsPath } = resolveEnvPaths(projectPath, envFiles);
534
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(envSelectedFile(envPath));
507
+ if (isDebug()) console.log(envSelectedFile(envPath));
535
508
  if (!envPath && projectPath) {
536
509
  let unmatchedEnvFiles = [];
537
510
  try {
@@ -573,7 +546,7 @@ class EnvPlugin {
573
546
  filteredEnvVars['import.meta.dirname'] = 'undefined';
574
547
  filteredEnvVars['import.meta.filename'] = 'undefined';
575
548
  const injectedCount = Object.keys(filteredEnvVars).filter((k)=>k.startsWith('process.env.EXTENSION_PUBLIC_')).length;
576
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(envInjectedPublicVars(injectedCount));
549
+ if (isDebug()) console.log(envInjectedPublicVars(injectedCount));
577
550
  const processShim = resolveProcessShim();
578
551
  if (!processShim) {
579
552
  filteredEnvVars['process.env'] = '{}';
@@ -691,7 +664,7 @@ class ZipPlugin {
691
664
  sourceZip.addLocalFile(__rspack_external_node_path_c5b9b54f.join(packageJsonDir, file), '.' === root ? '' : toPosix(root));
692
665
  });
693
666
  const sourcePath = __rspack_external_node_path_c5b9b54f.join(__rspack_external_node_path_c5b9b54f.dirname(outPath), `${name}-source.zip`);
694
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(packagingSourceFiles(sourcePath));
667
+ if (isDebug()) console.log(packagingSourceFiles(sourcePath));
695
668
  sourceZip.writeZip(sourcePath);
696
669
  created.push({
697
670
  kind: 'source',
@@ -703,14 +676,14 @@ class ZipPlugin {
703
676
  distZip.addLocalFolder(outPath);
704
677
  const filename = this.zipData.zipFilename ? sanitize(this.zipData.zipFilename) : name;
705
678
  const distPath = __rspack_external_node_path_c5b9b54f.join(outPath, `${filename}.zip`);
706
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(packagingDistributionFiles(distPath));
679
+ if (isDebug()) console.log(packagingDistributionFiles(distPath));
707
680
  distZip.writeZip(distPath);
708
681
  created.push({
709
682
  kind: 'dist',
710
683
  path: distPath
711
684
  });
712
685
  }
713
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
686
+ if (isDebug()) {
714
687
  const sourceItem = created.find((c)=>'source' === c.kind);
715
688
  const distItem = created.find((c)=>'dist' === c.kind);
716
689
  if (sourceItem && distItem) console.log(treeWithSourceAndDistFiles(this.browser, name, sourceItem.path, distItem.path));
@@ -792,7 +765,7 @@ class CompilationPlugin {
792
765
  zipFilename: this.zipFilename
793
766
  }
794
767
  }).apply(compiler);
795
- else if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
768
+ else if (isDebug()) {
796
769
  const reason = 'production' !== compiler.options.mode ? 'not production mode' : 'zip disabled';
797
770
  console.log(zipPackagingSkipped(reason));
798
771
  }
@@ -1311,7 +1284,7 @@ let userMessageDelivered = false;
1311
1284
  function isUsingLess(projectPath) {
1312
1285
  if (hasDependency(projectPath, 'less')) {
1313
1286
  if (!userMessageDelivered) {
1314
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('LESS')}`);
1287
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('LESS')}`);
1315
1288
  userMessageDelivered = true;
1316
1289
  }
1317
1290
  return true;
@@ -1331,7 +1304,7 @@ function tailwind_isUsingTailwind(projectPath) {
1331
1304
  const isUsingTailwind = hasDependency(projectPath, 'tailwindcss') || hasDependency(projectPath, '@tailwindcss/postcss');
1332
1305
  if (isUsingTailwind) {
1333
1306
  if (!tailwind_userMessageDelivered) {
1334
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('Tailwind')}`);
1307
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('Tailwind')}`);
1335
1308
  tailwind_userMessageDelivered = true;
1336
1309
  }
1337
1310
  }
@@ -1600,21 +1573,21 @@ function getDeclaredTailwindMajor(projectPath) {
1600
1573
  function isUsingPostCss(projectPath) {
1601
1574
  if (hasDependency(projectPath, 'postcss')) {
1602
1575
  if (!postcss_userMessageDelivered) {
1603
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('PostCSS')}`);
1576
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('PostCSS')}`);
1604
1577
  postcss_userMessageDelivered = true;
1605
1578
  }
1606
1579
  return true;
1607
1580
  }
1608
1581
  if (findPostCssConfig(projectPath)) {
1609
1582
  if (!postcss_userMessageDelivered) {
1610
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('PostCSS')}`);
1583
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('PostCSS')}`);
1611
1584
  postcss_userMessageDelivered = true;
1612
1585
  }
1613
1586
  return true;
1614
1587
  }
1615
1588
  if (tailwind_isUsingTailwind(projectPath)) {
1616
1589
  if (!postcss_userMessageDelivered) {
1617
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('PostCSS')}`);
1590
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('PostCSS')}`);
1618
1591
  postcss_userMessageDelivered = true;
1619
1592
  }
1620
1593
  return true;
@@ -1759,8 +1732,8 @@ async function maybeUsePostCss(projectPath, opts) {
1759
1732
  config: false,
1760
1733
  plugins: selfResolved.plugins
1761
1734
  };
1762
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) try {
1763
- console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} [extension.js:postcss] projectPath=%s selfResolvedPlugins=%d unresolved=%s`, projectPath, selfResolved.plugins.length, selfResolved.unresolved.join(',') || 'none');
1735
+ if (isDebug()) try {
1736
+ console.log(`${messaging_prefix('debug')} [extension.js:postcss] projectPath=%s selfResolvedPlugins=%d unresolved=%s`, projectPath, selfResolved.plugins.length, selfResolved.unresolved.join(',') || 'none');
1764
1737
  } catch {}
1765
1738
  return {
1766
1739
  test: /\.css$/,
@@ -1790,10 +1763,10 @@ async function maybeUsePostCss(projectPath, opts) {
1790
1763
  config: userConfigIsCjsInEsm || bypassUserConfigForTailwindCompat ? false : projectPath
1791
1764
  };
1792
1765
  if (pluginsFromOptions) postcssOptions.plugins = pluginsFromOptions;
1793
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) try {
1794
- console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} [extension.js:postcss] projectPath=%s userPostCssConfig=%s pkgHasPostCss=%s tailwindPresent=%s`, projectPath, userPostCssConfig || 'none', pkgHasPostCss, tailwindPresent);
1766
+ if (isDebug()) try {
1767
+ console.log(`${messaging_prefix('debug')} [extension.js:postcss] projectPath=%s userPostCssConfig=%s pkgHasPostCss=%s tailwindPresent=%s`, projectPath, userPostCssConfig || 'none', pkgHasPostCss, tailwindPresent);
1795
1768
  const resolvedPluginsCount = Array.isArray(postcssOptions.plugins) ? postcssOptions.plugins.length : 0;
1796
- console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} [extension.js:postcss] resolvedPlugins=%d config=%s cwd=%s`, resolvedPluginsCount, String(postcssOptions.config), String(postcssOptions.cwd));
1769
+ console.log(`${messaging_prefix('debug')} [extension.js:postcss] resolvedPlugins=%d config=%s cwd=%s`, resolvedPluginsCount, String(postcssOptions.config), String(postcssOptions.cwd));
1797
1770
  } catch {}
1798
1771
  return {
1799
1772
  test: /\.css$/,
@@ -1810,7 +1783,7 @@ let sass_userMessageDelivered = false;
1810
1783
  function isUsingSass(projectPath) {
1811
1784
  if (hasDependency(projectPath, 'sass')) {
1812
1785
  if (!sass_userMessageDelivered) {
1813
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('SASS')}`);
1786
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('SASS')}`);
1814
1787
  sass_userMessageDelivered = true;
1815
1788
  }
1816
1789
  return true;
@@ -2077,7 +2050,7 @@ class CssPlugin {
2077
2050
  ...compiler.options.module.rules,
2078
2051
  ...loaders
2079
2052
  ].filter(Boolean);
2080
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
2053
+ if (isDebug()) {
2081
2054
  const integrations = [];
2082
2055
  const usingTailwind = hasDependency(projectPath, 'tailwindcss');
2083
2056
  const usingPostcss = hasDependency(projectPath, 'postcss') || void 0 !== findPostCssConfig(projectPath) || usingSass || usingLess || usingTailwind;
@@ -2450,7 +2423,7 @@ let preact_userMessageDelivered = false;
2450
2423
  function isUsingPreact(projectPath) {
2451
2424
  if (hasDependency(projectPath, 'preact')) {
2452
2425
  if (!preact_userMessageDelivered) {
2453
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${messages_isUsingIntegration('Preact')}`);
2426
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('Preact')}`);
2454
2427
  preact_userMessageDelivered = true;
2455
2428
  }
2456
2429
  return true;
@@ -2492,7 +2465,7 @@ let react_userMessageDelivered = false;
2492
2465
  function isUsingReact(projectPath) {
2493
2466
  if (hasDependency(projectPath, 'react')) {
2494
2467
  if (!react_userMessageDelivered) {
2495
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${messages_isUsingIntegration('React')}`);
2468
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('React')}`);
2496
2469
  react_userMessageDelivered = true;
2497
2470
  }
2498
2471
  return true;
@@ -2559,10 +2532,6 @@ async function maybeUseReact(projectPath, options = {}) {
2559
2532
  };
2560
2533
  }
2561
2534
  let load_loader_options_userMessageDelivered = false;
2562
- function isAuthorMode() {
2563
- const v = String(process.env.EXTENSION_AUTHOR_MODE || '').trim().toLowerCase();
2564
- return 'true' === v || '1' === v || 'development' === v || 'dev' === v;
2565
- }
2566
2535
  function resolveLoaderConfigPath(projectPath, framework) {
2567
2536
  const candidates = [
2568
2537
  __rspack_external_node_path_c5b9b54f.join(projectPath, `${framework}.loader.ts`),
@@ -2575,7 +2544,7 @@ function resolveLoaderConfigPath(projectPath, framework) {
2575
2544
  async function loadLoaderOptions(projectPath, framework) {
2576
2545
  const configPath = resolveLoaderConfigPath(projectPath, framework);
2577
2546
  if (configPath) {
2578
- if (!load_loader_options_userMessageDelivered && isAuthorMode()) {
2547
+ if (!load_loader_options_userMessageDelivered && isDebug()) {
2579
2548
  const display = __rspack_external_node_path_c5b9b54f.basename(configPath);
2580
2549
  console.log(isUsingCustomLoader(display));
2581
2550
  load_loader_options_userMessageDelivered = true;
@@ -2604,7 +2573,7 @@ function svelte_resolveFromProject(id, projectPath) {
2604
2573
  function isUsingSvelte(projectPath) {
2605
2574
  const using = hasDependency(projectPath, 'svelte');
2606
2575
  if (using && !svelte_userMessageDelivered) {
2607
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(messages_isUsingIntegration('Svelte'));
2576
+ if (isDebug()) console.log(messages_isUsingIntegration('Svelte'));
2608
2577
  svelte_userMessageDelivered = true;
2609
2578
  }
2610
2579
  return using;
@@ -2701,7 +2670,7 @@ let vue_userMessageDelivered = false;
2701
2670
  function isUsingVue(projectPath) {
2702
2671
  const using = hasDependency(projectPath, 'vue');
2703
2672
  if (using && !vue_userMessageDelivered) {
2704
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${messages_isUsingIntegration('Vue')}`);
2673
+ if (isDebug()) console.log(`${messaging_prefix('debug')} ${messages_isUsingIntegration('Vue')}`);
2705
2674
  vue_userMessageDelivered = true;
2706
2675
  }
2707
2676
  return using;
@@ -3095,7 +3064,7 @@ class JsFrameworksPlugin {
3095
3064
  if (isUsingTypeScript(projectPath) || !!tsConfigPath) compiler.options.resolve.tsConfig = {
3096
3065
  configFile: tsConfigPath
3097
3066
  };
3098
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
3067
+ if (isDebug()) {
3099
3068
  const integrations = [];
3100
3069
  if (maybeInstallReact) integrations.push('React');
3101
3070
  if (maybeInstallPreact) integrations.push('Preact');
@@ -3162,7 +3131,7 @@ function perfBudgetWarning(assets) {
3162
3131
  const over = (a.size / a.budget * 100 - 100).toFixed(0);
3163
3132
  return ` ${a.name}\n size: ${fmtKiB(a.size)}\n budget: ${fmtKiB(a.budget)} (over by ${over}%)\n role: ${categoryRole(a.category)}`;
3164
3133
  });
3165
- const remediation = "Recommended: lazy-load with dynamic import(), code-split per route, or replace large SDKs with thin fetch wrappers. See https://rspack.rs/guide/optimization/code-splitting";
3134
+ const remediation = "Lazy-load with dynamic import(), code-split per route, or replace large SDKs with thin fetch wrappers.\nSee https://rspack.rs/guide/optimization/code-splitting";
3166
3135
  return `${header}\n\n${lines.join('\n')}\n\n${remediation}`;
3167
3136
  }
3168
3137
  function categoryRole(c) {
@@ -3870,13 +3839,13 @@ function emitRootAbsoluteRefs(compilation, context, publicDir) {
3870
3839
  }
3871
3840
  }
3872
3841
  function serverRestartRequiredFromSpecialFolderMessageOnly(addingOrRemoving, folder, typeOfAsset) {
3873
- return `${pintor.red('ERROR')} in ${pintor.yellow('manifest.json')} entrypoint: ${addingOrRemoving} ${pintor.yellow(typeOfAsset)} in ${pintor.underline(`${folder}/`)} requires a dev server restart to apply changes.`;
3842
+ return `${messaging_prefix('warn')} ${addingOrRemoving} ${pintor.yellow(typeOfAsset)} in ${pintor.underline(`${folder}/`)} changes the extension entrypoints.\nRestart the dev server to apply the change.`;
3874
3843
  }
3875
3844
  function specialFoldersSetupSummary(hasPublic, copyEnabled, ignoredCount) {
3876
- return `Special folders setup, public=${String(hasPublic)}, copy=${String(copyEnabled)}, ignored=${String(ignoredCount)}`;
3845
+ return `${messaging_prefix('debug')} folders setup public=${String(hasPublic)} copy=${String(copyEnabled)} ignored=${String(ignoredCount)}`;
3877
3846
  }
3878
3847
  function specialFolderChangeDetected(action, folder, relativePath) {
3879
- return `Special folders change, ${action} in ${folder}/: ${relativePath}`;
3848
+ return `${messaging_prefix('debug')} folders change=${action} scope=${folder} path=${relativePath}`;
3880
3849
  }
3881
3850
  class WarnUponFolderChanges {
3882
3851
  pendingChanges = [];
@@ -3949,7 +3918,7 @@ class WarnUponFolderChanges {
3949
3918
  compilation.errors?.push(err);
3950
3919
  }
3951
3920
  trackChange(projectPath, folder, change, filePath) {
3952
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFolderChangeDetected('add' === change ? 'add' : 'remove', folder, __rspack_external_node_path_c5b9b54f.relative(projectPath, filePath)));
3921
+ if (isDebug()) console.log(specialFolderChangeDetected('add' === change ? 'add' : 'remove', folder, __rspack_external_node_path_c5b9b54f.relative(projectPath, filePath)));
3953
3922
  this.pendingChanges.push({
3954
3923
  type: change,
3955
3924
  folder,
@@ -4047,7 +4016,7 @@ class SpecialFoldersPlugin {
4047
4016
  }
4048
4017
  ]
4049
4018
  }).apply(compiler);
4050
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFoldersSetupSummary(true, true, copyIgnore.length));
4019
+ if (isDebug()) console.log(specialFoldersSetupSummary(true, true, copyIgnore.length));
4051
4020
  }
4052
4021
  if ('development' === compiler.options.mode) {
4053
4022
  if (compiler.options.watchOptions) new WarnUponFolderChanges().apply(compiler);
@@ -4055,15 +4024,15 @@ class SpecialFoldersPlugin {
4055
4024
  }
4056
4025
  }
4057
4026
  function assetsRulesEnabled(rules) {
4058
- const list = rules.length > 0 ? rules.map((n)=>pintor.yellow(n)).join(', ') : pintor.gray('none');
4059
- return `${pintor.gray('⏵⏵⏵')} Assets: Rules enabled (${pintor.gray(String(rules.length))}) ${list}`;
4027
+ const kinds = rules.length > 0 ? rules.join(',').toLowerCase() : 'none';
4028
+ return `${messaging_prefix('debug')} assets rules=${rules.length} kinds=${kinds}`;
4060
4029
  }
4061
4030
  function assetsConfigsDetected(filenamePattern, svgRuleMode, svgInlineLimitKB, imageInlineLimitKB, fileInlineLimitKB) {
4062
- const fmt = (v)=>v || 0 === v ? pintor.underline(String(v)) : pintor.gray('n/a');
4063
- return `${pintor.gray('⏵⏵⏵')} Assets: Configs\n${pintor.gray('FILENAME_PATTERN')} ${pintor.underline(filenamePattern)}\n${pintor.gray('SVG_RULE')} ${pintor.yellow(svgRuleMode)}\n${pintor.gray('SVG_INLINE_LIMIT')} ${fmt(svgInlineLimitKB)}${svgInlineLimitKB ? pintor.gray('KB') : ''}\n${pintor.gray('IMAGE_INLINE_LIMIT')} ${fmt(imageInlineLimitKB)}${imageInlineLimitKB ? pintor.gray('KB') : ''}\n${pintor.gray('FILE_INLINE_LIMIT')} ${fmt(fileInlineLimitKB)}${fileInlineLimitKB ? pintor.gray('KB') : ''}`;
4031
+ const kb = (v)=>v || 0 === v ? `${v}KB` : 'none';
4032
+ return `${messaging_prefix('debug')} assets config pattern=${filenamePattern} svgRule=${svgRuleMode} svgInline=${kb(svgInlineLimitKB)} imageInline=${kb(imageInlineLimitKB)} fileInline=${kb(fileInlineLimitKB)}`;
4064
4033
  }
4065
4034
  function assetsEmittedSummary(total, byCategory) {
4066
- return `${pintor.gray('⏵⏵⏵')} Assets: Emitted ${pintor.gray(String(total))} file(s)\n${pintor.gray('SVG')} ${pintor.underline(String(byCategory.svg))}\n${pintor.gray('IMAGES')} ${pintor.underline(String(byCategory.images))}\n${pintor.gray('FONTS')} ${pintor.underline(String(byCategory.fonts))}\n${pintor.gray('FILES')} ${pintor.underline(String(byCategory.files))}`;
4035
+ return `${messaging_prefix('debug')} assets emitted=${total} svg=${byCategory.svg} images=${byCategory.images} fonts=${byCategory.fonts} files=${byCategory.files}`;
4067
4036
  }
4068
4037
  class StaticAssetsPlugin {
4069
4038
  static name = 'plugin-static-assets';
@@ -4153,7 +4122,7 @@ class StaticAssetsPlugin {
4153
4122
  ...compiler.options.module.rules,
4154
4123
  ...loaders
4155
4124
  ].filter((rule)=>Boolean(rule));
4156
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
4125
+ if (isDebug()) {
4157
4126
  const rulesEnabled = [];
4158
4127
  rulesEnabled.push(hasCustomSvgRule ? 'SVG(custom)' : 'SVG(default)');
4159
4128
  rulesEnabled.push('Images');
@@ -4247,7 +4216,10 @@ function javaScriptError(errorSourcePath, missingFilePath, opts) {
4247
4216
  lines.push(`Missing script file in ${pintor.underline(errorSourcePath)}.`);
4248
4217
  lines.push(`Update your ${pintor.yellow("<script>")} src to point to a file that exists.`);
4249
4218
  if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
4250
- if (opts?.deadRefHint) lines.push(`The build ships an empty placeholder for this script, so the page loads and no 404 appears in DevTools (likely dead code). Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
4219
+ if (opts?.deadRefHint) {
4220
+ lines.push("The build ships an empty placeholder for this script, so the page loads and no 404 appears in DevTools (likely dead code).");
4221
+ lines.push(`Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
4222
+ }
4251
4223
  lines.push('');
4252
4224
  lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
4253
4225
  return lines.join('\n');
@@ -4257,7 +4229,10 @@ function cssError(errorSourcePath, missingFilePath, opts) {
4257
4229
  lines.push(`Missing stylesheet in ${pintor.underline(errorSourcePath)}.`);
4258
4230
  lines.push(`Update your ${pintor.yellow('<link>')} href to point to a file that exists.`);
4259
4231
  if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
4260
- if (opts?.deadRefHint) lines.push(`Chrome loads the page anyway and 404s this reference silently, likely dead code. Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
4232
+ if (opts?.deadRefHint) {
4233
+ lines.push("Chrome loads the page anyway and 404s this reference silently, so it is likely dead code.");
4234
+ lines.push(`Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
4235
+ }
4261
4236
  lines.push('');
4262
4237
  lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
4263
4238
  return lines.join('\n');
@@ -4269,7 +4244,10 @@ function staticAssetError(errorSourcePath, missingFilePath, opts) {
4269
4244
  const ref = opts?.refLabel || `*${extname}`;
4270
4245
  lines.push(`Update the ${pintor.yellow(ref)} reference to point to a file that exists.`);
4271
4246
  if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
4272
- if (opts?.deadRefHint) lines.push(`Chrome loads the page anyway and 404s this reference silently, likely dead code. Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
4247
+ if (opts?.deadRefHint) {
4248
+ lines.push("Chrome loads the page anyway and 404s this reference silently, so it is likely dead code.");
4249
+ lines.push(`Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
4250
+ }
4273
4251
  lines.push('');
4274
4252
  lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
4275
4253
  return lines.join('\n');
@@ -4293,16 +4271,18 @@ function fileNotFound(errorSourcePath, missingFilePath, opts) {
4293
4271
  }
4294
4272
  function remoteResourceWarning(errorSourcePath, remoteUrl, kind) {
4295
4273
  const label = "script" === kind ? "<script>" : '<link>';
4296
- const cspHint = "script" === kind ? "Remote scripts are blocked by MV3 CSP; bundle or self-host instead." : 'Remote styles may be blocked; prefer bundling or self-hosting.';
4274
+ const cspHint = "script" === kind ? "Remote scripts are blocked by the MV3 CSP.\nBundle the script or self-host it instead." : 'Remote styles can be blocked by the CSP.\nBundle the stylesheet or self-host it instead.';
4297
4275
  const lines = [];
4298
- lines.push(`Remote ${pintor.yellow(label)} in ${pintor.underline(errorSourcePath)}. ${cspHint}`);
4276
+ lines.push(`Remote ${pintor.yellow(label)} in ${pintor.underline(errorSourcePath)}.`);
4277
+ lines.push(cspHint);
4299
4278
  lines.push('');
4300
4279
  lines.push(`${pintor.red('URL')} ${pintor.underline(remoteUrl)}`);
4301
4280
  return lines.join('\n');
4302
4281
  }
4303
4282
  function serverRestartRequiredFromHtml(relativeHtmlPath, absoluteHtmlPath) {
4304
4283
  const lines = [];
4305
- lines.push(`Entrypoint references changed. Restart the dev server to pick up changes to ${pintor.yellow("<script>")} and ${pintor.yellow('<link rel="stylesheet">')} entries.`);
4284
+ lines.push("Entrypoint references changed.");
4285
+ lines.push(`Restart the dev server to pick up changes to ${pintor.yellow("<script>")} and ${pintor.yellow('<link rel="stylesheet">')} entries.`);
4306
4286
  lines.push('');
4307
4287
  lines.push(`${pintor.gray('PATH')} ${pintor.underline(absoluteHtmlPath)}`);
4308
4288
  return lines.join('\n');
@@ -4310,7 +4290,8 @@ function serverRestartRequiredFromHtml(relativeHtmlPath, absoluteHtmlPath) {
4310
4290
  function manifestHtmlEntrypointChange(manifestField, pathAfter, pathBefore) {
4311
4291
  const lines = [];
4312
4292
  const fieldLabel = manifestField ? manifestField.replace(/\//g, '.') : void 0;
4313
- lines.push(`Entrypoint references changed${fieldLabel ? ` in ${pintor.yellow(fieldLabel)}` : ''}. Restart the dev server to pick up changes to manifest entrypoints.`);
4293
+ lines.push(`Entrypoint references changed${fieldLabel ? ` in ${pintor.yellow(fieldLabel)}` : ''}.`);
4294
+ lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
4314
4295
  lines.push('');
4315
4296
  if (pathBefore) lines.push(`${pintor.red('PATH BEFORE')} ${pintor.underline(pathBefore)}`);
4316
4297
  if (pathAfter) lines.push(`${pintor.green('PATH AFTER')} ${pintor.underline(pathAfter)}`);
@@ -5290,7 +5271,7 @@ function iconsMissingFile(manifestField, filePath, opts) {
5290
5271
  const lines = [];
5291
5272
  lines.push(`Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`);
5292
5273
  lines.push("The icon path must point to an existing file that will be packaged with the extension.");
5293
- lines.push(opts?.fatal ? "Browsers reject the whole extension when this file is missing. We fail the build early to protect you." : "Browsers can reject or misrender the extension when this file is missing. The build continues.");
5274
+ lines.push(opts?.fatal ? `Browsers reject the whole extension when this file is missing.\nThe build stops here to protect you.` : `Browsers can reject or misrender the extension when this file is missing.\nThe build continues.`);
5294
5275
  if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
5295
5276
  lines.push('');
5296
5277
  lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(filePath)}`);
@@ -5299,7 +5280,8 @@ function iconsMissingFile(manifestField, filePath, opts) {
5299
5280
  function themeImageIsEmpty(manifestField, filePath) {
5300
5281
  const lines = [];
5301
5282
  lines.push(`Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`);
5302
- lines.push("The theme image is empty (0 bytes). Chrome loads the extension but drops the entire theme, so no colors or images apply.");
5283
+ lines.push("The theme image is empty (0 bytes).");
5284
+ lines.push("Chrome loads the extension but drops the entire theme, so no colors or images apply.");
5303
5285
  lines.push('');
5304
5286
  lines.push(`${pintor.red('EMPTY FILE')} ${pintor.underline(filePath)}`);
5305
5287
  return lines.join('\n');
@@ -5307,20 +5289,21 @@ function themeImageIsEmpty(manifestField, filePath) {
5307
5289
  function manifestIconsEntrypointChange(manifestField, pathAfter, pathBefore) {
5308
5290
  const lines = [];
5309
5291
  const fieldLabel = manifestField ? manifestField.replace(/\//g, '.') : 'icons';
5310
- lines.push(`Entrypoint references changed in ${pintor.yellow(fieldLabel)}. Restart the dev server to pick up changes to manifest icons.`);
5292
+ lines.push(`Entrypoint references changed in ${pintor.yellow(fieldLabel)}.`);
5293
+ lines.push("Restart the dev server to pick up changes to manifest icons.");
5311
5294
  lines.push('');
5312
5295
  if (pathBefore) lines.push(`${pintor.red('PATH BEFORE')} ${pintor.underline(pathBefore)}`);
5313
5296
  if (pathAfter) lines.push(`${pintor.green('PATH AFTER')} ${pintor.underline(pathAfter)}`);
5314
5297
  return lines.join('\n');
5315
5298
  }
5316
5299
  function iconsEmitSummary(feature, stats) {
5317
- return `Icons ${pintor.yellow(feature)}, entries ${pintor.gray(String(stats.entries))}, public ${pintor.gray(String(stats.underPublic))}, emitted ${pintor.gray(String(stats.emitted))}, missing ${pintor.gray(String(stats.missing))}`;
5300
+ return `${messaging_prefix('debug')} icons emit feature=${feature} entries=${stats.entries} public=${stats.underPublic} emitted=${stats.emitted} missing=${stats.missing}`;
5318
5301
  }
5319
5302
  function iconsDepsTracked(addedCount) {
5320
- return `Icons file dependencies tracked: ${pintor.gray(String(addedCount))}`;
5303
+ return `${messaging_prefix('debug')} icons deps=${String(addedCount)}`;
5321
5304
  }
5322
5305
  function iconsNormalizationSummary(beforeKeys, afterKeys, changedCount) {
5323
- return `Icons include normalization, keys ${pintor.gray(String(beforeKeys.length))} → ${pintor.gray(String(afterKeys.length))}, normalized ${pintor.gray(String(changedCount))}`;
5306
+ return `${messaging_prefix('debug')} icons normalize keysBefore=${beforeKeys.length} keysAfter=${afterKeys.length} changed=${changedCount}`;
5324
5307
  }
5325
5308
  function iconValuesToStrings(response) {
5326
5309
  if (!response) return [];
@@ -5370,7 +5353,7 @@ class add_to_file_dependencies_AddToFileDependencies {
5370
5353
  added++;
5371
5354
  }
5372
5355
  }
5373
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(iconsDepsTracked(added));
5356
+ if (isDebug()) console.log(iconsDepsTracked(added));
5374
5357
  });
5375
5358
  });
5376
5359
  }
@@ -5486,7 +5469,7 @@ class EmitFile {
5486
5469
  compilation.emitAsset(filename, rawSource);
5487
5470
  emittedCount++;
5488
5471
  }
5489
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(iconsEmitSummary(feature, {
5472
+ if (isDebug()) console.log(iconsEmitSummary(feature, {
5490
5473
  entries: entriesTotal,
5491
5474
  underPublic: underPublicCount,
5492
5475
  emitted: emittedCount,
@@ -5506,7 +5489,7 @@ class IconsPlugin {
5506
5489
  }
5507
5490
  apply(compiler) {
5508
5491
  const normalizedIncludeList = normalizeIconIncludeKeys(this.includeList);
5509
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
5492
+ if (isDebug()) {
5510
5493
  const beforeKeys = Object.keys(this.includeList || {});
5511
5494
  const afterKeys = Object.keys(normalizedIncludeList || {});
5512
5495
  const changedCount = afterKeys.filter((k)=>k.includes('/default_icon') || k.includes('/theme_icons')).length;
@@ -5526,7 +5509,7 @@ function jsonMissingFile(manifestField, filePath, opts) {
5526
5509
  const lines = [];
5527
5510
  lines.push(`Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`);
5528
5511
  lines.push("The JSON path must point to an existing file that will be packaged with the extension.");
5529
- lines.push(opts?.fatal ? "Browsers can reject or crash the extension when required JSON files (like rulesets or managed schemas) are missing. We fail the build early to protect you." : "Browsers can reject or misread the extension when this file is missing. The build continues.");
5512
+ lines.push(opts?.fatal ? `Browsers can reject or crash the extension when required JSON files (like rulesets or managed schemas) are missing.\nThe build stops here to protect you.` : `Browsers can reject or misread the extension when this file is missing.\nThe build continues.`);
5530
5513
  if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
5531
5514
  lines.push('');
5532
5515
  lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(filePath)}`);
@@ -5534,7 +5517,7 @@ function jsonMissingFile(manifestField, filePath, opts) {
5534
5517
  }
5535
5518
  function invalidJsonSyntax(manifestField, file, cause) {
5536
5519
  return [
5537
- "Invalid JSON",
5520
+ "Invalid JSON.",
5538
5521
  "",
5539
5522
  `Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`,
5540
5523
  `The JSON at ${pintor.underline(file)} could not be parsed:`,
@@ -5543,7 +5526,7 @@ function invalidJsonSyntax(manifestField, file, cause) {
5543
5526
  }
5544
5527
  function invalidRulesetStructure(manifestField, file) {
5545
5528
  return [
5546
- "Invalid Declarative Net Request ruleset",
5529
+ "Invalid Declarative Net Request ruleset.",
5547
5530
  "",
5548
5531
  `Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`,
5549
5532
  "Chrome expects a top-level JSON array of rule objects.",
@@ -5552,7 +5535,7 @@ function invalidRulesetStructure(manifestField, file) {
5552
5535
  }
5553
5536
  function invalidManagedSchemaStructure(manifestField, file) {
5554
5537
  return [
5555
- "Invalid managed storage schema",
5538
+ "Invalid managed storage schema.",
5556
5539
  "",
5557
5540
  `Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`,
5558
5541
  "Expected a top-level JSON object describing the schema.",
@@ -5560,13 +5543,13 @@ function invalidManagedSchemaStructure(manifestField, file) {
5560
5543
  ].join('\n');
5561
5544
  }
5562
5545
  function jsonEmitSummary(feature, stats) {
5563
- return `JSON ${pintor.yellow(feature)}, entries ${pintor.gray(String(stats.entries))}, public ${pintor.gray(String(stats.underPublic))}, emitted ${pintor.gray(String(stats.emitted))}, missing ${pintor.gray(String(stats.missing))}, valid ${pintor.gray(String(stats.validatedOk))}, invalid ${pintor.gray(String(stats.invalid))}`;
5546
+ return `${messaging_prefix('debug')} json emit feature=${feature} entries=${stats.entries} public=${stats.underPublic} emitted=${stats.emitted} missing=${stats.missing} valid=${stats.validatedOk} invalid=${stats.invalid}`;
5564
5547
  }
5565
5548
  function jsonDepsTracked(addedCount) {
5566
- return `JSON file dependencies tracked: ${pintor.gray(String(addedCount))}`;
5549
+ return `${messaging_prefix('debug')} json deps=${String(addedCount)}`;
5567
5550
  }
5568
5551
  function jsonIncludeSummary(totalFeatures, criticalCount) {
5569
- return `JSON include summary, features ${pintor.gray(String(totalFeatures))}, critical ${pintor.gray(String(criticalCount))}`;
5552
+ return `${messaging_prefix('debug')} json include features=${String(totalFeatures)} critical=${String(criticalCount)}`;
5570
5553
  }
5571
5554
  function isCriticalJsonFeature(feature) {
5572
5555
  return feature.startsWith('declarative_net_request') || 'storage.managed_schema' === feature;
@@ -5610,7 +5593,7 @@ function processJsonAssets(compilation, manifestPath, includeList) {
5610
5593
  const manifestDir = __rspack_external_node_path_c5b9b54f.dirname(manifestPath);
5611
5594
  const projectPath = getProjectPathFromCompilation(compilation, manifestPath);
5612
5595
  const publicDir = __rspack_external_node_path_c5b9b54f.join(projectPath, 'public');
5613
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
5596
+ if (isDebug()) {
5614
5597
  const featureKeys = Object.keys(jsonFields || {});
5615
5598
  const criticalCount = featureKeys.filter((key)=>isCriticalJsonFeature(key)).length;
5616
5599
  console.log(jsonIncludeSummary(featureKeys.length, criticalCount));
@@ -5672,7 +5655,7 @@ function processJsonAssets(compilation, manifestPath, includeList) {
5672
5655
  else compilation.emitAsset(assetName, rawSource);
5673
5656
  emittedCount++;
5674
5657
  }
5675
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
5658
+ if (isDebug()) {
5676
5659
  const entries = Array.isArray(resource) ? resource.length : resource ? 1 : 0;
5677
5660
  console.log(jsonEmitSummary(feature, {
5678
5661
  entries,
@@ -5703,7 +5686,7 @@ function trackJsonDependencies(compilation, manifestPath, includeList) {
5703
5686
  }
5704
5687
  }
5705
5688
  }
5706
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(jsonDepsTracked(added));
5689
+ if (isDebug()) console.log(jsonDepsTracked(added));
5707
5690
  }
5708
5691
  class JsonPlugin {
5709
5692
  manifestPath;
@@ -5735,42 +5718,42 @@ function messages_entryNotFoundMessageOnly(manifestField, absPath) {
5735
5718
  return guidance + suffix;
5736
5719
  }
5737
5720
  function defaultLocaleSpecifiedButLocalesMissing() {
5738
- return 'default_locale is set, but the _locales folder is missing. Add _locales/<default>/messages.json.';
5721
+ return "default_locale is set, but the _locales folder is missing.\nAdd _locales/<default>/messages.json.";
5739
5722
  }
5740
5723
  function defaultLocaleFolderMissing(defaultLocale) {
5741
- return `Default locale folder is missing: _locales/${defaultLocale}. Create it and add messages.json.`;
5724
+ return `Default locale folder is missing: _locales/${defaultLocale}.\nCreate it and add messages.json.`;
5742
5725
  }
5743
5726
  function defaultLocaleMessagesMissing(defaultLocale) {
5744
- return `Default locale messages.json is missing: _locales/${defaultLocale}/messages.json. Create the file with your strings.`;
5727
+ return `Default locale messages.json is missing: _locales/${defaultLocale}/messages.json.\nCreate the file with your strings.`;
5745
5728
  }
5746
5729
  function localesPresentButNoDefaultLocale() {
5747
- return 'The _locales folder exists, but manifest.json is missing default_locale. Add default_locale to manifest.json.';
5730
+ return "The _locales folder exists, but manifest.json is missing default_locale.\nAdd default_locale to manifest.json.";
5748
5731
  }
5749
5732
  function invalidMessagesJson(absPath) {
5750
- return `Invalid JSON in locale messages file: ${absPath}. Fix the JSON syntax and try again.`;
5733
+ return `Invalid JSON in locale messages file: ${absPath}.\nFix the JSON syntax and try again.`;
5751
5734
  }
5752
5735
  function missingManifestMessageKey(key, defaultLocale) {
5753
5736
  const header = 'Check the i18n placeholders in your manifest.json file.';
5754
5737
  const localePath = defaultLocale ? `_locales/${defaultLocale}/messages.json` : '_locales/<default>/messages.json';
5755
- const guidance = `The key "${key}" referenced via __MSG_${key}__ must be defined in ${localePath}. Add the key to that file.`;
5738
+ const guidance = `The key "${key}" referenced via __MSG_${key}__ must be defined in ${localePath}.\nAdd the key to that file.`;
5756
5739
  const final = `MISSING KEY ${key} in ${localePath}`;
5757
5740
  return `${header}\n${guidance}\n\n${final}`;
5758
5741
  }
5759
5742
  function localesIncludeSummary(hasManifest, hasLocalesRoot, defaultLocale) {
5760
- const dl = defaultLocale ? `default_locale=${defaultLocale}` : 'default_locale=<none>';
5761
- return `Locales include summary, manifest=${String(hasManifest)}, localesRoot=${String(hasLocalesRoot)}, ${dl}`;
5743
+ const dl = defaultLocale || 'none';
5744
+ return `${messaging_prefix('debug')} locales include manifest=${String(hasManifest)} root=${String(hasLocalesRoot)} default_locale=${dl}`;
5762
5745
  }
5763
5746
  function localesEmitSummary(emitted, missing, discovered) {
5764
- return `Locales emitted=${String(emitted)}, missing=${String(missing)}, discovered=${String(discovered)}`;
5747
+ return `${messaging_prefix('debug')} locales emitted=${String(emitted)} missing=${String(missing)} discovered=${String(discovered)}`;
5765
5748
  }
5766
5749
  function localesDepsTracked(addedCount) {
5767
- return `Locales file dependencies tracked: ${String(addedCount)}`;
5750
+ return `${messaging_prefix('debug')} locales deps=${String(addedCount)}`;
5768
5751
  }
5769
5752
  function localesValidationDetected(issue) {
5770
- return `Locales validation detected: ${issue}`;
5753
+ return `${messaging_prefix('debug')} locales validation="${issue}"`;
5771
5754
  }
5772
5755
  function localesMustBeAtProjectRoot(foundAt, expectedAt) {
5773
- return `_locales/ is canonically placed at the project root (sibling of package.json, public/, dist/), mirroring public/ and how Chrome reads locales from the extension root in dist. Found in the legacy next-to-manifest location; the build will use it, but consider moving it for consistency with public/ and to silence this warning.\n\n found: ${foundAt}\n preferred: ${expectedAt}`;
5756
+ return `_locales/ is canonically placed at the project root, next to package.json, public/ and dist/, because Chrome reads locales from the extension root.\nThis one sits in the legacy next-to-manifest location.\nMove it to the project root to silence this warning.\nThe build uses it either way.\n\n found: ${foundAt}\n preferred: ${expectedAt}`;
5774
5757
  }
5775
5758
  function isUsableDir(p) {
5776
5759
  try {
@@ -5838,7 +5821,7 @@ function processLocaleAssets(compiler, compilation, manifestPath) {
5838
5821
  emittedCount++;
5839
5822
  }
5840
5823
  }
5841
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesEmitSummary(emittedCount, missingCount, discoveredList.length));
5824
+ if (isDebug()) console.log(localesEmitSummary(emittedCount, missingCount, discoveredList.length));
5842
5825
  }
5843
5826
  function trackLocaleDependencies(compilation, manifestPath, projectRoot) {
5844
5827
  if (compilation.errors?.length) return;
@@ -5850,7 +5833,7 @@ function trackLocaleDependencies(compilation, manifestPath, projectRoot) {
5850
5833
  added++;
5851
5834
  }
5852
5835
  }
5853
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesDepsTracked(added));
5836
+ if (isDebug()) console.log(localesDepsTracked(added));
5854
5837
  }
5855
5838
  function pushCompilationError(compiler, compilation, name, message, file) {
5856
5839
  const ErrorConstructor = compiler?.rspack?.WebpackError || Error;
@@ -5881,22 +5864,22 @@ function validateLocales(compiler, compilation, manifestPath) {
5881
5864
  compilation.warnings.push(warning);
5882
5865
  }
5883
5866
  }
5884
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesIncludeSummary(true, hasLocalesRoot, 'string' == typeof defaultLocale ? defaultLocale : void 0));
5867
+ if (isDebug()) console.log(localesIncludeSummary(true, hasLocalesRoot, 'string' == typeof defaultLocale ? defaultLocale : void 0));
5885
5868
  if ('string' == typeof defaultLocale && defaultLocale.trim()) {
5886
5869
  if (!hasLocalesRoot) {
5887
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected('default_locale set but _locales missing'));
5870
+ if (isDebug()) console.log(localesValidationDetected('default_locale set but _locales missing'));
5888
5871
  pushCompilationError(compiler, compilation, 'LocalesValidationError', defaultLocaleSpecifiedButLocalesMissing(), 'manifest.json');
5889
5872
  return false;
5890
5873
  }
5891
5874
  const defaultLocaleDir = __rspack_external_node_path_c5b9b54f.join(localesRoot, defaultLocale);
5892
5875
  if (!__rspack_external_node_fs_5ea92f0c.existsSync(defaultLocaleDir)) {
5893
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`missing _locales/${defaultLocale}`));
5876
+ if (isDebug()) console.log(localesValidationDetected(`missing _locales/${defaultLocale}`));
5894
5877
  pushCompilationError(compiler, compilation, 'LocalesValidationError', defaultLocaleFolderMissing(defaultLocale), 'manifest.json');
5895
5878
  return false;
5896
5879
  }
5897
5880
  const messagesJsonPath = __rspack_external_node_path_c5b9b54f.join(defaultLocaleDir, 'messages.json');
5898
5881
  if (!__rspack_external_node_fs_5ea92f0c.existsSync(messagesJsonPath)) {
5899
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`missing _locales/${defaultLocale}/messages.json`));
5882
+ if (isDebug()) console.log(localesValidationDetected(`missing _locales/${defaultLocale}/messages.json`));
5900
5883
  pushCompilationError(compiler, compilation, 'LocalesValidationError', defaultLocaleMessagesMissing(defaultLocale), 'manifest.json');
5901
5884
  return false;
5902
5885
  }
@@ -5905,7 +5888,7 @@ function validateLocales(compiler, compilation, manifestPath) {
5905
5888
  const content = __rspack_external_node_fs_5ea92f0c.readFileSync(messagesJsonPath, 'utf8');
5906
5889
  defaultLocaleMessages = JSON.parse(stripBom(content));
5907
5890
  } catch {
5908
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`invalid JSON in _locales/${defaultLocale}/messages.json`));
5891
+ if (isDebug()) console.log(localesValidationDetected(`invalid JSON in _locales/${defaultLocale}/messages.json`));
5909
5892
  pushCompilationError(compiler, compilation, 'LocalesValidationError', invalidMessagesJson(messagesJsonPath), 'manifest.json');
5910
5893
  return false;
5911
5894
  }
@@ -5927,21 +5910,21 @@ function validateLocales(compiler, compilation, manifestPath) {
5927
5910
  for (const key of referenced){
5928
5911
  const entry = dict?.[key];
5929
5912
  if (!entry || 'string' != typeof entry.message) {
5930
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`missing key "${key}" in default locale`));
5913
+ if (isDebug()) console.log(localesValidationDetected(`missing key "${key}" in default locale`));
5931
5914
  pushCompilationError(compiler, compilation, 'LocalesValidationError', missingManifestMessageKey(key, defaultLocale), 'manifest.json');
5932
5915
  return false;
5933
5916
  }
5934
5917
  }
5935
5918
  } catch (error) {
5936
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`could not scan __MSG__ placeholders in _locales/${defaultLocale}/messages.json: ${String(error?.message || error)}`));
5919
+ if (isDebug()) console.log(localesValidationDetected(`could not scan __MSG__ placeholders in _locales/${defaultLocale}/messages.json: ${String(error?.message || error)}`));
5937
5920
  }
5938
5921
  } else if (hasLocalesRoot) {
5939
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected('_locales present but no default_locale'));
5922
+ if (isDebug()) console.log(localesValidationDetected('_locales present but no default_locale'));
5940
5923
  pushCompilationError(compiler, compilation, 'LocalesValidationError', localesPresentButNoDefaultLocale(), 'manifest.json');
5941
5924
  return false;
5942
5925
  }
5943
5926
  } catch (error) {
5944
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`manifest.json could not be read for locale validation, deferring to manifest validation: ${String(error?.message || error)}`));
5927
+ if (isDebug()) console.log(localesValidationDetected(`manifest.json could not be read for locale validation, deferring to manifest validation: ${String(error?.message || error)}`));
5945
5928
  }
5946
5929
  try {
5947
5930
  const localesRoot = resolveLocalesFolder(manifestPath, projectRoot);
@@ -5953,14 +5936,14 @@ function validateLocales(compiler, compilation, manifestPath) {
5953
5936
  const s = __rspack_external_node_fs_5ea92f0c.readFileSync(msgPath, 'utf8');
5954
5937
  JSON.parse(stripBom(s));
5955
5938
  } catch {
5956
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`invalid JSON in ${msgPath}`));
5939
+ if (isDebug()) console.log(localesValidationDetected(`invalid JSON in ${msgPath}`));
5957
5940
  pushCompilationError(compiler, compilation, 'LocalesValidationError', invalidMessagesJson(msgPath), 'manifest.json');
5958
5941
  return false;
5959
5942
  }
5960
5943
  }
5961
5944
  }
5962
5945
  } catch (error) {
5963
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`could not scan _locales for JSON validity: ${String(error?.message || error)}`));
5946
+ if (isDebug()) console.log(localesValidationDetected(`could not scan _locales for JSON validity: ${String(error?.message || error)}`));
5964
5947
  }
5965
5948
  return true;
5966
5949
  }
@@ -5999,7 +5982,8 @@ class LocalesPlugin {
5999
5982
  }
6000
5983
  function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
6001
5984
  const lines = [];
6002
- lines.push("Entrypoint references changed. Restart the dev server to pick up changes to manifest entrypoints.");
5985
+ lines.push("Entrypoint references changed.");
5986
+ lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
6003
5987
  lines.push('');
6004
5988
  if (fileRemoved) lines.push(`${pintor.red('PATH BEFORE')} ${pintor.underline(fileRemoved)}`);
6005
5989
  if (fileAdded) lines.push(`${pintor.green('PATH AFTER')} ${pintor.underline(fileAdded)}`);
@@ -6007,46 +5991,50 @@ function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
6007
5991
  }
6008
5992
  function legacyManifestPathWarning(legacyPath) {
6009
5993
  const lines = [];
6010
- lines.push("⚠ Deprecated manifest path detected. This will be rewritten to standardized folders in the next major.");
5994
+ lines.push(`${messaging_prefix('warn')} Deprecated manifest path detected.`);
5995
+ lines.push("Extension.js rewrites it to the standardized folders in the next major.");
6011
5996
  lines.push('');
6012
5997
  lines.push(`${pintor.brightBlue('PATH')} ${pintor.underline(legacyPath)}`);
6013
5998
  return lines.join('\n');
6014
5999
  }
6015
6000
  function fatalManifestShapeFixed(field, detail) {
6016
6001
  const lines = [];
6017
- lines.push("⚠ Repaired a manifest field Chrome refuses to load the extension over. Fix it in your manifest.json.");
6002
+ lines.push(`${messaging_prefix('warn')} Repaired a manifest field Chrome refuses to load the extension over.`);
6003
+ lines.push("Fix it in your manifest.json.");
6018
6004
  lines.push('');
6019
6005
  lines.push(`${pintor.brightBlue('FIELD')} ${pintor.underline(field)}, ${detail}`);
6020
6006
  return lines.join('\n');
6021
6007
  }
6022
6008
  function missingGeckoDataCollectionPermissions() {
6023
6009
  const lines = [];
6024
- lines.push(`⚠ addons.mozilla.org requires ${pintor.yellow('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons. Declare {"required": ["none"]} if this extension transmits no data.`);
6010
+ lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.yellow('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
6011
+ lines.push('Declare {"required": ["none"]} if this extension transmits no data.');
6025
6012
  lines.push('');
6026
6013
  lines.push(`${pintor.brightBlue('DOCS')} ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')}`);
6027
6014
  return lines.join('\n');
6028
6015
  }
6029
6016
  function manifestInvalidError(error) {
6030
6017
  const lines = [];
6031
- lines.push(`Invalid ${pintor.yellow('manifest.json')}. Update your manifest and try again.`);
6018
+ lines.push(`Invalid ${pintor.yellow('manifest.json')}.`);
6019
+ lines.push("Update your manifest and try again.");
6032
6020
  lines.push('');
6033
- lines.push(`${pintor.red('ERROR')} ${pintor.red(String(error))}`);
6021
+ lines.push(`${pintor.red('REASON')} ${pintor.red(String(error))}`);
6034
6022
  return lines.join('\n');
6035
6023
  }
6036
6024
  function manifestIncludeSummary(browser, manifestPath) {
6037
- return `Manifest include summary, browser=${pintor.yellow(browser)}, path=${pintor.underline(manifestPath)}`;
6025
+ return `${messaging_prefix('debug')} manifest include browser=${browser} path=${manifestPath}`;
6038
6026
  }
6039
6027
  function manifestEmitSuccess() {
6040
- return "Manifest emitted to assets (schema stripped).";
6028
+ return `${messaging_prefix('debug')} manifest emitted=true schemaStripped=true`;
6041
6029
  }
6042
6030
  function manifestOverridesSummary(overrideKeys, devCssStubsAdded) {
6043
- return `Manifest overrides, keys=${pintor.gray(String(overrideKeys))}, devCssStubsAdded=${pintor.gray(String(devCssStubsAdded))}`;
6031
+ return `${messaging_prefix('debug')} manifest overrides keys=${String(overrideKeys)} devCssStubs=${String(devCssStubsAdded)}`;
6044
6032
  }
6045
6033
  function manifestDepsTracked(addedCount) {
6046
- return `Manifest file dependencies tracked: ${pintor.gray(String(addedCount))}`;
6034
+ return `${messaging_prefix('debug')} manifest deps=${String(addedCount)}`;
6047
6035
  }
6048
6036
  function manifestLegacyWarningsSummary(count) {
6049
- return `Manifest legacy warnings, count=${pintor.gray(String(count))}`;
6037
+ return `${messaging_prefix('debug')} manifest legacyWarnings=${String(count)}`;
6050
6038
  }
6051
6039
  class AddDependencies {
6052
6040
  dependencyList;
@@ -6060,7 +6048,7 @@ class AddDependencies {
6060
6048
  const alreadyPresent = 'function' == typeof deps?.has ? deps.has(dependency) : false;
6061
6049
  if (!alreadyPresent && 'function' == typeof deps?.add) deps.add(dependency);
6062
6050
  });
6063
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
6051
+ if (isDebug()) {
6064
6052
  const added = Array.isArray(this.dependencyList) ? this.dependencyList.length : 0;
6065
6053
  console.log(manifestDepsTracked(added));
6066
6054
  }
@@ -6076,7 +6064,7 @@ function patchBackground(manifest, browser) {
6076
6064
  const bg = manifest.background;
6077
6065
  const hasRunnableEntry = Boolean(bg && (bg.service_worker || Array.isArray(bg.scripts) && bg.scripts.length > 0 || bg.page));
6078
6066
  if (!hasRunnableEntry) {
6079
- if (constants_isGeckoBasedBrowser(String(browser))) return {
6067
+ if (isGeckoBasedBrowser(String(browser))) return {
6080
6068
  background: {
6081
6069
  ...manifest.background || {},
6082
6070
  scripts: [
@@ -6447,7 +6435,7 @@ class EmitManifest {
6447
6435
  setOriginalManifestContent(compilation, jsonString);
6448
6436
  setCurrentManifestContent(compilation, jsonString);
6449
6437
  compilation.emitAsset('manifest.json', new core_sources.RawSource(jsonString));
6450
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(manifestEmitSuccess());
6438
+ if (isDebug()) console.log(manifestEmitSuccess());
6451
6439
  });
6452
6440
  });
6453
6441
  }
@@ -6483,7 +6471,7 @@ class ManifestLegacyWarnings {
6483
6471
  count++;
6484
6472
  }
6485
6473
  });
6486
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(manifestLegacyWarningsSummary(count));
6474
+ if (isDebug()) console.log(manifestLegacyWarningsSummary(count));
6487
6475
  });
6488
6476
  });
6489
6477
  }
@@ -6503,21 +6491,23 @@ function cleanMatches(matches) {
6503
6491
  function warFieldError(filePath, opts) {
6504
6492
  const displayPath = opts?.overrideNotFoundPath || filePath;
6505
6493
  const lines = [];
6506
- if (opts?.relativeRef) lines.push(`The file ${pintor.yellow(opts.relativeRef)} defined in ${pintor.yellow('web_accessible_resources')} was not found`);
6507
- else lines.push(`${pintor.yellow('web_accessible_resources')}: file not found`);
6508
- lines.push(`Only list assets your pages fetch with ${pintor.yellow('chrome.runtime.getURL()')}. Imports from content scripts are bundled automatically and do not need to be listed here.`);
6494
+ if (opts?.relativeRef) lines.push(`The file ${pintor.yellow(opts.relativeRef)} defined in ${pintor.yellow('web_accessible_resources')} was not found.`);
6495
+ else lines.push(`A file listed in ${pintor.yellow('web_accessible_resources')} was not found.`);
6496
+ lines.push(`Only list assets your pages fetch with ${pintor.yellow('chrome.runtime.getURL()')}.`);
6497
+ lines.push("Imports from content scripts are bundled automatically and do not need to be listed here.");
6509
6498
  if (opts?.publicRootHint) {
6510
- lines.push(`To reference files in ${pintor.yellow('public/')}, use a leading '/' (e.g. ${pintor.yellow('/open-panel.gif')}). These resolve from the built extension root.`);
6499
+ lines.push(`To reference files in ${pintor.yellow('public/')}, use a leading '/' (e.g. ${pintor.yellow('/open-panel.gif')}).`);
6500
+ lines.push("These resolve from the built extension root.");
6511
6501
  lines.push('');
6512
- lines.push(`Fix: Add the file to ${pintor.yellow('public/')} or update the path to the correct '/...' location.`);
6502
+ lines.push(`Add the file to ${pintor.yellow('public/')}, or update the path to a root-absolute location.`);
6513
6503
  } else if (opts?.sourceSibling) {
6514
6504
  lines.push(`Found ${pintor.yellow(opts.sourceSibling)}, but web_accessible_resources entries are copied as-is, not compiled.`);
6515
6505
  lines.push('');
6516
- lines.push(`Fix: Import the file from a script so it gets bundled, or move a prebuilt copy to ${pintor.yellow('public/')} and reference it with a leading '/'.`);
6506
+ lines.push(`Import the file from a script so it gets bundled, or move a prebuilt copy to ${pintor.yellow('public/')} and reference it with a leading '/'.`);
6517
6507
  } else {
6518
6508
  lines.push("Relative paths must point to a real source file so the build can emit it.");
6519
6509
  lines.push('');
6520
- lines.push("Fix: Create the missing file or update the path to an existing source file.");
6510
+ lines.push("Create the missing file, or update the path to an existing source file.");
6521
6511
  }
6522
6512
  lines.push(`Learn more: ${pintor.underline('https://extension.js.org/docs/development/web-accessible-resources')}`);
6523
6513
  lines.push('');
@@ -6527,9 +6517,10 @@ function warFieldError(filePath, opts) {
6527
6517
  function warStringEntryInMv3(entry) {
6528
6518
  const lines = [];
6529
6519
  lines.push(`Check the ${pintor.yellow('web_accessible_resources')} field in your ${pintor.yellow('manifest.json')} file.`);
6530
- lines.push(`Manifest V3 requires object entries with ${pintor.yellow('resources')} and ${pintor.yellow('matches')} (or ${pintor.yellow('extension_ids')}). Plain string entries are the Manifest V2 format and Chrome rejects them at load time.`);
6520
+ lines.push(`Manifest V3 requires object entries with ${pintor.yellow('resources')} and ${pintor.yellow('matches')} (or ${pintor.yellow('extension_ids')}).`);
6521
+ lines.push("Plain string entries are the Manifest V2 format and Chrome rejects them at load time.");
6531
6522
  lines.push('');
6532
- lines.push(`Fix: Wrap it like ${pintor.yellow(`{"resources": ["${entry}"], "matches": ["<all_urls>"]}`)} with the matches your pages need.`);
6523
+ lines.push(`Wrap it like ${pintor.yellow(`{"resources": ["${entry}"], "matches": ["<all_urls>"]}`)} with the matches your pages need.`);
6533
6524
  lines.push('');
6534
6525
  lines.push(`${pintor.red('INVALID MV3 ENTRY')} ${pintor.underline(entry)}`);
6535
6526
  return lines.join('\n');
@@ -6537,16 +6528,17 @@ function warStringEntryInMv3(entry) {
6537
6528
  function warInvalidMatchPattern(pattern) {
6538
6529
  const lines = [];
6539
6530
  lines.push(`Check the ${pintor.yellow('web_accessible_resources')} field in your ${pintor.yellow('manifest.json')} file.`);
6540
- lines.push(`Chrome requires match patterns to end with ${pintor.yellow('/*')} and not include deeper paths. See ${pintor.underline('https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources#manifest_declaration')}`);
6531
+ lines.push(`Chrome requires match patterns to end with ${pintor.yellow('/*')} and not include deeper paths.`);
6532
+ lines.push(`See ${pintor.underline('https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources#manifest_declaration')}`);
6541
6533
  lines.push('');
6542
6534
  lines.push(`${pintor.red('INVALID MATCH PATTERN')} ${pintor.underline(pattern)}`);
6543
6535
  return lines.join('\n');
6544
6536
  }
6545
6537
  function entryImportsSummary(entryCount, totalResources) {
6546
- return `Web resources: content entry imports, entries=${String(entryCount)}, resources=${String(totalResources)}`;
6538
+ return `${messaging_prefix('debug')} war entryImports entries=${String(entryCount)} resources=${String(totalResources)}`;
6547
6539
  }
6548
6540
  function warPatchedSummary(v3Groups, v3ResourcesTotal, v2Resources) {
6549
- return `Web resources: WAR patched, v3Groups=${String(v3Groups)}, v3Resources=${String(v3ResourcesTotal)}, v2Resources=${String(v2Resources)}`;
6541
+ return `${messaging_prefix('debug')} war patched v3Groups=${String(v3Groups)} v3Resources=${String(v3ResourcesTotal)} v2Resources=${String(v2Resources)}`;
6550
6542
  }
6551
6543
  function isPublicRootLike(possiblePath) {
6552
6544
  const normalizedPath = paths_unixify(possiblePath || '');
@@ -6625,7 +6617,7 @@ function resolve_war_findSourceSibling(absOutputPath) {
6625
6617
  }
6626
6618
  }
6627
6619
  function isFirefox(browser) {
6628
- return !!browser && constants_isGeckoBasedBrowser(browser.toLowerCase());
6620
+ return !!browser && isGeckoBasedBrowser(browser.toLowerCase());
6629
6621
  }
6630
6622
  function isValidChromeMatchPattern(pattern) {
6631
6623
  if ('<all_urls>' === pattern) return true;
@@ -6971,7 +6963,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
6971
6963
  const source = JSON.stringify(canonicalManifest, null, 2);
6972
6964
  const rawSource = new core_sources.RawSource(source);
6973
6965
  setCurrentManifestContent(compilation, source);
6974
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) try {
6966
+ if (isDebug()) try {
6975
6967
  const v3Groups = 3 === canonicalManifest.manifest_version ? webAccessibleResourcesV3.length : 0;
6976
6968
  const v3ResourcesTotal = 3 === canonicalManifest.manifest_version ? webAccessibleResourcesV3.reduce((sum, g)=>sum + (g.resources?.length || 0), 0) : 0;
6977
6969
  const v2Resources = 2 === canonicalManifest.manifest_version ? webAccessibleResourcesV2.length : 0;
@@ -7305,7 +7297,7 @@ function salvageVersion(version) {
7305
7297
  return digits.map((digit)=>String(Math.min(Number(digit), 65535))).join('.');
7306
7298
  }
7307
7299
  function patchChromiumBackground(manifest, browser) {
7308
- if (constants_isGeckoBasedBrowser(String(browser))) return manifest;
7300
+ if (isGeckoBasedBrowser(String(browser))) return manifest;
7309
7301
  if (3 !== Number(manifest.manifest_version)) return manifest;
7310
7302
  const background = manifest.background;
7311
7303
  if (!background || !Array.isArray(background.scripts)) return manifest;
@@ -7387,7 +7379,7 @@ function purgeStaleHashedContentScripts(compilation, currentNames) {
7387
7379
  } catch {}
7388
7380
  }
7389
7381
  function isGeckoBrowser(browser) {
7390
- return constants_isGeckoBasedBrowser(String(browser));
7382
+ return isGeckoBasedBrowser(String(browser));
7391
7383
  }
7392
7384
  function patchGeckoBackground(manifest, browser) {
7393
7385
  if (!isGeckoBrowser(browser)) return manifest;
@@ -7441,7 +7433,7 @@ class UpdateManifest {
7441
7433
  if (patchedManifest.content_scripts) patchedManifest.content_scripts = this.applyDevOverrides(patchedManifest);
7442
7434
  patchedManifest = patchDevContentScriptManifestPaths(compilation, patchedManifest);
7443
7435
  }
7444
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) try {
7436
+ if (isDebug()) try {
7445
7437
  const overrideObj = JSON.parse(overrides || '{}');
7446
7438
  const overrideKeys = Object.keys(overrideObj || {}).length;
7447
7439
  let devCssStubsAdded = 0;
@@ -7460,7 +7452,7 @@ class UpdateManifest {
7460
7452
  warn.file = 'manifest.json';
7461
7453
  compilation.warnings.push(warn);
7462
7454
  }
7463
- if ('production' === compiler.options.mode && constants_isGeckoBasedBrowser(String(this.browser)) && gecko_data_collection_missingGeckoDataCollectionPermissions(patchedManifest)) {
7455
+ if ('production' === compiler.options.mode && isGeckoBasedBrowser(String(this.browser)) && gecko_data_collection_missingGeckoDataCollectionPermissions(patchedManifest)) {
7464
7456
  const warn = new WebpackError(missingGeckoDataCollectionPermissions());
7465
7457
  warn.name = 'AmoDataCollectionWarning';
7466
7458
  warn.file = 'manifest.json';
@@ -7485,7 +7477,7 @@ class ManifestPlugin {
7485
7477
  this.includeList = options.includeList;
7486
7478
  }
7487
7479
  apply(compiler) {
7488
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(manifestIncludeSummary(String(this.browser || 'chrome'), this.manifestPath));
7480
+ if (isDebug()) console.log(manifestIncludeSummary(String(this.browser || 'chrome'), this.manifestPath));
7489
7481
  new EmitManifest({
7490
7482
  manifestPath: this.manifestPath,
7491
7483
  browser: this.browser
@@ -8031,7 +8023,7 @@ class CollectContentEntryImports {
8031
8023
  const entryImports = collectContentScriptEntryImports(compilation, this.includeList);
8032
8024
  const shared = getSharedFor(compilation);
8033
8025
  shared.entryImports = entryImports;
8034
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
8026
+ if (isDebug()) {
8035
8027
  const keys = Object.keys(entryImports || {});
8036
8028
  const total = keys.reduce((acc, k)=>acc + (entryImports[k]?.length || 0), 0);
8037
8029
  console.log(entryImportsSummary(keys.length, total));
@@ -8292,7 +8284,7 @@ function webpackConfig(projectStructure, devOptions) {
8292
8284
  config: devOptions.extensions
8293
8285
  });
8294
8286
  const unpackedExtensionDirsToLoad = computeExtensionsToLoad(__rspack_external_node_path_c5b9b54f.resolve(__rspack_import_meta_dirname__, '..'), devOptions.mode, devOptions.browser, primaryExtensionOutputDir, companionUnpackedExtensionDirs, manifestPath);
8295
- const debug = 'true' === process.env.EXTENSION_AUTHOR_MODE;
8287
+ const debug = isDebug();
8296
8288
  const transpilePackageDirs = resolveTranspilePackageDirs(packageJsonDir, devOptions.transpilePackages);
8297
8289
  if (debug) {
8298
8290
  console.log(debugBrowser(devOptions.browser, devOptions.chromiumBinary, devOptions.geckoBinary));