extension 4.0.21 → 4.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -150,7 +150,9 @@ var __webpack_modules__ = {
150
150
  const updateSuffix = readUpdateSuffixOnce();
151
151
  console.log(_messages__rspack_import_5.io());
152
152
  console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, opts.browserVersionLine, updateSuffix || void 0, {
153
- profilePath: opts.profilePath
153
+ profilePath: opts.profilePath,
154
+ binaryPath: opts.binaryPath,
155
+ binaryProvenance: opts.binaryProvenance
154
156
  }));
155
157
  console.log(_messages__rspack_import_5.io());
156
158
  markCardPrinted(k, opts.browser, opts.outPath);
@@ -191,7 +193,9 @@ var __webpack_modules__ = {
191
193
  console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, browserLabel, updateSuffix || void 0, {
192
194
  includeExtensionId: opts.includeExtensionId,
193
195
  runLabel,
194
- profilePath: opts.profilePath
196
+ profilePath: opts.profilePath,
197
+ binaryPath: opts.binaryPath,
198
+ binaryProvenance: opts.binaryProvenance
195
199
  }));
196
200
  console.log(_messages__rspack_import_5.io());
197
201
  } else {
@@ -209,25 +213,32 @@ var __webpack_modules__ = {
209
213
  console.log(_messages__rspack_import_5.e_(manifest, opts.browser, message, browserLabel, updateSuffix || void 0, {
210
214
  includeExtensionId: opts.includeExtensionId,
211
215
  runLabel,
212
- profilePath: opts.profilePath
216
+ profilePath: opts.profilePath,
217
+ binaryPath: opts.binaryPath,
218
+ binaryProvenance: opts.binaryProvenance
213
219
  }));
214
220
  console.log(_messages__rspack_import_5.io());
215
221
  }
216
222
  } catch {
223
+ const provenanceNote = _messages__rspack_import_5.xX(opts.binaryProvenance);
217
224
  console.log(_messages__rspack_import_5.io());
218
225
  console.log((0, _helpers_messaging__rspack_import_3.Nr)({
219
226
  rows: [
220
227
  {
221
228
  label: 'Browser',
222
- value: browserLabel
229
+ value: provenanceNote ? `${browserLabel} ${provenanceNote}` : browserLabel
230
+ },
231
+ {
232
+ label: 'Binary',
233
+ value: provenanceNote ? _messages__rspack_import_5.Yy(opts.binaryPath || '') : ''
223
234
  },
224
235
  {
225
236
  label: 'Output',
226
- value: opts.outPath
237
+ value: _messages__rspack_import_5.Yy(opts.outPath)
227
238
  },
228
239
  {
229
240
  label: 'Profile',
230
- value: opts.profilePath || ''
241
+ value: _messages__rspack_import_5.Yy(opts.profilePath || '')
231
242
  }
232
243
  ]
233
244
  }));
@@ -469,59 +480,55 @@ var __webpack_modules__ = {
469
480
  return `${getLoggingPrefix('debug')} browser banner=failed reason="${message}"`;
470
481
  }
471
482
  function skippingBrowserLaunchDueToCompileErrors() {
472
- return `${getLoggingPrefix('warn')} Skip the browser launch due to compile errors.`;
483
+ return `${getLoggingPrefix('warn')} Skipping the browser launch, the build has compile errors.`;
473
484
  }
474
485
  function browserNotInstalledError(browser, browserBinaryLocation) {
475
- const isUnreachable = 'null' === browserBinaryLocation ? `Browser ${capitalizedBrowserName(browser)} is not installed.\n` : `Can't find the path for browser ${capitalizedBrowserName(browser)}.\n`;
486
+ const isUnreachable = 'null' === browserBinaryLocation ? `${capitalizedBrowserName(browser)} isn't installed.\n` : `Can't find the ${capitalizedBrowserName(browser)} binary.\n`;
476
487
  const wslHint = (()=>{
477
488
  if (!isWsl()) return '';
478
489
  const example = '/mnt/c/Program Files/Google/Chrome/Application/chrome.exe';
479
- return `\n\n${getLoggingPrefix('info')} WSL detected\n- Install a Linux browser in WSL, or\n- Provide a Windows binary path via ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray(`"${example}"`)}\n (Tip: a shell alias like ${pintor__rspack_import_8_default().gray('google-chrome=...')} won't be used by Extension.js; use a real path or wrapper script.)`;
490
+ return `\n\nWSL detected:\n- Install a Linux browser in WSL, or\n- Provide a Windows binary path via ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray(`"${example}"`)}\n (Tip: a shell alias like ${pintor__rspack_import_8_default().gray('google-chrome=...')} won't be used by Extension.js, use a real path or wrapper script.)`;
480
491
  })();
481
- return `${getLoggingPrefix('error')} ${isUnreachable}Either install the missing browser or choose a different one via ${pintor__rspack_import_8_default().blue('--browser')} ${pintor__rspack_import_8_default().gray('<chrome|edge|firefox>')}.\n\n${pintor__rspack_import_8_default().red('NOT FOUND')} ${pintor__rspack_import_8_default().underline(browserBinaryLocation || `${capitalizedBrowserName(browser)}BROWSER`)}` + wslHint;
492
+ return `${getLoggingPrefix('error')} ${isUnreachable}${pintor__rspack_import_8_default().gray('NOT FOUND')} ${pintor__rspack_import_8_default().underline(browserBinaryLocation || `${capitalizedBrowserName(browser)}BROWSER`)}\nInstall the missing browser, or choose another one with ${pintor__rspack_import_8_default().blue('--browser')} ${pintor__rspack_import_8_default().gray('<chrome|edge|firefox>')}.` + wslHint;
482
493
  }
483
494
  function usingManagedChromiumFamilyFallback(requestedBrowser, fallbackBrowser, binaryPath) {
484
- return `${getLoggingPrefix('info')} ${managedBrowserDisplayName(requestedBrowser)} is not installed, so the managed ${managedBrowserDisplayName(fallbackBrowser)} runs instead.\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(binaryPath)}\nRun ${pintor__rspack_import_8_default().blue(`npx extension install ${requestedBrowser}`)} to use ${managedBrowserDisplayName(requestedBrowser)} itself.`;
485
- }
486
- function resolvedBrowserBinary(browser, binaryPath, versionLine) {
487
- const version = versionLine && versionLine.trim().length > 0 ? versionLine.trim() : capitalizedBrowserName(browser);
488
- return `${getLoggingPrefix('info')} Browser: ${version} ${pintor__rspack_import_8_default().gray('at')} ${pintor__rspack_import_8_default().underline(binaryPath)}.`;
495
+ return `${getLoggingPrefix('info')} ${managedBrowserDisplayName(requestedBrowser)} isn't installed, so the managed ${managedBrowserDisplayName(fallbackBrowser)} runs instead.\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(binaryPath)}\nRun ${pintor__rspack_import_8_default().blue(`npx extension install ${requestedBrowser}`)} to use ${managedBrowserDisplayName(requestedBrowser)} itself.`;
489
496
  }
490
497
  function preferringSystemBrowserOverSnapshot(systemBinary, snapshotBinary) {
491
- return `${getLoggingPrefix('info')} Use the installed browser instead of the cached Chromium snapshot (a dev-channel build).\n${pintor__rspack_import_8_default().gray('USING')} ${pintor__rspack_import_8_default().underline(systemBinary)}\n${pintor__rspack_import_8_default().gray('CACHED')} ${pintor__rspack_import_8_default().underline(snapshotBinary)}\nSet ${pintor__rspack_import_8_default().blue('EXTENSION_PREFER_CHROMIUM_SNAPSHOT=true')} to use the cached snapshot.`;
498
+ return `${getLoggingPrefix('info')} Using the installed browser instead of the cached Chromium snapshot (a dev-channel build).\n${pintor__rspack_import_8_default().gray('USING')} ${pintor__rspack_import_8_default().underline(systemBinary)}\n${pintor__rspack_import_8_default().gray('CACHED')} ${pintor__rspack_import_8_default().underline(snapshotBinary)}\nSet ${pintor__rspack_import_8_default().blue('EXTENSION_PREFER_CHROMIUM_SNAPSHOT=true')} to use the cached snapshot.`;
492
499
  }
493
500
  function mv2NotSupportedByChromium(extensionPath) {
494
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow('This extension declares Manifest V2, which modern Chromium refuses to load.')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThe browser will reject it at launch (a native dialog, not a console error), so the dev session cannot attach.\nRun it on an MV2-capable browser (${pintor__rspack_import_8_default().blue('--browser firefox')}) or migrate the manifest to MV3.`;
501
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow('This extension declares Manifest V2, which modern Chromium refuses to load.')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThe browser will reject it at launch (a native dialog, not a console error), so the dev session can't attach.\nRun it on an MV2-capable browser (${pintor__rspack_import_8_default().blue('--browser firefox')}) or migrate the manifest to MV3.`;
495
502
  }
496
503
  function mv3BackgroundScriptsNotSupportedByChromium(extensionPath) {
497
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow("This MV3 extension declares Firefox-style background.scripts with no service_worker, Chromium refuses to load it.")}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThe browser rejects it at launch with no console error, so the dev session cannot attach.\nRun it on the browser it targets (${pintor__rspack_import_8_default().blue('--browser firefox')}) or declare ${pintor__rspack_import_8_default().blue('background.service_worker')} for Chromium.`;
504
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow("This MV3 extension declares Firefox-style background.scripts with no service_worker, Chromium refuses to load it.")}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThe browser rejects it at launch with no console error, so the dev session can't attach.\nRun it on the browser it targets (${pintor__rspack_import_8_default().blue('--browser firefox')}) or declare ${pintor__rspack_import_8_default().blue('background.service_worker')} for Chromium.`;
498
505
  }
499
506
  function unsupportedManifestVersionOnChromium(extensionPath, declared) {
500
507
  const value = void 0 === declared ? 'no manifest_version' : `manifest_version ${JSON.stringify(declared)}`;
501
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow(`This extension declares ${value}, which Chromium refuses as an unsupported manifest version.`)}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThe browser rejects it at launch (a native dialog, not a console error), so the dev session cannot attach.\nDeclare ${pintor__rspack_import_8_default().blue('"manifest_version": 3')} in the source manifest.`;
508
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow(`This extension declares ${value}, which Chromium refuses as an unsupported manifest version.`)}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThe browser rejects it at launch (a native dialog, not a console error), so the dev session can't attach.\nDeclare ${pintor__rspack_import_8_default().blue('"manifest_version": 3')} in the source manifest.`;
502
509
  }
503
510
  function chromiumInvalidMatchPatterns(extensionPath, patterns) {
504
511
  const shown = patterns.slice(0, 6);
505
512
  const more = patterns.length - shown.length;
506
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow('This extension declares match patterns Chrome refuses, the whole extension will not load.')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\n` + shown.map((pattern)=>`${pintor__rspack_import_8_default().gray('PATTERN')} ${pintor__rspack_import_8_default().red(pattern)}\n`).join('') + (more > 0 ? `${pintor__rspack_import_8_default().gray(`…and ${more} more`)}\n` : '') + `A match pattern's host wildcard must be ${pintor__rspack_import_8_default().blue('*')} or ${pintor__rspack_import_8_default().blue('*.domain.tld')}, ` + `a wildcard anywhere else in the host is invalid.\n` + `Replace the host with ${pintor__rspack_import_8_default().blue('*')} or ${pintor__rspack_import_8_default().blue('*.domain.tld')} in the source manifest.`;
513
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow("This extension declares match patterns Chrome refuses, the whole extension won't load.")}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\n` + shown.map((pattern)=>`${pintor__rspack_import_8_default().gray('PATTERN')} ${pintor__rspack_import_8_default().red(pattern)}\n`).join('') + (more > 0 ? `${pintor__rspack_import_8_default().gray(`…and ${more} more`)}\n` : '') + `A match pattern's host wildcard must be ${pintor__rspack_import_8_default().blue('*')} or ${pintor__rspack_import_8_default().blue('*.domain.tld')}, ` + `Chrome refuses a wildcard anywhere else in the host.\n` + `Replace the host with ${pintor__rspack_import_8_default().blue('*')} or ${pintor__rspack_import_8_default().blue('*.domain.tld')} in the source manifest.`;
507
514
  }
508
515
  function chromiumManifestLoadBlockers(extensionPath, blockers) {
509
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow('This manifest declares shapes Chrome refuses, the whole extension will not load.')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\n` + blockers.map((blocker)=>`${pintor__rspack_import_8_default().gray('REASON')} ${pintor__rspack_import_8_default().red(blocker)}\n`).join('') + `Chrome rejects the extension at load, so no service worker or content script ever runs.\n` + "Fix these in the source manifest.";
516
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow("This manifest declares shapes Chrome refuses, the whole extension won't load.")}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\n` + blockers.map((blocker)=>`${pintor__rspack_import_8_default().gray('REASON')} ${pintor__rspack_import_8_default().red(blocker)}\n`).join('') + `Chrome rejects the extension at load, so no service worker or content script ever runs.\n` + "Fix these in the source manifest.";
510
517
  }
511
518
  function chromiumExtensionLoadRefused(extensionPath, reason) {
512
- return `${getLoggingPrefix('error')} ${pintor__rspack_import_8_default().red('The browser refused to load this extension, so it is NOT running.')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\n` + (reason ? `${pintor__rspack_import_8_default().gray('REASON')} ${pintor__rspack_import_8_default().red(reason)}\n` : '') + `No service worker, content script, or page from this extension will run, and no Extension ID was assigned.\n` + `Fix the reason above and save.\n` + "If the browser does not pick it up, restart the dev session.";
519
+ return `${getLoggingPrefix('error')} ${pintor__rspack_import_8_default().red("The browser refused to load this extension, so it isn't running.")}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\n` + (reason ? `${pintor__rspack_import_8_default().gray('REASON')} ${pintor__rspack_import_8_default().red(reason)}\n` : '') + `No service worker, content script, or page from this extension will run, and no Extension ID was assigned.\n` + `Fix the reason above and save.\n` + "If the browser doesn't pick it up, restart the dev session.";
513
520
  }
514
521
  function chromiumExtensionLoadUnconfirmed(extensionPath) {
515
- return `${getLoggingPrefix('warn')} Extension.js could not confirm that the browser loaded this extension.\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThis browser rejected the debugging call that loads and verifies it, so the extension may be missing.\nChrome ignores the --load-extension switch unless the DisableLoadExtensionCommandLineSwitch policy is disabled.\nOpen chrome://extensions to check whether the extension is there, and report this if it is not.`;
522
+ return `${getLoggingPrefix('warn')} Extension.js couldn't confirm that the browser loaded this extension.\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionPath)}\nThis browser rejected the debugging call that loads and verifies it, so the extension may be missing.\nChrome ignores the --load-extension switch unless the DisableLoadExtensionCommandLineSwitch policy is disabled.\nOpen chrome://extensions to check whether the extension is there, and report this if it isn't.`;
516
523
  }
517
524
  function geckoAddonLoadRefused(addonPath, reason) {
518
- return `${getLoggingPrefix('error')} ${pintor__rspack_import_8_default().red('The browser refused to load this add-on, so it is NOT running.')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(addonPath)}\n` + (reason ? `${pintor__rspack_import_8_default().gray('REASON')} ${pintor__rspack_import_8_default().red(reason)}\n` : '') + `No background script, content script, or page from this add-on will run, and no Extension ID was assigned.\n` + `Fix the reason above and save.\n` + "If the browser does not pick it up, restart the dev session.";
525
+ return `${getLoggingPrefix('error')} ${pintor__rspack_import_8_default().red("The browser refused to load this add-on, so it isn't running.")}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(addonPath)}\n` + (reason ? `${pintor__rspack_import_8_default().gray('REASON')} ${pintor__rspack_import_8_default().red(reason)}\n` : '') + `No background script, content script, or page from this add-on will run, and no Extension ID was assigned.\n` + `Fix the reason above and save.\n` + "If the browser doesn't pick it up, restart the dev session.";
519
526
  }
520
527
  function devChannelSnapshotInUse(binaryPath) {
521
528
  return `${getLoggingPrefix('warn')} ${pintor__rspack_import_8_default().brightYellow('This is a Chromium tip-of-tree snapshot (dev channel, not a stable release).')}\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(binaryPath)}\nBehavior may differ from stable Chrome.\nInstall a stable browser or remove the snapshot to stop using it.`;
522
529
  }
523
530
  function browserLaunchError(browser, error) {
524
- return `${getLoggingPrefix('error')} Error launching ${capitalizedBrowserName(browser)}:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
531
+ return `${getLoggingPrefix('error')} Can't launch ${capitalizedBrowserName(browser)}.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
525
532
  }
526
533
  function enhancedProcessManagementCleanup(browser) {
527
534
  return `${getLoggingPrefix('debug')} proc cleanup browser=${browser}`;
@@ -530,53 +537,53 @@ var __webpack_modules__ = {
530
537
  return `${getLoggingPrefix('debug')} proc terminate browser=${browser} mode=graceful`;
531
538
  }
532
539
  function enhancedProcessManagementForceKill(browser) {
533
- return `${getLoggingPrefix('warn')} ${capitalizedBrowserName(browser)} did not exit gracefully, forcing the process to close.\nThis is a normal cleanup step and does not affect your build output.`;
540
+ return `${getLoggingPrefix('warn')} ${capitalizedBrowserName(browser)} didn't exit gracefully, forcing the process to close.\nThis is a normal cleanup step and doesn't affect your build output.`;
534
541
  }
535
542
  function enhancedProcessManagementCleanupError(browser, error) {
536
- return `${getLoggingPrefix('error')} Error during ${capitalizedBrowserName(browser)} cleanup:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
543
+ return `${getLoggingPrefix('error')} ${capitalizedBrowserName(browser)} cleanup failed.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
537
544
  }
538
545
  function enhancedProcessManagementUncaughtException(browser, error) {
539
- return `${getLoggingPrefix('error')} Uncaught exception in ${capitalizedBrowserName(browser)} process:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
546
+ return `${getLoggingPrefix('error')} Uncaught exception in the ${capitalizedBrowserName(browser)} process.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
540
547
  }
541
548
  function enhancedProcessManagementUnhandledRejection(browser, reason) {
542
- return `${getLoggingPrefix('error')} Unhandled rejection in ${capitalizedBrowserName(browser)} process:\n${pintor__rspack_import_8_default().red(errorDetail(reason))}`;
549
+ return `${getLoggingPrefix('error')} Unhandled rejection in the ${capitalizedBrowserName(browser)} process.\n${pintor__rspack_import_8_default().red(errorDetail(reason))}`;
543
550
  }
544
551
  function generalBrowserError(browser, error) {
545
- return `${getLoggingPrefix('error')} General error in ${capitalizedBrowserName(browser)}:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
552
+ return `${getLoggingPrefix('error')} ${capitalizedBrowserName(browser)} hit an unexpected error.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
546
553
  }
547
554
  function errorConnectingToBrowser(browser, port) {
548
555
  const where = 'number' == typeof port ? ` on port ${port}` : '';
549
- return `${getLoggingPrefix('error')} Unable to connect to ${capitalizedBrowserName(browser)}${where} after several retries.\nAnother browser instance is usually still holding that debugging port, often one left over from an earlier dev session.\nClose ${capitalizedBrowserName(browser)} windows opened by Extension.js and run the command again, or pass ${pintor__rspack_import_8_default().blue('--profile')} ${pintor__rspack_import_8_default().gray('<path>')} to launch against a separate profile.`;
556
+ return `${getLoggingPrefix('error')} Can't connect to ${capitalizedBrowserName(browser)}${where} after several retries.\nAnother browser instance is usually still holding that debugging port, often one left over from an earlier dev session.\nClose ${capitalizedBrowserName(browser)} windows opened by Extension.js and run the command again, or pass ${pintor__rspack_import_8_default().blue('--profile')} ${pintor__rspack_import_8_default().gray('<path>')} to launch against a separate profile.`;
550
557
  }
551
558
  function waitingForBrowserDebugger(browser, port, attempt, maxRetries) {
552
- return `${getLoggingPrefix('info')} Wait for the ${capitalizedBrowserName(browser)} debugger server on port ${port} (attempt ${attempt}/${maxRetries}).`;
559
+ return `${getLoggingPrefix('debug')} browser debugger=wait target=${browser} port=${port} attempt=${attempt}/${maxRetries}`;
553
560
  }
554
561
  function addonInstallError(browser, message) {
555
- return `${getLoggingPrefix('error')} Can't install add-on into ${capitalizedBrowserName(browser)}:\n${pintor__rspack_import_8_default().red(message)}`;
562
+ return `${getLoggingPrefix('error')} Can't install the add-on into ${capitalizedBrowserName(browser)}.\n${pintor__rspack_import_8_default().red(message)}`;
556
563
  }
557
564
  function messagingClientClosedError(browser) {
558
565
  return `${getLoggingPrefix('error')} The ${capitalizedBrowserName(browser)} messaging channel closed unexpectedly.\nThe browser exited, or its debugging connection was dropped while the dev session was still running.\nCheck whether the browser window was closed by hand, then run the command again.`;
559
566
  }
560
567
  function connectionClosedError(browser) {
561
- return `${getLoggingPrefix('error')} The debugging connection to ${capitalizedBrowserName(browser)} closed unexpectedly.\nReload and HMR need that connection, so the dev session cannot keep the extension up to date.\nRestart the dev session.\nIf it keeps happening, launch with ${pintor__rspack_import_8_default().blue('--profile')} ${pintor__rspack_import_8_default().gray('<path>')} to rule out a corrupted browser profile.`;
568
+ return `${getLoggingPrefix('error')} The debugging connection to ${capitalizedBrowserName(browser)} closed unexpectedly.\nReload and HMR need that connection, so the dev session can't keep the extension up to date.\nRestart the dev session.\nIf it keeps happening, launch with ${pintor__rspack_import_8_default().blue('--profile')} ${pintor__rspack_import_8_default().gray('<path>')} to rule out a corrupted browser profile.`;
562
569
  }
563
570
  function targetActorHasActiveRequestError(browser, targetActor) {
564
571
  return `${getLoggingPrefix('error')} Target actor ${pintor__rspack_import_8_default().gray(targetActor)} has an active request for ${capitalizedBrowserName(browser)}.`;
565
572
  }
566
573
  function parsingPacketError(browser, error) {
567
- return `${getLoggingPrefix('error')} Failed to parse packet from ${capitalizedBrowserName(browser)}:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
574
+ return `${getLoggingPrefix('error')} Can't parse a message from ${capitalizedBrowserName(browser)}.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
568
575
  }
569
576
  function messageWithoutSenderError(browser, message) {
570
- return `${getLoggingPrefix('error')} Message without sender from ${capitalizedBrowserName(browser)}:\n${pintor__rspack_import_8_default().red(JSON.stringify(message))}`;
577
+ return `${getLoggingPrefix('error')} Received a message without a sender from ${capitalizedBrowserName(browser)}.\n${pintor__rspack_import_8_default().red(JSON.stringify(message))}`;
571
578
  }
572
579
  function chromeProcessExited(code) {
573
580
  return `${getLoggingPrefix('debug')} proc exit browser=chrome code=${code}`;
574
581
  }
575
582
  function chromeProcessError(error) {
576
- return `${getLoggingPrefix('error')} Chrome process error:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
583
+ return `${getLoggingPrefix('error')} The Chrome process reported an error.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
577
584
  }
578
585
  function chromeFailedToSpawn(error) {
579
- return `${getLoggingPrefix('error')} Failed to spawn Chrome:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
586
+ return `${getLoggingPrefix('error')} Can't start the Chrome process.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
580
587
  }
581
588
  function chromeInitializingEnhancedReload() {
582
589
  return `${getLoggingPrefix('debug')} proc enhancedReload=init spawn=direct browser=chrome`;
@@ -585,16 +592,16 @@ var __webpack_modules__ = {
585
592
  return `${getLoggingPrefix('debug')} browser locate browser=${browser}`;
586
593
  }
587
594
  function devChromeProfilePath(path) {
588
- return `${getLoggingPrefix('info')} Chrome profile: ${pintor__rspack_import_8_default().underline(path)}`;
595
+ return `${getLoggingPrefix('debug')} browser profile=chrome path=${path}`;
589
596
  }
590
597
  function chromiumDryRunNotLaunching() {
591
- return `${getLoggingPrefix('info')} Dry run: skip the browser launch.`;
598
+ return `${getLoggingPrefix('info')} Dry run: skipping the browser launch.`;
592
599
  }
593
600
  function chromiumDryRunBinary(path) {
594
- return `${getLoggingPrefix('info')} Binary: ${pintor__rspack_import_8_default().underline(path)}.`;
601
+ return `${getLoggingPrefix('info')} ${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(path)}`;
595
602
  }
596
603
  function chromiumDryRunFlags(flags) {
597
- return `${getLoggingPrefix('info')} Flags: ${pintor__rspack_import_8_default().gray(flags)}.`;
604
+ return `${getLoggingPrefix('info')} ${pintor__rspack_import_8_default().gray('FLAGS')} ${pintor__rspack_import_8_default().gray(flags)}`;
598
605
  }
599
606
  function prettyPuppeteerInstallGuidance(browser, rawGuidance, cacheDir) {
600
607
  const dim = pintor__rspack_import_8_default().gray;
@@ -606,9 +613,7 @@ var __webpack_modules__ = {
606
613
  const finalCachePath = browserNorm && cacheDir ? node_path__rspack_import_3.join(cacheDir, browserNorm) : cacheDir;
607
614
  const installCommand = preferredManagedInstallCommand(browserNorm);
608
615
  const browserDisplay = managedBrowserDisplayName(browserNorm);
609
- body.push(`${getLoggingPrefix('warn')} Browser setup required`);
610
- body.push('');
611
- body.push(`${browserDisplay} is not available in the managed browser cache.`);
616
+ body.push(`${getLoggingPrefix('warn')} ${browserDisplay} isn't available in the managed browser cache.`);
612
617
  body.push('');
613
618
  body.push(pintor__rspack_import_8_default().gray(`Install ${browserDisplay} into the managed browser cache:`));
614
619
  body.push('');
@@ -621,9 +626,9 @@ var __webpack_modules__ = {
621
626
  }
622
627
  if (finalCachePath) {
623
628
  body.push('');
624
- body.push(`${dim('INSTALL PATH')} ${pintor__rspack_import_8_default().underline(finalCachePath)}`);
629
+ body.push(`${dim('PATH')} ${pintor__rspack_import_8_default().underline(finalCachePath)}`);
625
630
  }
626
- body.push(`${dim('NEXT')} Re-run your command after the install finishes.`);
631
+ body.push("Run your command again after the install finishes.");
627
632
  return `${body.join('\n')}\n`;
628
633
  }
629
634
  function firefoxLaunchCalled() {
@@ -636,16 +641,16 @@ var __webpack_modules__ = {
636
641
  return `${getLoggingPrefix('debug')} browser args=none`;
637
642
  }
638
643
  function firefoxFailedToStart(error) {
639
- return `${getLoggingPrefix('error')} Firefox failed to start:\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
644
+ return `${getLoggingPrefix('error')} Firefox failed to start.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
640
645
  }
641
646
  function firefoxDryRunNotLaunching() {
642
- return `${getLoggingPrefix('info')} Dry run: skip the browser launch.`;
647
+ return `${getLoggingPrefix('info')} Dry run: skipping the browser launch.`;
643
648
  }
644
649
  function firefoxDryRunBinary(path) {
645
- return `${getLoggingPrefix('info')} Binary (detected): ${pintor__rspack_import_8_default().underline(path)}.`;
650
+ return `${getLoggingPrefix('info')} ${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(path)}`;
646
651
  }
647
652
  function firefoxDryRunConfig(cfg) {
648
- return `${getLoggingPrefix('info')} Config: ${pintor__rspack_import_8_default().gray(cfg)}.`;
653
+ return `${getLoggingPrefix('info')} ${pintor__rspack_import_8_default().gray('CONFIG')} ${pintor__rspack_import_8_default().gray(cfg)}`;
649
654
  }
650
655
  function safariBuildCalled() {
651
656
  return `${getLoggingPrefix('debug')} browser build browser=safari`;
@@ -659,29 +664,29 @@ var __webpack_modules__ = {
659
664
  return `${getLoggingPrefix('warn')} Safari extensions can only be built on macOS.\nDetected ${pintor__rspack_import_8_default().gray(prettyPlatform(platform))}.\nTarget another browser via ${pintor__rspack_import_8_default().blue('--browser')} ${pintor__rspack_import_8_default().gray('<chrome|edge|firefox>')}, or run this command on a Mac with Xcode.`;
660
665
  }
661
666
  function safariPackagingSkippedNonMac(platform) {
662
- return `${getLoggingPrefix('warn')} Safari packaging needs macOS with Xcode, detected ${pintor__rspack_import_8_default().gray(prettyPlatform(platform))}, so the Xcode packaging step is skipped.\nThe web-extension build in ${pintor__rspack_import_8_default().yellow('dist/safari')} is still complete and can be packaged later on a Mac with ${pintor__rspack_import_8_default().blue('extension build --browser=safari')}.`;
667
+ return `${getLoggingPrefix('warn')} Safari packaging needs macOS with Xcode, detected ${pintor__rspack_import_8_default().gray(prettyPlatform(platform))}, so the Xcode packaging step is skipped.\nThe web-extension build in ${pintor__rspack_import_8_default().underline('dist/safari')} is still complete and can be packaged later on a Mac with ${pintor__rspack_import_8_default().blue('extension build --browser=safari')}.`;
663
668
  }
664
669
  function safariXcodeRequired(developerDir) {
665
670
  const current = developerDir ? `${pintor__rspack_import_8_default().gray('Active toolchain:')} ${pintor__rspack_import_8_default().underline(developerDir)}` : `${pintor__rspack_import_8_default().gray('No active developer directory was found.')}`;
666
671
  return `${getLoggingPrefix('error')} Safari packaging needs the full Xcode app (not just the Command Line Tools).\n${pintor__rspack_import_8_default().red('NOT FOUND')} ${pintor__rspack_import_8_default().underline('safari-web-extension-converter')}\n${current}\n\nTo enable Safari builds:\n- Install ${pintor__rspack_import_8_default().yellow('Xcode')} from the Mac App Store, then\n- Point the toolchain at it: ${pintor__rspack_import_8_default().blue('sudo xcode-select --switch')} ${pintor__rspack_import_8_default().gray('/Applications/Xcode.app')}\n- Finish setup once: ${pintor__rspack_import_8_default().blue('xcodebuild -runFirstLaunch')}\n\nPrefer to keep building now?\nTarget another browser via ${pintor__rspack_import_8_default().blue('--browser')} ${pintor__rspack_import_8_default().gray('<chrome|edge|firefox>')}.`;
667
672
  }
668
673
  function safariToolchainMissing(tool) {
669
- return `${getLoggingPrefix('error')} Safari packaging tool not found: ${pintor__rspack_import_8_default().underline(tool)}\nYour Xcode install looks incomplete.\nTry ${pintor__rspack_import_8_default().blue('xcodebuild -runFirstLaunch')}, or reinstall Xcode from the Mac App Store.`;
674
+ return `${getLoggingPrefix('error')} Can't find the Safari packaging tool.\n${pintor__rspack_import_8_default().gray('NOT FOUND')} ${pintor__rspack_import_8_default().underline(tool)}\nYour Xcode install looks incomplete.\nRun ${pintor__rspack_import_8_default().blue('xcodebuild -runFirstLaunch')}, or reinstall Xcode from the Mac App Store.`;
670
675
  }
671
676
  function safariConverting(extensionDir) {
672
- return `${getLoggingPrefix('info')} Convert the web extension into a Safari app project from ${pintor__rspack_import_8_default().underline(extensionDir)}.`;
677
+ return `${getLoggingPrefix('info')} Converting the web extension into a Safari app project…\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(extensionDir)}`;
673
678
  }
674
679
  function safariConverted(projectDir) {
675
- return `${getLoggingPrefix('success')} Generated the Safari Xcode project at ${pintor__rspack_import_8_default().underline(projectDir)}.`;
680
+ return `${getLoggingPrefix('success')} Generated the Safari Xcode project.\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(projectDir)}`;
676
681
  }
677
682
  function safariBuilding(scheme) {
678
- return `${getLoggingPrefix('info')} Build the Safari app with xcodebuild (scheme: ${pintor__rspack_import_8_default().gray(scheme)}).`;
683
+ return `${getLoggingPrefix('info')} Building the Safari app with xcodebuild (scheme ${pintor__rspack_import_8_default().gray(scheme)})…`;
679
684
  }
680
685
  function safariBuilt(appPath) {
681
- return `${getLoggingPrefix('success')} Built the Safari app at ${pintor__rspack_import_8_default().underline(appPath)}.`;
686
+ return `${getLoggingPrefix('success')} Built the Safari app.\n${pintor__rspack_import_8_default().gray('PATH')} ${pintor__rspack_import_8_default().underline(appPath)}`;
682
687
  }
683
688
  function safariOpening(target) {
684
- return `${getLoggingPrefix('info')} Open ${pintor__rspack_import_8_default().underline(target)}.`;
689
+ return `${getLoggingPrefix('info')} Opening ${pintor__rspack_import_8_default().underline(target)}`;
685
690
  }
686
691
  function safariToolFailed(tool, exitCode, outputTail) {
687
692
  const code = null === exitCode ? 'no exit code' : `exit ${exitCode}`;
@@ -689,13 +694,13 @@ var __webpack_modules__ = {
689
694
  return `${getLoggingPrefix('error')} Safari packaging tool ${pintor__rspack_import_8_default().underline(tool)} failed (${pintor__rspack_import_8_default().red(code)}).${tail}`;
690
695
  }
691
696
  function safariConverterWarnings(warnings) {
692
- return `${getLoggingPrefix('warn')} safari-web-extension-converter reported ${pintor__rspack_import_8_default().yellow(String(warnings.length))} warning(s), some manifest keys/APIs may not be supported by Safari:\n` + warnings.map((line)=>` ${pintor__rspack_import_8_default().gray('•')} ${line}`).join('\n');
697
+ return `${getLoggingPrefix('warn')} safari-web-extension-converter reported ${pintor__rspack_import_8_default().yellow(String(warnings.length))} ${1 === warnings.length ? 'warning' : 'warnings'}, some manifest keys/APIs may not be supported by Safari:\n` + warnings.map((line)=>` ${pintor__rspack_import_8_default().gray('•')} ${line}`).join('\n');
693
698
  }
694
699
  function safariDefaultBundleIdNote(bundleId) {
695
- return `${getLoggingPrefix('info')} Use the generated bundle id ${pintor__rspack_import_8_default().gray(bundleId)}.\nFor an app you plan to distribute, set your own with ${pintor__rspack_import_8_default().blue('--bundle-id')} now.\nChanging it later makes Safari treat the extension as a new identity.`;
700
+ return `${getLoggingPrefix('info')} Using the generated bundle id ${pintor__rspack_import_8_default().gray(bundleId)}.\nFor an app you plan to distribute, set your own with ${pintor__rspack_import_8_default().blue('--bundle-id')} now.\nChanging it later makes Safari treat the extension as a new identity.`;
696
701
  }
697
702
  function safariOpenHint(appPath, appName) {
698
- return `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\nThen enable ${pintor__rspack_import_8_default().brightBlue(appName)} via Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
703
+ return `${getLoggingPrefix('info')} Launch it once to register with Safari: ${pintor__rspack_import_8_default().blue('open')} ${pintor__rspack_import_8_default().underline(`"${appPath}"`)}\nThen enable ${pintor__rspack_import_8_default().yellow(appName)} via Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} and Safari ▸ Settings ▸ Extensions.`;
699
704
  }
700
705
  function safariDryRunNotBuilding() {
701
706
  return `${getLoggingPrefix('info')} Dry run: skip the Safari app build.`;
@@ -707,22 +712,22 @@ var __webpack_modules__ = {
707
712
  return `${getLoggingPrefix('info')} xcodebuild: ${pintor__rspack_import_8_default().gray(cmd)}.`;
708
713
  }
709
714
  function safariNextSteps(appName) {
710
- return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().brightBlue(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Advanced ▸ check ${pintor__rspack_import_8_default().yellow('“Show features for web developers”')}\n ${pintor__rspack_import_8_default().gray('2.')} Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} ${pintor__rspack_import_8_default().gray('(resets each launch)')}\n ${pintor__rspack_import_8_default().gray('3.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} The app window that just opened can also take you there.`;
715
+ return `${getLoggingPrefix('info')} One-time setup to load ${pintor__rspack_import_8_default().yellow(appName)} in Safari:\n ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Advanced ▸ check ${pintor__rspack_import_8_default().yellow('“Show features for web developers”')}\n ${pintor__rspack_import_8_default().gray('2.')} Safari ▸ Develop ▸ ${pintor__rspack_import_8_default().yellow('Allow Unsigned Extensions')} ${pintor__rspack_import_8_default().gray('(resets each launch)')}\n ${pintor__rspack_import_8_default().gray('3.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${pintor__rspack_import_8_default().yellow(appName)}\n ${pintor__rspack_import_8_default().gray('→')} The app window that just opened can also take you there.`;
711
716
  }
712
717
  function safariRegistered(appName) {
713
- return `${getLoggingPrefix('success')} Safari recognizes ${pintor__rspack_import_8_default().brightBlue(appName)}, finish enabling it with the steps above.`;
718
+ return `${getLoggingPrefix('success')} Safari recognizes ${pintor__rspack_import_8_default().yellow(appName)}, finish enabling it with the steps above.`;
714
719
  }
715
720
  function safariNotYetRegistered(appName) {
716
- return `${getLoggingPrefix('warn')} Safari hasn't picked up ${pintor__rspack_import_8_default().brightBlue(appName)} yet.\nOpen the app once, then check Safari ▸ Settings ▸ Extensions.`;
721
+ return `${getLoggingPrefix('warn')} Safari hasn't picked up ${pintor__rspack_import_8_default().yellow(appName)} yet.\nOpen the app once, then check Safari ▸ Settings ▸ Extensions.`;
717
722
  }
718
723
  function safariRebuilt(appName) {
719
- return `${getLoggingPrefix('success')} Rebuilt ${pintor__rspack_import_8_default().brightBlue(appName)}, reload the page (or toggle the extension) in Safari to see changes.`;
724
+ return `${getLoggingPrefix('success')} Rebuilt ${pintor__rspack_import_8_default().yellow(appName)}, reload the page (or toggle the extension) in Safari to see changes.`;
720
725
  }
721
726
  function safariProjectStale() {
722
- return `${getLoggingPrefix('info')} Regenerate the Xcode project, manifest.json or identity options changed since it was generated.`;
727
+ return `${getLoggingPrefix('info')} Regenerating the Xcode project, manifest.json or identity options changed since it was generated.`;
723
728
  }
724
729
  function safariForcedRegeneration() {
725
- return `${getLoggingPrefix('info')} Regenerate the Xcode project, --force-regenerate is set.`;
730
+ return `${getLoggingPrefix('info')} Regenerating the Xcode project, ${pintor__rspack_import_8_default().blue('--force-regenerate')} is set.`;
726
731
  }
727
732
  function safariRegenerationDiscards(preservedKeys) {
728
733
  return `${getLoggingPrefix('warn')} Regenerating replaces the Xcode project: customizations made in Xcode (entitlements, capabilities, added files/targets) are ${pintor__rspack_import_8_default().red('discarded')}.\nPreserved automatically: ${pintor__rspack_import_8_default().yellow(preservedKeys.join(', '))}.\nIf you customized the project, back it up before continuing.`;
@@ -731,7 +736,7 @@ var __webpack_modules__ = {
731
736
  return `${getLoggingPrefix('info')} Preserved Xcode build settings across regeneration: ${pintor__rspack_import_8_default().yellow(keys.join(', '))}.\nIf any other project-level tweaks were lost, reconfigure them in Xcode.`;
732
737
  }
733
738
  function safariSkippingConversion() {
734
- return `${getLoggingPrefix('info')} Skip the conversion, the Xcode project is up to date with manifest.json.`;
739
+ return `${getLoggingPrefix('info')} Skipping the conversion, the Xcode project is up to date with manifest.json.`;
735
740
  }
736
741
  function cdpClientFoundTargets(count) {
737
742
  return `${getLoggingPrefix('debug')} cdp targets=${count}`;
@@ -743,7 +748,7 @@ var __webpack_modules__ = {
743
748
  return `${getLoggingPrefix('debug')} cdp connected host=${host} port=${port}`;
744
749
  }
745
750
  function cdpClientConnectionError(error) {
746
- return `${getLoggingPrefix('error')} Chrome CDP Client connection error: ${pintor__rspack_import_8_default().red(error)}`;
751
+ return `${getLoggingPrefix('error')} The Chrome debugging connection failed.\n${pintor__rspack_import_8_default().red(error)}`;
747
752
  }
748
753
  function cdpClientBrowserConnectionEstablished() {
749
754
  return `${getLoggingPrefix('debug')} cdp browserConnection=established`;
@@ -752,11 +757,26 @@ var __webpack_modules__ = {
752
757
  return `${getLoggingPrefix('debug')} cdp connection=closed`;
753
758
  }
754
759
  function cdpClientExtensionInfoFailed(extensionId, error) {
755
- return `${getLoggingPrefix('error')} Chrome CDP Client: Failed to get extension info for ${pintor__rspack_import_8_default().gray(extensionId)}: ${pintor__rspack_import_8_default().red(error)}`;
760
+ return `${getLoggingPrefix('error')} Chrome couldn't read extension info for ${pintor__rspack_import_8_default().gray(extensionId)}.\n${pintor__rspack_import_8_default().red(error)}`;
756
761
  }
757
762
  function firefoxRdpClientConnected(host, port) {
758
763
  return `${getLoggingPrefix('debug')} rdp connected host=${host} port=${port}`;
759
764
  }
765
+ function collapseHomeDirInCardValue(value) {
766
+ const raw = String(value || '');
767
+ const home = node_os__rspack_import_2.homedir();
768
+ if (!home || !raw.startsWith(home)) return raw;
769
+ const rest = raw.slice(home.length);
770
+ if ('' === rest) return '~';
771
+ if (rest.startsWith(node_path__rspack_import_3.sep) || rest.startsWith('/')) return `~${rest}`;
772
+ return raw;
773
+ }
774
+ function binaryProvenanceNote(provenance) {
775
+ if ('pinned' === provenance) return '(pinned with --chromium-binary)';
776
+ if ('system' === provenance) return '(system, not the managed default)';
777
+ if ('snapshot' === provenance) return '(cached snapshot)';
778
+ return '';
779
+ }
760
780
  function runningInDevelopment(manifest, browser, message, browserVersionLine, updateSuffix, opts) {
761
781
  const capitalize = (str)=>str.charAt(0).toUpperCase() + str.slice(1);
762
782
  const manifestName = manifest.name || 'Extension.js';
@@ -775,10 +795,10 @@ var __webpack_modules__ = {
775
795
  default:
776
796
  browserDevToolsUrl = '';
777
797
  }
778
- if (!message.data) return `${getLoggingPrefix('error')} No Client Data Received for ${manifestName}\n\n${pintor__rspack_import_8_default().red("This error happens when the program can't get the data from your extension.")}\n${pintor__rspack_import_8_default().red('There are many reasons this might happen.')}\n${pintor__rspack_import_8_default().red('To fix, ensure that:')}\n\n- Your extension is set as enabled in ${pintor__rspack_import_8_default().underline(browserDevToolsUrl)}\n- No previous ${capitalize(browser)} browser instance is open\n\nIf that is not the case, restart both the ${pintor__rspack_import_8_default().yellow(manifest.name || '')} and the\n${pintor__rspack_import_8_default().yellow('Manager Extension')} in ${pintor__rspack_import_8_default().underline(browserDevToolsUrl)} and try again.\nIf the issue still persists, please report a bug:\n` + pintor__rspack_import_8_default().underline("https://github.com/extension-js/extension.js/issues");
798
+ if (!message.data) return `${getLoggingPrefix('error')} No client data received for ${manifestName}.\n\n${pintor__rspack_import_8_default().red("Extension.js can't read data from your extension.")}\n${pintor__rspack_import_8_default().red('To fix, ensure that:')}\n\n- Your extension is enabled in ${pintor__rspack_import_8_default().underline(browserDevToolsUrl)}\n- No previous ${capitalize(browser)} browser instance is open\n\nIf both hold, restart the ${pintor__rspack_import_8_default().yellow(manifest.name || '')} and the\n${pintor__rspack_import_8_default().yellow('Manager Extension')} in ${pintor__rspack_import_8_default().underline(browserDevToolsUrl)} and try again.\nIf the issue persists, report a bug:\n` + pintor__rspack_import_8_default().underline("https://github.com/extension-js/extension.js/issues");
779
799
  const { id = '', management } = message.data;
780
800
  if (!management) {
781
- if ((0, _helpers_messaging__rspack_import_9._o)()) return `${getLoggingPrefix('error')} No management API info received from the client for ${manifestName}.\nThe extension may not have finished loading, or the in-browser companion did not attach.`;
801
+ if ((0, _helpers_messaging__rspack_import_9._o)()) return `${getLoggingPrefix('error')} No management API info received from the client for ${manifestName}.\nThe extension may not have finished loading, or the in-browser companion didn't attach.`;
782
802
  }
783
803
  const { version = '' } = management;
784
804
  const extensionVersion = process.env.EXTENSION_DEVELOP_VERSION || process.env.EXTENSION_CLI_VERSION || (()=>{
@@ -788,7 +808,10 @@ var __webpack_modules__ = {
788
808
  return 'unknown';
789
809
  }
790
810
  })();
791
- const browserLabel = (0, _helpers_messaging__rspack_import_9.A6)(String(browser || 'unknown'), resolveBrowserVersionLine(browser, browserVersionLine));
811
+ const baseBrowserLabel = (0, _helpers_messaging__rspack_import_9.A6)(String(browser || 'unknown'), resolveBrowserVersionLine(browser, browserVersionLine));
812
+ const provenanceNote = binaryProvenanceNote(opts?.binaryProvenance);
813
+ const browserLabel = provenanceNote ? `${baseBrowserLabel} ${provenanceNote}` : baseBrowserLabel;
814
+ const binaryRowValue = provenanceNote ? collapseHomeDirInCardValue(String(opts?.binaryPath || '').trim()) : '';
792
815
  const cleanId = String(id || '').trim();
793
816
  const includeExtensionId = opts?.includeExtensionId !== false;
794
817
  const updateNotice = updateSuffix ? ` ${updateSuffix}` : '';
@@ -802,6 +825,10 @@ var __webpack_modules__ = {
802
825
  label: 'Browser',
803
826
  value: browserLabel
804
827
  },
828
+ {
829
+ label: 'Binary',
830
+ value: binaryRowValue
831
+ },
805
832
  {
806
833
  label: 'Extension',
807
834
  value: displayVersion ? `${displayName} ${displayVersion}` : displayName
@@ -812,7 +839,7 @@ var __webpack_modules__ = {
812
839
  },
813
840
  {
814
841
  label: 'Profile',
815
- value: String(opts?.profilePath || '').trim()
842
+ value: collapseHomeDirInCardValue(String(opts?.profilePath || '').trim())
816
843
  },
817
844
  {
818
845
  label: 'Run ID',
@@ -825,13 +852,13 @@ var __webpack_modules__ = {
825
852
  return ' ';
826
853
  }
827
854
  function devChromiumDebugPort(finalPort, requestedPort) {
828
- return `${getLoggingPrefix('info')} Chromium debug port: ${pintor__rspack_import_8_default().gray(finalPort.toString())} (requested ${pintor__rspack_import_8_default().gray(requestedPort.toString())})`;
855
+ return `${getLoggingPrefix('debug')} browser cdpPort=${finalPort} requested=${requestedPort}`;
829
856
  }
830
857
  function devFirefoxDebugPort(finalPort, requestedPort) {
831
- return `${getLoggingPrefix('info')} Firefox debug port: ${pintor__rspack_import_8_default().gray(finalPort.toString())} (requested ${pintor__rspack_import_8_default().gray(requestedPort.toString())})`;
858
+ return `${getLoggingPrefix('debug')} browser rdpPort=${finalPort} requested=${requestedPort}`;
832
859
  }
833
860
  function devFirefoxProfilePath(profilePath) {
834
- return `${getLoggingPrefix('info')} Firefox profile: ${pintor__rspack_import_8_default().underline(profilePath)}`;
861
+ return `${getLoggingPrefix('debug')} browser profile=firefox path=${profilePath}`;
835
862
  }
836
863
  function cdpUnifiedExtensionLog(ts, payload) {
837
864
  const data = (()=>{
@@ -844,22 +871,22 @@ var __webpack_modules__ = {
844
871
  return `[extension-log ${ts}] ${data}`;
845
872
  }
846
873
  function browserRunnerError(body) {
847
- return `${getLoggingPrefix('error')} ${pintor__rspack_import_8_default().brightBlue('Browser runner error')}\n${body}`;
874
+ return `${getLoggingPrefix('error')} ${body}`;
848
875
  }
849
876
  function requireChromiumBinaryForChromiumBased() {
850
- const body = `Configuration required\nProvide ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} when using ${pintor__rspack_import_8_default().yellow('chromium-based')}.\n`;
877
+ const body = `The ${pintor__rspack_import_8_default().yellow('chromium-based')} target needs a Chromium binary.\nPass ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} to choose one.\n`;
851
878
  return browserRunnerError(body);
852
879
  }
853
880
  function requireGeckoBinaryForGeckoBased() {
854
- const body = `Configuration required\nProvide ${pintor__rspack_import_8_default().blue('--gecko-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} when using ${pintor__rspack_import_8_default().yellow('gecko-based')} or ${pintor__rspack_import_8_default().yellow('firefox-based')}.\n`;
881
+ const body = `The ${pintor__rspack_import_8_default().yellow('gecko-based')} and ${pintor__rspack_import_8_default().yellow('firefox-based')} targets need a Firefox or Gecko binary.\nPass ${pintor__rspack_import_8_default().blue('--gecko-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} to choose one.\n`;
855
882
  return browserRunnerError(body);
856
883
  }
857
884
  function invalidChromiumBinaryPath(p) {
858
- const body = `Invalid binary path\nChromium binary not found at ${pintor__rspack_import_8_default().underline(p)}.\nProvide a working path via ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')}.`;
885
+ const body = `Can't find a Chromium binary at the given path.\n${pintor__rspack_import_8_default().gray('NOT FOUND')} ${pintor__rspack_import_8_default().underline(p)}\nPass ${pintor__rspack_import_8_default().blue('--chromium-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} with a working path.`;
859
886
  return browserRunnerError(body);
860
887
  }
861
888
  function invalidGeckoBinaryPath(p) {
862
- const body = `Invalid binary path\nFirefox/Gecko binary not found at ${pintor__rspack_import_8_default().underline(p)}.\nProvide a working path via ${pintor__rspack_import_8_default().blue('--gecko-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')}.`;
889
+ const body = `Can't find a Firefox or Gecko binary at the given path.\n${pintor__rspack_import_8_default().gray('NOT FOUND')} ${pintor__rspack_import_8_default().underline(p)}\nPass ${pintor__rspack_import_8_default().blue('--gecko-binary')} ${pintor__rspack_import_8_default().gray('<abs-path>')} with a working path.`;
863
890
  return browserRunnerError(body);
864
891
  }
865
892
  function rdpInvalidRequestPayload() {
@@ -917,6 +944,7 @@ var __webpack_modules__ = {
917
944
  WV: ()=>addonInstallError,
918
945
  XH: ()=>enhancedProcessManagementTerminating,
919
946
  Xi: ()=>safariXcodeRequired,
947
+ Yy: ()=>collapseHomeDirInCardValue,
920
948
  Z5: ()=>cdpClientExtensionInfoFailed,
921
949
  _D: ()=>browserLaunchError,
922
950
  aI: ()=>devChromeProfilePath,
@@ -934,7 +962,6 @@ var __webpack_modules__ = {
934
962
  fd: ()=>safariRegistered,
935
963
  fw: ()=>safariOpening,
936
964
  hE: ()=>cdpClientConnectionClosed,
937
- iL: ()=>resolvedBrowserBinary,
938
965
  io: ()=>emptyLine,
939
966
  iv: ()=>firefoxBinaryArgsExtracted,
940
967
  jP: ()=>rdpInvalidRequestPayload,
@@ -959,6 +986,7 @@ var __webpack_modules__ = {
959
986
  sY: ()=>creatingUserProfile,
960
987
  uK: ()=>safariConverting,
961
988
  wk: ()=>chromeFailedToSpawn,
989
+ xX: ()=>binaryProvenanceNote,
962
990
  xy: ()=>chromeInitializingEnhancedReload,
963
991
  y1: ()=>safariConverterWarnings,
964
992
  y7: ()=>skippingBrowserLaunchDueToCompileErrors,
@@ -1242,11 +1270,10 @@ var __webpack_modules__ = {
1242
1270
  var pintor__rspack_import_0_default = /*#__PURE__*/ __webpack_require__.n(pintor__rspack_import_0);
1243
1271
  var _helpers_messaging__rspack_import_1 = __webpack_require__("./helpers/messaging.ts");
1244
1272
  function ready(mode, browser) {
1245
- const key = String(browser || '').toLowerCase();
1246
- const extensionOutput = (0, _helpers_messaging__rspack_import_1.T_)(key);
1247
- const cap = 'firefox' === key || 'gecko-based' === key || 'firefox-based' === key ? 'Firefox' : String(browser || '').charAt(0).toUpperCase() + String(browser || '').slice(1);
1248
- const pretty = pintor__rspack_import_0_default().green(`ready for ${mode}`);
1249
- return `${(0, _helpers_messaging__rspack_import_1.Pl)('info')} ${cap} ${extensionOutput} ${pretty}.`;
1273
+ const noun = (0, _helpers_messaging__rspack_import_1.T_)(browser);
1274
+ const state = pintor__rspack_import_0_default().green(`ready for ${mode}`);
1275
+ const watching = 'development' === mode ? ' Watching for file changes.' : '';
1276
+ return `${(0, _helpers_messaging__rspack_import_1.Pl)('success')} ${noun} ${state}.${watching}`;
1250
1277
  }
1251
1278
  __webpack_require__.d(__webpack_exports__, {
1252
1279
  G: ()=>ready
@@ -1534,6 +1561,16 @@ var __webpack_modules__ = {
1534
1561
  swappedToSystem: false
1535
1562
  };
1536
1563
  }
1564
+ function classifyBinaryProvenance(opts) {
1565
+ if (opts.pinnedByFlag) return 'pinned';
1566
+ if (opts.usedManagedSnapshot) return 'snapshot';
1567
+ const root = node_path__rspack_import_3.resolve(String(opts.managedCacheRoot || '').trim());
1568
+ const binary = node_path__rspack_import_3.resolve(String(opts.binaryPath || '').trim());
1569
+ if (!root || !binary) return 'system';
1570
+ const relative = node_path__rspack_import_3.relative(root, binary);
1571
+ const underManagedRoot = relative.length > 0 && !relative.startsWith('..') && !node_path__rspack_import_3.isAbsolute(relative);
1572
+ return underManagedRoot ? 'managed' : 'system';
1573
+ }
1537
1574
  function parseEnvBrowserFlags(raw) {
1538
1575
  return String(raw || '').split(/\s+/).map((flag)=>flag.trim()).filter(Boolean);
1539
1576
  }
@@ -1709,6 +1746,7 @@ var __webpack_modules__ = {
1709
1746
  J1: ()=>prepareChromiumProfileForLaunch,
1710
1747
  Py: ()=>mergeChromiumFeatureSwitches,
1711
1748
  RE: ()=>markManagedEphemeralProfile,
1749
+ RU: ()=>classifyBinaryProvenance,
1712
1750
  W0: ()=>parseEnvBrowserFlags,
1713
1751
  ZO: ()=>isHeadlessGuardRequested,
1714
1752
  aY: ()=>findAvailablePortNear,
@@ -2660,7 +2698,9 @@ var __webpack_modules__ = {
2660
2698
  browser: args.browser,
2661
2699
  outPath: extensionOutputPath,
2662
2700
  browserVersionLine: args.browserVersionLine,
2663
- profilePath
2701
+ profilePath,
2702
+ binaryPath: args.binaryPath,
2703
+ binaryProvenance: args.binaryProvenance
2664
2704
  });
2665
2705
  if ('development' !== mode) return;
2666
2706
  const ready = await (0, manifest_readiness.fR)(extensionOutputPath, {
@@ -2674,7 +2714,9 @@ var __webpack_modules__ = {
2674
2714
  hostPort: args.hostPort,
2675
2715
  getInfo: async ()=>null,
2676
2716
  browserVersionLine: args.browserVersionLine,
2677
- profilePath
2717
+ profilePath,
2718
+ binaryPath: args.binaryPath,
2719
+ binaryProvenance: args.binaryProvenance
2678
2720
  });
2679
2721
  }
2680
2722
  class ChromiumLaunchPlugin {
@@ -2724,6 +2766,8 @@ var __webpack_modules__ = {
2724
2766
  const browser = this.options?.browser;
2725
2767
  let browserBinaryLocation = null;
2726
2768
  let printedGuidance = false;
2769
+ let binaryPinnedByFlag = false;
2770
+ let usedManagedSnapshot = false;
2727
2771
  const normalizePath = (p)=>{
2728
2772
  if (!p) return null;
2729
2773
  const normalized = (0, wsl_support.f7)(p);
@@ -2799,7 +2843,10 @@ var __webpack_modules__ = {
2799
2843
  if (choice.swappedToSystem && choice.binary) {
2800
2844
  console.log(messages.kK(choice.binary, browserBinaryLocation));
2801
2845
  browserBinaryLocation = choice.binary;
2802
- } else if (choice.usedManagedSnapshot) console.log(messages.JB(browserBinaryLocation));
2846
+ } else if (choice.usedManagedSnapshot) {
2847
+ usedManagedSnapshot = true;
2848
+ console.log(messages.JB(browserBinaryLocation));
2849
+ }
2803
2850
  }
2804
2851
  let skipDetection = Boolean(browserBinaryLocation);
2805
2852
  if (!browserBinaryLocation && (0, wsl_support.EV)()) {
@@ -2908,6 +2955,7 @@ var __webpack_modules__ = {
2908
2955
  process.exit(1);
2909
2956
  }
2910
2957
  browserBinaryLocation = normalized;
2958
+ binaryPinnedByFlag = true;
2911
2959
  }
2912
2960
  if (!browserBinaryLocation && !skipDetection) try {
2913
2961
  const env = managedEnvFor('chromium');
@@ -2970,6 +3018,7 @@ var __webpack_modules__ = {
2970
3018
  process.exit(1);
2971
3019
  }
2972
3020
  browserBinaryLocation = normalized;
3021
+ binaryPinnedByFlag = true;
2973
3022
  } else {
2974
3023
  console.error(messages.ne());
2975
3024
  process.exit(1);
@@ -3013,7 +3062,12 @@ var __webpack_modules__ = {
3013
3062
  const vLine = getBrowserVersionLine(browserBinaryLocation);
3014
3063
  if (vLine && vLine.trim().length > 0) browserVersionLine = vLine.trim();
3015
3064
  } catch {}
3016
- console.log(messages.iL(browser, browserBinaryLocation, browserVersionLine));
3065
+ const binaryProvenance = shared_utils.RU({
3066
+ binaryPath: browserBinaryLocation,
3067
+ managedCacheRoot: String(managedCacheRoot || ''),
3068
+ pinnedByFlag: binaryPinnedByFlag,
3069
+ usedManagedSnapshot
3070
+ });
3017
3071
  const extensionsToLoad = (0, runtime_options.fT)(this.options.extension);
3018
3072
  const resolvedBrowserVersion = /(\d+(?:\.\d+){0,3})/.exec(browserVersionLine || '')?.[1];
3019
3073
  for (const extPath of extensionsToLoad)try {
@@ -3067,6 +3121,8 @@ var __webpack_modules__ = {
3067
3121
  port: selectedPort
3068
3122
  },
3069
3123
  browserVersionLine,
3124
+ binaryPath: browserBinaryLocation,
3125
+ binaryProvenance,
3070
3126
  enableCdp
3071
3127
  });
3072
3128
  } catch {}
@@ -3111,7 +3167,9 @@ var __webpack_modules__ = {
3111
3167
  logSink: this.options.logSink,
3112
3168
  bannerPrintedOnce: false,
3113
3169
  cdpController: void 0,
3114
- browserVersionLine
3170
+ browserVersionLine,
3171
+ binaryPath: browserBinaryLocation,
3172
+ binaryProvenance
3115
3173
  };
3116
3174
  if (enableCdp) {
3117
3175
  const mod = await __webpack_require__.e(49).then(__webpack_require__.bind(__webpack_require__, "./browsers/run-chromium/chromium-launch/setup-cdp-after-launch.ts"));
@@ -4410,7 +4468,7 @@ var __webpack_modules__ = {
4410
4468
  } catch (error) {
4411
4469
  if (isErrorWithCode('ECONNREFUSED', error)) {
4412
4470
  lastError = error;
4413
- if (attempt % RETRY_LOG_EVERY_N_ATTEMPTS === 0) console.log(messages.GB(this.options.browser, port, attempt, MAX_RETRIES));
4471
+ if ((0, messaging._o)() && attempt % RETRY_LOG_EVERY_N_ATTEMPTS === 0) console.log(messages.GB(this.options.browser, port, attempt, MAX_RETRIES));
4414
4472
  await new Promise((resolve)=>setTimeout(resolve, RETRY_INTERVAL));
4415
4473
  } else {
4416
4474
  const err = error;
@@ -6256,7 +6314,7 @@ var __webpack_modules__ = {
6256
6314
  required: false
6257
6315
  }
6258
6316
  ],
6259
- description: 'Inspect a page or content DOM through the agent bridge (CDP-free; requires --allow-control)',
6317
+ description: 'Inspect a page or content DOM through the agent bridge (CDP-free, requires --allow-control)',
6260
6318
  supportsSourceInspection: true
6261
6319
  },
6262
6320
  {
@@ -6378,8 +6436,8 @@ var __webpack_modules__ = {
6378
6436
  function checkUpdates(packageJson, update) {
6379
6437
  const latest = String(update.latest);
6380
6438
  const releaseNotesUrl = `https://github.com/extension-js/extension.js/releases/tag/v${latest}`;
6381
- const suffix = external_pintor_default().gray(`(version ${latest} is available!)`);
6382
- const message = `${getLoggingPrefix('info')} 🧩 An ${external_pintor_default().blue('Extension.js')} update is available.\n\nYou are on version ${external_pintor_default().red(String(packageJson.version))}.\nThe latest stable is ${external_pintor_default().green(latest)}.\nSee what's new: ${external_pintor_default().underline(releaseNotesUrl)}\nUpdate to the latest stable to get fixes and new features.`;
6439
+ const suffix = external_pintor_default().gray(`(version ${latest} is available)`);
6440
+ const message = `${getLoggingPrefix('info')} An ${external_pintor_default().blue('Extension.js')} update is available.\n\nYou're on version ${external_pintor_default().red(String(packageJson.version))}.\nThe latest stable is ${external_pintor_default().green(latest)}.\nSee what's new: ${external_pintor_default().underline(releaseNotesUrl)}\nUpdate to the latest stable to get fixes and new features.`;
6383
6441
  return {
6384
6442
  suffix,
6385
6443
  message
@@ -6392,15 +6450,15 @@ Usage: extension [command] [options]
6392
6450
 
6393
6451
  Notes
6394
6452
  - All high-level commands offer their own \`--help\` with usage and flag lists.
6395
- - Telemetry is anonymous and privacy-safe by default; see ${messages_code('docs/TELEMETRY.md')} for the full contract.
6453
+ - Telemetry is anonymous and privacy-safe by default, see ${messages_code('docs/TELEMETRY.md')} for the full contract.
6396
6454
 
6397
6455
  Example
6398
6456
  - ${messages_code('extension create --help')} outputs information about the "create" command.
6399
6457
 
6400
- Available Commands
6458
+ Available commands
6401
6459
  ${availableCommandsBlock()}
6402
6460
 
6403
- Common Options
6461
+ Common options
6404
6462
  - ${messages_code('--browser')} ${messages_arg('<chrome|edge|firefox|chromium|chromium-based|gecko-based|firefox-based>')} Target browser/engine (default: chromium)
6405
6463
  - ${messages_code('--profile')} ${messages_arg('<path|boolean>')} Browser profile configuration
6406
6464
  - ${messages_code('--polyfill')} ${messages_arg('[boolean]')} Enable/disable cross-browser polyfill
@@ -6409,23 +6467,23 @@ Common Options
6409
6467
  - ${messages_code('--output')} ${messages_arg('<pretty|json>')} Result format for ${messages_code('--ai-help')} and machine-readable command results (default: pretty)
6410
6468
  ${messages_code('--format')} and ${messages_code('--wait-format')} still work as deprecated aliases of ${messages_code('--output')}
6411
6469
  - ${messages_code('--help')} Show help output
6412
- - ${messages_code('--port')} ${messages_arg('<number>')} Development server port (default: 8080; use 0 for OS-assigned)
6413
- - ${messages_code('--host')} ${messages_arg('<address>')} Dev server host (default: 127.0.0.1; use 0.0.0.0 for Docker/devcontainers)
6414
- - ${messages_code('--public-host')} ${messages_arg('<address>')} Connectable host the browser dials for HMR + reload bridge when it differs from ${messages_code('--host')} (remote/devcontainer; default: the bind host, or 127.0.0.1 when bound to 0.0.0.0)
6470
+ - ${messages_code('--port')} ${messages_arg('<number>')} Development server port (default: 8080, use 0 for OS-assigned)
6471
+ - ${messages_code('--host')} ${messages_arg('<address>')} Dev server host (default: 127.0.0.1, use 0.0.0.0 for Docker/devcontainers)
6472
+ - ${messages_code('--public-host')} ${messages_arg('<address>')} Connectable host the browser dials for HMR + reload bridge when it differs from ${messages_code('--host')} (remote/devcontainer, default: the bind host, or 127.0.0.1 when bound to 0.0.0.0)
6415
6473
  - ${messages_code('--starting-url')} ${messages_arg('<url>')} Initial URL to load in browser
6416
6474
  - ${messages_code('--silent')} ${messages_arg('[boolean]')} Suppress console output during build
6417
6475
 
6418
- Browser-Specific Options
6476
+ Browser-specific options
6419
6477
  - ${messages_code('--chromium-binary')} ${messages_arg('<path>')} Custom Chromium binary path
6420
6478
  - ${messages_code('--gecko-binary')}/${messages_code('--firefox-binary')} ${messages_arg('<path>')} Custom Firefox/Gecko binary path
6421
6479
  Use ${messages_code('flatpak:org.mozilla.firefox')} as the path to launch a Flatpak-installed Firefox
6422
6480
 
6423
- Build Options
6481
+ Build options
6424
6482
  - ${messages_code('--zip')} ${messages_arg('[boolean]')} Create ZIP archive of built extension
6425
6483
  - ${messages_code('--zip-source')} ${messages_arg('[boolean]')} Include source files in ZIP
6426
6484
  - ${messages_code('--zip-filename')} ${messages_arg('<name>')} Custom ZIP filename
6427
6485
 
6428
- ${external_pintor_default().underline('Centralized Logger (terminal output)')}
6486
+ ${external_pintor_default().underline('Centralized logger (terminal output)')}
6429
6487
  - The manager extension embeds a centralized logger that streams events to the CLI.
6430
6488
  - Enable and filter logs directly via ${messages_code('extension dev')} flags:
6431
6489
  - ${messages_code('--logs')} ${messages_arg('<off|error|warn|info|debug|trace>')} Minimum level (default: off)
@@ -6440,17 +6498,17 @@ ${external_pintor_default().underline('Centralized Logger (terminal output)')}
6440
6498
  ${messages_code('extension --help')}
6441
6499
  This command outputs a help file with key command options.
6442
6500
 
6443
- ${external_pintor_default().underline('Path Resolution (important)')}
6501
+ ${external_pintor_default().underline('Path resolution (important)')}
6444
6502
  - Leading ${messages_code('/')} in manifest/HTML means extension root (the directory containing ${messages_code('manifest.json')}).
6445
6503
  - Relative paths resolve from the ${messages_code('manifest.json')} directory.
6446
6504
  - Absolute OS paths are used as-is.
6447
6505
 
6448
- AI Assistants
6506
+ AI assistants
6449
6507
  - For AI-oriented guidance and deeper tips, run ${messages_code('extension --ai-help')}
6450
6508
  - For machine-readable AI guidance, run ${messages_code('extension --ai-help --output json')}
6451
6509
 
6452
6510
  Report issues
6453
- - ${external_pintor_default().underline('https://github.com/cezaraugusto/extension/issues/new')}`;
6511
+ - ${external_pintor_default().underline('https://github.com/extension-js/extension.js/issues/new')}`;
6454
6512
  }
6455
6513
  function unsupportedBrowserFlag(value, supported) {
6456
6514
  return `${getLoggingPrefix('error')} Unsupported --browser value: ${value}.\n${external_pintor_default().red('Choose one of:')} ${supported.join(', ')}${external_pintor_default().red('.')}`;
@@ -6459,7 +6517,7 @@ AI Assistants
6459
6517
  return `${getLoggingPrefix('error')} ${flags.map(messages_code).join(', ')} only appl${1 === flags.length ? 'ies' : 'y'} to Safari targets.\nAdd ${messages_code('--browser safari')} (or ${messages_code('webkit-based')}).`;
6460
6518
  }
6461
6519
  function safariInvalidBundleId(bundleId) {
6462
- return `${getLoggingPrefix('error')} Invalid bundle identifier: ${messages_code(bundleId)}.\nUse reverse-DNS form: dot-separated segments of letters, digits and hyphens, each starting with a letter (e.g. ${messages_code('com.example.my-extension')}).`;
6520
+ return `${getLoggingPrefix('error')} Can't use ${messages_code(bundleId)} as a bundle identifier.\nUse reverse-DNS form: dot-separated segments of letters, digits and hyphens, each starting with a letter (e.g. ${messages_code('com.example.my-extension')}).`;
6463
6521
  }
6464
6522
  function safariCommandNotSupported(command) {
6465
6523
  return `${getLoggingPrefix('error')} ${messages_code(command)} can't load an extension into Safari automatically.\nSafari extensions ship inside a signed app and are enabled by hand, so there's no live browser session to load into, unlike Chromium and Firefox.\nBuild the Safari app instead: ${messages_code('extension build --browser safari')}\nThen open the generated app and enable it in Safari → Settings → Extensions.`;
@@ -6467,30 +6525,30 @@ AI Assistants
6467
6525
  function programAIHelp() {
6468
6526
  return `\n${getLoggingPrefix('info')} ${external_pintor_default().gray('Development tips for extension developers and AI assistants')}
6469
6527
 
6470
- Browser-Specific Configuration
6528
+ Browser-specific configuration
6471
6529
  - Use browser prefixes in manifest.json for browser-specific fields:
6472
6530
  ${messages_code('{"firefox:manifest": 2, "chrome:manifest": 3}')}
6473
6531
  This applies manifest v2 to Firefox only, v3 to Chrome/Edge.
6474
6532
 
6475
- Centralized Logger (for AI & CI)
6533
+ Centralized logger (for AI & CI)
6476
6534
  - Logs from all contexts are centralized by the manager extension and streamed to the CLI.
6477
6535
  - Prefer these flags to control terminal logs during ${messages_code('extension dev')}:
6478
6536
  - ${messages_code('--logs')} ${messages_arg('<off|error|warn|info|debug|trace>')} Minimum level
6479
6537
  - ${messages_code('--log-context')} ${messages_arg('<list|all>')} Contexts to include
6480
- - ${messages_code('--log-format')} ${messages_arg('<pretty|json|ndjson>')} Pretty for humans; JSON for machines/NDJSON pipelines
6538
+ - ${messages_code('--log-format')} ${messages_arg('<pretty|json|ndjson>')} Pretty for humans, JSON for machines/NDJSON pipelines
6481
6539
  - ${messages_code('--no-log-timestamps')} ${messages_arg(' ')} Disable timestamps (pretty)
6482
6540
  - ${messages_code('--no-log-color')} ${messages_arg(' ')} Disable ANSI colors (pretty)
6483
6541
  - ${messages_code('--log-url')} ${messages_arg('<substring|/regex/>')} Filter by URL
6484
6542
  - ${messages_code('--log-tab')} ${messages_arg('<id>')} Filter by tabId
6485
6543
  - Good CI pattern: ${messages_code('EXTENSION_DEBUG=1 EXTENSION_AUTO_EXIT_MS=6000 extension dev ./ext --logs=info --log-format=json')}
6486
6544
 
6487
- Special Folders for Entrypoints
6545
+ Special folders for entrypoints
6488
6546
  - Use special folders to handle entrypoints and assets not declared in manifest.json:
6489
6547
  - ${external_pintor_default().underline(messages_code('public/'))} - Static assets automatically copied to build (resolves to output root)
6490
6548
  - ${external_pintor_default().underline(messages_code('pages/'))} - HTML files not declared in manifest (e.g., welcome pages)
6491
6549
  - ${external_pintor_default().underline(messages_code("scripts/"))} - JavaScript files not declared in manifest (e.g., executable scripts)
6492
6550
 
6493
- Predictable Output Paths
6551
+ Predictable output paths
6494
6552
  - Core HTML destinations are standardized across browsers so you can reference them safely in code/tests:
6495
6553
  - ${messages_code('devtools_page')} → ${messages_code('devtools/index.html')}
6496
6554
  - ${messages_code('sidebar_action.default_panel')} (MV2) and ${messages_code('side_panel.default_path')} (MV3) → ${messages_code('sidebar/index.html')}
@@ -6504,31 +6562,31 @@ Predictable Output Paths
6504
6562
  - ${messages_code("user_scripts.api_script")} → ${messages_code("user_scripts/api_script.js")}
6505
6563
  - ${messages_code('icons/*')} → ${messages_code('icons/')} (feature-specific icon folders preserved where applicable)
6506
6564
 
6507
- Public & Special Folders (Output Behavior)
6565
+ Public & special folders (output behavior)
6508
6566
  - ${external_pintor_default().underline(messages_code('public/'))} is the web root in output. Authors can use ${messages_code('/foo')}, ${messages_code('/public/foo')}, ${messages_code('public/foo')}, or ${messages_code('./public/foo')} and they all emit as ${messages_code('dist/<browser>/foo')}.
6509
- - ${external_pintor_default().underline(messages_code('pages/'))} files emit as ${messages_code('pages/<name>.html')}. Relative assets referenced inside page HTML are emitted under ${messages_code('assets/')} preserving relative structure; public-root URLs are preserved.
6567
+ - ${external_pintor_default().underline(messages_code('pages/'))} files emit as ${messages_code('pages/<name>.html')}. Relative assets referenced inside page HTML are emitted under ${messages_code('assets/')} preserving relative structure, public-root URLs are preserved.
6510
6568
  - ${external_pintor_default().underline(messages_code("scripts/"))} files emit as ${messages_code("scripts/<name>.js")} with extracted CSS when applicable.
6511
6569
 
6512
- Shadow DOM for Content Scripts
6570
+ Shadow DOM for content scripts
6513
6571
  - Add ${messages_code('use shadow-dom')} directive to content scripts for style isolation
6514
6572
  - Automatically creates ${messages_code('#extension-root')} element with shadow DOM
6515
6573
  - All CSS imports are automatically injected into shadow DOM
6516
6574
  - Prevents style conflicts with host page
6517
6575
 
6518
- Environment Variables
6576
+ Environment variables
6519
6577
  - Use ${messages_code(messages_arg('EXTENSION_PUBLIC_*'))} prefix for variables accessible in extension code
6520
6578
  - Supported in both ${messages_code('process.env')} and ${messages_code('import.meta.env')}
6521
6579
  - Environment file priority: ${external_pintor_default().underline(messages_code(messages_arg('.env.{browser}.{mode}')))} > ${external_pintor_default().underline(messages_code(messages_arg('.env.{browser}')))} > ${external_pintor_default().underline(messages_code(messages_arg('.env.{mode}')))} > ${external_pintor_default().underline(messages_code(messages_arg('.env')))}
6522
6580
  - Example: ${messages_code(messages_arg('EXTENSION_PUBLIC_API_KEY=your_key'))}
6523
6581
 
6524
- Available Templates
6582
+ Available templates
6525
6583
  - ${external_pintor_default().green('Frameworks')}: ${messages_code(messages_arg('react'))}, ${messages_code(messages_arg('preact'))}, ${messages_code(messages_arg('vue'))}, ${messages_code(messages_arg('svelte'))}
6526
6584
  - ${external_pintor_default().green('Languages')}: ${messages_code(messages_arg("javascript"))}, ${messages_code(messages_arg("typescript"))}
6527
6585
  - ${external_pintor_default().green('Contexts')}: ${messages_code(messages_arg('content'))} (content scripts), ${messages_code(messages_arg('new'))} (new tab), ${messages_code(messages_arg('action'))} (popup)
6528
6586
  - ${external_pintor_default().green('Styling')}: ${messages_code(messages_arg('tailwind'))}, ${messages_code(messages_arg('sass'))}, ${messages_code(messages_arg('less'))}
6529
6587
  - ${external_pintor_default().green('Configs')}: ${messages_code(messages_arg('eslint'))}, ${messages_code(messages_arg('prettier'))}, ${messages_code(messages_arg('stylelint'))}
6530
6588
 
6531
- Webpack/Rspack Configuration
6589
+ Webpack/Rspack configuration
6532
6590
  - Create ${external_pintor_default().underline(messages_code(messages_arg('extension.config.js')))} for custom webpack configuration
6533
6591
  - Function receives base config, return modified config
6534
6592
  - Supports all webpack/rspack loaders and plugins
@@ -6540,14 +6598,14 @@ Webpack/Rspack Configuration
6540
6598
  ${messages_code(' }')}
6541
6599
  ${messages_code('}')}
6542
6600
 
6543
- Managed Dependencies (Important)
6601
+ Managed dependencies (important)
6544
6602
  - ${external_pintor_default().green('Do not add')} packages that ${external_pintor_default().blue('Extension.js')} already ships in its own toolchain.
6545
6603
  - The guard only triggers when a managed package is declared in your ${messages_code('package.json')} ${external_pintor_default().gray('and')} is imported (as a module specifier) in your ${external_pintor_default().underline(messages_code('extension.config.js'))}.
6546
6604
  - In that case, the program will ${external_pintor_default().red('print an error and abort')} to avoid version conflicts.
6547
6605
  - Remove the duplicate from your project ${messages_code('package.json')} or avoid referencing it in ${external_pintor_default().underline(messages_code('extension.config.js'))} and rely on the built-in version instead.
6548
6606
  - If you truly need a different version, open an issue so we can evaluate a safe upgrade.
6549
6607
 
6550
- Framework-Specific Configuration
6608
+ Framework-specific configuration
6551
6609
  - Create ${external_pintor_default().underline(messages_code(messages_arg('vue.loader.js')))} for Vue-specific loader configuration
6552
6610
  - Create ${external_pintor_default().underline(messages_code(messages_arg('svelte.loader.js')))} for Svelte-specific loader configuration
6553
6611
  - Automatically detected and used by Extension.js
@@ -6561,26 +6619,26 @@ Framework-Specific Configuration
6561
6619
  Hot Module Replacement (HMR)
6562
6620
  - Automatically enabled in development mode
6563
6621
  - CSS changes trigger automatic style updates
6564
- - React components fast-refresh; Svelte components hot-update
6622
+ - React components fast-refresh, Svelte components hot-update
6565
6623
  - Preact and Vue rebuild with a live reload (component state resets)
6566
6624
  - Content scripts automatically re-inject on changes
6567
6625
  - Service workers, _locales and manifest changes reload the extension
6568
6626
 
6569
- Non-Destructive Testing in CI
6627
+ Non-destructive testing in CI
6570
6628
  - Prefer ${messages_code('EXTENSION_DEBUG=1')} to copy local templates and avoid network.
6571
6629
  - Reuse Playwright's Chromium via ${messages_code('--chromium-binary')} path when available.
6572
6630
  - Set ${messages_code(messages_arg('EXTENSION_AUTO_EXIT_MS'))} and ${messages_code(messages_arg('EXTENSION_FORCE_KILL_MS'))} for non-interactive dev sessions.
6573
6631
 
6574
- File Watching & HMR Examples
6575
- - Content script JS/TS changes trigger reinjection; CSS changes update styles live.
6632
+ File watching & HMR examples
6633
+ - Content script JS/TS changes trigger reinjection, CSS changes update styles live.
6576
6634
  - For watch-source HTML prints, update a visible string in ${messages_code("content/scripts.*")} and assert it appears in stdout.
6577
6635
 
6578
6636
  Troubleshooting
6579
- - Use ${messages_code('--silent true')} during builds to reduce noise; logs still surface errors.
6637
+ - Use ${messages_code('--silent true')} during builds to reduce noise, logs still surface errors.
6580
6638
  - When ports conflict, pass ${messages_code('--port 0')} to auto-select an available port.
6581
6639
  - In Docker/devcontainers, pass ${messages_code('--host 0.0.0.0')} so the dev server is reachable from the host.
6582
6640
 
6583
- Non-Interactive / Auto Mode (CI)
6641
+ Non-interactive / auto mode (CI)
6584
6642
  - Set ${messages_code(messages_arg('EXTENSION_AUTO_EXIT_MS'))} to enable self-termination after N milliseconds.
6585
6643
  Useful when ${messages_code('pnpm extension dev')} would otherwise hang under Rspack watch.
6586
6644
  Example: ${messages_code(messages_arg('EXTENSION_AUTO_EXIT_MS=6000'))} pnpm extension dev ./templates/react --browser chrome --starting-url ${messages_arg('https://example.com')}
@@ -6597,7 +6655,7 @@ Flatpak Firefox
6597
6655
  - Use ${messages_code('--gecko-binary flatpak:org.mozilla.firefox')} (or ${messages_code('--firefox-binary')}) to launch a Flatpak-installed Firefox.
6598
6656
  - Extension.js rewrites the binary path to ${messages_code('flatpak run')} with the correct filesystem grants automatically.
6599
6657
 
6600
- Cross-Browser Compatibility
6658
+ Cross-browser compatibility
6601
6659
  - Use ${messages_code('--polyfill')} flag to enable webextension-polyfill
6602
6660
  - Automatically handles browser API differences
6603
6661
  - Supports Chrome, Edge, Firefox with single codebase`;
@@ -6687,7 +6745,7 @@ Cross-Browser Compatibility
6687
6745
  readyContract: {
6688
6746
  readyPath: 'dist/extension-js/<browser>/ready.json',
6689
6747
  eventsPath: 'dist/extension-js/<browser>/events.ndjson',
6690
- waitFlag: '--wait blocks until ready.json reports ready (or error) then exits; pair with --output json for machine output (--wait-format is a deprecated alias)',
6748
+ waitFlag: '--wait blocks until ready.json reports ready (or error) then exits, pair with --output json for machine output (--wait-format is a deprecated alias)',
6691
6749
  statuses: [
6692
6750
  'starting',
6693
6751
  'ready',
@@ -6752,7 +6810,7 @@ Cross-Browser Compatibility
6752
6810
  };
6753
6811
  }
6754
6812
  function invalidAIHelpFormat(value) {
6755
- return `${getLoggingPrefix('error')} Invalid value for ${messages_code('--output')}: ${external_pintor_default().red(String(value))}.\n${external_pintor_default().red('Pass')} ${messages_arg('pretty')} ${external_pintor_default().red('or')} ${messages_arg('json')}${external_pintor_default().red(', for example')} ${messages_code('extension --ai-help --output json')}${external_pintor_default().red('.')}`;
6813
+ return `${getLoggingPrefix('error')} Can't use ${external_pintor_default().red(String(value))} as a value for ${messages_code('--output')}.\n${external_pintor_default().red('Pass')} ${messages_arg('pretty')} ${external_pintor_default().red('or')} ${messages_arg('json')}${external_pintor_default().red(', for example')} ${messages_code('extension --ai-help --output json')}${external_pintor_default().red('.')}`;
6756
6814
  }
6757
6815
  function removedNoRunnerFlag() {
6758
6816
  return `${getLoggingPrefix('error')} ${messages_code('--no-runner')} was removed.\nUse ${messages_code('--no-browser')} instead.`;
@@ -6761,7 +6819,7 @@ Cross-Browser Compatibility
6761
6819
  return `${getLoggingPrefix('warn')} ${messages_code(flag)} is deprecated and maps to ${messages_code('--output')}.\nPass ${messages_code('--output')} ${messages_arg('<pretty|json>')} instead.`;
6762
6820
  }
6763
6821
  function noBrowserNotSupportedForCommand(command) {
6764
- return `${getLoggingPrefix('error')} ${messages_code('--no-browser')} is only supported for ${messages_code('dev')}, ${messages_code('start')}, and ${messages_code('preview')}.\nReceived command: ${messages_code(command || '(none)')}`;
6822
+ return `${getLoggingPrefix('error')} ${messages_code('--no-browser')} is only supported for ${messages_code('dev')}, ${messages_code('start')}, and ${messages_code('preview')}.\n${messaging.Sc.label('GOT')} ${messages_code(command || '(none)')}`;
6765
6823
  }
6766
6824
  function readRecentConsole(projectPath, browser, target, limit) {
6767
6825
  const file = external_node_path_default().resolve(projectPath, 'dist', 'extension-js', browser, 'logs.ndjson');
@@ -7440,6 +7498,29 @@ Cross-Browser Compatibility
7440
7498
  if (refs) error.refs = refs;
7441
7499
  return messaging.Pr.fail(command, 'usage', error);
7442
7500
  }
7501
+ const SUGGESTION_PATTERN = /\(Did you mean (one of )?(.+)\?\)/;
7502
+ function sentenceCase(input) {
7503
+ const trimmed = input.trim();
7504
+ const capitalized = trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
7505
+ return /[.!?]$/.test(capitalized) ? capitalized : `${capitalized}.`;
7506
+ }
7507
+ function commanderHumanError(err, command) {
7508
+ const commanderCode = String(err.code);
7509
+ const message = String(err.message || 'the command line could not be parsed').replace(/^error:\s*/i, '').trim();
7510
+ const refs = refsFromMessage(commanderCode, message);
7511
+ let label;
7512
+ let noun = 'options';
7513
+ if ('commander.unknownOption' === commanderCode && refs?.flag) label = `Unknown option ${refs.flag}.`;
7514
+ else if ('commander.unknownCommand' === commanderCode && refs?.command) {
7515
+ label = `Unknown command ${refs.command}.`;
7516
+ noun = 'commands';
7517
+ } else if ('commander.optionMissingArgument' === commanderCode && refs?.flag) label = `Missing value for ${refs.flag}.`;
7518
+ if (!label) label = sentenceCase(message.split('\n')[0]);
7519
+ const helpTarget = 'options' === noun && command && 'extension' !== command ? `extension ${command}` : 'extension';
7520
+ const suggestion = SUGGESTION_PATTERN.exec(message);
7521
+ const remedy = suggestion ? `Did you mean ${suggestion[1] || ''}${external_pintor_default().blue(suggestion[2])}?` : `Run ${external_pintor_default().blue(`${helpTarget} --help`)} to see the ${noun}.`;
7522
+ return `${(0, messaging.Pl)('error')} ${label}\n${remedy}`;
7523
+ }
7443
7524
  function internalErrorEnvelope(err, command) {
7444
7525
  return messaging.Pr.fail(command, 'failed', {
7445
7526
  code: messaging.Lp.E_INTERNAL,
@@ -9217,7 +9298,9 @@ Cross-Browser Compatibility
9217
9298
  process.env.EXTENSION_CLI_UPDATE_SUFFIX = updateMessage.suffix;
9218
9299
  });
9219
9300
  const extensionJs = external_commander_namespaceObject.program;
9220
- extensionJs.name(String(index_cliPackageJson.name)).description(String(index_cliPackageJson.description)).version(String(index_cliPackageJson.version)).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').addOption(new external_commander_namespaceObject.Option('--format <pretty|json>').hideHelp()).addHelpText('after', programUserHelp()).showHelpAfterError(true).showSuggestionAfterError(true).exitOverride();
9301
+ extensionJs.name(String(index_cliPackageJson.name)).description(String(index_cliPackageJson.description)).version(String(index_cliPackageJson.version)).option('--no-telemetry', 'disable anonymous telemetry for this run').option('--ai-help', 'show AI-assistant oriented help and tips').addOption(new external_commander_namespaceObject.Option('--format <pretty|json>').hideHelp()).addHelpText('after', programUserHelp()).configureOutput({
9302
+ outputError: ()=>{}
9303
+ }).showSuggestionAfterError(true).exitOverride();
9221
9304
  registerCreateCommand(extensionJs);
9222
9305
  registerDevCommand(extensionJs);
9223
9306
  registerStartCommand(extensionJs);
@@ -9263,6 +9346,7 @@ Cross-Browser Compatibility
9263
9346
  const exitCode = commanderExitCode(err);
9264
9347
  if (0 === exitCode) process.exit(0);
9265
9348
  markCommandFailure();
9349
+ console.error(commanderHumanError(err, commandName));
9266
9350
  if (asJson) writeStdoutFrame(commanderErrorEnvelope(err, commandName));
9267
9351
  process.exit(exitCode);
9268
9352
  }