@optique/core 1.0.0-dev.1216 → 1.0.0-dev.1227

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
@@ -47,9 +47,11 @@ function defaultSectionOrder(a, b) {
47
47
  * @param page The documentation page to format
48
48
  * @param options Formatting options to customize the output
49
49
  * @returns A formatted string representation of the documentation page
50
- * @throws {TypeError} If `programName` contains a CR or LF character, or if
50
+ * @throws {TypeError} If `programName` contains a CR or LF character, if
51
51
  * any non-empty section's title is empty, whitespace-only, or contains a CR
52
- * or LF character.
52
+ * or LF character, or if `maxWidth` is not a finite integer.
53
+ * @throws {RangeError} If any entry needs a description column and `maxWidth`
54
+ * is too small to fit the minimum layout (less than `termIndent + 4`).
53
55
  *
54
56
  * @example
55
57
  * ```typescript
@@ -73,6 +75,20 @@ function formatDocPage(programName, page, options = {}) {
73
75
  if (/[\r\n]/.test(programName)) throw new TypeError("Program name must not contain newlines.");
74
76
  const termIndent = options.termIndent ?? 2;
75
77
  const termWidth = options.termWidth ?? 26;
78
+ if (options.maxWidth != null && (!Number.isFinite(options.maxWidth) || !Number.isInteger(options.maxWidth))) throw new TypeError(`maxWidth must be a finite integer, got ${options.maxWidth}.`);
79
+ if (options.maxWidth != null) {
80
+ const hasEntries = page.sections.some((s) => s.entries.length > 0);
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;
84
+ if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
85
+ }
86
+ let effectiveTermWidth;
87
+ if (options.maxWidth == null) effectiveTermWidth = termWidth;
88
+ else {
89
+ const availableForColumns = options.maxWidth - termIndent - 2;
90
+ effectiveTermWidth = availableForColumns >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(availableForColumns / 2));
91
+ }
76
92
  let output = "";
77
93
  if (page.brief != null) {
78
94
  output += require_message.formatMessage(page.brief, {
@@ -124,9 +140,9 @@ function formatDocPage(programName, page, options = {}) {
124
140
  optionsSeparator: ", ",
125
141
  maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - termIndent
126
142
  });
127
- const descColumnWidth = options.maxWidth == null ? void 0 : options.maxWidth - termIndent - termWidth - 2;
143
+ const descColumnWidth = options.maxWidth == null ? void 0 : options.maxWidth - termIndent - effectiveTermWidth - 2;
128
144
  const termVisibleWidth = lastLineVisibleLength(term);
129
- const extraTermOffset = descColumnWidth != null ? Math.max(0, termVisibleWidth - termWidth) : 0;
145
+ const extraTermOffset = descColumnWidth != null ? Math.max(0, termVisibleWidth - effectiveTermWidth) : 0;
130
146
  const currentExtraOffset = () => description.includes("\n") ? 0 : extraTermOffset;
131
147
  const descFormatOptions = {
132
148
  colors: options.colors,
@@ -200,7 +216,7 @@ function formatDocPage(programName, page, options = {}) {
200
216
  const formattedChoices = options.colors ? `\x1b[2m${choicesText}\x1b[0m` : choicesText;
201
217
  description += formattedChoices;
202
218
  }
203
- output += `${" ".repeat(termIndent)}${ansiAwareRightPad(term, termWidth)} ${description === "" ? "" : indentLines(description, termIndent + termWidth + 2)}\n`;
219
+ output += `${" ".repeat(termIndent)}${ansiAwareRightPad(term, effectiveTermWidth)}${description === "" ? "" : ` ${indentLines(description, termIndent + effectiveTermWidth + 2)}`}\n`;
204
220
  }
205
221
  }
206
222
  if (page.examples != null) {
package/dist/doc.d.cts CHANGED
@@ -263,9 +263,11 @@ interface DocPageFormatOptions {
263
263
  * @param page The documentation page to format
264
264
  * @param options Formatting options to customize the output
265
265
  * @returns A formatted string representation of the documentation page
266
- * @throws {TypeError} If `programName` contains a CR or LF character, or if
266
+ * @throws {TypeError} If `programName` contains a CR or LF character, if
267
267
  * any non-empty section's title is empty, whitespace-only, or contains a CR
268
- * or LF character.
268
+ * or LF character, or if `maxWidth` is not a finite integer.
269
+ * @throws {RangeError} If any entry needs a description column and `maxWidth`
270
+ * is too small to fit the minimum layout (less than `termIndent + 4`).
269
271
  *
270
272
  * @example
271
273
  * ```typescript
package/dist/doc.d.ts CHANGED
@@ -263,9 +263,11 @@ interface DocPageFormatOptions {
263
263
  * @param page The documentation page to format
264
264
  * @param options Formatting options to customize the output
265
265
  * @returns A formatted string representation of the documentation page
266
- * @throws {TypeError} If `programName` contains a CR or LF character, or if
266
+ * @throws {TypeError} If `programName` contains a CR or LF character, if
267
267
  * any non-empty section's title is empty, whitespace-only, or contains a CR
268
- * or LF character.
268
+ * or LF character, or if `maxWidth` is not a finite integer.
269
+ * @throws {RangeError} If any entry needs a description column and `maxWidth`
270
+ * is too small to fit the minimum layout (less than `termIndent + 4`).
269
271
  *
270
272
  * @example
271
273
  * ```typescript
package/dist/doc.js CHANGED
@@ -47,9 +47,11 @@ function defaultSectionOrder(a, b) {
47
47
  * @param page The documentation page to format
48
48
  * @param options Formatting options to customize the output
49
49
  * @returns A formatted string representation of the documentation page
50
- * @throws {TypeError} If `programName` contains a CR or LF character, or if
50
+ * @throws {TypeError} If `programName` contains a CR or LF character, if
51
51
  * any non-empty section's title is empty, whitespace-only, or contains a CR
52
- * or LF character.
52
+ * or LF character, or if `maxWidth` is not a finite integer.
53
+ * @throws {RangeError} If any entry needs a description column and `maxWidth`
54
+ * is too small to fit the minimum layout (less than `termIndent + 4`).
53
55
  *
54
56
  * @example
55
57
  * ```typescript
@@ -73,6 +75,20 @@ function formatDocPage(programName, page, options = {}) {
73
75
  if (/[\r\n]/.test(programName)) throw new TypeError("Program name must not contain newlines.");
74
76
  const termIndent = options.termIndent ?? 2;
75
77
  const termWidth = options.termWidth ?? 26;
78
+ if (options.maxWidth != null && (!Number.isFinite(options.maxWidth) || !Number.isInteger(options.maxWidth))) throw new TypeError(`maxWidth must be a finite integer, got ${options.maxWidth}.`);
79
+ if (options.maxWidth != null) {
80
+ const hasEntries = page.sections.some((s) => s.entries.length > 0);
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;
84
+ if (options.maxWidth < minWidth) throw new RangeError(`maxWidth must be at least ${minWidth}, got ${options.maxWidth}.`);
85
+ }
86
+ let effectiveTermWidth;
87
+ if (options.maxWidth == null) effectiveTermWidth = termWidth;
88
+ else {
89
+ const availableForColumns = options.maxWidth - termIndent - 2;
90
+ effectiveTermWidth = availableForColumns >= termWidth + 1 ? termWidth : Math.max(1, Math.floor(availableForColumns / 2));
91
+ }
76
92
  let output = "";
77
93
  if (page.brief != null) {
78
94
  output += formatMessage(page.brief, {
@@ -124,9 +140,9 @@ function formatDocPage(programName, page, options = {}) {
124
140
  optionsSeparator: ", ",
125
141
  maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - termIndent
126
142
  });
127
- const descColumnWidth = options.maxWidth == null ? void 0 : options.maxWidth - termIndent - termWidth - 2;
143
+ const descColumnWidth = options.maxWidth == null ? void 0 : options.maxWidth - termIndent - effectiveTermWidth - 2;
128
144
  const termVisibleWidth = lastLineVisibleLength(term);
129
- const extraTermOffset = descColumnWidth != null ? Math.max(0, termVisibleWidth - termWidth) : 0;
145
+ const extraTermOffset = descColumnWidth != null ? Math.max(0, termVisibleWidth - effectiveTermWidth) : 0;
130
146
  const currentExtraOffset = () => description.includes("\n") ? 0 : extraTermOffset;
131
147
  const descFormatOptions = {
132
148
  colors: options.colors,
@@ -200,7 +216,7 @@ function formatDocPage(programName, page, options = {}) {
200
216
  const formattedChoices = options.colors ? `\x1b[2m${choicesText}\x1b[0m` : choicesText;
201
217
  description += formattedChoices;
202
218
  }
203
- output += `${" ".repeat(termIndent)}${ansiAwareRightPad(term, termWidth)} ${description === "" ? "" : indentLines(description, termIndent + termWidth + 2)}\n`;
219
+ output += `${" ".repeat(termIndent)}${ansiAwareRightPad(term, effectiveTermWidth)}${description === "" ? "" : ` ${indentLines(description, termIndent + effectiveTermWidth + 2)}`}\n`;
204
220
  }
205
221
  }
206
222
  if (page.examples != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1216+3e445dce",
3
+ "version": "1.0.0-dev.1227+f9861245",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",