@optique/core 1.0.0-dev.1239 → 1.0.0-dev.1244

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/doc.cjs CHANGED
@@ -79,9 +79,42 @@ function formatDocPage(programName, page, options = {}) {
79
79
  if (options.maxWidth != null) {
80
80
  const hasEntries = page.sections.some((s) => s.entries.length > 0);
81
81
  const hasContent = (msg) => Array.isArray(msg) && msg.length > 0;
82
- const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some((e) => hasContent(e.description) || options.showDefault && hasContent(e.default) || options.showChoices && hasContent(e.choices)));
83
- const minWidth = needsDescColumn ? termIndent + 4 : hasEntries ? termIndent + 1 : 1;
82
+ const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some((e) => hasContent(e.description) || options.showDefault && e.default != null || options.showChoices && e.choices != null));
83
+ let minDescWidth = 1;
84
+ if (needsDescColumn) {
85
+ if (options.showDefault && page.sections.some((s) => s.entries.some((e) => e.default != null))) {
86
+ const prefix = typeof options.showDefault === "object" ? options.showDefault.prefix ?? " [" : " [";
87
+ const suffix = typeof options.showDefault === "object" ? options.showDefault.suffix ?? "]" : "]";
88
+ const hasEmptyDefault = page.sections.some((s) => s.entries.some((e) => e.default != null && Array.isArray(e.default) && e.default.length === 0));
89
+ minDescWidth = Math.max(minDescWidth, hasEmptyDefault ? prefix.length + suffix.length : prefix.length);
90
+ }
91
+ if (options.showChoices && page.sections.some((s) => s.entries.some((e) => e.choices != null))) {
92
+ const prefix = typeof options.showChoices === "object" ? options.showChoices.prefix ?? " (" : " (";
93
+ const suffix = typeof options.showChoices === "object" ? options.showChoices.suffix ?? ")" : ")";
94
+ const label = typeof options.showChoices === "object" ? options.showChoices.label ?? "choices: " : "choices: ";
95
+ const hasEmptyChoices = page.sections.some((s) => s.entries.some((e) => e.choices != null && Array.isArray(e.choices) && e.choices.length === 0));
96
+ minDescWidth = Math.max(minDescWidth, hasEmptyChoices ? prefix.length + label.length + suffix.length : prefix.length + label.length);
97
+ }
98
+ }
99
+ const splitEntryMin = termIndent + 2 + Math.max(2, 2 * minDescWidth - 1);
100
+ const fixedEntryMin = termIndent + 2 + termWidth + minDescWidth;
101
+ const entryMin = needsDescColumn ? Math.min(splitEntryMin, fixedEntryMin) : hasEntries ? termIndent + 1 : 1;
102
+ const usageMin = page.usage != null ? 8 + programName.length : 1;
103
+ let sectionMin = 1;
104
+ if (page.examples != null) sectionMin = Math.max(sectionMin, 9);
105
+ if (page.author != null) sectionMin = Math.max(sectionMin, 7);
106
+ if (page.bugs != null) sectionMin = Math.max(sectionMin, 5);
107
+ const minWidth = Math.max(entryMin, usageMin, sectionMin);
84
108
  if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
109
+ if (needsDescColumn && minDescWidth > 1) {
110
+ const avail = options.maxWidth - termIndent - 2;
111
+ const effTW = avail >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(avail / 2));
112
+ const descW = avail - effTW;
113
+ if (descW < minDescWidth) {
114
+ const needed = termIndent + termWidth + 2 + minDescWidth;
115
+ throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
116
+ }
117
+ }
85
118
  }
86
119
  let effectiveTermWidth;
87
120
  if (options.maxWidth == null) effectiveTermWidth = termWidth;
package/dist/doc.js CHANGED
@@ -79,9 +79,42 @@ function formatDocPage(programName, page, options = {}) {
79
79
  if (options.maxWidth != null) {
80
80
  const hasEntries = page.sections.some((s) => s.entries.length > 0);
81
81
  const hasContent = (msg) => Array.isArray(msg) && msg.length > 0;
82
- const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some((e) => hasContent(e.description) || options.showDefault && hasContent(e.default) || options.showChoices && hasContent(e.choices)));
83
- const minWidth = needsDescColumn ? termIndent + 4 : hasEntries ? termIndent + 1 : 1;
82
+ const needsDescColumn = hasEntries && page.sections.some((s) => s.entries.some((e) => hasContent(e.description) || options.showDefault && e.default != null || options.showChoices && e.choices != null));
83
+ let minDescWidth = 1;
84
+ if (needsDescColumn) {
85
+ if (options.showDefault && page.sections.some((s) => s.entries.some((e) => e.default != null))) {
86
+ const prefix = typeof options.showDefault === "object" ? options.showDefault.prefix ?? " [" : " [";
87
+ const suffix = typeof options.showDefault === "object" ? options.showDefault.suffix ?? "]" : "]";
88
+ const hasEmptyDefault = page.sections.some((s) => s.entries.some((e) => e.default != null && Array.isArray(e.default) && e.default.length === 0));
89
+ minDescWidth = Math.max(minDescWidth, hasEmptyDefault ? prefix.length + suffix.length : prefix.length);
90
+ }
91
+ if (options.showChoices && page.sections.some((s) => s.entries.some((e) => e.choices != null))) {
92
+ const prefix = typeof options.showChoices === "object" ? options.showChoices.prefix ?? " (" : " (";
93
+ const suffix = typeof options.showChoices === "object" ? options.showChoices.suffix ?? ")" : ")";
94
+ const label = typeof options.showChoices === "object" ? options.showChoices.label ?? "choices: " : "choices: ";
95
+ const hasEmptyChoices = page.sections.some((s) => s.entries.some((e) => e.choices != null && Array.isArray(e.choices) && e.choices.length === 0));
96
+ minDescWidth = Math.max(minDescWidth, hasEmptyChoices ? prefix.length + label.length + suffix.length : prefix.length + label.length);
97
+ }
98
+ }
99
+ const splitEntryMin = termIndent + 2 + Math.max(2, 2 * minDescWidth - 1);
100
+ const fixedEntryMin = termIndent + 2 + termWidth + minDescWidth;
101
+ const entryMin = needsDescColumn ? Math.min(splitEntryMin, fixedEntryMin) : hasEntries ? termIndent + 1 : 1;
102
+ const usageMin = page.usage != null ? 8 + programName.length : 1;
103
+ let sectionMin = 1;
104
+ if (page.examples != null) sectionMin = Math.max(sectionMin, 9);
105
+ if (page.author != null) sectionMin = Math.max(sectionMin, 7);
106
+ if (page.bugs != null) sectionMin = Math.max(sectionMin, 5);
107
+ const minWidth = Math.max(entryMin, usageMin, sectionMin);
84
108
  if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
109
+ if (needsDescColumn && minDescWidth > 1) {
110
+ const avail = options.maxWidth - termIndent - 2;
111
+ const effTW = avail >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(avail / 2));
112
+ const descW = avail - effTW;
113
+ if (descW < minDescWidth) {
114
+ const needed = termIndent + termWidth + 2 + minDescWidth;
115
+ throw new RangeError(`maxWidth must be at least ${needed}, got ${options.maxWidth}.`);
116
+ }
117
+ }
85
118
  }
86
119
  let effectiveTermWidth;
87
120
  if (options.maxWidth == null) effectiveTermWidth = termWidth;
@@ -460,6 +460,19 @@ function float(options = {}) {
460
460
  };
461
461
  }
462
462
  /**
463
+ * The set of URL schemes that are considered "special" by the WHATWG URL
464
+ * Standard. These schemes always use the `://` authority syntax.
465
+ * Non-special schemes use only `:` (e.g., `mailto:`, `urn:`).
466
+ */
467
+ const SPECIAL_URL_SCHEMES = new Set([
468
+ "ftp",
469
+ "file",
470
+ "http",
471
+ "https",
472
+ "ws",
473
+ "wss"
474
+ ]);
475
+ /**
463
476
  * Creates a {@link ValueParser} for URL values.
464
477
  *
465
478
  * This parser validates that the input is a well-formed URL and optionally
@@ -515,12 +528,15 @@ function url(options = {}) {
515
528
  return value.href;
516
529
  },
517
530
  *suggest(prefix) {
518
- if (allowedProtocols && prefix.length > 0 && !prefix.includes("://")) for (const protocol of allowedProtocols) {
531
+ if (allowedProtocols && prefix.length > 0 && !prefix.includes(":")) for (const protocol of allowedProtocols) {
519
532
  const cleanProtocol = protocol.replace(/:+$/, "");
520
- if (cleanProtocol.startsWith(prefix.toLowerCase())) yield {
521
- kind: "literal",
522
- text: `${cleanProtocol}://`
523
- };
533
+ if (cleanProtocol.startsWith(prefix.toLowerCase())) {
534
+ const suffix = SPECIAL_URL_SCHEMES.has(cleanProtocol) ? "://" : ":";
535
+ yield {
536
+ kind: "literal",
537
+ text: `${cleanProtocol}${suffix}`
538
+ };
539
+ }
524
540
  }
525
541
  }
526
542
  };
@@ -460,6 +460,19 @@ function float(options = {}) {
460
460
  };
461
461
  }
462
462
  /**
463
+ * The set of URL schemes that are considered "special" by the WHATWG URL
464
+ * Standard. These schemes always use the `://` authority syntax.
465
+ * Non-special schemes use only `:` (e.g., `mailto:`, `urn:`).
466
+ */
467
+ const SPECIAL_URL_SCHEMES = new Set([
468
+ "ftp",
469
+ "file",
470
+ "http",
471
+ "https",
472
+ "ws",
473
+ "wss"
474
+ ]);
475
+ /**
463
476
  * Creates a {@link ValueParser} for URL values.
464
477
  *
465
478
  * This parser validates that the input is a well-formed URL and optionally
@@ -515,12 +528,15 @@ function url(options = {}) {
515
528
  return value.href;
516
529
  },
517
530
  *suggest(prefix) {
518
- if (allowedProtocols && prefix.length > 0 && !prefix.includes("://")) for (const protocol of allowedProtocols) {
531
+ if (allowedProtocols && prefix.length > 0 && !prefix.includes(":")) for (const protocol of allowedProtocols) {
519
532
  const cleanProtocol = protocol.replace(/:+$/, "");
520
- if (cleanProtocol.startsWith(prefix.toLowerCase())) yield {
521
- kind: "literal",
522
- text: `${cleanProtocol}://`
523
- };
533
+ if (cleanProtocol.startsWith(prefix.toLowerCase())) {
534
+ const suffix = SPECIAL_URL_SCHEMES.has(cleanProtocol) ? "://" : ":";
535
+ yield {
536
+ kind: "literal",
537
+ text: `${cleanProtocol}${suffix}`
538
+ };
539
+ }
524
540
  }
525
541
  }
526
542
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1239+e5c4f6ba",
3
+ "version": "1.0.0-dev.1244+338f4cf1",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",