extension-develop 4.0.21 → 4.0.22-canary.1785348713.017c274a

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.
Files changed (30) hide show
  1. package/dist/0~dev-server.mjs +2 -1
  2. package/dist/0~rspack-config.mjs +137 -189
  3. package/dist/0~stats-handler.mjs +74 -10
  4. package/dist/101.mjs +98 -107
  5. package/dist/266.mjs +41 -9
  6. package/dist/839.mjs +68 -17
  7. package/dist/845.mjs +25 -29
  8. package/dist/dev-server/compiler-hooks.d.ts +1 -0
  9. package/dist/dev-server/messages.d.ts +1 -1
  10. package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
  11. package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +4 -4
  12. package/dist/extension-js-devtools/chrome/pages/welcome.js +1 -1
  13. package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
  14. package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +4 -4
  15. package/dist/extension-js-devtools/chromium/pages/welcome.js +1 -1
  16. package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
  17. package/dist/extension-js-devtools/edge/pages/centralized-logger.js +4 -4
  18. package/dist/extension-js-devtools/edge/pages/welcome.js +1 -1
  19. package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
  20. package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +4 -4
  21. package/dist/extension-js-devtools/firefox/pages/welcome.js +1 -1
  22. package/dist/lib/messages.d.ts +6 -8
  23. package/dist/lib/stats-handler.d.ts +13 -0
  24. package/dist/plugin-compilation/boring.d.ts +1 -1
  25. package/dist/plugin-compilation/compilation-lib/messages.d.ts +0 -2
  26. package/dist/plugin-compilation/index.d.ts +2 -0
  27. package/dist/plugin-compilation/zip-artifacts.d.ts +7 -0
  28. package/package.json +1 -1
  29. package/dist/0~branding.mjs +0 -26
  30. package/dist/plugin-compilation/compilation-lib/shared-state.d.ts +0 -7
@@ -12,12 +12,12 @@ import { filterKeysForThisBrowser as external_browser_extension_manifest_fields_
12
12
  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
- import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, treeWithDistFilesBrowser, packagingDistributionFiles, zipArtifactReady, resolveCompanionExtensionDirs, debugContextPath, toPosixPath, isGeckoBasedBrowser, spacerLine, PlaywrightPlugin, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
15
+ import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, treeWithDistFilesBrowser, packagingDistributionFiles, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, PlaywrightPlugin, isGeckoBasedBrowser, spacerLine, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
16
16
  import { stripBom, parseJsonSafe } from "./23.mjs";
17
17
  import { isResourceUnderDirs, canonicalizeDir, toResourceKey } from "./93.mjs";
18
18
  import { prefix as messaging_prefix, isDebug } from "./349.mjs";
19
- import { jsFrameworksHmrSummary, isUsingTypeScript, resolvePackageManager, humanLine, jsFrameworksIntegrationsEnabled, jsFrameworksConfigsDetected, ensureTypeScriptConfig, hasDependency, resolveDevelopInstallRoot, resolveDevelopDistFile, isUsingCustomLoader, getUserTypeScriptConfigFile, isUsingIntegration as messages_isUsingIntegration } from "./839.mjs";
20
- import { scrubBrand, makeSanitizedConsole } from "./0~branding.mjs";
19
+ import { jsFrameworksHmrSummary, isUsingTypeScript, resolvePackageManager, humanLine, jsFrameworksIntegrationsEnabled, jsFrameworksConfigsDetected, recordZipArtifact, hasDependency, resolveDevelopInstallRoot, resolveDevelopDistFile, isUsingCustomLoader, ensureTypeScriptConfig, isUsingIntegration as messages_isUsingIntegration, getUserTypeScriptConfigFile } from "./839.mjs";
20
+ import { renderStatsBlocks, makeSanitizedConsole } from "./0~stats-handler.mjs";
21
21
  import { getCanonicalContentScriptEntryName, parseCanonicalContentScriptAsset, EXTENSIONJS_CONTENT_SCRIPT_LAYER, isCanonicalContentScriptAsset, getCanonicalContentScriptJsAssetName, getCanonicalContentScriptCssAssetName } from "./291.mjs";
22
22
  import { hasProjectDependency, findNearestProjectManifestSync, PROJECT_MANIFEST_FILENAMES, readProjectDependencies } from "./80.mjs";
23
23
  import { cssIntegrationsEnabled, cssConfigsDetected, deadCssUrlRef, missingSassDependency, isUsingIntegration, postCssPluginNotResolved } from "./845.mjs";
@@ -200,7 +200,7 @@ function getLoggingPrefix(type) {
200
200
  }
201
201
  const messages_code = (text)=>pintor.blue(text);
202
202
  function webextensionPolyfillNotFound() {
203
- 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')}.`;
203
+ return `${getLoggingPrefix('warn')} webextension-polyfill isn't installed.\nThe browser API polyfill is disabled for this build.\nInstall it with ${messages_code('npm install webextension-polyfill')}.`;
204
204
  }
205
205
  function browserKey(browser) {
206
206
  return String(browser || 'unknown');
@@ -289,7 +289,8 @@ function setupNoBrowserBannerOnFirstDone(opts) {
289
289
  humanLine(browserRunnerDisabled({
290
290
  browser: opts.browser,
291
291
  manifestPath: opts.manifestPath,
292
- readyPath: opts.readyPath
292
+ readyPath: opts.readyPath,
293
+ distPath: opts.distPath
293
294
  }));
294
295
  humanLine(spacerLine());
295
296
  humanLine(messages_ready('development', opts.browser));
@@ -300,21 +301,17 @@ function setupCompilerDoneDiagnostics(compiler, port) {
300
301
  compiler.hooks.done.tap('extension.js:done', (stats)=>{
301
302
  try {
302
303
  if (stats?.hasErrors?.()) {
303
- const str = stats?.toString?.({
304
- colors: true,
305
- all: false,
304
+ const str = renderStatsBlocks(stats, {
306
305
  errors: true,
307
306
  warnings: true
308
307
  });
309
- if (str) console.error(scrubBrand(str));
308
+ if (str) console.error(str);
310
309
  } else if (stats?.hasWarnings?.()) {
311
- const str = stats?.toString?.({
312
- colors: true,
313
- all: false,
310
+ const str = renderStatsBlocks(stats, {
314
311
  errors: false,
315
312
  warnings: true
316
313
  });
317
- if (str) console.warn(scrubBrand(str));
314
+ if (str) console.warn(str);
318
315
  }
319
316
  if (!reportedNoEntries && 'number' == typeof port) {
320
317
  const info = stats.toJson({
@@ -330,14 +327,12 @@ function setupCompilerDoneDiagnostics(compiler, port) {
330
327
  console.warn(noEntrypointsDetected(port));
331
328
  }
332
329
  }
333
- } catch (error) {
334
- const str = stats?.toString({
335
- colors: true,
336
- all: false,
330
+ } catch {
331
+ const str = renderStatsBlocks(stats, {
337
332
  errors: true,
338
333
  warnings: true
339
334
  });
340
- if (str) console.error(scrubBrand(str));
335
+ if (str) console.error(str);
341
336
  }
342
337
  });
343
338
  }
@@ -350,10 +345,10 @@ function boring(manifestName, durationMs, stats) {
350
345
  const hasErrors = stats.hasErrors();
351
346
  const hasWarnings = stats.hasWarnings();
352
347
  const arrow = hasErrors ? messaging_prefix('error') : hasWarnings ? messaging_prefix('warn') : messaging_prefix('info');
353
- const label = hasErrors ? pintor.red('with errors') : hasWarnings ? pintor.yellow('with warnings') : pintor.green('successfully');
348
+ const status = hasErrors ? `compiled ${pintor.red('with errors')}` : hasWarnings ? `compiled ${pintor.yellow('with warnings')}` : 'compiled';
354
349
  const app = manifestName;
355
350
  const time = `${durationMs} ms`;
356
- return `${arrow} ${timestamp} ${app} compiled ${label} in ${time}.`;
351
+ return `${arrow} ${timestamp} ${app} ${status} in ${time}.`;
357
352
  }
358
353
  function cleanDistStarting(distPath) {
359
354
  return `${messaging_prefix('debug')} clean start path=${distPath}`;
@@ -376,34 +371,12 @@ function envInjectedPublicVars(count) {
376
371
  function envNoMatchingFile(browser, mode, presentFiles, expectedCandidates) {
377
372
  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.`;
378
373
  }
379
- const sharedState = {
380
- bannerPrinted: false,
381
- pendingCompilationLine: ''
382
- };
383
- function markBannerPrinted() {
384
- sharedState.bannerPrinted = true;
385
- if (sharedState.pendingCompilationLine) {
386
- humanLine(sharedState.pendingCompilationLine);
387
- sharedState.pendingCompilationLine = '';
388
- }
389
- }
390
- function isBannerPrinted() {
391
- if (sharedState.bannerPrinted) return true;
392
- if ('true' === process.env.EXTENSION_CLI_BANNER_PRINTED) {
393
- markBannerPrinted();
394
- return true;
395
- }
396
- return false;
397
- }
398
- function setPendingCompilationLine(line) {
399
- sharedState.pendingCompilationLine = line;
400
- }
401
374
  class BoringPlugin {
402
375
  static name = 'plugin-boring';
403
376
  manifestPath;
404
377
  browser;
405
378
  sawUserInvalidation = false;
406
- printedPostBannerStartupSuccess = false;
379
+ printedStartupSuccess = false;
407
380
  lastKnownManifestName;
408
381
  constructor(options){
409
382
  this.manifestPath = options.manifestPath;
@@ -412,10 +385,7 @@ class BoringPlugin {
412
385
  apply(compiler) {
413
386
  compiler.hooks.watchClose.tap('develop:brand:watch-close', ()=>{
414
387
  this.sawUserInvalidation = false;
415
- this.printedPostBannerStartupSuccess = false;
416
- });
417
- compiler.hooks.afterDone?.tap('develop:brand:flush', ()=>{
418
- isBannerPrinted();
388
+ this.printedStartupSuccess = false;
419
389
  });
420
390
  compiler.hooks.done.tap('develop:brand', (stats)=>{
421
391
  const hasErrors = Boolean(stats?.hasErrors?.());
@@ -450,14 +420,9 @@ class BoringPlugin {
450
420
  });
451
421
  if (hasUserFileChange) this.sawUserInvalidation = true;
452
422
  }
453
- if (browserLaunchEnabled && !isBannerPrinted() && !hasErrors && !hasWarnings) {
454
- this.printedPostBannerStartupSuccess = true;
455
- setPendingCompilationLine(line);
456
- return;
457
- }
458
423
  if (browserLaunchEnabled && !hasErrors && !hasWarnings) {
459
- if (!this.sawUserInvalidation) if (this.printedPostBannerStartupSuccess) return;
460
- else this.printedPostBannerStartupSuccess = true;
424
+ if (!this.sawUserInvalidation) if (this.printedStartupSuccess) return;
425
+ else this.printedStartupSuccess = true;
461
426
  }
462
427
  humanLine(line);
463
428
  } catch {}
@@ -1414,7 +1379,11 @@ class ZipPlugin {
1414
1379
  try {
1415
1380
  size = __rspack_external_node_fs_5ea92f0c.statSync(artifact.path).size;
1416
1381
  } catch {}
1417
- console.log(zipArtifactReady(this.browser, artifact.path, size));
1382
+ recordZipArtifact(stats?.compilation, {
1383
+ kind: artifact.kind,
1384
+ path: artifact.path,
1385
+ size
1386
+ });
1418
1387
  }
1419
1388
  if (isDebug()) {
1420
1389
  const sourceItem = created.find((c)=>'source' === c.kind);
@@ -1438,6 +1407,7 @@ class CompilationPlugin {
1438
1407
  zipSource;
1439
1408
  zipFilename;
1440
1409
  port;
1410
+ command;
1441
1411
  constructor(options){
1442
1412
  this.manifestPath = options.manifestPath;
1443
1413
  this.browser = options.browser || 'chrome';
@@ -1446,6 +1416,7 @@ class CompilationPlugin {
1446
1416
  this.zipSource = options.zipSource;
1447
1417
  this.zipFilename = options.zipFilename;
1448
1418
  this.port = options.port;
1419
+ this.command = options.command;
1449
1420
  }
1450
1421
  applyIgnoreWarnings(compiler) {
1451
1422
  const existing = compiler.options.ignoreWarnings;
@@ -1506,7 +1477,7 @@ class CompilationPlugin {
1506
1477
  manifestPath: this.manifestPath,
1507
1478
  browser: this.browser || 'chrome'
1508
1479
  }).apply(compiler);
1509
- setupCompilerDoneDiagnostics(compiler, this.port);
1480
+ if ('build' !== this.command && 'start' !== this.command) setupCompilerDoneDiagnostics(compiler, this.port);
1510
1481
  }
1511
1482
  }
1512
1483
  const BUNDLED_DEPENDENCY_VERSIONS = {
@@ -3831,7 +3802,8 @@ function fmtKiB(bytes) {
3831
3802
  return `${kib.toFixed(1)} KiB`;
3832
3803
  }
3833
3804
  function perfBudgetWarning(assets) {
3834
- const header = `${1 === assets.length ? 'asset exceeds' : 'assets exceed'} the extension performance budget. Browser extensions inject content scripts on every navigation and wake service workers from cold, so we apply tighter budgets than the rspack default.`;
3805
+ const count = assets.length;
3806
+ const header = `${1 === count ? 'One asset exceeds' : `${count} assets exceed`} the extension performance budget. Browser extensions inject content scripts on every navigation and wake service workers from cold, so Extension.js applies tighter budgets than the rspack default.`;
3835
3807
  const lines = assets.map((a)=>{
3836
3808
  const over = (a.size / a.budget * 100 - 100).toFixed(0);
3837
3809
  return ` ${a.name}\n size: ${fmtKiB(a.size)}\n budget: ${fmtKiB(a.budget)} (over by ${over}%)\n role: ${categoryRole(a.category)}`;
@@ -5465,7 +5437,7 @@ function reportToCompilation(compilation, compiler, message, type = 'error', fil
5465
5437
  compilation[bucket].push(issue);
5466
5438
  }
5467
5439
  function backgroundIsRequiredMessageOnly(backgroundChunkName) {
5468
- return `Check the ${pintor.yellow(backgroundChunkName.replace('/', '.'))} field in your ${pintor.yellow('manifest.json')} file.`;
5440
+ return `Check the ${pintor.blue(backgroundChunkName.replace('/', '.'))} field in your ${pintor.blue('manifest.json')} file.`;
5469
5441
  }
5470
5442
  class SetupBackgroundEntry {
5471
5443
  manifestPath;
@@ -7668,47 +7640,41 @@ class WasmPlugin {
7668
7640
  }
7669
7641
  function javaScriptError(errorSourcePath, missingFilePath, opts) {
7670
7642
  const lines = [];
7671
- lines.push(`Missing script file in ${pintor.underline(errorSourcePath)}.`);
7672
- lines.push(`Update your ${pintor.yellow("<script>")} src to point to a file that exists.`);
7673
- if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
7674
- if (opts?.deadRefHint) {
7675
- lines.push("The build ships an empty placeholder for this script, so the page loads and no 404 appears in DevTools (likely dead code).");
7676
- lines.push(`Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
7677
- }
7678
- lines.push('');
7679
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7643
+ lines.push("The page references a script file that doesn't exist.");
7644
+ lines.push(`${pintor.gray('PATH')} ${pintor.underline(errorSourcePath)}`);
7645
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7646
+ if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.blue('public/')}), not your source directory.`);
7647
+ 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).");
7648
+ lines.push(`Update the ${pintor.blue("<script>")} src to point to a file that exists.`);
7649
+ if (opts?.deadRefHint) lines.push(`Set ${pintor.blue('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
7680
7650
  return lines.join('\n');
7681
7651
  }
7682
7652
  function cssError(errorSourcePath, missingFilePath, opts) {
7683
7653
  const lines = [];
7684
- lines.push(`Missing stylesheet in ${pintor.underline(errorSourcePath)}.`);
7685
- lines.push(`Update your ${pintor.yellow('<link>')} href to point to a file that exists.`);
7686
- if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
7687
- if (opts?.deadRefHint) {
7688
- lines.push("Chrome loads the page anyway and 404s this reference silently, so it is likely dead code.");
7689
- lines.push(`Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
7690
- }
7691
- lines.push('');
7692
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7654
+ lines.push("The page references a stylesheet that doesn't exist.");
7655
+ lines.push(`${pintor.gray('PATH')} ${pintor.underline(errorSourcePath)}`);
7656
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7657
+ if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.blue('public/')}), not your source directory.`);
7658
+ if (opts?.deadRefHint) lines.push("Chrome loads the page anyway and 404s this reference silently, so it is likely dead code.");
7659
+ lines.push(`Update the ${pintor.blue('<link>')} href to point to a file that exists.`);
7660
+ if (opts?.deadRefHint) lines.push(`Set ${pintor.blue('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
7693
7661
  return lines.join('\n');
7694
7662
  }
7695
7663
  function staticAssetError(errorSourcePath, missingFilePath, opts) {
7696
7664
  const extname = __rspack_external_node_path_c5b9b54f.extname(missingFilePath);
7697
7665
  const lines = [];
7698
- lines.push(`Missing asset in ${pintor.underline(errorSourcePath)}.`);
7666
+ lines.push("The page references an asset that doesn't exist.");
7667
+ lines.push(`${pintor.gray('PATH')} ${pintor.underline(errorSourcePath)}`);
7668
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7699
7669
  const ref = opts?.refLabel || `*${extname}`;
7700
- lines.push(`Update the ${pintor.yellow(ref)} reference to point to a file that exists.`);
7701
- if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
7702
- if (opts?.deadRefHint) {
7703
- lines.push("Chrome loads the page anyway and 404s this reference silently, so it is likely dead code.");
7704
- lines.push(`Set ${pintor.yellow('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
7705
- }
7706
- lines.push('');
7707
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7670
+ if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.blue('public/')}), not your source directory.`);
7671
+ if (opts?.deadRefHint) lines.push("Chrome loads the page anyway and 404s this reference silently, so it is likely dead code.");
7672
+ lines.push(`Update the ${pintor.blue(ref)} reference to point to a file that exists.`);
7673
+ if (opts?.deadRefHint) lines.push(`Set ${pintor.blue('EXTENSION_STRICT_REFS=true')} to make this a build error.`);
7708
7674
  return lines.join('\n');
7709
7675
  }
7710
7676
  function fileNotFound(errorSourcePath, missingFilePath, opts) {
7711
- if (!errorSourcePath) throw new Error('This state should not occur. Please report a bug.');
7677
+ if (!errorSourcePath) throw new Error('This state should not occur. Report a bug.');
7712
7678
  switch(__rspack_external_node_path_c5b9b54f.extname(missingFilePath)){
7713
7679
  case '.js':
7714
7680
  case '.ts':
@@ -7726,38 +7692,34 @@ function fileNotFound(errorSourcePath, missingFilePath, opts) {
7726
7692
  }
7727
7693
  function remoteResourceWarning(errorSourcePath, remoteUrl, kind) {
7728
7694
  const label = "script" === kind ? "<script>" : '<link>';
7729
- 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.';
7730
7695
  const lines = [];
7731
- lines.push(`Remote ${pintor.yellow(label)} in ${pintor.underline(errorSourcePath)}.`);
7732
- lines.push(cspHint);
7733
- lines.push('');
7734
- lines.push(`${pintor.red('URL')} ${pintor.underline(remoteUrl)}`);
7696
+ lines.push("script" === kind ? `The page loads a remote ${pintor.blue(label)}, which the MV3 CSP blocks.` : `The page loads a remote ${pintor.blue(label)}, which the CSP can block.`);
7697
+ lines.push(`${pintor.gray('PATH')} ${pintor.underline(errorSourcePath)}`);
7698
+ lines.push(`${pintor.gray('GOT')} ${pintor.underline(remoteUrl)}`);
7699
+ lines.push("script" === kind ? "Bundle the script or self-host it instead." : "Bundle the stylesheet or self-host it instead.");
7735
7700
  return lines.join('\n');
7736
7701
  }
7737
7702
  function serverRestartRequiredFromHtml(relativeHtmlPath, absoluteHtmlPath) {
7738
7703
  const lines = [];
7739
7704
  lines.push("Entrypoint references changed.");
7740
- lines.push(`Restart the dev server to pick up changes to ${pintor.yellow("<script>")} and ${pintor.yellow('<link rel="stylesheet">')} entries.`);
7741
- lines.push('');
7742
7705
  lines.push(`${pintor.gray('PATH')} ${pintor.underline(absoluteHtmlPath)}`);
7706
+ lines.push(`Restart the dev server to pick up changes to ${pintor.blue("<script>")} and ${pintor.blue('<link rel="stylesheet">')} entries.`);
7743
7707
  return lines.join('\n');
7744
7708
  }
7745
7709
  function manifestHtmlEntrypointChange(manifestField, pathAfter, pathBefore) {
7746
7710
  const lines = [];
7747
7711
  const fieldLabel = manifestField ? manifestField.replace(/\//g, '.') : void 0;
7748
- lines.push(`Entrypoint references changed${fieldLabel ? ` in ${pintor.yellow(fieldLabel)}` : ''}.`);
7712
+ lines.push(`Entrypoint references changed${fieldLabel ? ` in ${pintor.blue(fieldLabel)}` : ''}.`);
7713
+ if (pathBefore) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(pathBefore)}`);
7714
+ if (pathAfter) lines.push(`${pintor.gray('GOT')} ${pintor.underline(pathAfter)}`);
7749
7715
  lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
7750
- lines.push('');
7751
- if (pathBefore) lines.push(`${pintor.red('PATH BEFORE')} ${pintor.underline(pathBefore)}`);
7752
- if (pathAfter) lines.push(`${pintor.green('PATH AFTER')} ${pintor.underline(pathAfter)}`);
7753
7716
  return lines.join('\n');
7754
7717
  }
7755
7718
  function manifestPageMissing(manifestField, missingFilePath) {
7756
7719
  const lines = [];
7757
- lines.push(`Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`);
7758
- lines.push("The page path must point to an existing HTML file that will be bundled.");
7759
- lines.push('');
7760
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7720
+ lines.push(`Can't find the page listed in ${pintor.blue(manifestField)}.`);
7721
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(missingFilePath)}`);
7722
+ lines.push(`Update the path in your ${pintor.blue('manifest.json')} to an HTML file that exists.`);
7761
7723
  return lines.join('\n');
7762
7724
  }
7763
7725
  function manifestFieldMessageOnly(manifestField) {
@@ -7765,7 +7727,7 @@ function manifestFieldMessageOnly(manifestField) {
7765
7727
  const contentIndex = manifestField.split('-')[1];
7766
7728
  const isContentScripts = manifestField.startsWith("content_scripts");
7767
7729
  const fieldLabel = isContentScripts ? `content_scripts (index ${contentIndex})` : manifestFieldName;
7768
- return `Check the ${pintor.yellow(fieldLabel)} field in your ${pintor.yellow('manifest.json')} file.`;
7730
+ return `Check the ${pintor.blue(fieldLabel)} field in your ${pintor.blue('manifest.json')} file.`;
7769
7731
  }
7770
7732
  function injectCssLink(headNode, feature, firstLinkAttrs, hrefOverride) {
7771
7733
  const linkTag = __rspack_external_parse5_utilities_78b19c6a.createNode('link');
@@ -8752,12 +8714,11 @@ class HtmlPlugin {
8752
8714
  }
8753
8715
  function iconsMissingFile(manifestField, filePath, opts) {
8754
8716
  const lines = [];
8755
- lines.push(`Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`);
8756
- lines.push("The icon path must point to an existing file that will be packaged with the extension.");
8757
- 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.`);
8758
- if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
8759
- lines.push('');
8760
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(filePath)}`);
8717
+ lines.push(`Can't find an icon file listed in ${pintor.blue(manifestField)}.`);
8718
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(filePath)}`);
8719
+ lines.push(opts?.fatal ? `Browsers reject the whole extension when this file is missing.\nThe build stops here.` : `Browsers can reject or misrender the extension when this file is missing.\nThe build continues.`);
8720
+ if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.blue('public/')}), not your source directory.`);
8721
+ lines.push(`Update the icon path in your ${pintor.blue('manifest.json')} to a file that ships with the extension.`);
8761
8722
  return lines.join('\n');
8762
8723
  }
8763
8724
  function themeImageMissingFile(manifestField, filePath, opts) {
@@ -8782,11 +8743,10 @@ function themeImageIsEmpty(manifestField, filePath) {
8782
8743
  function manifestIconsEntrypointChange(manifestField, pathAfter, pathBefore) {
8783
8744
  const lines = [];
8784
8745
  const fieldLabel = manifestField ? manifestField.replace(/\//g, '.') : 'icons';
8785
- lines.push(`Entrypoint references changed in ${pintor.yellow(fieldLabel)}.`);
8746
+ lines.push(`Entrypoint references changed in ${pintor.blue(fieldLabel)}.`);
8747
+ if (pathBefore) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(pathBefore)}`);
8748
+ if (pathAfter) lines.push(`${pintor.gray('GOT')} ${pintor.underline(pathAfter)}`);
8786
8749
  lines.push("Restart the dev server to pick up changes to manifest icons.");
8787
- lines.push('');
8788
- if (pathBefore) lines.push(`${pintor.red('PATH BEFORE')} ${pintor.underline(pathBefore)}`);
8789
- if (pathAfter) lines.push(`${pintor.green('PATH AFTER')} ${pintor.underline(pathAfter)}`);
8790
8750
  return lines.join('\n');
8791
8751
  }
8792
8752
  function iconsEmitSummary(feature, stats) {
@@ -9002,39 +8962,35 @@ class IconsPlugin {
9002
8962
  }
9003
8963
  function jsonMissingFile(manifestField, filePath, opts) {
9004
8964
  const lines = [];
9005
- lines.push(`Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`);
9006
- lines.push("The JSON path must point to an existing file that will be packaged with the extension.");
9007
- 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.`);
9008
- if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.yellow('public/')}), not your source directory.`);
9009
- lines.push('');
9010
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(filePath)}`);
8965
+ lines.push(`Can't find the JSON file listed in ${pintor.blue(manifestField)}.`);
8966
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(filePath)}`);
8967
+ lines.push(opts?.fatal ? `Browsers can reject or crash the extension when required JSON files like rulesets are missing.\nThe build stops here.` : `Browsers can reject or misread the extension when this file is missing.\nThe build continues.`);
8968
+ if (opts?.publicRootHint) lines.push(`Paths starting with '/' are resolved from the extension output root (served from ${pintor.blue('public/')}), not your source directory.`);
8969
+ lines.push(`Update the JSON path in your ${pintor.blue('manifest.json')} to a file that ships with the extension.`);
9011
8970
  return lines.join('\n');
9012
8971
  }
9013
8972
  function invalidJsonSyntax(manifestField, file, cause) {
9014
8973
  return [
9015
- "Invalid JSON.",
9016
- "",
9017
- `Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`,
9018
- `The JSON at ${pintor.underline(file)} could not be parsed:`,
9019
- `${pintor.red(cause)}`
8974
+ `Can't parse the JSON file listed in ${pintor.blue(manifestField)}.`,
8975
+ `${pintor.gray('PATH')} ${pintor.underline(file)}`,
8976
+ `${pintor.gray('REASON')} ${pintor.underline(cause)}`,
8977
+ "Fix the JSON syntax, then rebuild."
9020
8978
  ].join('\n');
9021
8979
  }
9022
8980
  function invalidRulesetStructure(manifestField, file) {
9023
8981
  return [
9024
- "Invalid Declarative Net Request ruleset.",
9025
- "",
9026
- `Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`,
9027
- "Chrome expects a top-level JSON array of rule objects.",
9028
- `${pintor.red('INVALID SHAPE')} ${pintor.underline(file)}`
8982
+ `The Declarative Net Request ruleset listed in ${pintor.blue(manifestField)} isn't a rule array.`,
8983
+ `${pintor.gray('PATH')} ${pintor.underline(file)}`,
8984
+ `${pintor.gray('EXPECTED')} ${pintor.underline('a top-level JSON array of rule objects')}`,
8985
+ "Update the file to contain an array of rules."
9029
8986
  ].join('\n');
9030
8987
  }
9031
8988
  function invalidManagedSchemaStructure(manifestField, file) {
9032
8989
  return [
9033
- "Invalid managed storage schema.",
9034
- "",
9035
- `Check the ${pintor.yellow(manifestField)} field in your ${pintor.yellow('manifest.json')} file.`,
9036
- "Expected a top-level JSON object describing the schema.",
9037
- `${pintor.red('INVALID SHAPE')} ${pintor.underline(file)}`
8990
+ `The managed storage schema listed in ${pintor.blue(manifestField)} isn't a schema object.`,
8991
+ `${pintor.gray('PATH')} ${pintor.underline(file)}`,
8992
+ `${pintor.gray('EXPECTED')} ${pintor.underline('a top-level JSON object describing the schema')}`,
8993
+ "Update the file to contain a schema object."
9038
8994
  ].join('\n');
9039
8995
  }
9040
8996
  function jsonEmitSummary(feature, stats) {
@@ -9205,34 +9161,34 @@ class JsonPlugin {
9205
9161
  }
9206
9162
  }
9207
9163
  function manifestNotFoundMessageOnly(absPath) {
9208
- return `Check for a valid manifest.json file.\n\nNOT FOUND ${absPath}`;
9164
+ return `Can't find a manifest.json file.\nNOT FOUND ${absPath}\nAdd a manifest.json file to your project root.`;
9209
9165
  }
9210
9166
  function messages_entryNotFoundMessageOnly(manifestField, absPath) {
9211
- const guidance = `Check the ${manifestField} field in your manifest.json file.`;
9212
- const suffix = absPath ? `\n\nNOT FOUND ${absPath}` : '';
9213
- return guidance + suffix;
9167
+ const lines = [
9168
+ `Can't find the file listed in ${manifestField}.`
9169
+ ];
9170
+ if (absPath) lines.push(`NOT FOUND ${absPath}`);
9171
+ lines.push(`Update the ${manifestField} field in your manifest.json file.`);
9172
+ return lines.join('\n');
9214
9173
  }
9215
9174
  function defaultLocaleSpecifiedButLocalesMissing() {
9216
9175
  return "default_locale is set, but the _locales folder is missing.\nAdd _locales/<default>/messages.json.";
9217
9176
  }
9218
9177
  function defaultLocaleFolderMissing(defaultLocale) {
9219
- return `Default locale folder is missing: _locales/${defaultLocale}.\nCreate it and add messages.json.`;
9178
+ return `The default locale folder is missing.\nNOT FOUND _locales/${defaultLocale}\nCreate the folder and add a messages.json file.`;
9220
9179
  }
9221
9180
  function defaultLocaleMessagesMissing(defaultLocale) {
9222
- return `Default locale messages.json is missing: _locales/${defaultLocale}/messages.json.\nCreate the file with your strings.`;
9181
+ return `The default locale messages.json file is missing.\nNOT FOUND _locales/${defaultLocale}/messages.json\nCreate the file with your strings.`;
9223
9182
  }
9224
9183
  function localesPresentButNoDefaultLocale() {
9225
9184
  return "The _locales folder exists, but manifest.json is missing default_locale.\nAdd default_locale to manifest.json.";
9226
9185
  }
9227
9186
  function invalidMessagesJson(absPath) {
9228
- return `Invalid JSON in locale messages file: ${absPath}.\nFix the JSON syntax and try again.`;
9187
+ return `Can't parse a locale messages.json file.\nPATH ${absPath}\nFix the JSON syntax and try again.`;
9229
9188
  }
9230
9189
  function missingManifestMessageKey(key, defaultLocale) {
9231
- const header = 'Check the i18n placeholders in your manifest.json file.';
9232
9190
  const localePath = defaultLocale ? `_locales/${defaultLocale}/messages.json` : '_locales/<default>/messages.json';
9233
- const guidance = `The key "${key}" referenced via __MSG_${key}__ must be defined in ${localePath}.\nAdd the key to that file.`;
9234
- const final = `MISSING KEY ${key} in ${localePath}`;
9235
- return `${header}\n${guidance}\n\n${final}`;
9191
+ return `The manifest references __MSG_${key}__, but the key "${key}" isn't defined.\nNOT FOUND ${key}\nPATH ${localePath}\nAdd the key to the messages file.`;
9236
9192
  }
9237
9193
  function localesIncludeSummary(hasManifest, hasLocalesRoot, defaultLocale) {
9238
9194
  const dl = defaultLocale || 'none';
@@ -9248,7 +9204,7 @@ function localesValidationDetected(issue) {
9248
9204
  return `${messaging_prefix('debug')} locales validation="${issue}"`;
9249
9205
  }
9250
9206
  function localesMustBeAtProjectRoot(foundAt, expectedAt) {
9251
- 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}`;
9207
+ return `The _locales folder sits in the legacy next-to-manifest location.\nGOT ${foundAt}\nEXPECTED ${expectedAt}\nChrome reads locales from the extension root, so _locales/ is canonically placed at the project root.\nThe build uses it either way.\nMove the folder to the project root to silence this warning.`;
9252
9208
  }
9253
9209
  function isUsableDir(p) {
9254
9210
  try {
@@ -9478,26 +9434,23 @@ class LocalesPlugin {
9478
9434
  function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
9479
9435
  const lines = [];
9480
9436
  lines.push("Entrypoint references changed.");
9437
+ if (fileRemoved) lines.push(`${pintor.gray('EXPECTED')} ${pintor.underline(fileRemoved)}`);
9438
+ if (fileAdded) lines.push(`${pintor.gray('GOT')} ${pintor.underline(fileAdded)}`);
9481
9439
  lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
9482
- lines.push('');
9483
- if (fileRemoved) lines.push(`${pintor.red('PATH BEFORE')} ${pintor.underline(fileRemoved)}`);
9484
- if (fileAdded) lines.push(`${pintor.green('PATH AFTER')} ${pintor.underline(fileAdded)}`);
9485
9440
  return lines.join('\n');
9486
9441
  }
9487
9442
  function legacyManifestPathWarning(legacyPath) {
9488
9443
  const lines = [];
9489
- lines.push(`${messaging_prefix('warn')} Deprecated manifest path detected.`);
9444
+ lines.push(`${messaging_prefix('warn')} The manifest uses a deprecated path.`);
9445
+ lines.push(`${pintor.gray('PATH')} ${pintor.underline(legacyPath)}`);
9490
9446
  lines.push("Extension.js rewrites it to the standardized folders in the next major.");
9491
- lines.push('');
9492
- lines.push(`${pintor.brightBlue('PATH')} ${pintor.underline(legacyPath)}`);
9493
9447
  return lines.join('\n');
9494
9448
  }
9495
9449
  function fatalManifestShapeFixed(field, detail) {
9496
9450
  const lines = [];
9497
- lines.push(`${messaging_prefix('warn')} Repaired a manifest field Chrome refuses to load the extension over.`);
9498
- lines.push("Fix it in your manifest.json.");
9499
- lines.push('');
9500
- lines.push(`${pintor.brightBlue('FIELD')} ${pintor.underline(field)}, ${detail}`);
9451
+ lines.push(`${messaging_prefix('warn')} Repaired the ${pintor.blue(field)} field, which Chrome refuses to load the extension over.`);
9452
+ lines.push(`${pintor.gray('REASON')} ${pintor.underline(detail)}`);
9453
+ lines.push(`Fix the field in your ${pintor.blue('manifest.json')} file.`);
9501
9454
  return lines.join('\n');
9502
9455
  }
9503
9456
  function invalidThemeValue(field, detail, value) {
@@ -9511,18 +9464,16 @@ function invalidThemeValue(field, detail, value) {
9511
9464
  }
9512
9465
  function missingGeckoDataCollectionPermissions() {
9513
9466
  const lines = [];
9514
- lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.yellow('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
9515
- lines.push('Declare {"required": ["none"]} if this extension transmits no data.');
9516
- lines.push('');
9517
- lines.push(`${pintor.brightBlue('DOCS')} ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')}`);
9467
+ lines.push(`${messaging_prefix('warn')} addons.mozilla.org requires ${pintor.blue('browser_specific_settings.gecko.data_collection_permissions')} for new add-ons.`);
9468
+ lines.push(`Declare ${pintor.blue('{"required": ["none"]}')} if this extension transmits no data.`);
9469
+ lines.push(`See ${pintor.underline('https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/')} for details.`);
9518
9470
  return lines.join('\n');
9519
9471
  }
9520
9472
  function manifestInvalidError(error) {
9521
9473
  const lines = [];
9522
- lines.push(`Invalid ${pintor.yellow('manifest.json')}.`);
9474
+ lines.push(`Can't read your ${pintor.blue('manifest.json')} file.`);
9475
+ lines.push(`${pintor.gray('REASON')} ${pintor.underline(String(error))}`);
9523
9476
  lines.push("Update your manifest and try again.");
9524
- lines.push('');
9525
- lines.push(`${pintor.red('REASON')} ${pintor.red(String(error))}`);
9526
9477
  return lines.join('\n');
9527
9478
  }
9528
9479
  function manifestIncludeSummary(browser, manifestPath) {
@@ -9995,47 +9946,43 @@ function cleanMatches(matches) {
9995
9946
  function warFieldError(filePath, opts) {
9996
9947
  const displayPath = opts?.overrideNotFoundPath || filePath;
9997
9948
  const lines = [];
9998
- if (opts?.relativeRef) lines.push(`The file ${pintor.yellow(opts.relativeRef)} defined in ${pintor.yellow('web_accessible_resources')} was not found.`);
9999
- else lines.push(`A file listed in ${pintor.yellow('web_accessible_resources')} was not found.`);
10000
- lines.push(`Only list assets your pages fetch with ${pintor.yellow('chrome.runtime.getURL()')}.`);
10001
- lines.push("Imports from content scripts are bundled automatically and do not need to be listed here.");
9949
+ if (opts?.relativeRef) lines.push(`Can't find the file ${pintor.blue(opts.relativeRef)} listed in ${pintor.blue('web_accessible_resources')}.`);
9950
+ else lines.push(`Can't find a file listed in ${pintor.blue('web_accessible_resources')}.`);
9951
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(displayPath)}`);
9952
+ lines.push(`Only list assets your pages fetch with ${pintor.blue('chrome.runtime.getURL()')}.`);
9953
+ lines.push("Imports from content scripts are bundled automatically and don't need to be listed here.");
10002
9954
  if (opts?.publicRootHint) {
10003
- lines.push(`To reference files in ${pintor.yellow('public/')}, use a leading '/' (e.g. ${pintor.yellow('/open-panel.gif')}).`);
9955
+ lines.push(`To reference files in ${pintor.blue('public/')}, use a leading '/' (for example ${pintor.blue('/open-panel.gif')}).`);
10004
9956
  lines.push("These resolve from the built extension root.");
10005
- lines.push('');
10006
- lines.push(`Add the file to ${pintor.yellow('public/')}, or update the path to a root-absolute location.`);
9957
+ lines.push(`Learn more: ${pintor.underline('https://extension.js.org/docs/development/web-accessible-resources')}`);
9958
+ lines.push(`Add the file to ${pintor.blue('public/')}, or update the path to a root-absolute location.`);
10007
9959
  } else if (opts?.sourceSibling) {
10008
- lines.push(`Found ${pintor.yellow(opts.sourceSibling)}, but web_accessible_resources entries are copied as-is, not compiled.`);
10009
- lines.push('');
10010
- 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 '/'.`);
9960
+ lines.push(`Found ${pintor.underline(opts.sourceSibling)}, but web_accessible_resources entries are copied as-is, not compiled.`);
9961
+ lines.push(`Learn more: ${pintor.underline('https://extension.js.org/docs/development/web-accessible-resources')}`);
9962
+ lines.push("- Import the file from a script so it gets bundled.");
9963
+ lines.push(`- Move a prebuilt copy to ${pintor.blue('public/')} and reference it with a leading '/'.`);
10011
9964
  } else {
10012
9965
  lines.push("Relative paths must point to a real source file so the build can emit it.");
10013
- lines.push('');
9966
+ lines.push(`Learn more: ${pintor.underline('https://extension.js.org/docs/development/web-accessible-resources')}`);
10014
9967
  lines.push("Create the missing file, or update the path to an existing source file.");
10015
9968
  }
10016
- lines.push(`Learn more: ${pintor.underline('https://extension.js.org/docs/development/web-accessible-resources')}`);
10017
- lines.push('');
10018
- lines.push(`${pintor.red('NOT FOUND')} ${pintor.underline(displayPath)}`);
10019
9969
  return lines.join('\n');
10020
9970
  }
10021
9971
  function warStringEntryInMv3(entry) {
10022
9972
  const lines = [];
10023
- lines.push(`Check the ${pintor.yellow('web_accessible_resources')} field in your ${pintor.yellow('manifest.json')} file.`);
10024
- lines.push(`Manifest V3 requires object entries with ${pintor.yellow('resources')} and ${pintor.yellow('matches')} (or ${pintor.yellow('extension_ids')}).`);
10025
- lines.push("Plain string entries are the Manifest V2 format and Chrome rejects them at load time.");
10026
- lines.push('');
10027
- lines.push(`Wrap it like ${pintor.yellow(`{"resources": ["${entry}"], "matches": ["<all_urls>"]}`)} with the matches your pages need.`);
10028
- lines.push('');
10029
- lines.push(`${pintor.red('INVALID MV3 ENTRY')} ${pintor.underline(entry)}`);
9973
+ lines.push(`Chrome rejects plain string entries in ${pintor.blue('web_accessible_resources')} under Manifest V3.`);
9974
+ lines.push(`${pintor.gray('GOT')} ${pintor.underline(entry)}`);
9975
+ lines.push("Plain string entries are the Manifest V2 format.");
9976
+ lines.push(`Manifest V3 requires object entries with ${pintor.blue('resources')} and ${pintor.blue('matches')} (or ${pintor.blue('extension_ids')}).`);
9977
+ lines.push(`Wrap it like ${pintor.blue(`{"resources": ["${entry}"], "matches": ["<all_urls>"]}`)} with the matches your pages need.`);
10030
9978
  return lines.join('\n');
10031
9979
  }
10032
9980
  function warInvalidMatchPattern(pattern) {
10033
9981
  const lines = [];
10034
- lines.push(`Check the ${pintor.yellow('web_accessible_resources')} field in your ${pintor.yellow('manifest.json')} file.`);
10035
- lines.push(`Chrome requires match patterns to end with ${pintor.yellow('/*')} and not include deeper paths.`);
10036
- lines.push(`See ${pintor.underline('https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources#manifest_declaration')}`);
10037
- lines.push('');
10038
- lines.push(`${pintor.red('INVALID MATCH PATTERN')} ${pintor.underline(pattern)}`);
9982
+ lines.push(`Chrome rejects a match pattern in ${pintor.blue('web_accessible_resources')}.`);
9983
+ lines.push(`${pintor.gray('GOT')} ${pintor.underline(pattern)}`);
9984
+ lines.push(`Match patterns must end with ${pintor.blue('/*')} and can't include deeper paths.`);
9985
+ lines.push(`Update the pattern in your ${pintor.blue('manifest.json')} file. See ${pintor.underline('https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources#manifest_declaration')} for the format.`);
10039
9986
  return lines.join('\n');
10040
9987
  }
10041
9988
  function entryImportsSummary(entryCount, totalResources) {
@@ -11878,7 +11825,8 @@ function webpackConfig(projectStructure, devOptions) {
11878
11825
  zip: true === devOptions.zip,
11879
11826
  zipSource: true === devOptions.zipSource,
11880
11827
  zipFilename: devOptions.zipFilename,
11881
- port: 'string' == typeof devOptions.port ? parseInt(devOptions.port, 10) : devOptions.port
11828
+ port: 'string' == typeof devOptions.port ? parseInt(devOptions.port, 10) : devOptions.port,
11829
+ command: devOptions.metadataCommand
11882
11830
  }),
11883
11831
  new StaticAssetsPlugin({
11884
11832
  manifestPath,