extension-develop 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.
@@ -1,25 +1,89 @@
1
1
  import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
2
- import { scrubBrand } from "./0~branding.mjs";
2
+ import { __webpack_require__ } from "./0~rslib-runtime.mjs";
3
+ import { prefix } from "./349.mjs";
4
+ var stats_handler_namespaceObject = {};
5
+ __webpack_require__.r(stats_handler_namespaceObject);
6
+ __webpack_require__.d(stats_handler_namespaceObject, {
7
+ handleStatsErrors: ()=>handleStatsErrors,
8
+ renderStatsBlocks: ()=>renderStatsBlocks,
9
+ wrapStatsBlocks: ()=>wrapStatsBlocks
10
+ });
11
+ function scrubBrand(txt, brand = 'Extension.js') {
12
+ if (!txt) return txt;
13
+ const safeBrand = brand.replace(/\$/g, '$$$$');
14
+ const preserved = [];
15
+ const preserve = (value)=>{
16
+ const token = `__EXT_BRAND_PRESERVE_${preserved.length}__`;
17
+ preserved.push(value);
18
+ return token;
19
+ };
20
+ let output = txt.replace(/\bRspack\b(?=\s+performance recommendations:)/gi, preserve).replace(/https?:\/\/rspack\.(?:rs|dev)\/[^\s)]+/gi, preserve).replace(/(?<!@)\bRspack\b/gi, safeBrand).replace(/(?<!@)\bWebpack\b/gi, safeBrand).replace(/(?<!@)\bwebpack-dev-server\b/gi, `${safeBrand} dev server`).replace(/(?<!@)\bRspackDevServer\b/gi, `${safeBrand} dev server`).replace(/ModuleBuildError:\s*/g, '').replace(/ModuleParseError:\s*/g, '').replace(/Error:\s*Module\s+build\s+failed.*?\n/gi, '').replace(/\n{3,}/g, '\n\n').replace(/\n{2}(?=WARNING in )/g, '\n');
21
+ preserved.forEach((value, index)=>{
22
+ output = output.replace(`__EXT_BRAND_PRESERVE_${index}__`, value);
23
+ });
24
+ return output;
25
+ }
26
+ function makeSanitizedConsole(brand = 'Extension.js') {
27
+ const sanitize = (a)=>'string' == typeof a ? scrubBrand(a, brand) : a;
28
+ return {
29
+ log: (...args)=>console.log(...args.map(sanitize)),
30
+ info: (...args)=>console.info(...args.map(sanitize)),
31
+ warn: (...args)=>console.warn(...args.map(sanitize)),
32
+ error: (...args)=>console.error(...args.map(sanitize))
33
+ };
34
+ }
35
+ const ANSI_PATTERN = /\u001b\[[0-9;]*m/g;
36
+ function wrapStatsBlocks(raw) {
37
+ const lines = String(raw || '').split('\n');
38
+ const wrapped = [];
39
+ let inBlock = false;
40
+ for (const line of lines){
41
+ const plain = line.replace(ANSI_PATTERN, '');
42
+ const errorHead = /^ERROR(?: in (.+))?$/.exec(plain);
43
+ const warningHead = /^WARNING(?: in (.+))?$/.exec(plain);
44
+ if (errorHead || warningHead) {
45
+ const file = String((errorHead || warningHead)?.[1] || '').trim().replace(/\.$/, '');
46
+ const kind = errorHead ? 'error' : 'warning';
47
+ const channel = errorHead ? 'error' : 'warn';
48
+ const location = file ? ` in ${file}` : '';
49
+ wrapped.push(`${prefix(channel)} Build ${kind}${location}.`);
50
+ inBlock = true;
51
+ continue;
52
+ }
53
+ if (inBlock && plain.trim().length > 0) {
54
+ wrapped.push(` ${line}`);
55
+ continue;
56
+ }
57
+ wrapped.push(line);
58
+ }
59
+ return wrapped.join('\n');
60
+ }
61
+ function renderStatsBlocks(stats, opts) {
62
+ const raw = stats.toString({
63
+ colors: true,
64
+ all: false,
65
+ errors: opts.errors,
66
+ warnings: opts.warnings
67
+ });
68
+ if (!raw) return '';
69
+ return wrapStatsBlocks(scrubBrand(raw));
70
+ }
3
71
  function handleStatsErrors(stats) {
4
72
  try {
5
73
  const verbose = '1' === String(process.env.EXTENSION_VERBOSE || '').trim();
6
- const str = stats.toString({
7
- colors: true,
8
- all: false,
74
+ const str = renderStatsBlocks(stats, {
9
75
  errors: true,
10
76
  warnings: !!verbose
11
77
  });
12
- if (str) console.error(scrubBrand(str));
78
+ if (str) console.error(str);
13
79
  } catch {
14
80
  try {
15
- const str = stats.toString({
16
- colors: true,
17
- all: false,
81
+ const str = renderStatsBlocks(stats, {
18
82
  errors: true,
19
83
  warnings: true
20
84
  });
21
- if (str) console.error(scrubBrand(str));
85
+ if (str) console.error(str);
22
86
  } catch {}
23
87
  }
24
88
  }
25
- export { handleStatsErrors };
89
+ export { makeSanitizedConsole, renderStatsBlocks, stats_handler_namespaceObject };
package/dist/101.mjs CHANGED
@@ -8,9 +8,9 @@ import node_fs from "node:fs";
8
8
  import node_path from "node:path";
9
9
  import { getSpecialFoldersData } from "browser-extension-manifest-fields";
10
10
  import { createHash } from "node:crypto";
11
- import { fmt, browserRowValue, isDebug, artifactNoun as messaging_artifactNoun, prefix as messaging_prefix, card } from "./349.mjs";
12
- import { stripBom, parseJsonSafe } from "./23.mjs";
11
+ import { fmt, browserRowValue, isDebug, artifactNoun, prefix as messaging_prefix, card } from "./349.mjs";
13
12
  import { findNearestDenoConfigSync, validateDenoConfig, PROJECT_MANIFEST_FILENAMES, readProjectDependencies } from "./80.mjs";
13
+ import { stripBom, parseJsonSafe } from "./23.mjs";
14
14
  import { readyContractPath, browserArtifactsDir, eventsPath as session_paths_eventsPath } from "./494.mjs";
15
15
  import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
16
16
  import { dirname as __rspack_dirname } from "node:path";
@@ -29,20 +29,20 @@ function resolvedWorkspaceManifest(projectPath, manifestPath) {
29
29
  const manifestDir = __rspack_external_node_path_c5b9b54f.dirname(manifestPath);
30
30
  const packageDir = 'src' === __rspack_external_node_path_c5b9b54f.basename(manifestDir) ? __rspack_external_node_path_c5b9b54f.dirname(manifestDir) : manifestDir;
31
31
  const display = __rspack_external_node_path_c5b9b54f.relative(projectPath, packageDir) || packageDir;
32
- return `${getLoggingPrefix('info')} ${pintor.gray('Workspace root detected.')}\n${pintor.gray('PACKAGE')} ${pintor.brightBlue(display)}`;
32
+ return `${getLoggingPrefix('info')} ${pintor.gray('Workspace root detected.')}\n${pintor.gray('PACKAGE')} ${pintor.underline(display)}`;
33
33
  }
34
34
  function remoteFetchTimedOut(target, ms) {
35
- return `${getLoggingPrefix('error')} Timed out after ${pintor.yellow(`${Math.round(ms / 1000)}s`)} fetching ${pintor.underline(target)}.\n${pintor.red('Check your network, or set EXTENSION_FETCH_TIMEOUT_MS to allow more time.')}`;
35
+ return `${getLoggingPrefix('error')} Timed out after ${Math.round(ms / 1000)} s fetching the remote file.\n${pintor.gray('URL')} ${pintor.underline(target)}\nCheck your network, or set ${pintor.blue('EXTENSION_FETCH_TIMEOUT_MS')} to allow more time.`;
36
36
  }
37
37
  function manifestInvalidJson(manifestPath, error) {
38
38
  const detail = error instanceof Error ? error.message : String(error);
39
- return `${getLoggingPrefix('error')} Could not parse manifest.json.\nIt is not valid JSON.\n${pintor.red('Fix the syntax error and try again.')}\n${pintor.gray('PATH')} ${pintor.underline(manifestPath)}\n${pintor.red(detail)}`;
39
+ return `${getLoggingPrefix('error')} Couldn't parse manifest.json as JSON.\n${pintor.gray('PATH')} ${pintor.underline(manifestPath)}\n${pintor.gray('REASON')} ${pintor.red(detail)}\nFix the syntax error, then run the command again.`;
40
40
  }
41
41
  function notAnExtensionManifestError(manifestPath) {
42
- return `${getLoggingPrefix('error')} manifest.json is not a browser extension manifest.\nIt has no ${pintor.yellow('manifest_version')} field.\n${pintor.red('This looks like a PWA web-app manifest.')}\n${pintor.red('Point Extension.js at the directory that contains your extension manifest.')}\n${pintor.gray('PATH')} ${pintor.underline(manifestPath)}`;
42
+ return `${getLoggingPrefix('error')} manifest.json isn't a browser extension manifest.\nIt has no ${pintor.blue('manifest_version')} field, so it looks like a PWA web-app manifest.\n${pintor.gray('PATH')} ${pintor.underline(manifestPath)}\nPoint Extension.js at the directory that contains your extension manifest.`;
43
43
  }
44
44
  function manifestNotFoundError(manifestPath, candidates = []) {
45
- const base = `${getLoggingPrefix('error')} Manifest file not found.\n${pintor.red('Ensure the path to your extension exists and try again.')}\n${pintor.red('NOT FOUND')}\n${pintor.gray('PATH')} ${pintor.underline(manifestPath)}`;
45
+ const base = `${getLoggingPrefix('error')} Manifest file not found.\n${pintor.gray('NOT FOUND')} ${pintor.underline(manifestPath)}\nEnsure the path to your extension exists, then try again.`;
46
46
  if (!candidates.length) return base;
47
47
  const projectRoot = __rspack_external_node_path_c5b9b54f.dirname(manifestPath);
48
48
  const hint = 1 === candidates.length ? "Did you mean to point at this workspace package?" : "Did you mean to point at one of these workspace packages?";
@@ -52,25 +52,24 @@ function manifestNotFoundError(manifestPath, candidates = []) {
52
52
  const display = __rspack_external_node_path_c5b9b54f.isAbsolute(normalized) ? __rspack_external_node_path_c5b9b54f.relative(projectRoot, normalized) || normalized : normalized;
53
53
  return ` extension dev ${display}`;
54
54
  }).join('\n');
55
- return `${base}\n\n${pintor.gray(hint)}\n${pintor.brightBlue(suggestions)}`;
55
+ return `${base}\n\n${pintor.gray(hint)}\n${pintor.blue(suggestions)}`;
56
56
  }
57
- function previewing(browser) {
58
- return `${getLoggingPrefix('info')} Preview the extension on ${capitalizedBrowserName(browser)}.`;
57
+ function previewing(browser, noBrowser) {
58
+ const suffix = noBrowser ? ' (no-browser mode)' : '';
59
+ return `${getLoggingPrefix('info')} Previewing on ${capitalizedBrowserName(browser)}${suffix}.`;
59
60
  }
60
- function starting(browser) {
61
- return `${getLoggingPrefix('info')} Start the extension on ${capitalizedBrowserName(browser)}.`;
62
- }
63
- function previewSkippedNoBrowser(browser) {
64
- return `${getLoggingPrefix('info')} Skip the browser launch for ${capitalizedBrowserName(browser)} (no-browser).`;
61
+ function starting(browser, noBrowser) {
62
+ const suffix = noBrowser ? ' (no-browser mode)' : '';
63
+ return `${getLoggingPrefix('info')} Starting on ${capitalizedBrowserName(browser)}${suffix}.`;
65
64
  }
66
65
  function extensionLoadRecovered() {
67
- return `${getLoggingPrefix('success')} The browser accepted the extension.\nIt is running now.`;
66
+ return `${getLoggingPrefix('success')} The browser accepted the extension.\nIt's running now.`;
68
67
  }
69
68
  function extensionLoadStillRefused(reason) {
70
69
  return `${getLoggingPrefix('error')} The browser still refuses to load this extension.\n${pintor.gray('REASON')} ${pintor.red(reason)}`;
71
70
  }
72
71
  function browserLaunchFailed(browser, reason) {
73
- return `${getLoggingPrefix('error')} ${capitalizedBrowserName(browser)} could not be started, so the extension is NOT running.\n${reason}\nThe dev server keeps watching, but nothing will load until this is fixed.`;
72
+ return `${getLoggingPrefix('error')} ${capitalizedBrowserName(browser)} couldn't start, so the extension isn't running.\n${reason}\nThe dev server keeps watching, but nothing will load until this is fixed.`;
74
73
  }
75
74
  function authorInstallNotice(target) {
76
75
  return `${messaging_prefix('debug')} install target=${target}`;
@@ -79,45 +78,25 @@ function projectInstallFallbackToNpm(pmName) {
79
78
  return `${getLoggingPrefix('warn')} Dependency install with ${pmName} failed.\nExtension.js retries once with npm so the build can continue.`;
80
79
  }
81
80
  function projectInstallScriptsDisabled(pmName) {
82
- return `${getLoggingPrefix('info')} Install the project dependencies with ${pmName}.\nLifecycle scripts are disabled for safety.\nSet EXTENSION_ALLOW_INSTALL_SCRIPTS=true to run them.`;
81
+ return `${getLoggingPrefix('info')} Installing the project dependencies with ${pmName}…\nLifecycle scripts are disabled for safety.\nSet ${pintor.blue('EXTENSION_ALLOW_INSTALL_SCRIPTS=true')} to run them.`;
83
82
  }
84
- function buildWebpack(projectDir, stats, browser) {
83
+ function buildAssetsTree(stats) {
85
84
  const statsJson = stats?.toJson?.({
86
85
  all: false,
87
- assets: true,
88
- timings: true
86
+ assets: true
89
87
  });
90
- const outputPath = 'string' == typeof stats?.compilation?.outputOptions?.path ? stats.compilation.outputOptions.path : '';
91
- const distManifestPath = outputPath ? __rspack_external_node_path_c5b9b54f.join(outputPath, 'manifest.json') : '';
92
- const manifestPath = distManifestPath && __rspack_external_node_fs_5ea92f0c.existsSync(distManifestPath) ? distManifestPath : __rspack_external_node_path_c5b9b54f.join(projectDir, 'manifest.json');
93
- let manifest = {};
94
- try {
95
- manifest = JSON.parse(stripBom(__rspack_external_node_fs_5ea92f0c.readFileSync(manifestPath, 'utf8')));
96
- } catch {
97
- manifest = {
98
- name: __rspack_external_node_path_c5b9b54f.basename(projectDir),
99
- version: ''
100
- };
101
- }
102
88
  const assets = statsJson?.assets || [];
103
- const heading = `${getLoggingPrefix('info')} Build ${pintor.blue(manifest.name)} with the ${capitalizedBrowserName(browser)} defaults.\n`;
104
- const buildTime = `\nBuild completed in ${((statsJson?.time || 0) / 1000).toFixed(2)} seconds.\n`;
105
- const buildTarget = `Build Target: ${pintor.gray(capitalizedBrowserName(browser))}\n`;
106
- const buildStatus = `Build Status: ${stats?.hasErrors?.() ? pintor.red('Failed') : pintor.green('Success')}\n`;
107
- const version = `\nVersion: ${pintor.gray(manifest.version)}\n`;
108
- const size = `Size: ${pintor.gray(getAssetsSize(assets))}\n`;
109
- let output = '';
110
- output += heading;
111
- output += getAssetsTree(assets);
112
- output += version;
113
- output += size;
114
- output += buildTarget;
115
- output += buildStatus;
116
- output += buildTime;
117
- return output;
89
+ return getAssetsTree(assets);
90
+ }
91
+ function buildComplete(browser, distDisplayPath, totalBytes) {
92
+ const noun = artifactNoun(String(browser));
93
+ const size = 'number' == typeof totalBytes && totalBytes > 0 ? ` (${getHumanSize(totalBytes)})` : '';
94
+ return `${getLoggingPrefix('success')} ${noun} built for production in ${pintor.underline(distDisplayPath)}${size}.`;
118
95
  }
119
- function buildSuccess() {
120
- return `${getLoggingPrefix('success')} Build succeeded with no warnings.\nYour extension is ${pintor.green('ready for deployment')}.`;
96
+ function buildFailed(errorCount) {
97
+ const count = Math.max(1, Math.floor(errorCount || 1));
98
+ const noun = 1 === count ? 'error' : 'errors';
99
+ return `${getLoggingPrefix('error')} Build failed with ${count} ${noun}.`;
121
100
  }
122
101
  function getWarningMessage(warning) {
123
102
  if (!warning) return '';
@@ -167,12 +146,9 @@ function suggestedHintForWarning(category) {
167
146
  if ('Deprecation' === category) return 'Move to the supported API or plugin path before the next update.';
168
147
  if ('Configuration' === category) return 'Review extension and bundler config keys, then remove or rename invalid options.';
169
148
  if ('Compatibility' === category) return 'Verify browser target and manifest compatibility for this build.';
170
- if ('Runtime-risk' === category) return 'Address this before release; it may fail or degrade at runtime.';
149
+ if ('Runtime-risk' === category) return 'Address this before release. It may fail or degrade at runtime.';
171
150
  return 'Re-run with EXTENSION_VERBOSE=1 to inspect full warning details.';
172
151
  }
173
- function buildSuccessWithWarnings(warningCount) {
174
- return `${getLoggingPrefix('warn')} Build succeeded with ${warningCount} warning(s).\nYour extension is ${pintor.green('ready for deployment')}.`;
175
- }
176
152
  function buildWarningsDetails(warnings) {
177
153
  if (!Array.isArray(warnings) || 0 === warnings.length) return '';
178
154
  const blocks = [];
@@ -192,7 +168,7 @@ function buildWarningsDetails(warnings) {
192
168
  return blocks.join('\n\n');
193
169
  }
194
170
  function fetchingProjectPath(owner, project) {
195
- return fmt.block('Fetch project', [
171
+ return fmt.block('Fetching project', [
196
172
  [
197
173
  'URL',
198
174
  fmt.val(`https://github.com/${owner}/${project}`)
@@ -200,20 +176,20 @@ function fetchingProjectPath(owner, project) {
200
176
  ]);
201
177
  }
202
178
  function downloadingProjectPath(projectName) {
203
- const formatted = isPathLike(projectName) ? pintor.underline(projectName) : pintor.yellow(projectName);
204
- return `${getLoggingPrefix('info')} Download ${formatted}.`;
179
+ const formatted = isPathLike(projectName) ? pintor.underline(projectName) : projectName;
180
+ return `${getLoggingPrefix('info')} Downloading ${formatted}…`;
205
181
  }
206
182
  function creatingProjectPath(projectPath) {
207
- return `${getLoggingPrefix('info')} Create a new browser extension.\n${pintor.gray('PATH')} ${pintor.underline(projectPath)}`;
183
+ return `${getLoggingPrefix('info')} Creating a new browser extension…\n${pintor.gray('PATH')} ${pintor.underline(projectPath)}`;
208
184
  }
209
185
  function downloadedProjectFolderNotFound(cwd, candidates) {
210
- return `${getLoggingPrefix('error')} Downloaded project folder not found.\n${pintor.gray('PATH')} ${pintor.underline(cwd)}\n${pintor.gray('Tried')} ${pintor.underline(candidates.join(', '))}`;
186
+ return `${getLoggingPrefix('error')} Downloaded project folder not found.\n${pintor.gray('PATH')} ${pintor.underline(cwd)}\n${pintor.gray('NOT FOUND')} ${pintor.underline(candidates.join(', '))}`;
211
187
  }
212
188
  function packagingSourceFiles(zipPath) {
213
189
  return `${messaging_prefix('debug')} zip pack=source gitignore=excluded path=${zipPath}`;
214
190
  }
215
- function zipArtifactReady(browser, zipPath, sizeInBytes) {
216
- return `${messaging_prefix('info')} zip browser=${String(browser)} path=${zipPath} (${getFileSize(sizeInBytes)})`;
191
+ function zipArtifactReady(zipPath, sizeInBytes) {
192
+ return `${getLoggingPrefix('success')} Packaged ${pintor.underline(zipPath)} (${getHumanSize(sizeInBytes)}).`;
217
193
  }
218
194
  function packagingDistributionFiles(zipPath) {
219
195
  return `${messaging_prefix('debug')} zip pack=dist path=${zipPath}`;
@@ -228,13 +204,13 @@ function treeWithSourceFiles(name, ext, browser, zipPath) {
228
204
  return `${messaging_prefix('debug')} zip name=${name}-source.${ext} browser=${String(browser)} source=${zipPath}`;
229
205
  }
230
206
  function writingTypeDefinitions(manifest) {
231
- return `${getLoggingPrefix('info')} Write the type definitions for ${pintor.blue(manifest.name || '')}.`;
207
+ return `${getLoggingPrefix('info')} Writing the type definitions for ${manifest.name || 'the extension'}…`;
232
208
  }
233
209
  function writingTypeDefinitionsError(error) {
234
- return `${getLoggingPrefix('error')} Failed to write the extension type definition.\nCheck the file permissions, then try again.\n${pintor.red(String(error))}`;
210
+ return `${getLoggingPrefix('error')} Couldn't write the extension type definitions.\n${pintor.gray('REASON')} ${pintor.red(String(error))}\nCheck the file permissions, then try again.`;
235
211
  }
236
212
  function downloadingText(url) {
237
- return fmt.block('Download extension', [
213
+ return fmt.block('Downloading extension', [
238
214
  [
239
215
  'URL',
240
216
  fmt.val(url)
@@ -242,22 +218,22 @@ function downloadingText(url) {
242
218
  ]);
243
219
  }
244
220
  function unpackagingExtension(zipFilePath) {
245
- return `${getLoggingPrefix('info')} Unpackage the browser extension.\n${pintor.gray('PATH')} ${pintor.underline(zipFilePath)}`;
221
+ return `${getLoggingPrefix('info')} Unpackaging the browser extension…\n${pintor.gray('PATH')} ${pintor.underline(zipFilePath)}`;
246
222
  }
247
223
  function unpackagedSuccessfully() {
248
- return `${getLoggingPrefix('info')} Browser extension unpackaged ${pintor.green('successfully')}.`;
224
+ return `${getLoggingPrefix('success')} Extension unpackaged.`;
249
225
  }
250
226
  function failedToDownloadOrExtractZIPFileError(error) {
251
- return `${getLoggingPrefix('error')} Failed to download or extract ZIP file.\nCheck the URL and your network, then try again.\n${pintor.red(String(error))}`;
227
+ return `${getLoggingPrefix('error')} Couldn't download or extract the ZIP file.\n${pintor.gray('REASON')} ${pintor.red(String(error))}\nCheck the URL and your network, then try again.`;
252
228
  }
253
229
  function invalidRemoteZip(url, contentType) {
254
- return `${getLoggingPrefix('error')} Remote URL does not appear to be a ZIP archive.\nUse a direct-download URL, or download the file and pass the local path.\n${pintor.gray('URL')} ${pintor.underline(url)}\n${pintor.gray('Content-Type')} ${pintor.underline(contentType || 'unknown')}`;
230
+ return `${getLoggingPrefix('error')} The remote URL doesn't point to a ZIP archive.\n${pintor.gray('URL')} ${pintor.underline(url)}\n${pintor.gray('GOT')} ${pintor.underline(contentType || 'unknown')}\nUse a direct-download URL, or download the file and pass the local path.`;
255
231
  }
256
232
  function notAZipArchive(source, contentType) {
257
- return `${getLoggingPrefix('error')} The downloaded content is not a ZIP archive.\n${pintor.gray('SOURCE')} ${pintor.underline(source)}\n` + (contentType ? `${pintor.gray('Content-Type')} ${pintor.underline(contentType)}\n` : '') + "This usually means the URL requires authentication (for example a Slack, Google Drive, or Dropbox file page) and returned an HTML login " + `page instead of the file.\n` + "Download the ZIP through the browser and pass the local path instead, or use a direct-download URL.";
233
+ return `${getLoggingPrefix('error')} The downloaded content isn't a ZIP archive.\n${pintor.gray('SOURCE')} ${pintor.underline(source)}\n` + (contentType ? `${pintor.gray('GOT')} ${pintor.underline(contentType)}\n` : '') + `The URL likely requires authentication and returned an HTML login page instead of the file.\n` + `This happens with Slack, Google Drive, and Dropbox file pages.\n` + "Download the ZIP in the browser and pass the local path, or use a direct-download URL.";
258
234
  }
259
235
  function localZipNotFound(zipFilePath) {
260
- return `${getLoggingPrefix('error')} ZIP file not found.\nCheck the path and try again.\n${pintor.gray('PATH')} ${pintor.underline(zipFilePath)}`;
236
+ return `${getLoggingPrefix('error')} ZIP file not found.\n${pintor.gray('NOT FOUND')} ${pintor.underline(zipFilePath)}\nCheck the path, then try again.`;
261
237
  }
262
238
  function capitalizedBrowserName(browser) {
263
239
  const b = String(browser || '');
@@ -267,12 +243,11 @@ function capitalizedBrowserName(browser) {
267
243
  function getFileSize(fileSizeInBytes) {
268
244
  return `${(fileSizeInBytes / 1024).toFixed(2)}KB`;
269
245
  }
270
- function getAssetsSize(assets) {
271
- let totalSize = 0;
272
- assets?.forEach((asset)=>{
273
- totalSize += asset?.size || 0;
274
- });
275
- return getFileSize(totalSize);
246
+ function getHumanSize(sizeInBytes) {
247
+ const bytes = Math.max(0, sizeInBytes || 0);
248
+ if (bytes < 1024) return `${bytes} B`;
249
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
250
+ return `${(bytes / 1048576).toFixed(1)} MB`;
276
251
  }
277
252
  function printTree(node, prefix = '') {
278
253
  let output = '';
@@ -302,6 +277,7 @@ function getAssetsTree(assets) {
302
277
  else currentLevel = currentLevel[part];
303
278
  });
304
279
  });
280
+ if (0 === Object.keys(assetTree).length) return '';
305
281
  return `.\n${printTree(assetTree)}`;
306
282
  }
307
283
  function formatWarningLabelLine(label, value) {
@@ -369,17 +345,18 @@ function debugExtensionsToLoad(extensions) {
369
345
  return `${messaging_prefix('debug')} extensions count=${extensions.length} paths=${extensions.join(',')}`;
370
346
  }
371
347
  function noCompanionExtensionsResolved() {
372
- return `${getLoggingPrefix('warn')} No companion extensions resolved from ${pintor.underline('extensions')} config.\n${pintor.gray('Ensure each companion extension is an unpacked extension directory containing a manifest.json (e.g., ./extensions/<name>/manifest.json).')}`;
348
+ return `${getLoggingPrefix('warn')} No companion extensions resolved from the ${pintor.blue('extensions')} config.\nPoint each entry at an unpacked extension directory that contains a manifest.json, for example ./extensions/<name>/manifest.json.`;
373
349
  }
374
350
  function configLoadingError(configPath, error) {
375
- return `${getLoggingPrefix('error')} Could not load ${pintor.brightBlue('extension.config.js')}.\nFix the config file, then run the command again.\n${fmt.label('PATH')} ${fmt.val(configPath)}\n` + pintor.red(fmt.truncate(error, 1200));
351
+ return `${getLoggingPrefix('error')} Couldn't load ${pintor.blue('extension.config.js')}.\n${fmt.label('PATH')} ${fmt.val(configPath)}\n${pintor.red(fmt.truncate(error, 1200))}\nFix the config file, then run the command again.`;
376
352
  }
377
353
  function buildCommandFailed(error) {
378
354
  const message = (()=>{
379
355
  if (error instanceof Error && error.message) return error.message;
380
356
  return String(error || 'Unknown error');
381
357
  })();
382
- return `${getLoggingPrefix('error')} Build failed.\n${pintor.red(fmt.truncate(message, 1200))}`;
358
+ if (message.includes(getLoggingPrefix('error'))) return message;
359
+ return `${getLoggingPrefix('error')} ${pintor.red(fmt.truncate(message, 1200))}`;
383
360
  }
384
361
  function devCommandFailed(error) {
385
362
  const message = (()=>{
@@ -390,7 +367,7 @@ function devCommandFailed(error) {
390
367
  }
391
368
  function managedDependencyConflict(duplicates, userPackageJsonPath) {
392
369
  const list = duplicates.map((d)=>`- ${pintor.yellow(d)}`).join('\n');
393
- return `${getLoggingPrefix('error')} Your project declares dependencies that are managed by ${pintor.blue('Extension.js')} and referenced in ${pintor.underline('extension.config.js')}.\n${pintor.red('This can cause version conflicts and break the development/build process.')}\n\n${pintor.gray('Managed dependencies (remove these from your package.json):')}\n${list}\n\n${pintor.gray('PATH')} ${pintor.underline(userPackageJsonPath)}\nIf you need a different version, open an issue so we can consider bundling it safely.\nOperation aborted.`;
370
+ return `${getLoggingPrefix('error')} Your project declares dependencies that Extension.js already manages, so the build was aborted.\n${pintor.red('Duplicate declarations can cause version conflicts and break the build.')}\n\n${pintor.gray('Remove these from your package.json:')}\n${list}\n\n${pintor.gray('PATH')} ${pintor.underline(userPackageJsonPath)}\nIf you need a different version, open an issue so we can consider bundling it safely.`;
394
371
  }
395
372
  function loadCommonJsConfigWithStableDirname(absolutePath) {
396
373
  const code = __rspack_external_node_fs_5ea92f0c.readFileSync(absolutePath, 'utf-8');
@@ -650,7 +627,7 @@ async function config_loader_isUsingExperimentalConfig(projectPath) {
650
627
  }
651
628
  return false;
652
629
  }
653
- var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.0.21","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.1.1","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","adm-zip":"^0.6.0","browser-extension-manifest-fields":"^2.2.9","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","dotenv":"^17.2.3","es-module-lexer":"^2.1.0","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.18","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
630
+ var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.0.22","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.1.1","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","adm-zip":"^0.6.0","browser-extension-manifest-fields":"^2.2.9","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","dotenv":"^17.2.3","es-module-lexer":"^2.1.0","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.18","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
654
631
  function asAbsolute(p) {
655
632
  return __rspack_external_node_path_c5b9b54f.isAbsolute(p) ? p : __rspack_external_node_path_c5b9b54f.resolve(p);
656
633
  }
@@ -1580,11 +1557,10 @@ function messages_getLoggingPrefix(type) {
1580
1557
  return messaging_prefix(type);
1581
1558
  }
1582
1559
  function messages_ready(mode, browser) {
1583
- const key = String(browser || '').toLowerCase();
1584
- const extensionOutput = messaging_artifactNoun(key);
1585
- const cap = 'firefox' === key || 'gecko-based' === key || 'firefox-based' === key ? 'Firefox' : String(browser || '').charAt(0).toUpperCase() + String(browser || '').slice(1);
1586
- const pretty = pintor.green(`ready for ${mode}`);
1587
- return `${messages_getLoggingPrefix('info')} ${cap} ${extensionOutput} ${pretty}.`;
1560
+ const noun = artifactNoun(browser);
1561
+ const state = pintor.green(`ready for ${mode}`);
1562
+ const watching = 'development' === mode ? ' Watching for file changes.' : '';
1563
+ return `${messages_getLoggingPrefix('success')} ${noun} ${state}.${watching}`;
1588
1564
  }
1589
1565
  function readJsonRecord(filePath) {
1590
1566
  try {
@@ -1605,6 +1581,15 @@ function getExtensionVersion() {
1605
1581
  }
1606
1582
  })();
1607
1583
  }
1584
+ function collapseHomeDirInCardValue(value) {
1585
+ const raw = String(value || '');
1586
+ const home = __rspack_external_node_os_74b4b876.homedir();
1587
+ if (!home || !raw.startsWith(home)) return raw;
1588
+ const rest = raw.slice(home.length);
1589
+ if ('' === rest) return '~';
1590
+ if (rest.startsWith(__rspack_external_node_path_c5b9b54f.sep) || rest.startsWith('/')) return `~${rest}`;
1591
+ return raw;
1592
+ }
1608
1593
  function browserRunnerDisabled(args) {
1609
1594
  const manifest = readJsonRecord(args.manifestPath);
1610
1595
  const ready = readJsonRecord(args.readyPath);
@@ -1616,17 +1601,24 @@ function browserRunnerDisabled(args) {
1616
1601
  const extensionVersion = String(manifest?.version || '').trim();
1617
1602
  const extensionLabel = extensionVersion ? `${extensionName} ${extensionVersion}` : extensionName;
1618
1603
  const extensionJsVersion = getExtensionVersion();
1604
+ const updateSuffix = process.env.EXTENSION_CLI_UPDATE_SUFFIX || '';
1605
+ if (updateSuffix) delete process.env.EXTENSION_CLI_UPDATE_SUFFIX;
1619
1606
  return card({
1620
1607
  version: extensionJsVersion,
1608
+ suffix: updateSuffix,
1621
1609
  rows: [
1622
1610
  {
1623
1611
  label: 'Browser',
1624
- value: browserRowValue(String(args.browser || 'unknown'), args.browserModeLabel || `${browserLabel} (build-only mode)`)
1612
+ value: browserRowValue(String(args.browser || 'unknown'), `${browserLabel} (no-browser mode)`)
1625
1613
  },
1626
1614
  {
1627
1615
  label: 'Extension',
1628
1616
  value: extensionLabel
1629
1617
  },
1618
+ {
1619
+ label: 'Output',
1620
+ value: collapseHomeDirInCardValue(String(args.distPath || '').trim())
1621
+ },
1630
1622
  {
1631
1623
  label: 'Run ID',
1632
1624
  value: runLabel
@@ -1635,43 +1627,43 @@ function browserRunnerDisabled(args) {
1635
1627
  });
1636
1628
  }
1637
1629
  function portInUse(requestedPort, newPort) {
1638
- return `The requested port ${pintor.brightBlue(requestedPort.toString())} is in use.\nThe dev server uses ${pintor.brightBlue(newPort.toString())} instead.`;
1630
+ return `${messages_getLoggingPrefix('warn')} Port ${requestedPort} is in use.\nThe dev server listens on port ${newPort} instead.`;
1639
1631
  }
1640
1632
  function extensionJsRunnerError(error) {
1641
- return `Extension.js could not start the runner.\n${pintor.red(String(error))}`;
1633
+ return `${messages_getLoggingPrefix('error')} Extension.js couldn't start the runner.\n${pintor.red(String(error))}`;
1642
1634
  }
1643
1635
  function autoExitModeEnabled(ms) {
1644
- return `Auto-exit is enabled.\nThe process exits after ${pintor.brightBlue(ms.toString())} ms if idle.`;
1636
+ return `${messages_getLoggingPrefix('info')} Auto-exit is enabled.\nThe process exits after ${ms} ms of idle time.`;
1645
1637
  }
1646
1638
  function autoExitTriggered(ms) {
1647
- return `Auto-exit triggered after ${pintor.brightBlue(ms.toString())} ms.\nClean up and exit.`;
1639
+ return `${messages_getLoggingPrefix('info')} Auto-exit triggered after ${ms} ms.\nThe process cleans up and exits now.`;
1648
1640
  }
1649
1641
  function autoExitForceKill(ms) {
1650
- return `Force-kill the process after ${pintor.brightBlue(ms.toString())} ms to ensure exit.`;
1642
+ return `${messages_getLoggingPrefix('warn')} The process didn't exit within ${ms} ms, so it exits forcibly now.`;
1651
1643
  }
1652
1644
  function devServerStartTimeout(ms) {
1653
1645
  return [
1654
- `Dev server startup is taking longer than expected (${pintor.brightBlue(ms.toString())} ms).`,
1655
- "The bundler may have encountered an error before emitting the first build.",
1656
- `If nothing else prints, try setting ${pintor.brightBlue('EXTENSION_VERBOSE=1')} for more logs.`
1646
+ `${messages_getLoggingPrefix('warn')} The dev server didn't start within ${ms} ms.`,
1647
+ "The bundler may have hit an error before emitting the first build.",
1648
+ `If nothing else prints, set ${pintor.blue('EXTENSION_VERBOSE=1')} to see more logs.`
1657
1649
  ].join('\n');
1658
1650
  }
1659
1651
  function bundlerFatalError(error) {
1660
1652
  const text = error instanceof Error ? error.stack || error.message : String(error);
1661
- return `Build failed to start:\n${pintor.red(text)}`;
1653
+ return `${messages_getLoggingPrefix('error')} The build failed to start.\n${pintor.red(text)}`;
1662
1654
  }
1663
1655
  function bundlerRecompiling() {
1664
- return "Recompile due to file changes…";
1656
+ return `${messages_getLoggingPrefix('info')} Recompiling due to file changes…`;
1665
1657
  }
1666
1658
  function noEntrypointsDetected(port) {
1667
1659
  return [
1668
- "No entrypoints or assets were produced by the initial compilation.",
1669
- `The dev server is running on 127.0.0.1:${pintor.brightBlue(port.toString())}, but nothing is being built.`,
1660
+ `${messages_getLoggingPrefix('warn')} The first compilation produced no entrypoints or assets.`,
1661
+ `The dev server is running on 127.0.0.1:${port}, but nothing is being built.`,
1670
1662
  "Possible causes:",
1671
- " Empty or missing entry configuration.",
1672
- " Extension-related plugins are disabled (entries not derived from manifest).",
1673
- " All sources are ignored or excluded.",
1674
- `Try enabling verbose logs with ${pintor.brightBlue('EXTENSION_VERBOSE=1')} or review your extension config.`
1663
+ "- Empty or missing entry configuration.",
1664
+ "- Extension plugins are disabled, so entries aren't derived from the manifest.",
1665
+ "- All sources are ignored or excluded.",
1666
+ `Set ${pintor.blue('EXTENSION_VERBOSE=1')} to see verbose logs, or review your extension config.`
1675
1667
  ].join('\n');
1676
1668
  }
1677
1669
  function spacerLine() {
@@ -2241,11 +2233,10 @@ async function extensionPreview(pathOrRemoteUrl, previewOptions, browserLauncher
2241
2233
  browser: browserLabel,
2242
2234
  manifestPath: projectStructure.manifestPath,
2243
2235
  readyPath: metadata.readyPath,
2244
- browserModeLabel: `${browserLabel.charAt(0).toUpperCase() + browserLabel.slice(1)} (no-browser mode)`
2236
+ distPath: outputPath
2245
2237
  }));
2246
2238
  console.log(spacerLine());
2247
- console.log(runningMessage(browser));
2248
- console.log(previewSkippedNoBrowser(browser));
2239
+ console.log(runningMessage(browser, true));
2249
2240
  metadata.writeReady();
2250
2241
  return;
2251
2242
  }
@@ -2304,4 +2295,4 @@ async function extensionPreview(pathOrRemoteUrl, previewOptions, browserLauncher
2304
2295
  await browserLauncher(resolvedOpts);
2305
2296
  metadata.writeReady();
2306
2297
  }
2307
- export { CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, PlaywrightPlugin, asAbsolute, assertNoManagedDependencyConflicts, authorInstallNotice, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserLaunchFailed, browserRunnerDisabled, buildCommandFailed, buildSuccess, buildSuccessWithWarnings, buildWarningsDetails, buildWebpack, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, debugBrowser, debugContextPath, debugDirs, debugExtensionsToLoad, debugOutputPath, devCommandFailed, devServerStartTimeout, downloadingText, extensionJsRunnerError, extensionLoadRecovered, extensionLoadStillRefused, extensionPreview, failedToDownloadOrExtractZIPFileError, getDirs, getDistPath, getProjectStructure, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, invalidRemoteZip, isChromiumBasedBrowser, isGeckoBasedBrowser, loadBrowserConfig, loadCommandConfig, loadCustomConfig, localZipNotFound, manifestInvalidJson, messages_ready, needsInstall, noCompanionExtensionsResolved, noEntrypointsDetected, normalizeBrowser, notAZipArchive, package_namespaceObject, packagingDistributionFiles, packagingSourceFiles, portInUse, projectInstallFallbackToNpm, projectInstallScriptsDisabled, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, sanitize, spacerLine, toPosixPath, treeWithDistFilesBrowser, treeWithSourceAndDistFiles, treeWithSourceFiles, unpackagedSuccessfully, unpackagingExtension, writingTypeDefinitions, writingTypeDefinitionsError, zipArtifactReady };
2298
+ export { CHROMIUM_FAMILY_ALIASES, GECKO_FAMILY_ALIASES, PlaywrightPlugin, asAbsolute, assertNoManagedDependencyConflicts, authorInstallNotice, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserLaunchFailed, browserRunnerDisabled, buildAssetsTree, buildCommandFailed, buildComplete, buildFailed, buildWarningsDetails, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, debugBrowser, debugContextPath, debugDirs, debugExtensionsToLoad, debugOutputPath, devCommandFailed, devServerStartTimeout, downloadingText, extensionJsRunnerError, extensionLoadRecovered, extensionLoadStillRefused, extensionPreview, failedToDownloadOrExtractZIPFileError, getDirs, getDistPath, getProjectStructure, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, invalidRemoteZip, isChromiumBasedBrowser, isGeckoBasedBrowser, loadBrowserConfig, loadCommandConfig, loadCustomConfig, localZipNotFound, manifestInvalidJson, messages_ready, needsInstall, noCompanionExtensionsResolved, noEntrypointsDetected, normalizeBrowser, notAZipArchive, package_namespaceObject, packagingDistributionFiles, packagingSourceFiles, portInUse, projectInstallFallbackToNpm, projectInstallScriptsDisabled, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, sanitize, spacerLine, toPosixPath, treeWithDistFilesBrowser, treeWithSourceAndDistFiles, treeWithSourceFiles, unpackagedSuccessfully, unpackagingExtension, writingTypeDefinitions, writingTypeDefinitionsError, zipArtifactReady };
package/dist/266.mjs CHANGED
@@ -2,27 +2,59 @@ import { createRequire as __extjsCreateRequire } from "node:module"; const requi
2
2
  import pintor from "pintor";
3
3
  import { prefix } from "./349.mjs";
4
4
  function importScriptsDependencyMissing(workerPath, literal, expectedPath, sourceSibling) {
5
- const sibling = sourceSibling ? `Found ${pintor.yellow(sourceSibling)}, but importScripts dependencies are copied as-is, not compiled.\n` : '';
6
- return `The background service_worker ${pintor.yellow(workerPath)} calls importScripts(${pintor.yellow(`'${literal}'`)}), but ${pintor.yellow(expectedPath)} is not part of the output.\nThe call will fail at runtime.\n` + sibling + `Move the file to ${pintor.yellow(expectedPath)} (or ${pintor.yellow('public/')}) so it ships with the extension, or import it from the worker so it ` + "gets bundled.";
5
+ const lines = [];
6
+ lines.push(`The background service worker calls importScripts('${literal}'), but the file isn't in the output.`);
7
+ lines.push(`${pintor.gray('PATH')} ${pintor.underline(workerPath)}`);
8
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(expectedPath)}`);
9
+ lines.push("The call fails at runtime.");
10
+ if (sourceSibling) lines.push(`Found ${pintor.underline(sourceSibling)}, but importScripts dependencies are copied as-is, not compiled.`);
11
+ lines.push(`- Move the file to ${pintor.blue(expectedPath)} or ${pintor.blue('public/')} so it ships with the extension.`);
12
+ lines.push("- Import it from the worker so it gets bundled.");
13
+ return lines.join('\n');
7
14
  }
8
15
  function injectedFileDependencyMissing(assetName, literal, expectedPath, sourceSibling) {
9
- const sibling = sourceSibling ? `Found ${pintor.yellow(sourceSibling)}, but injected files are copied as-is, not compiled.\n` : '';
10
- return `${pintor.yellow(assetName)} injects ${pintor.yellow(`'${literal}'`)} via executeScript/insertCSS, but ${pintor.yellow(expectedPath)} is not part of the output.\nThe injection will fail at runtime.\n` + sibling + `Move the file to ${pintor.yellow(expectedPath)} (or ${pintor.yellow('public/')}) so it ships with the extension.`;
16
+ const lines = [];
17
+ lines.push(`${assetName} injects '${literal}' via executeScript/insertCSS, but the file isn't in the output.`);
18
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(expectedPath)}`);
19
+ lines.push("The injection fails at runtime.");
20
+ if (sourceSibling) lines.push(`Found ${pintor.underline(sourceSibling)}, but injected files are copied as-is, not compiled.`);
21
+ lines.push(`Move the file to ${pintor.blue(expectedPath)} or ${pintor.blue('public/')} so it ships with the extension.`);
22
+ return lines.join('\n');
11
23
  }
12
24
  function fetchedFileDependencyMissing(assetName, literal, expectedPath) {
13
- return `${pintor.yellow(assetName)} loads ${pintor.yellow(`'${literal}'`)} at runtime (fetch/XMLHttpRequest/new URL), but ${pintor.yellow(expectedPath)} is not part of the output.\nThe request will fail at runtime.\nMove the file so it resolves to ${pintor.yellow(expectedPath)} (or serve it from ${pintor.yellow('public/')}) so it ships with the extension.`;
25
+ const lines = [];
26
+ lines.push(`${assetName} loads '${literal}' at runtime (fetch/XMLHttpRequest/new URL), but the file isn't in the output.`);
27
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(expectedPath)}`);
28
+ lines.push("The request fails at runtime.");
29
+ lines.push(`Move the file so it resolves to ${pintor.blue(expectedPath)}, or serve it from ${pintor.blue('public/')} so it ships with the extension.`);
30
+ return lines.join('\n');
14
31
  }
15
32
  function getURLDependencyMissing(assetName, literal, expectedPath) {
16
- return `${pintor.yellow(assetName)} references ${pintor.yellow(`'${literal}'`)} via chrome.runtime.getURL(), but ${pintor.yellow(expectedPath)} is not part of the output.\nThe reference will fail at runtime.\nMove the file to ${pintor.yellow(expectedPath)} (or ${pintor.yellow('public/')}) so it ships with the extension.`;
33
+ const lines = [];
34
+ lines.push(`${assetName} references '${literal}' via chrome.runtime.getURL(), but the file isn't in the output.`);
35
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(expectedPath)}`);
36
+ lines.push("The reference fails at runtime.");
37
+ lines.push(`Move the file to ${pintor.blue(expectedPath)} or ${pintor.blue('public/')} so it ships with the extension.`);
38
+ return lines.join('\n');
17
39
  }
18
40
  function runtimeSetSurfaceDependencyMissing(assetName, literal, expectedPath) {
19
- return `${pintor.yellow(assetName)} sets ${pintor.yellow(`'${literal}'`)} as a runtime surface (setPopup/setOptions), but ${pintor.yellow(expectedPath)} is not part of the output.\nThe surface will open a 404 at runtime.\nMove the file to ${pintor.yellow(expectedPath)} (or ${pintor.yellow('public/')}) so it ships with the extension.`;
41
+ const lines = [];
42
+ lines.push(`${assetName} sets '${literal}' as a runtime surface (setPopup/setOptions), but the file isn't in the output.`);
43
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(expectedPath)}`);
44
+ lines.push("The surface opens a 404 at runtime.");
45
+ lines.push(`Move the file to ${pintor.blue(expectedPath)} or ${pintor.blue('public/')} so it ships with the extension.`);
46
+ return lines.join('\n');
20
47
  }
21
48
  function staticImportDependencyMissing(assetName, literal, expectedPath) {
22
- return `${pintor.yellow(assetName)} (copied verbatim into the output) imports ${pintor.yellow(`'${literal}'`)}, but ${pintor.yellow(expectedPath)} is not part of the output.\nThe import will fail at runtime.\nMove the file to ${pintor.yellow(expectedPath)} (or ${pintor.yellow('public/')}) so it ships with the extension.`;
49
+ const lines = [];
50
+ lines.push(`${assetName} (copied verbatim into the output) imports '${literal}', but the file isn't in the output.`);
51
+ lines.push(`${pintor.gray('NOT FOUND')} ${pintor.underline(expectedPath)}`);
52
+ lines.push("The import fails at runtime.");
53
+ lines.push(`Move the file to ${pintor.blue(expectedPath)} or ${pintor.blue('public/')} so it ships with the extension.`);
54
+ return lines.join('\n');
23
55
  }
24
56
  function reservedScriptsFolder(relPath, indicators) {
25
57
  const reasons = indicators.map((r)=>`- ${pintor.gray(r)}`).join('\n');
26
- return `${prefix('error')} scripts/ is a reserved folder in Extension.js.\nEvery file under ${pintor.yellow("scripts/")} is wrapped with the browser content-script mount runtime, so Node.js-only files placed here will fail to parse or run.\nRename the folder at the project root (for example ${pintor.yellow('bin/')}, ${pintor.yellow('tools/')}, ${pintor.yellow('ops/')}, ${pintor.yellow('tasks/')}, or ${pintor.yellow("ci-scripts/")}) or move the file out of scripts/.\n\n${pintor.red('NODE.JS SHAPE')}\n${reasons}\n${pintor.red('NOT ALLOWED')} ${pintor.underline(relPath)}`;
58
+ return `${prefix('error')} scripts/ is a reserved folder in Extension.js.\n${pintor.gray('PATH')} ${pintor.underline(relPath)}\nEvery file under ${pintor.blue("scripts/")} is wrapped with the browser content-script mount runtime, so Node.js-only files placed here fail to parse or run.\nThis file looks Node.js-only:\n${reasons}\nRename the folder at the project root (for example ${pintor.blue('bin/')}, ${pintor.blue('tools/')}, or ${pintor.blue('tasks/')}), or move the file out of scripts/.`;
27
59
  }
28
60
  export { fetchedFileDependencyMissing, getURLDependencyMissing, importScriptsDependencyMissing, injectedFileDependencyMissing, reservedScriptsFolder, runtimeSetSurfaceDependencyMissing, staticImportDependencyMissing };