@jskit-ai/jskit-cli 0.2.38 → 0.2.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,23 @@ import {
3
3
  ensureObject,
4
4
  sortStrings
5
5
  } from "../../shared/collectionUtils.js";
6
+ import {
7
+ createColorFormatter,
8
+ renderInlineCodeSpans,
9
+ writeWrappedLines
10
+ } from "../../shared/outputFormatting.js";
6
11
 
7
12
  const JSKIT_SCOPE_PREFIX = "@jskit-ai/";
13
+ const HELP_TEXT_BY_KEY = Object.freeze({
14
+ "page-target-file":
15
+ "Vue page file relative to src/pages/. It must resolve to a configured surface.",
16
+ "existing-page-target-file":
17
+ "Existing Vue page file relative to src/pages/. It must resolve to a configured surface.",
18
+ "existing-vue-sfc-target-file":
19
+ "Existing Vue SFC path relative to app root.",
20
+ "crud-target-root":
21
+ "Route root directory relative to src/pages/ (example: admin/products)."
22
+ });
8
23
 
9
24
  function isHelpToken(value = "") {
10
25
  return String(value || "").trim().toLowerCase() === "help";
@@ -23,6 +38,15 @@ function resolvePackageSummary(entry = {}) {
23
38
  return String(descriptor.description || "").trim();
24
39
  }
25
40
 
41
+ function resolveHelpText(rawValue = "", helpTextKey = "") {
42
+ const normalizedValue = String(rawValue || "").trim();
43
+ if (normalizedValue) {
44
+ return normalizedValue;
45
+ }
46
+
47
+ return String(HELP_TEXT_BY_KEY[String(helpTextKey || "").trim()] || "").trim();
48
+ }
49
+
26
50
  function buildPackageOptionRows(packageEntry = {}) {
27
51
  const descriptor = ensureObject(packageEntry?.descriptor);
28
52
  const optionSchemas = ensureObject(descriptor.options);
@@ -37,7 +61,9 @@ function buildPackageOptionRows(packageEntry = {}) {
37
61
  defaultValue: String(schema.defaultValue || "").trim(),
38
62
  allowEmpty: schema.allowEmpty === true,
39
63
  promptLabel: String(schema.promptLabel || "").trim(),
40
- promptHint: String(schema.promptHint || "").trim()
64
+ promptHint: String(schema.promptHint || "").trim(),
65
+ helpLabel: resolveHelpText(schema.helpLabel, schema.helpLabelKey),
66
+ helpHint: resolveHelpText(schema.helpHint, schema.helpHintKey)
41
67
  }));
42
68
  }
43
69
 
@@ -75,7 +101,7 @@ function normalizeSubcommandPositionalArgRows(rawRows = []) {
75
101
  rows.push(Object.freeze({
76
102
  name,
77
103
  required: row.required !== false,
78
- description: String(row.description || "").trim()
104
+ description: resolveHelpText(row.description, row.descriptionKey)
79
105
  }));
80
106
  }
81
107
  return rows;
@@ -136,31 +162,112 @@ function normalizeHelpExampleRows(rawRows = []) {
136
162
  return rows;
137
163
  }
138
164
 
139
- function appendHelpExamples(lines = [], exampleRows = []) {
165
+ function normalizeHelpNoteRows(rawRows = []) {
166
+ const rows = [];
167
+
168
+ for (const rawRow of ensureArray(rawRows)) {
169
+ if (typeof rawRow === "string") {
170
+ const note = String(rawRow || "").trim();
171
+ if (note) {
172
+ rows.push(note);
173
+ }
174
+ continue;
175
+ }
176
+
177
+ const row = ensureObject(rawRow);
178
+ const note = resolveHelpText(row.text || row.note || "", row.textKey || row.noteKey);
179
+ if (note) {
180
+ rows.push(note);
181
+ }
182
+ }
183
+
184
+ return rows;
185
+ }
186
+
187
+ function normalizeHelpParagraphRows(rawValue = "") {
188
+ if (Array.isArray(rawValue)) {
189
+ return normalizeHelpNoteRows(rawValue);
190
+ }
191
+
192
+ const sourceText = String(rawValue || "").trim();
193
+ if (!sourceText) {
194
+ return [];
195
+ }
196
+
197
+ return sourceText
198
+ .split(/\n\s*\n/u)
199
+ .map((paragraph) => paragraph.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean).join(" "))
200
+ .filter(Boolean);
201
+ }
202
+
203
+ function appendHelpLongDescription(lines = [], rawLongDescription = "", { color = null } = {}) {
204
+ const paragraphs = normalizeHelpParagraphRows(rawLongDescription);
205
+ if (paragraphs.length < 1) {
206
+ return;
207
+ }
208
+
209
+ lines.push("");
210
+ lines.push(color ? color.heading("Long:") : "Long:");
211
+ appendSeparatedBlocks(lines, paragraphs.map((paragraph) => renderInlineCodeSpans(paragraph, color)));
212
+ }
213
+
214
+ function appendHelpExamples(lines = [], exampleRows = [], { color = null } = {}) {
140
215
  const examples = ensureArray(exampleRows);
141
216
  if (examples.length < 1) {
142
217
  return;
143
218
  }
144
219
 
145
220
  lines.push("");
146
- lines.push(`Examples (${examples.length}):`);
147
- for (const example of examples) {
148
- const label = String(example?.label || "").trim();
149
- if (label) {
150
- lines.push(`- ${label}`);
151
- for (const commandLine of ensureArray(example?.lines)) {
152
- lines.push(` ${commandLine}`);
221
+ lines.push(color ? color.heading(`Examples (${examples.length}):`) : `Examples (${examples.length}):`);
222
+ appendSeparatedBlocks(
223
+ lines,
224
+ examples.map((example) => {
225
+ const block = [];
226
+ const label = String(example?.label || "").trim();
227
+ if (label) {
228
+ block.push(`- ${color ? color.item(label) : label}`);
229
+ for (const commandLine of ensureArray(example?.lines)) {
230
+ block.push(` ${commandLine}`);
231
+ }
232
+ return block;
153
233
  }
154
- continue;
155
- }
156
234
 
157
- const commandLines = ensureArray(example?.lines);
158
- if (commandLines.length < 1) {
159
- continue;
235
+ const commandLines = ensureArray(example?.lines);
236
+ if (commandLines.length < 1) {
237
+ return block;
238
+ }
239
+ block.push(`- ${commandLines[0]}`);
240
+ for (const commandLine of commandLines.slice(1)) {
241
+ block.push(` ${commandLine}`);
242
+ }
243
+ return block;
244
+ }).filter((block) => block.length > 0)
245
+ );
246
+ }
247
+
248
+ function appendHelpNotes(lines = [], rawNotes = [], { color = null } = {}) {
249
+ const notes = normalizeHelpNoteRows(rawNotes);
250
+ if (notes.length < 1) {
251
+ return;
252
+ }
253
+
254
+ lines.push("");
255
+ lines.push(color ? color.heading(`Notes (${notes.length}):`) : `Notes (${notes.length}):`);
256
+ appendSeparatedBlocks(
257
+ lines,
258
+ notes.map((note) => `- ${renderInlineCodeSpans(note, color)}`)
259
+ );
260
+ }
261
+
262
+ function appendSeparatedBlocks(lines = [], blocks = []) {
263
+ const normalizedBlocks = ensureArray(blocks);
264
+ for (const [index, block] of normalizedBlocks.entries()) {
265
+ if (index > 0) {
266
+ lines.push("");
160
267
  }
161
- lines.push(`- ${commandLines[0]}`);
162
- for (const commandLine of commandLines.slice(1)) {
163
- lines.push(` ${commandLine}`);
268
+ const lineList = Array.isArray(block) ? block : [block];
269
+ for (const line of lineList) {
270
+ lines.push(line);
164
271
  }
165
272
  }
166
273
  }
@@ -194,10 +301,12 @@ function resolveGeneratorSubcommandMetadata(packageEntry = {}) {
194
301
  exportName,
195
302
  primary: primarySubcommand === name.toLowerCase(),
196
303
  description: String(definition.description || "").trim(),
304
+ longDescription: normalizeHelpParagraphRows(definition.longDescription),
197
305
  positionalArgs: normalizeSubcommandPositionalArgRows(definition.positionalArgs),
198
306
  optionNames,
199
307
  requiredOptionNames,
200
- examples: normalizeHelpExampleRows(definition.examples)
308
+ examples: normalizeHelpExampleRows(definition.examples),
309
+ notes: normalizeHelpNoteRows(definition.notes)
201
310
  }));
202
311
  }
203
312
 
@@ -207,7 +316,7 @@ function resolveGeneratorSubcommandMetadata(packageEntry = {}) {
207
316
  });
208
317
  }
209
318
 
210
- function formatOptionSummary(optionRow = {}) {
319
+ function formatOptionSummary(optionRow = {}, { color = null } = {}) {
211
320
  const status = optionRow.required ? "required" : "optional";
212
321
  const hasDefaultValue = String(optionRow.defaultValue || "").length > 0;
213
322
  const optionalDefaultSuffix = optionRow.required
@@ -217,14 +326,22 @@ function formatOptionSummary(optionRow = {}) {
217
326
  ? `; default: ${optionRow.defaultValue}`
218
327
  : optionalDefaultSuffix;
219
328
  const allowEmptySuffix = optionRow.allowEmpty ? "; allow-empty" : "";
220
- const labelParts = [optionRow.promptLabel, optionRow.promptHint].filter(Boolean);
329
+ const labelParts = [
330
+ String(optionRow.helpLabel || "").trim() || String(optionRow.promptLabel || "").trim(),
331
+ String(optionRow.helpHint || "").trim() || String(optionRow.promptHint || "").trim()
332
+ ].filter(Boolean);
221
333
  const label = labelParts.join(". ");
222
- const typeSuffix = optionRow.inputType ? `<${optionRow.inputType}> ` : "";
334
+ const normalizedInputType = String(optionRow.inputType || "").trim().toLowerCase();
335
+ const typeSuffix = normalizedInputType && normalizedInputType !== "flag" && normalizedInputType !== "boolean"
336
+ ? `<${optionRow.inputType}> `
337
+ : "";
223
338
  const baseDescription = label || "No description provided.";
224
339
  const description = optionRow.name === "placement-component-token"
225
- ? `${baseDescription} Use jskit list-link-items to discover link-item tokens.`
340
+ ? `${baseDescription} Use \`jskit list-link-items\` to discover link-item tokens.`
226
341
  : baseDescription;
227
- return `- --${optionRow.name} ${typeSuffix}[${status}${defaultSuffix}${allowEmptySuffix}]: ${description}`.trim();
342
+ const optionName = `--${optionRow.name}`;
343
+ const renderedOptionName = color ? color.item(optionName) : optionName;
344
+ return `- ${renderedOptionName} ${typeSuffix}[${status}${defaultSuffix}${allowEmptySuffix}]: ${renderInlineCodeSpans(description, color)}`.trim();
228
345
  }
229
346
 
230
347
  function formatPositionalArgUsageToken(arg = {}) {
@@ -238,14 +355,15 @@ function formatPositionalArgUsageToken(arg = {}) {
238
355
  return name;
239
356
  }
240
357
 
241
- function formatPositionalArgSummary(arg = {}) {
358
+ function formatPositionalArgSummary(arg = {}, { color = null } = {}) {
242
359
  const name = String(arg.name || "").trim();
243
360
  if (!name) {
244
361
  return "";
245
362
  }
246
363
  const status = arg.required === false ? "optional" : "required";
247
- const description = String(arg.description || "").trim() || "No description provided.";
248
- return `- ${name} [${status}]: ${description}`;
364
+ const description = renderInlineCodeSpans(String(arg.description || "").trim() || "No description provided.", color);
365
+ const renderedName = color ? color.item(name) : name;
366
+ return `- ${renderedName} [${status}]: ${description}`;
249
367
  }
250
368
 
251
369
  function findGeneratorSubcommandRow(packageEntry = {}, subcommandName = "") {
@@ -326,23 +444,29 @@ function renderGenerateCatalogHelp({
326
444
  return;
327
445
  }
328
446
 
447
+ const color = createColorFormatter(io.stdout);
329
448
  const lines = [];
330
- lines.push("Generate command");
449
+ lines.push(color.heading("Generate command"));
331
450
  lines.push("");
332
- lines.push(`Available generators (${generators.length}):`);
451
+ lines.push(color.heading(`Available generators (${generators.length}):`));
333
452
  for (const generator of generators) {
334
453
  const shortIdSuffix =
335
- generator.shortId && generator.shortId !== generator.packageId ? `${generator.shortId} ` : "";
454
+ generator.shortId && generator.shortId !== generator.packageId
455
+ ? `${color.item(generator.shortId)} `
456
+ : "";
336
457
  const versionSuffix = generator.version ? ` (${generator.version})` : "";
337
458
  const descriptionSuffix = generator.description ? `: ${generator.description}` : "";
338
- lines.push(`- ${shortIdSuffix}${generator.packageId}${versionSuffix}${descriptionSuffix}`.trim());
459
+ lines.push(`- ${shortIdSuffix}${color.item(generator.packageId)}${versionSuffix}${descriptionSuffix}`.trim());
339
460
  }
340
461
  lines.push("");
341
- lines.push("Use:");
462
+ lines.push(color.heading("Use:"));
342
463
  lines.push("- jskit generate <generatorId> help");
343
464
  lines.push("- jskit generate <generatorId> [subcommand] [subcommand args...] [--<option> <value>...]");
344
465
  lines.push("- jskit list generators");
345
- io.stdout.write(`${lines.join("\n")}\n`);
466
+ writeWrappedLines({
467
+ stdout: io.stdout,
468
+ lines
469
+ });
346
470
  }
347
471
 
348
472
  function renderAddCatalogHelp({
@@ -390,34 +514,38 @@ function renderAddCatalogHelp({
390
514
  return;
391
515
  }
392
516
 
517
+ const color = createColorFormatter(io.stdout);
393
518
  const lines = [];
394
- lines.push("Add command");
519
+ lines.push(color.heading("Add command"));
395
520
  lines.push("");
396
- lines.push(`Available bundles (${bundles.length}):`);
521
+ lines.push(color.heading(`Available bundles (${bundles.length}):`));
397
522
  for (const bundle of bundles) {
398
523
  const versionSuffix = bundle.version ? ` (${bundle.version})` : "";
399
524
  const countSuffix = ` [packages:${bundle.packageCount}]`;
400
525
  const descriptionSuffix = bundle.description ? `: ${bundle.description}` : "";
401
- lines.push(`- ${bundle.bundleId}${versionSuffix}${countSuffix}${descriptionSuffix}`);
526
+ lines.push(`- ${color.item(bundle.bundleId)}${versionSuffix}${countSuffix}${descriptionSuffix}`);
402
527
  }
403
528
  lines.push("");
404
- lines.push(`Available runtime packages (${runtimePackages.length}):`);
529
+ lines.push(color.heading(`Available runtime packages (${runtimePackages.length}):`));
405
530
  for (const runtimePackage of runtimePackages) {
406
531
  const shortIdSuffix =
407
532
  runtimePackage.shortId && runtimePackage.shortId !== runtimePackage.packageId
408
- ? `${runtimePackage.shortId} `
533
+ ? `${color.item(runtimePackage.shortId)} `
409
534
  : "";
410
535
  const versionSuffix = runtimePackage.version ? ` (${runtimePackage.version})` : "";
411
536
  const descriptionSuffix = runtimePackage.description ? `: ${runtimePackage.description}` : "";
412
- lines.push(`- ${shortIdSuffix}${runtimePackage.packageId}${versionSuffix}${descriptionSuffix}`.trim());
537
+ lines.push(`- ${shortIdSuffix}${color.item(runtimePackage.packageId)}${versionSuffix}${descriptionSuffix}`.trim());
413
538
  }
414
539
  lines.push("");
415
- lines.push("Use:");
540
+ lines.push(color.heading("Use:"));
416
541
  lines.push("- jskit add package <packageId> help");
417
542
  lines.push("- jskit add bundle <bundleId> help");
418
543
  lines.push("- jskit add package <packageId> [--<option> <value>...]");
419
544
  lines.push("- jskit add bundle <bundleId> [--<option> <value>...]");
420
- io.stdout.write(`${lines.join("\n")}\n`);
545
+ writeWrappedLines({
546
+ stdout: io.stdout,
547
+ lines
548
+ });
421
549
  }
422
550
 
423
551
  function renderGeneratePackageHelp({
@@ -434,13 +562,11 @@ function renderGeneratePackageHelp({
434
562
  const preferredId = toShortPackageId(packageId) || packageId;
435
563
  const usage = Object.freeze([
436
564
  `jskit generate ${preferredId} help`,
437
- `jskit generate ${preferredId} help <subcommand>`,
438
565
  `jskit generate ${preferredId} <subcommand> help`,
439
566
  `jskit generate ${preferredId} [subcommand] [subcommand args...] [--<option> <value>...]`
440
567
  ]);
441
568
  const resolvedFrom = String(packageIdInput || "").trim();
442
569
  const resolvedFromLabel = resolvedFrom && resolvedFrom !== packageId ? resolvedFrom : "";
443
- const hasRequiredWithDefaults = optionRows.some((row) => row.required && row.defaultValue);
444
570
 
445
571
  if (json) {
446
572
  io.stdout.write(`${JSON.stringify({
@@ -458,47 +584,60 @@ function renderGeneratePackageHelp({
458
584
  return;
459
585
  }
460
586
 
587
+ const color = createColorFormatter(io.stdout);
461
588
  const lines = [];
462
- lines.push(`Generator help: ${packageId}`);
589
+ lines.push(`Generator help: ${color.emphasis(packageId)}`);
463
590
  if (resolvedFromLabel) {
464
- lines.push(`Resolved from: ${resolvedFromLabel}`);
591
+ lines.push(`Resolved from: ${color.item(resolvedFromLabel)}`);
465
592
  }
466
593
  if (summary) {
467
594
  lines.push(`Description: ${summary}`);
468
595
  }
469
596
  lines.push("");
470
- lines.push("Use:");
597
+ lines.push(color.heading("Use:"));
471
598
  for (const usageLine of usage) {
472
599
  lines.push(`- ${usageLine}`);
473
600
  }
474
601
  lines.push("");
475
602
 
476
603
  const subcommands = ensureArray(generatorMetadata.subcommands);
604
+ const shouldShowPackageExamples = subcommands.length < 1;
605
+ const shouldShowPackageOptions = subcommands.length < 1;
606
+ const hasRequiredWithDefaults = optionRows.some((row) => row.required && row.defaultValue);
477
607
  if (subcommands.length > 0) {
478
- lines.push(`Subcommands (${subcommands.length}):`);
608
+ lines.push(color.heading(`Subcommands (${subcommands.length}):`));
479
609
  for (const subcommand of subcommands) {
480
- const primarySuffix = subcommand.primary ? " [primary]" : "";
610
+ const primarySuffix = subcommand.primary ? color.dim(" [primary]") : "";
481
611
  const descriptionSuffix = subcommand.description ? `: ${subcommand.description}` : "";
482
- lines.push(`- ${subcommand.name}${primarySuffix}${descriptionSuffix}`);
612
+ lines.push(`- ${color.item(subcommand.name)}${primarySuffix}${descriptionSuffix}`);
483
613
  }
484
- lines.push("- Use subcommand help for details: jskit generate <generatorId> <subcommand> help");
614
+ lines.push("");
615
+ lines.push("Use subcommand help for positional args, options, notes, and examples:");
616
+ lines.push(` ${color.item("jskit generate <generatorId> <subcommand> help")}`);
485
617
  }
486
618
 
487
- appendHelpExamples(lines, primarySubcommandRow?.examples);
488
- lines.push("");
489
- lines.push(`Options (${optionRows.length}):`);
490
- if (optionRows.length > 0) {
491
- for (const optionRow of optionRows) {
492
- lines.push(formatOptionSummary(optionRow));
493
- }
494
- } else {
495
- lines.push("- No inline options.");
619
+ if (shouldShowPackageExamples) {
620
+ appendHelpExamples(lines, primarySubcommandRow?.examples, { color });
496
621
  }
497
- if (hasRequiredWithDefaults) {
622
+ if (shouldShowPackageOptions) {
498
623
  lines.push("");
499
- lines.push("Note: required options with defaults are auto-filled when omitted.");
624
+ lines.push(color.heading(`Options (${optionRows.length}):`));
625
+ if (optionRows.length > 0) {
626
+ for (const optionRow of optionRows) {
627
+ lines.push(formatOptionSummary(optionRow, { color }));
628
+ }
629
+ } else {
630
+ lines.push("- No inline options.");
631
+ }
632
+ if (hasRequiredWithDefaults) {
633
+ lines.push("");
634
+ lines.push("Note: required options with defaults are auto-filled when omitted.");
635
+ }
500
636
  }
501
- io.stdout.write(`${lines.join("\n")}\n`);
637
+ writeWrappedLines({
638
+ stdout: io.stdout,
639
+ lines
640
+ });
502
641
  }
503
642
 
504
643
  function renderGenerateSubcommandHelp({
@@ -551,8 +690,10 @@ function renderGenerateSubcommandHelp({
551
690
  name: subcommandRow.name,
552
691
  primary: subcommandRow.primary,
553
692
  description: effectiveDescription,
693
+ longDescription: ensureArray(subcommandRow.longDescription),
554
694
  positionalArgs,
555
695
  examples: ensureArray(subcommandRow.examples),
696
+ notes: ensureArray(subcommandRow.notes),
556
697
  options: subcommandOptionRows
557
698
  },
558
699
  usage
@@ -560,47 +701,49 @@ function renderGenerateSubcommandHelp({
560
701
  return true;
561
702
  }
562
703
 
704
+ const color = createColorFormatter(io.stdout);
563
705
  const lines = [];
564
- lines.push(`Generator subcommand help: ${packageId} ${subcommandRow.name}`);
706
+ lines.push(`Generator subcommand help: ${color.emphasis(packageId)} ${color.item(subcommandRow.name)}`);
565
707
  if (resolvedFromLabel) {
566
- lines.push(`Resolved from: ${resolvedFromLabel}`);
567
- }
568
- if (summary) {
569
- lines.push(`Generator: ${summary}`);
570
- }
571
- lines.push(`Description: ${effectiveDescription}`);
572
- if (subcommandRow.primary) {
573
- lines.push("Note: this is the primary generator command (same behavior as running without a subcommand).");
708
+ lines.push(`Resolved from: ${color.item(resolvedFromLabel)}`);
574
709
  }
710
+ lines.push(`Description: ${renderInlineCodeSpans(effectiveDescription, color)}`);
711
+ appendHelpLongDescription(lines, subcommandRow.longDescription, { color });
575
712
  lines.push("");
576
- lines.push("Use:");
713
+ lines.push(color.heading("Use:"));
577
714
  for (const usageLine of usage) {
578
715
  lines.push(`- ${usageLine}`);
579
716
  }
580
717
  lines.push("");
581
- lines.push(`Positional args (${positionalArgs.length}):`);
718
+ lines.push(color.heading(`Positional args (${positionalArgs.length}):`));
582
719
  if (positionalArgs.length > 0) {
583
- for (const positionalArg of positionalArgs) {
584
- lines.push(formatPositionalArgSummary(positionalArg));
585
- }
720
+ appendSeparatedBlocks(
721
+ lines,
722
+ positionalArgs.map((positionalArg) => formatPositionalArgSummary(positionalArg, { color }))
723
+ );
586
724
  } else {
587
725
  lines.push("- No positional arguments.");
588
726
  }
727
+ appendHelpExamples(lines, subcommandRow.examples, { color });
728
+ appendHelpNotes(lines, subcommandRow.notes, { color });
589
729
  lines.push("");
590
- lines.push(`Options (${subcommandOptionRows.length}):`);
730
+ lines.push(color.heading(`Options (${subcommandOptionRows.length}):`));
591
731
  if (subcommandOptionRows.length > 0) {
592
- for (const optionRow of subcommandOptionRows) {
593
- lines.push(formatOptionSummary(optionRow));
594
- }
732
+ appendSeparatedBlocks(
733
+ lines,
734
+ subcommandOptionRows.map((optionRow) => formatOptionSummary(optionRow, { color }))
735
+ );
595
736
  } else {
596
737
  lines.push("- No inline options.");
597
738
  }
598
- appendHelpExamples(lines, subcommandRow.examples);
599
739
  if (hasRequiredWithDefaults) {
600
740
  lines.push("");
601
741
  lines.push("Note: required options with defaults are auto-filled when omitted.");
602
742
  }
603
- io.stdout.write(`${lines.join("\n")}\n`);
743
+ writeWrappedLines({
744
+ stdout: io.stdout,
745
+ lines
746
+ });
604
747
  return true;
605
748
  }
606
749
 
@@ -635,25 +778,27 @@ function renderAddPackageHelp({
635
778
  return;
636
779
  }
637
780
 
781
+ const color = createColorFormatter(io.stdout);
638
782
  const lines = [];
639
- lines.push(`Package help: ${packageId}`);
783
+ lines.push(`Package help: ${color.emphasis(packageId)}`);
640
784
  if (resolvedFromLabel) {
641
- lines.push(`Resolved from: ${resolvedFromLabel}`);
785
+ lines.push(`Resolved from: ${color.item(resolvedFromLabel)}`);
642
786
  }
643
787
  if (summary) {
644
788
  lines.push(`Description: ${summary}`);
645
789
  }
646
790
  lines.push("");
647
- lines.push("Use:");
791
+ lines.push(color.heading("Use:"));
648
792
  for (const usageLine of usage) {
649
793
  lines.push(`- ${usageLine}`);
650
794
  }
651
795
  lines.push("");
652
- lines.push(`Options (${optionRows.length}):`);
796
+ lines.push(color.heading(`Options (${optionRows.length}):`));
653
797
  if (optionRows.length > 0) {
654
- for (const optionRow of optionRows) {
655
- lines.push(formatOptionSummary(optionRow));
656
- }
798
+ appendSeparatedBlocks(
799
+ lines,
800
+ optionRows.map((optionRow) => formatOptionSummary(optionRow, { color }))
801
+ );
657
802
  } else {
658
803
  lines.push("- No inline options.");
659
804
  }
@@ -661,7 +806,10 @@ function renderAddPackageHelp({
661
806
  lines.push("");
662
807
  lines.push("Note: required options with defaults are auto-filled when omitted.");
663
808
  }
664
- io.stdout.write(`${lines.join("\n")}\n`);
809
+ writeWrappedLines({
810
+ stdout: io.stdout,
811
+ lines
812
+ });
665
813
  }
666
814
 
667
815
  function renderAddBundleHelp({
@@ -691,27 +839,33 @@ function renderAddBundleHelp({
691
839
  return;
692
840
  }
693
841
 
842
+ const color = createColorFormatter(io.stdout);
694
843
  const lines = [];
695
- lines.push(`Bundle help: ${bundleId}`);
844
+ lines.push(`Bundle help: ${color.emphasis(bundleId)}`);
696
845
  if (description) {
697
846
  lines.push(`Description: ${description}`);
698
847
  }
699
848
  lines.push("");
700
- lines.push(`Included packages (${packageIds.length}):`);
849
+ lines.push(color.heading(`Included packages (${packageIds.length}):`));
701
850
  for (const packageId of packageIds) {
702
- lines.push(`- ${packageId}`);
851
+ lines.push(`- ${color.item(packageId)}`);
703
852
  }
704
853
  lines.push("");
705
- lines.push("Inline options:");
706
- lines.push("- Bundles do not define direct options.");
707
- lines.push("- Pass package options through using --<option> <value>.");
708
- lines.push("- Use package help to inspect option contracts for included packages.");
854
+ lines.push(color.heading("Inline options:"));
855
+ appendSeparatedBlocks(lines, [
856
+ "- Bundles do not define direct options.",
857
+ "- Pass package options through using --<option> <value>.",
858
+ "- Use package help to inspect option contracts for included packages."
859
+ ]);
709
860
  lines.push("");
710
- lines.push("Use:");
861
+ lines.push(color.heading("Use:"));
711
862
  for (const usageLine of usage) {
712
863
  lines.push(`- ${usageLine}`);
713
864
  }
714
- io.stdout.write(`${lines.join("\n")}\n`);
865
+ writeWrappedLines({
866
+ stdout: io.stdout,
867
+ lines
868
+ });
715
869
  }
716
870
 
717
871
  export {