@optique/man 0.10.7-dev.485 → 1.0.0-dev.1109
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 +12 -3
- package/dist/cli.cjs +136 -36
- package/dist/cli.js +124 -24
- package/dist/{generator-zoVk04OH.cjs → generator-RyVL5b_V.cjs} +32 -32
- package/dist/{generator-CCa36YC2.js → generator-YM0drazb.js} +31 -2
- package/dist/index.cjs +5 -3
- package/dist/index.d.cts +12 -9
- package/dist/index.d.ts +12 -9
- package/dist/index.js +4 -4
- package/dist/{man-BMb0Vyt9.d.cts → man-B1Q2mhit.d.ts} +34 -3
- package/dist/man-BE1OY_lJ.js +386 -0
- package/dist/man-CkvscTlM.cjs +432 -0
- package/dist/{man-tclTvdWs.d.ts → man-DKwa47XV.d.cts} +33 -2
- package/dist/man.cjs +2 -2
- package/dist/man.d.cts +1 -1
- package/dist/man.d.ts +1 -1
- package/dist/man.js +2 -2
- package/dist/{roff-C_MiRXVS.js → roff-CCdIQO7B.js} +47 -6
- package/dist/{roff-72Am6STB.d.cts → roff-COeDIWWF.d.cts} +49 -2
- package/dist/{roff-B36zMxYc.d.ts → roff-CgYQDHBN.d.ts} +49 -2
- package/dist/{roff-EpcecLXU.cjs → roff-DJ-LkRXl.cjs} +58 -5
- package/dist/roff.cjs +3 -1
- package/dist/roff.d.cts +2 -2
- package/dist/roff.d.ts +2 -2
- package/dist/roff.js +2 -2
- package/package.json +3 -3
- package/dist/man-DGnow1Jr.cjs +0 -235
- package/dist/man-Leuf7kOn.js +0 -218
|
@@ -2,6 +2,20 @@ import { Message } from "@optique/core/message";
|
|
|
2
2
|
|
|
3
3
|
//#region src/roff.d.ts
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for roff formatting of messages.
|
|
7
|
+
*
|
|
8
|
+
* @since 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
interface RoffFormatOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Whether to wrap `value` and `values` terms in double quotes.
|
|
13
|
+
* Defaults to `true`.
|
|
14
|
+
*
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
readonly quotes?: boolean;
|
|
18
|
+
}
|
|
5
19
|
/**
|
|
6
20
|
* Escapes special roff characters in plain text.
|
|
7
21
|
*
|
|
@@ -15,6 +29,38 @@ import { Message } from "@optique/core/message";
|
|
|
15
29
|
* @since 0.10.0
|
|
16
30
|
*/
|
|
17
31
|
declare function escapeRoff(text: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Escapes roff-sensitive characters inside a quoted value in body text.
|
|
34
|
+
* Handles backslashes and double quotes so the value can be safely
|
|
35
|
+
* placed between literal `"` delimiters in roff text output (e.g.,
|
|
36
|
+
* `value()` / `values()` message terms).
|
|
37
|
+
*
|
|
38
|
+
* This function is *not* safe for roff request arguments such as
|
|
39
|
+
* `.SH "..."`, where groff performs an extra level of escape
|
|
40
|
+
* interpretation. Use {@link escapeRequestArg} for that purpose.
|
|
41
|
+
*
|
|
42
|
+
* @param text The raw value text.
|
|
43
|
+
* @returns The escaped text safe for use inside roff double quotes
|
|
44
|
+
* in body text.
|
|
45
|
+
* @since 1.0.0
|
|
46
|
+
*/
|
|
47
|
+
declare function escapeQuotedValue(text: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Escapes roff-sensitive characters inside a quoted roff request argument
|
|
50
|
+
* (e.g., `.SH "..."`). Unlike {@link escapeQuotedValue}, this function
|
|
51
|
+
* replaces backslashes with the `\(rs` glyph instead of `\\`, because
|
|
52
|
+
* groff performs an extra level of escape interpretation on request
|
|
53
|
+
* arguments — `\\` would still be parsed as an escape prefix.
|
|
54
|
+
*
|
|
55
|
+
* Line breaks (`\r\n`, `\r`, `\n`) are normalized to spaces because a
|
|
56
|
+
* raw newline would split the request line and cause the remainder to be
|
|
57
|
+
* parsed as new roff input.
|
|
58
|
+
*
|
|
59
|
+
* @param text The raw argument text.
|
|
60
|
+
* @returns The escaped text safe for use inside a quoted roff request.
|
|
61
|
+
* @since 1.0.0
|
|
62
|
+
*/
|
|
63
|
+
declare function escapeRequestArg(text: string): string;
|
|
18
64
|
/**
|
|
19
65
|
* Escapes hyphens in option names to prevent line breaks.
|
|
20
66
|
*
|
|
@@ -57,9 +103,10 @@ declare function escapeHyphens(text: string): string;
|
|
|
57
103
|
* ```
|
|
58
104
|
*
|
|
59
105
|
* @param msg The message to format.
|
|
106
|
+
* @param options Optional formatting options.
|
|
60
107
|
* @returns The roff-formatted string.
|
|
61
108
|
* @since 0.10.0
|
|
62
109
|
*/
|
|
63
|
-
declare function formatMessageAsRoff(msg: Message): string;
|
|
110
|
+
declare function formatMessageAsRoff(msg: Message, options?: RoffFormatOptions): string;
|
|
64
111
|
//#endregion
|
|
65
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
112
|
+
export { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
|
@@ -2,6 +2,20 @@ import { Message } from "@optique/core/message";
|
|
|
2
2
|
|
|
3
3
|
//#region src/roff.d.ts
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Options for roff formatting of messages.
|
|
7
|
+
*
|
|
8
|
+
* @since 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
interface RoffFormatOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Whether to wrap `value` and `values` terms in double quotes.
|
|
13
|
+
* Defaults to `true`.
|
|
14
|
+
*
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
readonly quotes?: boolean;
|
|
18
|
+
}
|
|
5
19
|
/**
|
|
6
20
|
* Escapes special roff characters in plain text.
|
|
7
21
|
*
|
|
@@ -15,6 +29,38 @@ import { Message } from "@optique/core/message";
|
|
|
15
29
|
* @since 0.10.0
|
|
16
30
|
*/
|
|
17
31
|
declare function escapeRoff(text: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Escapes roff-sensitive characters inside a quoted value in body text.
|
|
34
|
+
* Handles backslashes and double quotes so the value can be safely
|
|
35
|
+
* placed between literal `"` delimiters in roff text output (e.g.,
|
|
36
|
+
* `value()` / `values()` message terms).
|
|
37
|
+
*
|
|
38
|
+
* This function is *not* safe for roff request arguments such as
|
|
39
|
+
* `.SH "..."`, where groff performs an extra level of escape
|
|
40
|
+
* interpretation. Use {@link escapeRequestArg} for that purpose.
|
|
41
|
+
*
|
|
42
|
+
* @param text The raw value text.
|
|
43
|
+
* @returns The escaped text safe for use inside roff double quotes
|
|
44
|
+
* in body text.
|
|
45
|
+
* @since 1.0.0
|
|
46
|
+
*/
|
|
47
|
+
declare function escapeQuotedValue(text: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Escapes roff-sensitive characters inside a quoted roff request argument
|
|
50
|
+
* (e.g., `.SH "..."`). Unlike {@link escapeQuotedValue}, this function
|
|
51
|
+
* replaces backslashes with the `\(rs` glyph instead of `\\`, because
|
|
52
|
+
* groff performs an extra level of escape interpretation on request
|
|
53
|
+
* arguments — `\\` would still be parsed as an escape prefix.
|
|
54
|
+
*
|
|
55
|
+
* Line breaks (`\r\n`, `\r`, `\n`) are normalized to spaces because a
|
|
56
|
+
* raw newline would split the request line and cause the remainder to be
|
|
57
|
+
* parsed as new roff input.
|
|
58
|
+
*
|
|
59
|
+
* @param text The raw argument text.
|
|
60
|
+
* @returns The escaped text safe for use inside a quoted roff request.
|
|
61
|
+
* @since 1.0.0
|
|
62
|
+
*/
|
|
63
|
+
declare function escapeRequestArg(text: string): string;
|
|
18
64
|
/**
|
|
19
65
|
* Escapes hyphens in option names to prevent line breaks.
|
|
20
66
|
*
|
|
@@ -57,9 +103,10 @@ declare function escapeHyphens(text: string): string;
|
|
|
57
103
|
* ```
|
|
58
104
|
*
|
|
59
105
|
* @param msg The message to format.
|
|
106
|
+
* @param options Optional formatting options.
|
|
60
107
|
* @returns The roff-formatted string.
|
|
61
108
|
* @since 0.10.0
|
|
62
109
|
*/
|
|
63
|
-
declare function formatMessageAsRoff(msg: Message): string;
|
|
110
|
+
declare function formatMessageAsRoff(msg: Message, options?: RoffFormatOptions): string;
|
|
64
111
|
//#endregion
|
|
65
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
112
|
+
export { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
|
@@ -41,6 +41,42 @@ function escapeRoff(text) {
|
|
|
41
41
|
return escapeLineStarts(escapeBackslashes(text));
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
+
* Escapes roff-sensitive characters inside a quoted value in body text.
|
|
45
|
+
* Handles backslashes and double quotes so the value can be safely
|
|
46
|
+
* placed between literal `"` delimiters in roff text output (e.g.,
|
|
47
|
+
* `value()` / `values()` message terms).
|
|
48
|
+
*
|
|
49
|
+
* This function is *not* safe for roff request arguments such as
|
|
50
|
+
* `.SH "..."`, where groff performs an extra level of escape
|
|
51
|
+
* interpretation. Use {@link escapeRequestArg} for that purpose.
|
|
52
|
+
*
|
|
53
|
+
* @param text The raw value text.
|
|
54
|
+
* @returns The escaped text safe for use inside roff double quotes
|
|
55
|
+
* in body text.
|
|
56
|
+
* @since 1.0.0
|
|
57
|
+
*/
|
|
58
|
+
function escapeQuotedValue(text) {
|
|
59
|
+
return escapeBackslashes(text).replace(/"/g, "\\(dq");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Escapes roff-sensitive characters inside a quoted roff request argument
|
|
63
|
+
* (e.g., `.SH "..."`). Unlike {@link escapeQuotedValue}, this function
|
|
64
|
+
* replaces backslashes with the `\(rs` glyph instead of `\\`, because
|
|
65
|
+
* groff performs an extra level of escape interpretation on request
|
|
66
|
+
* arguments — `\\` would still be parsed as an escape prefix.
|
|
67
|
+
*
|
|
68
|
+
* Line breaks (`\r\n`, `\r`, `\n`) are normalized to spaces because a
|
|
69
|
+
* raw newline would split the request line and cause the remainder to be
|
|
70
|
+
* parsed as new roff input.
|
|
71
|
+
*
|
|
72
|
+
* @param text The raw argument text.
|
|
73
|
+
* @returns The escaped text safe for use inside a quoted roff request.
|
|
74
|
+
* @since 1.0.0
|
|
75
|
+
*/
|
|
76
|
+
function escapeRequestArg(text) {
|
|
77
|
+
return text.replace(/\r\n|\r|\n/g, " ").replace(/\\/g, "\\(rs").replace(/"/g, "\\(dq");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
44
80
|
* Escapes hyphens in option names to prevent line breaks.
|
|
45
81
|
*
|
|
46
82
|
* In roff, a regular hyphen (`-`) can be used as a line break point.
|
|
@@ -61,18 +97,22 @@ function escapeHyphens(text) {
|
|
|
61
97
|
* is done in formatMessageAsRoff after all terms are joined.
|
|
62
98
|
*
|
|
63
99
|
* @param term The message term to format.
|
|
100
|
+
* @param options Optional formatting options.
|
|
64
101
|
* @returns The roff-formatted string.
|
|
65
102
|
*/
|
|
66
|
-
function formatTermAsRoff(term) {
|
|
103
|
+
function formatTermAsRoff(term, options) {
|
|
67
104
|
switch (term.type) {
|
|
68
105
|
case "text": return escapeBackslashes(term.text);
|
|
69
106
|
case "optionName": return `\\fB${escapeHyphens(term.optionName)}\\fR`;
|
|
70
107
|
case "optionNames": return term.optionNames.map((name) => `\\fB${escapeHyphens(name)}\\fR`).join(", ");
|
|
71
108
|
case "metavar": return `\\fI${escapeBackslashes(term.metavar)}\\fR`;
|
|
72
|
-
case "value":
|
|
109
|
+
case "value":
|
|
110
|
+
if (options?.quotes === false) return escapeBackslashes(term.value);
|
|
111
|
+
return `"${escapeQuotedValue(term.value)}"`;
|
|
73
112
|
case "values":
|
|
74
113
|
if (term.values.length === 0) return "";
|
|
75
|
-
return term.values.map((v) =>
|
|
114
|
+
if (options?.quotes === false) return term.values.map((v) => escapeBackslashes(v)).join(" ");
|
|
115
|
+
return term.values.map((v) => `"${escapeQuotedValue(v)}"`).join(" ");
|
|
76
116
|
case "envVar": return `\\fB${escapeBackslashes(term.envVar)}\\fR`;
|
|
77
117
|
case "commandLine": return `\\fB${escapeHyphens(escapeBackslashes(term.commandLine))}\\fR`;
|
|
78
118
|
case "lineBreak": return "\n";
|
|
@@ -113,11 +153,12 @@ function formatTermAsRoff(term) {
|
|
|
113
153
|
* ```
|
|
114
154
|
*
|
|
115
155
|
* @param msg The message to format.
|
|
156
|
+
* @param options Optional formatting options.
|
|
116
157
|
* @returns The roff-formatted string.
|
|
117
158
|
* @since 0.10.0
|
|
118
159
|
*/
|
|
119
|
-
function formatMessageAsRoff(msg) {
|
|
120
|
-
const joined = msg.map(formatTermAsRoff).join("");
|
|
160
|
+
function formatMessageAsRoff(msg, options) {
|
|
161
|
+
const joined = msg.map((t) => formatTermAsRoff(t, options)).join("");
|
|
121
162
|
const escaped = escapeLineStarts(joined);
|
|
122
163
|
return escaped.replace(/\n\n+/g, "\n.PP\n");
|
|
123
164
|
}
|
|
@@ -129,6 +170,18 @@ Object.defineProperty(exports, 'escapeHyphens', {
|
|
|
129
170
|
return escapeHyphens;
|
|
130
171
|
}
|
|
131
172
|
});
|
|
173
|
+
Object.defineProperty(exports, 'escapeQuotedValue', {
|
|
174
|
+
enumerable: true,
|
|
175
|
+
get: function () {
|
|
176
|
+
return escapeQuotedValue;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
Object.defineProperty(exports, 'escapeRequestArg', {
|
|
180
|
+
enumerable: true,
|
|
181
|
+
get: function () {
|
|
182
|
+
return escapeRequestArg;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
132
185
|
Object.defineProperty(exports, 'escapeRoff', {
|
|
133
186
|
enumerable: true,
|
|
134
187
|
get: function () {
|
package/dist/roff.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
const require_roff = require('./roff-
|
|
1
|
+
const require_roff = require('./roff-DJ-LkRXl.cjs');
|
|
2
2
|
|
|
3
3
|
exports.escapeHyphens = require_roff.escapeHyphens;
|
|
4
|
+
exports.escapeQuotedValue = require_roff.escapeQuotedValue;
|
|
5
|
+
exports.escapeRequestArg = require_roff.escapeRequestArg;
|
|
4
6
|
exports.escapeRoff = require_roff.escapeRoff;
|
|
5
7
|
exports.formatMessageAsRoff = require_roff.formatMessageAsRoff;
|
package/dist/roff.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-
|
|
2
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
1
|
+
import { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-COeDIWWF.cjs";
|
|
2
|
+
export { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
package/dist/roff.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-
|
|
2
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
1
|
+
import { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-CgYQDHBN.js";
|
|
2
|
+
export { RoffFormatOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
package/dist/roff.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-
|
|
1
|
+
import { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-CCdIQO7B.js";
|
|
2
2
|
|
|
3
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
3
|
+
export { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/man",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-dev.1109+fa132665",
|
|
4
4
|
"description": "Man page generator for Optique CLI parsers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"optique-man": "./dist/cli.js"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@optique/core": "0.
|
|
88
|
-
"@optique/run": "0.
|
|
87
|
+
"@optique/core": "1.0.0-dev.1109+fa132665",
|
|
88
|
+
"@optique/run": "1.0.0-dev.1109+fa132665"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@types/node": "^20.19.9",
|
package/dist/man-DGnow1Jr.cjs
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
const require_roff = require('./roff-EpcecLXU.cjs');
|
|
2
|
-
|
|
3
|
-
//#region src/man.ts
|
|
4
|
-
/**
|
|
5
|
-
* Formats a date for use in man pages.
|
|
6
|
-
*
|
|
7
|
-
* @param date The date to format, or undefined.
|
|
8
|
-
* @returns The formatted date string, or undefined.
|
|
9
|
-
* @since 0.10.0
|
|
10
|
-
*/
|
|
11
|
-
function formatDateForMan(date) {
|
|
12
|
-
if (date === void 0) return void 0;
|
|
13
|
-
if (typeof date === "string") return date;
|
|
14
|
-
const months = [
|
|
15
|
-
"January",
|
|
16
|
-
"February",
|
|
17
|
-
"March",
|
|
18
|
-
"April",
|
|
19
|
-
"May",
|
|
20
|
-
"June",
|
|
21
|
-
"July",
|
|
22
|
-
"August",
|
|
23
|
-
"September",
|
|
24
|
-
"October",
|
|
25
|
-
"November",
|
|
26
|
-
"December"
|
|
27
|
-
];
|
|
28
|
-
return `${months[date.getMonth()]} ${date.getFullYear()}`;
|
|
29
|
-
}
|
|
30
|
-
function escapeThField(value) {
|
|
31
|
-
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Formats a single {@link UsageTerm} as roff markup for the SYNOPSIS section.
|
|
35
|
-
*
|
|
36
|
-
* @param term The usage term to format.
|
|
37
|
-
* @returns The roff-formatted string.
|
|
38
|
-
* @since 0.10.0
|
|
39
|
-
*/
|
|
40
|
-
function formatUsageTermAsRoff(term) {
|
|
41
|
-
if ("hidden" in term && term.hidden) return "";
|
|
42
|
-
switch (term.type) {
|
|
43
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
44
|
-
case "option": {
|
|
45
|
-
const names = term.names.map((name) => `\\fB${require_roff.escapeHyphens(name)}\\fR`).join(" | ");
|
|
46
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
47
|
-
return `[${names}${metavarPart}]`;
|
|
48
|
-
}
|
|
49
|
-
case "command": return `\\fB${term.name}\\fR`;
|
|
50
|
-
case "optional": {
|
|
51
|
-
const inner = formatUsageAsRoff(term.terms);
|
|
52
|
-
return `[${inner}]`;
|
|
53
|
-
}
|
|
54
|
-
case "multiple": {
|
|
55
|
-
const inner = formatUsageAsRoff(term.terms);
|
|
56
|
-
if (term.min < 1) return `[${inner} ...]`;
|
|
57
|
-
return `${inner} ...`;
|
|
58
|
-
}
|
|
59
|
-
case "exclusive": {
|
|
60
|
-
const alternatives = term.terms.map((t) => formatUsageAsRoff(t)).join(" | ");
|
|
61
|
-
return `(${alternatives})`;
|
|
62
|
-
}
|
|
63
|
-
case "literal": return term.value;
|
|
64
|
-
case "passthrough": return "[...]";
|
|
65
|
-
default: {
|
|
66
|
-
const _exhaustive = term;
|
|
67
|
-
throw new TypeError(`Unknown usage term type: ${_exhaustive.type}.`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Formats a {@link Usage} array as roff markup.
|
|
73
|
-
*
|
|
74
|
-
* @param usage The usage terms to format.
|
|
75
|
-
* @returns The roff-formatted string.
|
|
76
|
-
*/
|
|
77
|
-
function formatUsageAsRoff(usage) {
|
|
78
|
-
return usage.map(formatUsageTermAsRoff).filter((s) => s !== "").join(" ");
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Formats a {@link DocEntry}'s term for man page output.
|
|
82
|
-
*
|
|
83
|
-
* @param term The usage term from the entry.
|
|
84
|
-
* @returns The roff-formatted term string.
|
|
85
|
-
*/
|
|
86
|
-
function formatDocEntryTerm(term) {
|
|
87
|
-
switch (term.type) {
|
|
88
|
-
case "option": {
|
|
89
|
-
const names = term.names.map((name) => `\\fB${require_roff.escapeHyphens(name)}\\fR`).join(", ");
|
|
90
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
91
|
-
return `${names}${metavarPart}`;
|
|
92
|
-
}
|
|
93
|
-
case "command": return `\\fB${term.name}\\fR`;
|
|
94
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
95
|
-
case "literal": return term.value;
|
|
96
|
-
default: return formatUsageTermAsRoff(term);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Formats a {@link DocSection} as roff markup with .TP macros.
|
|
101
|
-
*
|
|
102
|
-
* @param section The section to format.
|
|
103
|
-
* @returns The roff-formatted section content.
|
|
104
|
-
*/
|
|
105
|
-
function formatDocSectionEntries(section) {
|
|
106
|
-
const lines = [];
|
|
107
|
-
for (const entry of section.entries) {
|
|
108
|
-
lines.push(".TP");
|
|
109
|
-
lines.push(formatDocEntryTerm(entry.term));
|
|
110
|
-
if (entry.description) {
|
|
111
|
-
let desc = require_roff.formatMessageAsRoff(entry.description);
|
|
112
|
-
if (entry.default) desc += ` [${require_roff.formatMessageAsRoff(entry.default)}]`;
|
|
113
|
-
lines.push(desc);
|
|
114
|
-
} else if (entry.default) lines.push(`[${require_roff.formatMessageAsRoff(entry.default)}]`);
|
|
115
|
-
}
|
|
116
|
-
return lines.join("\n");
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Formats a {@link DocPage} as a complete man page in roff format.
|
|
120
|
-
*
|
|
121
|
-
* This function generates a man page following the standard man(7) format,
|
|
122
|
-
* including sections for NAME, SYNOPSIS, DESCRIPTION, OPTIONS, and more.
|
|
123
|
-
*
|
|
124
|
-
* @example
|
|
125
|
-
* ```typescript
|
|
126
|
-
* import { formatDocPageAsMan } from "@optique/man/man";
|
|
127
|
-
* import type { DocPage } from "@optique/core/doc";
|
|
128
|
-
*
|
|
129
|
-
* const page: DocPage = {
|
|
130
|
-
* brief: message`A sample CLI application`,
|
|
131
|
-
* usage: [{ type: "argument", metavar: "FILE" }],
|
|
132
|
-
* sections: [],
|
|
133
|
-
* };
|
|
134
|
-
*
|
|
135
|
-
* const manPage = formatDocPageAsMan(page, {
|
|
136
|
-
* name: "myapp",
|
|
137
|
-
* section: 1,
|
|
138
|
-
* version: "1.0.0",
|
|
139
|
-
* });
|
|
140
|
-
* ```
|
|
141
|
-
*
|
|
142
|
-
* @param page The documentation page to format.
|
|
143
|
-
* @param options The man page options.
|
|
144
|
-
* @returns The complete man page in roff format.
|
|
145
|
-
* @since 0.10.0
|
|
146
|
-
*/
|
|
147
|
-
function formatDocPageAsMan(page, options) {
|
|
148
|
-
const lines = [];
|
|
149
|
-
const thParts = [escapeThField(options.name.toUpperCase()), options.section.toString()];
|
|
150
|
-
const hasDate = options.date != null;
|
|
151
|
-
const hasVersion = options.version != null;
|
|
152
|
-
const hasManual = options.manual != null;
|
|
153
|
-
if (hasDate) thParts.push(`"${escapeThField(formatDateForMan(options.date))}"`);
|
|
154
|
-
else if (hasVersion || hasManual) thParts.push("\"\"");
|
|
155
|
-
if (hasVersion) thParts.push(`"${escapeThField(`${options.name} ${options.version}`)}"`);
|
|
156
|
-
else if (hasManual) thParts.push("\"\"");
|
|
157
|
-
if (hasManual) thParts.push(`"${escapeThField(options.manual)}"`);
|
|
158
|
-
lines.push(`.TH ${thParts.join(" ")}`);
|
|
159
|
-
lines.push(".SH NAME");
|
|
160
|
-
if (page.brief) lines.push(`${options.name} \\- ${require_roff.formatMessageAsRoff(page.brief)}`);
|
|
161
|
-
else lines.push(options.name);
|
|
162
|
-
if (page.usage) {
|
|
163
|
-
lines.push(".SH SYNOPSIS");
|
|
164
|
-
lines.push(`.B ${options.name}`);
|
|
165
|
-
const usageStr = formatUsageAsRoff(page.usage);
|
|
166
|
-
if (usageStr) lines.push(usageStr);
|
|
167
|
-
}
|
|
168
|
-
if (page.description) {
|
|
169
|
-
lines.push(".SH DESCRIPTION");
|
|
170
|
-
lines.push(require_roff.formatMessageAsRoff(page.description));
|
|
171
|
-
}
|
|
172
|
-
for (const section of page.sections) {
|
|
173
|
-
if (section.entries.length === 0) continue;
|
|
174
|
-
const title = section.title?.toUpperCase() ?? "OPTIONS";
|
|
175
|
-
lines.push(`.SH ${title}`);
|
|
176
|
-
lines.push(formatDocSectionEntries(section));
|
|
177
|
-
}
|
|
178
|
-
if (options.environment && options.environment.entries.length > 0) {
|
|
179
|
-
lines.push(".SH ENVIRONMENT");
|
|
180
|
-
lines.push(formatDocSectionEntries(options.environment));
|
|
181
|
-
}
|
|
182
|
-
if (options.files && options.files.entries.length > 0) {
|
|
183
|
-
lines.push(".SH FILES");
|
|
184
|
-
lines.push(formatDocSectionEntries(options.files));
|
|
185
|
-
}
|
|
186
|
-
if (options.exitStatus && options.exitStatus.entries.length > 0) {
|
|
187
|
-
lines.push(".SH EXIT STATUS");
|
|
188
|
-
lines.push(formatDocSectionEntries(options.exitStatus));
|
|
189
|
-
}
|
|
190
|
-
if (options.examples) {
|
|
191
|
-
lines.push(".SH EXAMPLES");
|
|
192
|
-
lines.push(require_roff.formatMessageAsRoff(options.examples));
|
|
193
|
-
}
|
|
194
|
-
if (options.bugs) {
|
|
195
|
-
lines.push(".SH BUGS");
|
|
196
|
-
lines.push(require_roff.formatMessageAsRoff(options.bugs));
|
|
197
|
-
}
|
|
198
|
-
if (options.seeAlso && options.seeAlso.length > 0) {
|
|
199
|
-
lines.push(".SH SEE ALSO");
|
|
200
|
-
const refs = options.seeAlso.map((ref, i) => {
|
|
201
|
-
const suffix = i < options.seeAlso.length - 1 ? "," : "";
|
|
202
|
-
return `.BR ${ref.name} (${ref.section})${suffix}`;
|
|
203
|
-
});
|
|
204
|
-
lines.push(refs.join("\n"));
|
|
205
|
-
}
|
|
206
|
-
if (options.author) {
|
|
207
|
-
lines.push(".SH AUTHOR");
|
|
208
|
-
lines.push(require_roff.formatMessageAsRoff(options.author));
|
|
209
|
-
}
|
|
210
|
-
if (page.footer) {
|
|
211
|
-
lines.push(".PP");
|
|
212
|
-
lines.push(require_roff.formatMessageAsRoff(page.footer));
|
|
213
|
-
}
|
|
214
|
-
return lines.join("\n");
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
//#endregion
|
|
218
|
-
Object.defineProperty(exports, 'formatDateForMan', {
|
|
219
|
-
enumerable: true,
|
|
220
|
-
get: function () {
|
|
221
|
-
return formatDateForMan;
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
Object.defineProperty(exports, 'formatDocPageAsMan', {
|
|
225
|
-
enumerable: true,
|
|
226
|
-
get: function () {
|
|
227
|
-
return formatDocPageAsMan;
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
Object.defineProperty(exports, 'formatUsageTermAsRoff', {
|
|
231
|
-
enumerable: true,
|
|
232
|
-
get: function () {
|
|
233
|
-
return formatUsageTermAsRoff;
|
|
234
|
-
}
|
|
235
|
-
});
|