@optique/core 0.1.0-dev.1

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/README.md ADDED
@@ -0,0 +1,475 @@
1
+ Optique: Type-safe combinatorial CLI parser for TypeScript
2
+ ==========================================================
3
+
4
+ > [!CAUTION]
5
+ > Optique is currently in early development for proof of concept purposes,
6
+ > and is not yet ready for production use. The API is subject to change,
7
+ > and there may be bugs or missing features.
8
+
9
+ Optique is a type-safe combinatorial CLI *parser* for TypeScript inspired by
10
+ Haskell's [optparse-applicative] and TypeScript's [Zod]. It provides composable
11
+ parsers for building command-line interfaces with full type safety and
12
+ automatic type inference.
13
+
14
+ > [!NOTE]
15
+ > Optique is a parsing library that focuses on extracting and
16
+ > validating command-line arguments. It doesn't dictate your application's
17
+ > structure, handle command execution, or provide scaffolding—it simply
18
+ > transforms command-line input into well-typed data structures that your
19
+ > application can use.
20
+
21
+ Unlike traditional CLI parsers that rely on configuration objects or
22
+ string-based definitions, Optique uses a functional approach where parsers
23
+ are first-class values that can be combined, transformed, and reused.
24
+ This compositional design makes it easy to express complex argument structures
25
+ while maintaining complete type safety throughout your application.
26
+
27
+ > [!TIP]
28
+ > *Building CLI apps?* Consider *@optique/run* for automatic `process.argv`
29
+ > handling and `process.exit()` integration. This core package is perfect for
30
+ > libraries, web apps, or when you need full control over argument parsing.
31
+
32
+ [optparse-applicative]: https://github.com/pcapriotti/optparse-applicative
33
+ [Zod]: https://zod.dev/
34
+
35
+
36
+ Core concepts
37
+ -------------
38
+
39
+ Optique is built around several key concepts:
40
+
41
+ - *Value parsers* convert strings to typed values
42
+ (`string()`, `integer()`, `url()`, etc.)
43
+
44
+ - *Primitive parsers* handle the basic building blocks:
45
+
46
+ - `option()` for command-line flags and their arguments
47
+ - `argument()` for positional arguments
48
+ - `command()` for subcommands
49
+
50
+ - *Modifying combinators* transform and combine parsers:
51
+ - `optional()` makes parsers optional
52
+ - `withDefault()` provides default values for optional parsers
53
+ - `multiple()` allows repetition
54
+ - `or()` creates alternatives
55
+ - `merge()` combines object parsers
56
+
57
+ - *Construct combinators* build structured results:
58
+
59
+ - `object()` groups parsers into objects
60
+ - `tuple()` combines parsers into tuples
61
+
62
+ The library automatically infers the result type of your parser composition,
63
+ ensuring that your parsed CLI arguments are fully typed without manual type
64
+ annotations. When parsing fails, you get detailed error messages that help
65
+ users understand what went wrong.
66
+
67
+
68
+ Example
69
+ -------
70
+
71
+ ~~~~ typescript
72
+ import { run } from "@optique/core/facade";
73
+ import { formatMessage } from "@optique/core/message";
74
+ import {
75
+ argument,
76
+ merge,
77
+ multiple,
78
+ object,
79
+ option,
80
+ optional,
81
+ or,
82
+ withDefault
83
+ } from "@optique/core/parser";
84
+ import { choice, integer, locale, string, url } from "@optique/core/valueparser";
85
+ import process from "node:process";
86
+
87
+ // Define a sophisticated CLI with grouped and reusable option sets
88
+ const networkOptions = object("Network", {
89
+ port: option("-p", "--port", integer({ min: 1, max: 65535 })),
90
+ host: withDefault(
91
+ option("-h", "--host", string({ metavar: "HOST" })),
92
+ "localhost",
93
+ ),
94
+ });
95
+
96
+ const loggingOptions = object("Logging", {
97
+ verbose: optional(option("-v", "--verbose")),
98
+ logFile: optional(option("--log-file", string({ metavar: "FILE" }))),
99
+ });
100
+
101
+ const parser = or(
102
+ // Server mode: merge network and logging options with server-specific config
103
+ merge(
104
+ networkOptions,
105
+ loggingOptions,
106
+ object("Server", {
107
+ locales: multiple(option("-l", "--locale", locale())),
108
+ config: argument(string({ metavar: "CONFIG_FILE" })),
109
+ }),
110
+ ),
111
+ object("Client mode", {
112
+ connect: option(
113
+ "-c", "--connect",
114
+ url({ allowedProtocols: ["http:", "https:"] }),
115
+ ),
116
+ headers: multiple(option("-H", "--header", string())),
117
+ timeout: withDefault(option("-t", "--timeout", integer({ min: 0 })), 30000),
118
+ files: multiple(argument(string({ metavar: "FILE" })), { min: 1, max: 5 }),
119
+ }),
120
+ );
121
+
122
+ const result = run(parser, "myapp", process.argv.slice(2), {
123
+ colors: true,
124
+ help: "both",
125
+ onError: process.exit,
126
+ });
127
+
128
+ // TypeScript automatically infers the complex union type with optional fields
129
+ if ("port" in result) {
130
+ const server = result;
131
+ console.log(`Starting server on ${server.host}:${server.port}`);
132
+ console.log(`Supported locales: ${server.locales.join(", ") || "default"}`);
133
+ if (server.verbose) console.log("Verbose mode enabled");
134
+ if (server.logFile) console.log(`Logging to: ${server.logFile}`);
135
+ } else {
136
+ const client = result;
137
+ console.log(`Connecting to ${client.connect}`);
138
+ console.log(`Processing ${client.files.length} files`);
139
+ console.log(`Timeout: ${client.timeout}ms`);
140
+ }
141
+ ~~~~
142
+
143
+ This example demonstrates Optique's powerful combinators:
144
+
145
+ - **`merge()`** combines multiple `object()` parsers into a single unified
146
+ parser, enabling modular and reusable option groups
147
+ - **`optional()`** makes parsers optional, returning `undefined` when not
148
+ provided
149
+ - **`withDefault()`** provides default values instead of `undefined` for
150
+ optional parameters, improving usability
151
+ - **`multiple()`** allows repeating options/arguments with configurable
152
+ constraints
153
+ - **`or()`** creates mutually exclusive alternatives
154
+ - **`object()`** groups related options into structured data
155
+
156
+ The parser demonstrates modular design by:
157
+
158
+ - Separating network options (`--port`, `--host`) for reusability
159
+ - Grouping logging configuration (`--verbose`, `--log-file`) separately
160
+ - Merging reusable groups with server-specific options using `merge()`
161
+ - Supporting complex scenarios like multiple locales: `-l en-US -l fr-FR`
162
+
163
+ All with full type safety and automatic inference!
164
+
165
+
166
+ Parser combinators
167
+ ------------------
168
+
169
+ Optique provides several types of parsers and combinators for building sophisticated CLI interfaces:
170
+
171
+ ### Primitive parsers
172
+
173
+ - **`option()`**: Handles command-line flags and their arguments
174
+
175
+ ~~~~ typescript
176
+ option("-p", "--port", integer({ min: 1, max: 65535 }))
177
+ option("-v", "--verbose") // Boolean flag
178
+ ~~~~
179
+
180
+ - **`argument()`**: Handles positional arguments
181
+
182
+ ~~~~ typescript
183
+ argument(string({ metavar: "FILE" }))
184
+ ~~~~
185
+
186
+ - **`command()`**: Matches subcommands for `git`-like CLI interfaces
187
+
188
+ ~~~~ typescript
189
+ command("add", object({ file: argument(string()) }))
190
+ ~~~~
191
+
192
+ ### Modifying combinators
193
+
194
+ - **`optional()`**: Makes any parser optional, returning `undefined` if not
195
+ matched
196
+
197
+ ~~~~ typescript
198
+ const parser = object({
199
+ name: option("-n", "--name", string()),
200
+ verbose: optional(option("-v", "--verbose")), // undefined if not provided
201
+ });
202
+ ~~~~
203
+
204
+ - **`withDefault()`**: Makes any parser provide a default value instead of
205
+ `undefined` when not matched
206
+
207
+ ~~~~ typescript
208
+ const parser = object({
209
+ name: option("-n", "--name", string()),
210
+ port: withDefault(option("-p", "--port", integer()), 8080), // 8080 if not provided
211
+ host: withDefault(option("-h", "--host", string()), "localhost"),
212
+ });
213
+ ~~~~
214
+
215
+ - **`multiple()`**: Allows repeating a parser multiple times with constraints
216
+
217
+ ~~~~ typescript
218
+ const parser = object({
219
+ // Multiple locales: -l en -l fr
220
+ locales: multiple(option("-l", "--locale", locale())),
221
+ // 1-3 input files required
222
+ files: multiple(argument(string()), { min: 1, max: 3 }),
223
+ });
224
+ ~~~~
225
+
226
+ - **`or()`**: Creates mutually exclusive alternatives
227
+ (try first, then second, etc.)
228
+
229
+ ~~~~ typescript
230
+ or(
231
+ command("add", addParser),
232
+ command("remove", removeParser)
233
+ )
234
+ ~~~~
235
+
236
+ - **`merge()`**: Merges multiple `object()` parsers into a single parser,
237
+ enabling modular composition of option groups
238
+
239
+ ~~~~ typescript
240
+ merge(networkOptions, loggingOptions, serverOptions)
241
+ ~~~~
242
+
243
+ ### Construct combinators
244
+
245
+ - **`object()`**: Combines multiple parsers into a structured object
246
+
247
+ ~~~~ typescript
248
+ object("Server", {
249
+ port: option("-p", "--port", integer()),
250
+ host: option("-h", "--host", string()),
251
+ })
252
+ ~~~~
253
+
254
+ - **`tuple()`**: Combines multiple parsers into a tuple with preserved order
255
+
256
+ ~~~~ typescript
257
+ tuple(
258
+ option("-u", "--user", string()),
259
+ option("-p", "--port", integer())
260
+ )
261
+ ~~~~
262
+
263
+ ### Advanced patterns
264
+
265
+ The `merge()` combinator enables powerful modular designs by separating concerns
266
+ into reusable option groups:
267
+
268
+ ~~~~ typescript
269
+ // Define reusable option groups
270
+ const databaseOptions = object("Database", {
271
+ dbHost: option("--db-host", string()),
272
+ dbPort: option("--db-port", integer({ min: 1, max: 65535 })),
273
+ dbName: option("--db-name", string()),
274
+ });
275
+
276
+ const authOptions = object("Authentication", {
277
+ username: option("-u", "--user", string()),
278
+ password: optional(option("-p", "--password", string())),
279
+ token: optional(option("-t", "--token", string())),
280
+ });
281
+
282
+ const loggingOptions = object("Logging", {
283
+ logLevel: option("--log-level", choice(["debug", "info", "warn", "error"])),
284
+ logFile: optional(option("--log-file", string())),
285
+ });
286
+
287
+ // Combine groups differently for different modes
288
+ const parser = or(
289
+ // Development: all options available
290
+ merge(
291
+ object("Dev", { dev: option("--dev") }),
292
+ databaseOptions,
293
+ authOptions,
294
+ loggingOptions
295
+ ),
296
+ // Production: database and auth required, enhanced logging
297
+ merge(
298
+ object("Prod", { config: option("-c", "--config", string()) }),
299
+ databaseOptions,
300
+ authOptions,
301
+ loggingOptions,
302
+ object("Production", {
303
+ workers: multiple(option("-w", "--worker", integer({ min: 1 }))),
304
+ })
305
+ ),
306
+ );
307
+ ~~~~
308
+
309
+ This approach promotes:
310
+
311
+ - *Reusability*: Option groups can be shared across different command modes
312
+ - *Maintainability*: Changes to option groups automatically propagate
313
+ - *Modularity*: Each concern is separated into its own focused parser
314
+ - *Flexibility*: Different combinations for different use cases
315
+
316
+ The `multiple()` combinator is especially powerful when combined with `object()`
317
+ parsers, as it provides empty arrays as defaults when no matches are found,
318
+ allowing for clean optional repeated arguments.
319
+
320
+ ### Quick subcommand example
321
+
322
+ For a quick introduction to subcommands, here's a simple `git`-like interface:
323
+
324
+ ~~~~ typescript
325
+ import { run } from "@optique/core/facade";
326
+ import { argument, command, constant, object, option, or } from "@optique/core/parser";
327
+ import { string } from "@optique/core/valueparser";
328
+ import process from "node:process";
329
+
330
+ const parser = or(
331
+ command("add", object({
332
+ type: constant("add"),
333
+ all: option("-A", "--all"),
334
+ file: argument(string()),
335
+ })),
336
+ command("commit", object({
337
+ type: constant("commit"),
338
+ message: option("-m", "--message", string()),
339
+ amend: option("--amend"),
340
+ })),
341
+ );
342
+
343
+ const result = run(parser, "git", ["commit", "-m", "Fix parser bug"], {
344
+ help: "both",
345
+ onError: process.exit,
346
+ });
347
+ // result.type === "commit"
348
+ // result.message === "Fix parser bug"
349
+ // result.amend === false
350
+ ~~~~
351
+
352
+ ### Subcommands
353
+
354
+ The `command()` combinator enables building git-like CLI interfaces with
355
+ subcommands. Each subcommand can have its own set of options and arguments:
356
+
357
+ ~~~~ typescript
358
+ import { run } from "@optique/core/facade";
359
+ import {
360
+ argument,
361
+ command,
362
+ constant,
363
+ multiple,
364
+ object,
365
+ option,
366
+ optional,
367
+ or,
368
+ } from "@optique/core/parser";
369
+ import { string } from "@optique/core/valueparser";
370
+ import process from "node:process";
371
+
372
+ const parser = or(
373
+ command("show", object({
374
+ type: constant("show"),
375
+ progress: option("-p", "--progress"),
376
+ verbose: optional(option("-v", "--verbose")),
377
+ id: argument(string({ metavar: "ITEM_ID" })),
378
+ })),
379
+ command("edit", object({
380
+ type: constant("edit"),
381
+ editor: optional(option("-e", "--editor", string({ metavar: "EDITOR" }))),
382
+ backup: option("-b", "--backup"),
383
+ id: argument(string({ metavar: "ITEM_ID" })),
384
+ })),
385
+ command("delete", object({
386
+ type: constant("delete"),
387
+ force: option("-f", "--force"),
388
+ recursive: optional(option("-r", "--recursive")),
389
+ items: multiple(argument(string({ metavar: "ITEM_ID" })), { min: 1 }),
390
+ })),
391
+ );
392
+
393
+ const result = run(parser, "myapp", process.argv.slice(2), {
394
+ colors: true,
395
+ help: "both",
396
+ onError: process.exit,
397
+ });
398
+
399
+ // TypeScript infers a union type with discriminated subcommands
400
+ switch (result.type) {
401
+ case "show":
402
+ console.log(`Showing item: ${result.id}`);
403
+ if (result.progress) console.log("Progress enabled");
404
+ if (result.verbose) console.log("Verbose mode enabled");
405
+ break;
406
+ case "edit":
407
+ console.log(`Editing item: ${result.id}`);
408
+ if (result.editor) console.log(`Using editor: ${result.editor}`);
409
+ if (result.backup) console.log("Backup enabled");
410
+ break;
411
+ case "delete":
412
+ console.log(`Deleting items: ${result.items.join(", ")}`);
413
+ if (result.force) console.log("Force delete enabled");
414
+ if (result.recursive) console.log("Recursive delete enabled");
415
+ break;
416
+ }
417
+ ~~~~
418
+
419
+ This example demonstrates:
420
+
421
+ - *Subcommand routing*: `command("show", ...)` matches the first argument
422
+ and applies the inner parser to remaining arguments
423
+ - *Type discrimination*: Using `constant()` with unique values enables
424
+ TypeScript to discriminate between subcommand types
425
+ - *Per-subcommand options*: Each subcommand can have its own unique set
426
+ of options and arguments
427
+ - *Complex arguments*: The `delete` command shows multiple required arguments
428
+
429
+ Example usage:
430
+
431
+ ~~~~ bash
432
+ # Show command with options
433
+ $ myapp show --progress --verbose item123
434
+
435
+ # Edit command with optional editor
436
+ $ myapp edit --editor vim --backup item456
437
+
438
+ # Delete command with multiple items
439
+ $ myapp delete --force item1 item2 item3
440
+ ~~~~
441
+
442
+ ### Advanced subcommand patterns
443
+
444
+ You can also combine subcommands with global options using `object()`:
445
+
446
+ ~~~~ typescript
447
+ const parser = object({
448
+ // Global options available to all subcommands
449
+ debug: optional(option("--debug")),
450
+ config: optional(option("-c", "--config", string())),
451
+
452
+ // Subcommand with its own options
453
+ command: or(
454
+ command("server", object({
455
+ type: constant("server" as const),
456
+ port: option("-p", "--port", integer({ min: 1, max: 65535 })),
457
+ daemon: option("-d", "--daemon"),
458
+ })),
459
+ command("client", object({
460
+ type: constant("client" as const),
461
+ connect: option("--connect", url()),
462
+ timeout: optional(option("-t", "--timeout", integer())),
463
+ })),
464
+ ),
465
+ });
466
+ ~~~~
467
+
468
+ This allows for commands like:
469
+
470
+ ~~~~ bash
471
+ $ myapp --debug --config app.json server --port 8080 --daemon
472
+ $ myapp client --connect http://localhost:8080 --timeout 5000
473
+ ~~~~
474
+
475
+ <!-- cSpell: ignore optparse myapp -->
package/dist/doc.cjs ADDED
@@ -0,0 +1,104 @@
1
+ const require_message = require('./message.cjs');
2
+ const require_usage = require('./usage.cjs');
3
+
4
+ //#region src/doc.ts
5
+ /**
6
+ * Formats a documentation page into a human-readable string.
7
+ *
8
+ * This function takes a structured {@link DocPage} and converts it into
9
+ * a formatted string suitable for display in terminals or documentation.
10
+ * The formatting includes proper indentation, alignment, and optional
11
+ * color support.
12
+ *
13
+ * @param programName The name of the program, used in usage lines
14
+ * @param page The documentation page to format
15
+ * @param options Formatting options to customize the output
16
+ * @returns A formatted string representation of the documentation page
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const page: DocPage = {
21
+ * brief: "A CLI tool",
22
+ * usage: [{ type: "literal", value: "myapp" }],
23
+ * sections: [{
24
+ * title: "Options",
25
+ * entries: [{
26
+ * term: { type: "option", short: "-v", long: "--verbose" },
27
+ * description: "Enable verbose output"
28
+ * }]
29
+ * }]
30
+ * };
31
+ *
32
+ * const formatted = formatDocPage("myapp", page, { colors: true });
33
+ * console.log(formatted);
34
+ * ```
35
+ */
36
+ function formatDocPage(programName, page, options = {}) {
37
+ const termIndent = options.termIndent ?? 2;
38
+ const termWidth = options.termWidth ?? 26;
39
+ let output = "";
40
+ if (page.brief != null) {
41
+ output += require_message.formatMessage(page.brief, {
42
+ colors: options.colors,
43
+ maxWidth: options.maxWidth,
44
+ quotes: !options.colors
45
+ });
46
+ output += "\n";
47
+ }
48
+ if (page.usage != null) {
49
+ output += "Usage: ";
50
+ output += indentLines(require_usage.formatUsage(programName, page.usage, {
51
+ colors: options.colors,
52
+ maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - 7,
53
+ expandCommands: true
54
+ }), 7);
55
+ output += "\n";
56
+ }
57
+ if (page.description != null) {
58
+ output += "\n";
59
+ output += require_message.formatMessage(page.description, {
60
+ colors: options.colors,
61
+ maxWidth: options.maxWidth,
62
+ quotes: !options.colors
63
+ });
64
+ output += "\n";
65
+ }
66
+ const sections = page.sections.toSorted((a, b) => a.title == null && b.title == null ? 0 : a.title == null ? -1 : 1);
67
+ for (const section of sections) {
68
+ output += "\n";
69
+ if (section.title != null) output += `${section.title}:\n`;
70
+ for (const entry of section.entries) {
71
+ const term = require_usage.formatUsageTerm(entry.term, {
72
+ colors: options.colors,
73
+ optionsSeparator: ", ",
74
+ maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - termIndent
75
+ });
76
+ output += `${" ".repeat(termIndent)}${ansiAwareRightPad(term, termWidth)} ${entry.description == null ? "" : indentLines(require_message.formatMessage(entry.description, {
77
+ colors: options.colors,
78
+ quotes: !options.colors,
79
+ maxWidth: options.maxWidth == null ? void 0 : options.maxWidth - termIndent - termWidth - 2
80
+ }), termIndent + termWidth + 2)}\n`;
81
+ }
82
+ }
83
+ if (page.footer != null) {
84
+ output += "\n";
85
+ output += require_message.formatMessage(page.footer, {
86
+ colors: options.colors,
87
+ maxWidth: options.maxWidth,
88
+ quotes: !options.colors
89
+ });
90
+ }
91
+ return output;
92
+ }
93
+ function indentLines(text, indent) {
94
+ return text.split("\n").join("\n" + " ".repeat(indent));
95
+ }
96
+ function ansiAwareRightPad(text, length, char = " ") {
97
+ const ansiEscapeCodeRegex = /\x1B\[[0-9;]*[a-zA-Z]/g;
98
+ const strippedText = text.replace(ansiEscapeCodeRegex, "");
99
+ if (strippedText.length >= length) return text;
100
+ return text + char.repeat(length - strippedText.length);
101
+ }
102
+
103
+ //#endregion
104
+ exports.formatDocPage = formatDocPage;
package/dist/doc.d.cts ADDED
@@ -0,0 +1,129 @@
1
+ import { Message } from "./message.cjs";
2
+ import { Usage, UsageTerm } from "./usage.cjs";
3
+
4
+ //#region src/doc.d.ts
5
+
6
+ /**
7
+ * A documentation entry which describes a specific usage of a command or
8
+ * option. It includes a subject (the usage), a description, and an optional
9
+ * default value.
10
+ */
11
+ interface DocEntry {
12
+ /**
13
+ * The subject of the entry, which is typically a command or option
14
+ * usage.
15
+ */
16
+ readonly term: UsageTerm;
17
+ /**
18
+ * A description of the entry, which provides additional context or
19
+ * information about the usage.
20
+ */
21
+ readonly description?: Message;
22
+ /**
23
+ * An optional default value for the entry, which can be used to
24
+ * indicate what the default behavior is if the command or option is not
25
+ * specified.
26
+ */
27
+ readonly default?: string;
28
+ }
29
+ /**
30
+ * A section in a document that groups related entries together.
31
+ */
32
+ interface DocSection {
33
+ readonly title?: string;
34
+ readonly entries: readonly DocEntry[];
35
+ }
36
+ /**
37
+ * A document page that contains multiple sections, each with its own brief
38
+ * and a list of entries. This structure is used to organize documentation
39
+ * for commands, options, and other related information.
40
+ */
41
+ interface DocPage {
42
+ readonly brief?: Message;
43
+ readonly usage?: Usage;
44
+ readonly description?: Message;
45
+ readonly sections: readonly DocSection[];
46
+ readonly footer?: Message;
47
+ }
48
+ /**
49
+ * A documentation fragment that can be either an entry or a section.
50
+ * Fragments are building blocks used to construct documentation pages.
51
+ */
52
+ type DocFragment = {
53
+ readonly type: "entry";
54
+ } & DocEntry | {
55
+ readonly type: "section";
56
+ } & DocSection;
57
+ /**
58
+ * A collection of documentation fragments with an optional description.
59
+ * This structure is used to gather fragments before organizing them into
60
+ * a final document page.
61
+ */
62
+ interface DocFragments {
63
+ /**
64
+ * An optional description that applies to the entire collection of fragments.
65
+ */
66
+ readonly description?: Message;
67
+ /**
68
+ * An array of documentation fragments that can be entries or sections.
69
+ */
70
+ readonly fragments: readonly DocFragment[];
71
+ }
72
+ /**
73
+ * Options for formatting a documentation page.
74
+ */
75
+ interface DocPageFormatOptions {
76
+ /**
77
+ * Whether to include ANSI color codes in the output.
78
+ * @default `false`
79
+ */
80
+ colors?: boolean;
81
+ /**
82
+ * Number of spaces to indent terms in documentation entries.
83
+ * @default `2`
84
+ */
85
+ termIndent?: number;
86
+ /**
87
+ * Width allocated for terms before descriptions start.
88
+ * @default `26`
89
+ */
90
+ termWidth?: number;
91
+ /**
92
+ * Maximum width of the entire formatted output.
93
+ */
94
+ maxWidth?: number;
95
+ }
96
+ /**
97
+ * Formats a documentation page into a human-readable string.
98
+ *
99
+ * This function takes a structured {@link DocPage} and converts it into
100
+ * a formatted string suitable for display in terminals or documentation.
101
+ * The formatting includes proper indentation, alignment, and optional
102
+ * color support.
103
+ *
104
+ * @param programName The name of the program, used in usage lines
105
+ * @param page The documentation page to format
106
+ * @param options Formatting options to customize the output
107
+ * @returns A formatted string representation of the documentation page
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const page: DocPage = {
112
+ * brief: "A CLI tool",
113
+ * usage: [{ type: "literal", value: "myapp" }],
114
+ * sections: [{
115
+ * title: "Options",
116
+ * entries: [{
117
+ * term: { type: "option", short: "-v", long: "--verbose" },
118
+ * description: "Enable verbose output"
119
+ * }]
120
+ * }]
121
+ * };
122
+ *
123
+ * const formatted = formatDocPage("myapp", page, { colors: true });
124
+ * console.log(formatted);
125
+ * ```
126
+ */
127
+ declare function formatDocPage(programName: string, page: DocPage, options?: DocPageFormatOptions): string;
128
+ //#endregion
129
+ export { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, formatDocPage };