@optique/man 1.0.0-dev.783 → 1.0.0-dev.885
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/cli.cjs +18 -9
- package/dist/cli.js +18 -9
- package/dist/{generator-BDKtMiuq.cjs → generator-Bal_ioLr.cjs} +1 -1
- package/dist/{generator-DGiXLyTu.js → generator-CdDVvD4r.js} +1 -1
- package/dist/index.cjs +5 -3
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/{man-CAYHrsaf.js → man-BBDifH_Y.js} +39 -23
- package/dist/{man-Dh4GLG_Q.d.cts → man-CGKLHWkS.d.ts} +4 -1
- package/dist/{man-CT30XV48.cjs → man-DFKETOWN.cjs} +39 -23
- package/dist/{man-DrdGbys8.d.ts → man-xPX8GhXq.d.cts} +4 -1
- 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-72Am6STB.d.cts → roff-C_87xXP6.d.cts} +33 -1
- package/dist/{roff-C_MiRXVS.js → roff-Cl0vekdg.cjs} +69 -3
- package/dist/{roff-EpcecLXU.cjs → roff-CwBRpWCo.js} +39 -21
- package/dist/{roff-B36zMxYc.d.ts → roff-DlmeL3KB.d.ts} +33 -1
- 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/cli.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_man = require('./man-
|
|
3
|
-
require('./roff-
|
|
4
|
-
const require_generator = require('./generator-
|
|
2
|
+
const require_man = require('./man-DFKETOWN.cjs');
|
|
3
|
+
require('./roff-Cl0vekdg.cjs');
|
|
4
|
+
const require_generator = require('./generator-Bal_ioLr.cjs');
|
|
5
5
|
const __optique_core_constructs = require_man.__toESM(require("@optique/core/constructs"));
|
|
6
6
|
const __optique_core_primitives = require_man.__toESM(require("@optique/core/primitives"));
|
|
7
7
|
const __optique_core_valueparser = require_man.__toESM(require("@optique/core/valueparser"));
|
|
@@ -17,7 +17,7 @@ const node_url = require_man.__toESM(require("node:url"));
|
|
|
17
17
|
|
|
18
18
|
//#region deno.json
|
|
19
19
|
var name = "@optique/man";
|
|
20
|
-
var version = "1.0.0-dev.
|
|
20
|
+
var version = "1.0.0-dev.885+3300ebe1";
|
|
21
21
|
var license = "MIT";
|
|
22
22
|
var exports$1 = {
|
|
23
23
|
".": "./src/index.ts",
|
|
@@ -330,13 +330,21 @@ async function tryRegisterTsx() {
|
|
|
330
330
|
* Checks if a value is a Program object.
|
|
331
331
|
*/
|
|
332
332
|
function isProgram(value) {
|
|
333
|
-
|
|
333
|
+
try {
|
|
334
|
+
return value != null && typeof value === "object" && "parser" in value && "metadata" in value && typeof value.metadata === "object" && value.metadata != null && typeof value.metadata.name === "string" && isParser(value.parser);
|
|
335
|
+
} catch {
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
334
338
|
}
|
|
335
339
|
/**
|
|
336
340
|
* Checks if a value is a Parser object.
|
|
337
341
|
*/
|
|
338
342
|
function isParser(value) {
|
|
339
|
-
|
|
343
|
+
try {
|
|
344
|
+
return value != null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "$mode" in value && "usage" in value && "getDocFragments" in value && typeof value.getDocFragments === "function";
|
|
345
|
+
} catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
340
348
|
}
|
|
341
349
|
/**
|
|
342
350
|
* Infers the program name from a file path.
|
|
@@ -344,7 +352,7 @@ function isParser(value) {
|
|
|
344
352
|
function inferNameFromPath(filePath) {
|
|
345
353
|
const base = (0, node_path.basename)(filePath);
|
|
346
354
|
const ext = (0, node_path.extname)(base);
|
|
347
|
-
return base.slice(0, -ext.length);
|
|
355
|
+
return ext.length > 0 ? base.slice(0, -ext.length) : base;
|
|
348
356
|
}
|
|
349
357
|
/**
|
|
350
358
|
* Gets available exports from a module.
|
|
@@ -377,19 +385,20 @@ async function main() {
|
|
|
377
385
|
if (target === void 0) exportNotFoundError(args.file, args.exportName, getAvailableExports(mod));
|
|
378
386
|
if (!isProgram(target) && !isParser(target)) notProgramOrParserError(args.file, args.exportName, describeType(target));
|
|
379
387
|
const name$1 = args.name ?? (isProgram(target) ? target.metadata.name : null) ?? inferNameFromPath(args.file);
|
|
388
|
+
const date = args.date ?? /* @__PURE__ */ new Date();
|
|
380
389
|
let manPage;
|
|
381
390
|
try {
|
|
382
391
|
if (isProgram(target)) manPage = await require_generator.generateManPageAsync(target, {
|
|
383
392
|
section: args.section,
|
|
384
393
|
name: args.name,
|
|
385
|
-
date
|
|
394
|
+
date,
|
|
386
395
|
version: args.versionString,
|
|
387
396
|
manual: args.manual
|
|
388
397
|
});
|
|
389
398
|
else manPage = await require_generator.generateManPageAsync(target, {
|
|
390
399
|
name: name$1,
|
|
391
400
|
section: args.section,
|
|
392
|
-
date
|
|
401
|
+
date,
|
|
393
402
|
version: args.versionString,
|
|
394
403
|
manual: args.manual
|
|
395
404
|
});
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./roff-
|
|
3
|
-
import "./man-
|
|
4
|
-
import { generateManPageAsync } from "./generator-
|
|
2
|
+
import "./roff-CwBRpWCo.js";
|
|
3
|
+
import "./man-BBDifH_Y.js";
|
|
4
|
+
import { generateManPageAsync } from "./generator-CdDVvD4r.js";
|
|
5
5
|
import { object } from "@optique/core/constructs";
|
|
6
6
|
import { argument, option } from "@optique/core/primitives";
|
|
7
7
|
import { choice, string } from "@optique/core/valueparser";
|
|
@@ -17,7 +17,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
17
17
|
|
|
18
18
|
//#region deno.json
|
|
19
19
|
var name = "@optique/man";
|
|
20
|
-
var version = "1.0.0-dev.
|
|
20
|
+
var version = "1.0.0-dev.885+3300ebe1";
|
|
21
21
|
var license = "MIT";
|
|
22
22
|
var exports = {
|
|
23
23
|
".": "./src/index.ts",
|
|
@@ -330,13 +330,21 @@ async function tryRegisterTsx() {
|
|
|
330
330
|
* Checks if a value is a Program object.
|
|
331
331
|
*/
|
|
332
332
|
function isProgram(value) {
|
|
333
|
-
|
|
333
|
+
try {
|
|
334
|
+
return value != null && typeof value === "object" && "parser" in value && "metadata" in value && typeof value.metadata === "object" && value.metadata != null && typeof value.metadata.name === "string" && isParser(value.parser);
|
|
335
|
+
} catch {
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
334
338
|
}
|
|
335
339
|
/**
|
|
336
340
|
* Checks if a value is a Parser object.
|
|
337
341
|
*/
|
|
338
342
|
function isParser(value) {
|
|
339
|
-
|
|
343
|
+
try {
|
|
344
|
+
return value != null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "$mode" in value && "usage" in value && "getDocFragments" in value && typeof value.getDocFragments === "function";
|
|
345
|
+
} catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
340
348
|
}
|
|
341
349
|
/**
|
|
342
350
|
* Infers the program name from a file path.
|
|
@@ -344,7 +352,7 @@ function isParser(value) {
|
|
|
344
352
|
function inferNameFromPath(filePath) {
|
|
345
353
|
const base = basename(filePath);
|
|
346
354
|
const ext = extname(base);
|
|
347
|
-
return base.slice(0, -ext.length);
|
|
355
|
+
return ext.length > 0 ? base.slice(0, -ext.length) : base;
|
|
348
356
|
}
|
|
349
357
|
/**
|
|
350
358
|
* Gets available exports from a module.
|
|
@@ -377,19 +385,20 @@ async function main() {
|
|
|
377
385
|
if (target === void 0) exportNotFoundError(args.file, args.exportName, getAvailableExports(mod));
|
|
378
386
|
if (!isProgram(target) && !isParser(target)) notProgramOrParserError(args.file, args.exportName, describeType(target));
|
|
379
387
|
const name$1 = args.name ?? (isProgram(target) ? target.metadata.name : null) ?? inferNameFromPath(args.file);
|
|
388
|
+
const date = args.date ?? /* @__PURE__ */ new Date();
|
|
380
389
|
let manPage;
|
|
381
390
|
try {
|
|
382
391
|
if (isProgram(target)) manPage = await generateManPageAsync(target, {
|
|
383
392
|
section: args.section,
|
|
384
393
|
name: args.name,
|
|
385
|
-
date
|
|
394
|
+
date,
|
|
386
395
|
version: args.versionString,
|
|
387
396
|
manual: args.manual
|
|
388
397
|
});
|
|
389
398
|
else manPage = await generateManPageAsync(target, {
|
|
390
399
|
name: name$1,
|
|
391
400
|
section: args.section,
|
|
392
|
-
date
|
|
401
|
+
date,
|
|
393
402
|
version: args.versionString,
|
|
394
403
|
manual: args.manual
|
|
395
404
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
const require_man = require('./man-
|
|
2
|
-
const require_roff = require('./roff-
|
|
3
|
-
const require_generator = require('./generator-
|
|
1
|
+
const require_man = require('./man-DFKETOWN.cjs');
|
|
2
|
+
const require_roff = require('./roff-Cl0vekdg.cjs');
|
|
3
|
+
const require_generator = require('./generator-Bal_ioLr.cjs');
|
|
4
4
|
|
|
5
5
|
exports.escapeHyphens = require_roff.escapeHyphens;
|
|
6
|
+
exports.escapeQuotedValue = require_roff.escapeQuotedValue;
|
|
7
|
+
exports.escapeRequestArg = require_roff.escapeRequestArg;
|
|
6
8
|
exports.escapeRoff = require_roff.escapeRoff;
|
|
7
9
|
exports.formatDateForMan = require_man.formatDateForMan;
|
|
8
10
|
exports.formatDocPageAsMan = require_man.formatDocPageAsMan;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-
|
|
2
|
-
import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-
|
|
1
|
+
import { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-C_87xXP6.cjs";
|
|
2
|
+
import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-xPX8GhXq.cjs";
|
|
3
3
|
import { Mode, ModeValue, Parser } from "@optique/core/parser";
|
|
4
4
|
import { Program } from "@optique/core/program";
|
|
5
5
|
|
|
@@ -156,4 +156,4 @@ declare function generateManPage(parser: Parser<"sync", unknown, unknown>, optio
|
|
|
156
156
|
declare function generateManPage(parser: Parser<"async", unknown, unknown>, options: GenerateManPageOptions): Promise<string>;
|
|
157
157
|
declare function generateManPage<M extends Mode>(parser: Parser<M, unknown, unknown>, options: GenerateManPageOptions): ModeValue<M, string>;
|
|
158
158
|
//#endregion
|
|
159
|
-
export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, escapeHyphens, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|
|
159
|
+
export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-
|
|
2
|
-
import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-
|
|
1
|
+
import { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-DlmeL3KB.js";
|
|
2
|
+
import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-CGKLHWkS.js";
|
|
3
3
|
import { Program } from "@optique/core/program";
|
|
4
4
|
import { Mode, ModeValue, Parser } from "@optique/core/parser";
|
|
5
5
|
|
|
@@ -156,4 +156,4 @@ declare function generateManPage(parser: Parser<"sync", unknown, unknown>, optio
|
|
|
156
156
|
declare function generateManPage(parser: Parser<"async", unknown, unknown>, options: GenerateManPageOptions): Promise<string>;
|
|
157
157
|
declare function generateManPage<M extends Mode>(parser: Parser<M, unknown, unknown>, options: GenerateManPageOptions): ModeValue<M, string>;
|
|
158
158
|
//#endregion
|
|
159
|
-
export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, escapeHyphens, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|
|
159
|
+
export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-
|
|
2
|
-
import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-
|
|
3
|
-
import { generateManPage, generateManPageAsync, generateManPageSync } from "./generator-
|
|
1
|
+
import { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-CwBRpWCo.js";
|
|
2
|
+
import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-BBDifH_Y.js";
|
|
3
|
+
import { generateManPage, generateManPageAsync, generateManPageSync } from "./generator-CdDVvD4r.js";
|
|
4
4
|
|
|
5
|
-
export { escapeHyphens, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|
|
5
|
+
export { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { escapeHyphens, formatMessageAsRoff } from "./roff-
|
|
1
|
+
import { escapeHyphens, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-CwBRpWCo.js";
|
|
2
2
|
import { isDocHidden, isUsageHidden } from "@optique/core/usage";
|
|
3
3
|
|
|
4
4
|
//#region src/man.ts
|
|
@@ -31,6 +31,9 @@ function formatDateForMan(date) {
|
|
|
31
31
|
function escapeThField(value) {
|
|
32
32
|
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
33
33
|
}
|
|
34
|
+
function formatCommandNameAsRoff(name) {
|
|
35
|
+
return `\\fB${escapeHyphens(escapeRoff(name))}\\fR`;
|
|
36
|
+
}
|
|
34
37
|
/**
|
|
35
38
|
* Formats a single {@link UsageTerm} as roff markup for the SYNOPSIS section.
|
|
36
39
|
*
|
|
@@ -42,13 +45,13 @@ function escapeThField(value) {
|
|
|
42
45
|
function formatUsageTermAsRoff(term) {
|
|
43
46
|
if ("hidden" in term && isUsageHidden(term.hidden)) return "";
|
|
44
47
|
switch (term.type) {
|
|
45
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
48
|
+
case "argument": return `\\fI${escapeRoff(term.metavar)}\\fR`;
|
|
46
49
|
case "option": {
|
|
47
50
|
const names = term.names.map((name) => `\\fB${escapeHyphens(name)}\\fR`).join(" | ");
|
|
48
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
51
|
+
const metavarPart = term.metavar ? ` \\fI${escapeRoff(term.metavar)}\\fR` : "";
|
|
49
52
|
return `[${names}${metavarPart}]`;
|
|
50
53
|
}
|
|
51
|
-
case "command": return
|
|
54
|
+
case "command": return formatCommandNameAsRoff(term.name);
|
|
52
55
|
case "optional": {
|
|
53
56
|
const inner = formatUsageAsRoff(term.terms);
|
|
54
57
|
if (inner === "") return "";
|
|
@@ -66,7 +69,7 @@ function formatUsageTermAsRoff(term) {
|
|
|
66
69
|
if (alternatives.length === 1) return alternatives[0];
|
|
67
70
|
return `(${alternatives.join(" | ")})`;
|
|
68
71
|
}
|
|
69
|
-
case "literal": return term.value;
|
|
72
|
+
case "literal": return escapeRoff(term.value);
|
|
70
73
|
case "passthrough": return "[...]";
|
|
71
74
|
case "ellipsis": return "...";
|
|
72
75
|
default: {
|
|
@@ -95,12 +98,12 @@ function formatDocEntryTerm(term) {
|
|
|
95
98
|
switch (term.type) {
|
|
96
99
|
case "option": {
|
|
97
100
|
const names = term.names.map((name) => `\\fB${escapeHyphens(name)}\\fR`).join(", ");
|
|
98
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
101
|
+
const metavarPart = term.metavar ? ` \\fI${escapeRoff(term.metavar)}\\fR` : "";
|
|
99
102
|
return `${names}${metavarPart}`;
|
|
100
103
|
}
|
|
101
|
-
case "command": return
|
|
102
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
103
|
-
case "literal": return term.value;
|
|
104
|
+
case "command": return formatCommandNameAsRoff(term.name);
|
|
105
|
+
case "argument": return `\\fI${escapeRoff(term.metavar)}\\fR`;
|
|
106
|
+
case "literal": return escapeRoff(term.value);
|
|
104
107
|
default: return formatDocUsageTermAsRoff(term);
|
|
105
108
|
}
|
|
106
109
|
}
|
|
@@ -130,14 +133,14 @@ function formatDocUsageTermAsRoff(term) {
|
|
|
130
133
|
if (alternatives.length === 1) return alternatives[0];
|
|
131
134
|
return `(${alternatives.join(" | ")})`;
|
|
132
135
|
}
|
|
133
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
136
|
+
case "argument": return `\\fI${escapeRoff(term.metavar)}\\fR`;
|
|
134
137
|
case "option": {
|
|
135
138
|
const names = term.names.map((name) => `\\fB${escapeHyphens(name)}\\fR`).join(", ");
|
|
136
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
139
|
+
const metavarPart = term.metavar ? ` \\fI${escapeRoff(term.metavar)}\\fR` : "";
|
|
137
140
|
return `${names}${metavarPart}`;
|
|
138
141
|
}
|
|
139
|
-
case "command": return
|
|
140
|
-
case "literal": return term.value;
|
|
142
|
+
case "command": return formatCommandNameAsRoff(term.name);
|
|
143
|
+
case "literal": return escapeRoff(term.value);
|
|
141
144
|
case "passthrough": return "[...]";
|
|
142
145
|
case "ellipsis": return "...";
|
|
143
146
|
default: {
|
|
@@ -201,26 +204,39 @@ function formatDocSectionEntries(section) {
|
|
|
201
204
|
* @param page The documentation page to format.
|
|
202
205
|
* @param options The man page options.
|
|
203
206
|
* @returns The complete man page in roff format.
|
|
207
|
+
* @throws {TypeError} If the program name is empty.
|
|
208
|
+
* @throws {RangeError} If the section number is not a valid man page section
|
|
209
|
+
* (1–8).
|
|
204
210
|
* @since 0.10.0
|
|
205
211
|
*/
|
|
206
212
|
function formatDocPageAsMan(page, options) {
|
|
213
|
+
if (options.name === "") throw new TypeError("Program name must not be empty.");
|
|
214
|
+
if (!Number.isInteger(options.section) || options.section < 1 || options.section > 8) {
|
|
215
|
+
let repr;
|
|
216
|
+
try {
|
|
217
|
+
repr = JSON.stringify(options.section);
|
|
218
|
+
} catch {
|
|
219
|
+
repr = String(typeof options.section);
|
|
220
|
+
}
|
|
221
|
+
throw new RangeError(`Invalid man page section number (must be 1–8): ${repr}`);
|
|
222
|
+
}
|
|
207
223
|
const lines = [];
|
|
208
|
-
const thParts = [escapeThField(options.name.toUpperCase()), options.section.toString()];
|
|
209
|
-
const hasDate = options.date != null;
|
|
210
|
-
const hasVersion = options.version != null;
|
|
211
|
-
const hasManual = options.manual != null;
|
|
224
|
+
const thParts = [escapeHyphens(escapeThField(options.name).toUpperCase()), options.section.toString()];
|
|
225
|
+
const hasDate = options.date != null && options.date !== "";
|
|
226
|
+
const hasVersion = options.version != null && options.version !== "";
|
|
227
|
+
const hasManual = options.manual != null && options.manual !== "";
|
|
212
228
|
if (hasDate) thParts.push(`"${escapeThField(formatDateForMan(options.date))}"`);
|
|
213
229
|
else if (hasVersion || hasManual) thParts.push("\"\"");
|
|
214
|
-
if (hasVersion) thParts.push(`"${escapeThField(
|
|
230
|
+
if (hasVersion) thParts.push(`"${escapeHyphens(escapeThField(options.name))} ${escapeThField(options.version)}"`);
|
|
215
231
|
else if (hasManual) thParts.push("\"\"");
|
|
216
232
|
if (hasManual) thParts.push(`"${escapeThField(options.manual)}"`);
|
|
217
233
|
lines.push(`.TH ${thParts.join(" ")}`);
|
|
218
234
|
lines.push(".SH NAME");
|
|
219
|
-
if (page.brief) lines.push(`${options.name} \\- ${formatMessageAsRoff(page.brief)}`);
|
|
220
|
-
else lines.push(options.name);
|
|
235
|
+
if (page.brief) lines.push(`${escapeHyphens(escapeRoff(options.name))} \\- ${formatMessageAsRoff(page.brief)}`);
|
|
236
|
+
else lines.push(escapeHyphens(escapeRoff(options.name)));
|
|
221
237
|
if (page.usage) {
|
|
222
238
|
lines.push(".SH SYNOPSIS");
|
|
223
|
-
lines.push(`.B ${options.name}`);
|
|
239
|
+
lines.push(`.B ${escapeHyphens(escapeRoff(options.name))}`);
|
|
224
240
|
const usageStr = formatUsageAsRoff(page.usage);
|
|
225
241
|
if (usageStr) lines.push(usageStr);
|
|
226
242
|
}
|
|
@@ -233,7 +249,7 @@ function formatDocPageAsMan(page, options) {
|
|
|
233
249
|
const content = formatDocSectionEntries(section);
|
|
234
250
|
if (content === "") continue;
|
|
235
251
|
const title = section.title?.toUpperCase() ?? "OPTIONS";
|
|
236
|
-
lines.push(`.SH ${title}`);
|
|
252
|
+
lines.push(`.SH "${escapeRequestArg(title)}"`);
|
|
237
253
|
lines.push(content);
|
|
238
254
|
}
|
|
239
255
|
if (options.environment && options.environment.entries.length > 0) {
|
|
@@ -269,7 +285,7 @@ function formatDocPageAsMan(page, options) {
|
|
|
269
285
|
lines.push(".SH SEE ALSO");
|
|
270
286
|
const refs = options.seeAlso.map((ref, i) => {
|
|
271
287
|
const suffix = i < options.seeAlso.length - 1 ? "," : "";
|
|
272
|
-
return `.BR ${ref.name} (${ref.section})${suffix}`;
|
|
288
|
+
return `.BR ${escapeHyphens(escapeRoff(ref.name))} (${ref.section})${suffix}`;
|
|
273
289
|
});
|
|
274
290
|
lines.push(refs.join("\n"));
|
|
275
291
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Message } from "@optique/core/message";
|
|
2
|
-
import { DocPage, DocSection } from "@optique/core/doc";
|
|
3
2
|
import { UsageTerm } from "@optique/core/usage";
|
|
3
|
+
import { DocPage, DocSection } from "@optique/core/doc";
|
|
4
4
|
|
|
5
5
|
//#region src/man.d.ts
|
|
6
6
|
|
|
@@ -121,6 +121,9 @@ declare function formatUsageTermAsRoff(term: UsageTerm): string;
|
|
|
121
121
|
* @param page The documentation page to format.
|
|
122
122
|
* @param options The man page options.
|
|
123
123
|
* @returns The complete man page in roff format.
|
|
124
|
+
* @throws {TypeError} If the program name is empty.
|
|
125
|
+
* @throws {RangeError} If the section number is not a valid man page section
|
|
126
|
+
* (1–8).
|
|
124
127
|
* @since 0.10.0
|
|
125
128
|
*/
|
|
126
129
|
declare function formatDocPageAsMan(page: DocPage, options: ManPageOptions): string;
|
|
@@ -21,7 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
}) : target, mod));
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
|
-
const require_roff = require('./roff-
|
|
24
|
+
const require_roff = require('./roff-Cl0vekdg.cjs');
|
|
25
25
|
const __optique_core_usage = __toESM(require("@optique/core/usage"));
|
|
26
26
|
|
|
27
27
|
//#region src/man.ts
|
|
@@ -54,6 +54,9 @@ function formatDateForMan(date) {
|
|
|
54
54
|
function escapeThField(value) {
|
|
55
55
|
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
56
56
|
}
|
|
57
|
+
function formatCommandNameAsRoff(name) {
|
|
58
|
+
return `\\fB${require_roff.escapeHyphens(require_roff.escapeRoff(name))}\\fR`;
|
|
59
|
+
}
|
|
57
60
|
/**
|
|
58
61
|
* Formats a single {@link UsageTerm} as roff markup for the SYNOPSIS section.
|
|
59
62
|
*
|
|
@@ -65,13 +68,13 @@ function escapeThField(value) {
|
|
|
65
68
|
function formatUsageTermAsRoff(term) {
|
|
66
69
|
if ("hidden" in term && (0, __optique_core_usage.isUsageHidden)(term.hidden)) return "";
|
|
67
70
|
switch (term.type) {
|
|
68
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
71
|
+
case "argument": return `\\fI${require_roff.escapeRoff(term.metavar)}\\fR`;
|
|
69
72
|
case "option": {
|
|
70
73
|
const names = term.names.map((name) => `\\fB${require_roff.escapeHyphens(name)}\\fR`).join(" | ");
|
|
71
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
74
|
+
const metavarPart = term.metavar ? ` \\fI${require_roff.escapeRoff(term.metavar)}\\fR` : "";
|
|
72
75
|
return `[${names}${metavarPart}]`;
|
|
73
76
|
}
|
|
74
|
-
case "command": return
|
|
77
|
+
case "command": return formatCommandNameAsRoff(term.name);
|
|
75
78
|
case "optional": {
|
|
76
79
|
const inner = formatUsageAsRoff(term.terms);
|
|
77
80
|
if (inner === "") return "";
|
|
@@ -89,7 +92,7 @@ function formatUsageTermAsRoff(term) {
|
|
|
89
92
|
if (alternatives.length === 1) return alternatives[0];
|
|
90
93
|
return `(${alternatives.join(" | ")})`;
|
|
91
94
|
}
|
|
92
|
-
case "literal": return term.value;
|
|
95
|
+
case "literal": return require_roff.escapeRoff(term.value);
|
|
93
96
|
case "passthrough": return "[...]";
|
|
94
97
|
case "ellipsis": return "...";
|
|
95
98
|
default: {
|
|
@@ -118,12 +121,12 @@ function formatDocEntryTerm(term) {
|
|
|
118
121
|
switch (term.type) {
|
|
119
122
|
case "option": {
|
|
120
123
|
const names = term.names.map((name) => `\\fB${require_roff.escapeHyphens(name)}\\fR`).join(", ");
|
|
121
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
124
|
+
const metavarPart = term.metavar ? ` \\fI${require_roff.escapeRoff(term.metavar)}\\fR` : "";
|
|
122
125
|
return `${names}${metavarPart}`;
|
|
123
126
|
}
|
|
124
|
-
case "command": return
|
|
125
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
126
|
-
case "literal": return term.value;
|
|
127
|
+
case "command": return formatCommandNameAsRoff(term.name);
|
|
128
|
+
case "argument": return `\\fI${require_roff.escapeRoff(term.metavar)}\\fR`;
|
|
129
|
+
case "literal": return require_roff.escapeRoff(term.value);
|
|
127
130
|
default: return formatDocUsageTermAsRoff(term);
|
|
128
131
|
}
|
|
129
132
|
}
|
|
@@ -153,14 +156,14 @@ function formatDocUsageTermAsRoff(term) {
|
|
|
153
156
|
if (alternatives.length === 1) return alternatives[0];
|
|
154
157
|
return `(${alternatives.join(" | ")})`;
|
|
155
158
|
}
|
|
156
|
-
case "argument": return `\\fI${term.metavar}\\fR`;
|
|
159
|
+
case "argument": return `\\fI${require_roff.escapeRoff(term.metavar)}\\fR`;
|
|
157
160
|
case "option": {
|
|
158
161
|
const names = term.names.map((name) => `\\fB${require_roff.escapeHyphens(name)}\\fR`).join(", ");
|
|
159
|
-
const metavarPart = term.metavar ? ` \\fI${term.metavar}\\fR` : "";
|
|
162
|
+
const metavarPart = term.metavar ? ` \\fI${require_roff.escapeRoff(term.metavar)}\\fR` : "";
|
|
160
163
|
return `${names}${metavarPart}`;
|
|
161
164
|
}
|
|
162
|
-
case "command": return
|
|
163
|
-
case "literal": return term.value;
|
|
165
|
+
case "command": return formatCommandNameAsRoff(term.name);
|
|
166
|
+
case "literal": return require_roff.escapeRoff(term.value);
|
|
164
167
|
case "passthrough": return "[...]";
|
|
165
168
|
case "ellipsis": return "...";
|
|
166
169
|
default: {
|
|
@@ -224,26 +227,39 @@ function formatDocSectionEntries(section) {
|
|
|
224
227
|
* @param page The documentation page to format.
|
|
225
228
|
* @param options The man page options.
|
|
226
229
|
* @returns The complete man page in roff format.
|
|
230
|
+
* @throws {TypeError} If the program name is empty.
|
|
231
|
+
* @throws {RangeError} If the section number is not a valid man page section
|
|
232
|
+
* (1–8).
|
|
227
233
|
* @since 0.10.0
|
|
228
234
|
*/
|
|
229
235
|
function formatDocPageAsMan(page, options) {
|
|
236
|
+
if (options.name === "") throw new TypeError("Program name must not be empty.");
|
|
237
|
+
if (!Number.isInteger(options.section) || options.section < 1 || options.section > 8) {
|
|
238
|
+
let repr;
|
|
239
|
+
try {
|
|
240
|
+
repr = JSON.stringify(options.section);
|
|
241
|
+
} catch {
|
|
242
|
+
repr = String(typeof options.section);
|
|
243
|
+
}
|
|
244
|
+
throw new RangeError(`Invalid man page section number (must be 1–8): ${repr}`);
|
|
245
|
+
}
|
|
230
246
|
const lines = [];
|
|
231
|
-
const thParts = [escapeThField(options.name.toUpperCase()), options.section.toString()];
|
|
232
|
-
const hasDate = options.date != null;
|
|
233
|
-
const hasVersion = options.version != null;
|
|
234
|
-
const hasManual = options.manual != null;
|
|
247
|
+
const thParts = [require_roff.escapeHyphens(escapeThField(options.name).toUpperCase()), options.section.toString()];
|
|
248
|
+
const hasDate = options.date != null && options.date !== "";
|
|
249
|
+
const hasVersion = options.version != null && options.version !== "";
|
|
250
|
+
const hasManual = options.manual != null && options.manual !== "";
|
|
235
251
|
if (hasDate) thParts.push(`"${escapeThField(formatDateForMan(options.date))}"`);
|
|
236
252
|
else if (hasVersion || hasManual) thParts.push("\"\"");
|
|
237
|
-
if (hasVersion) thParts.push(`"${escapeThField(
|
|
253
|
+
if (hasVersion) thParts.push(`"${require_roff.escapeHyphens(escapeThField(options.name))} ${escapeThField(options.version)}"`);
|
|
238
254
|
else if (hasManual) thParts.push("\"\"");
|
|
239
255
|
if (hasManual) thParts.push(`"${escapeThField(options.manual)}"`);
|
|
240
256
|
lines.push(`.TH ${thParts.join(" ")}`);
|
|
241
257
|
lines.push(".SH NAME");
|
|
242
|
-
if (page.brief) lines.push(`${options.name} \\- ${require_roff.formatMessageAsRoff(page.brief)}`);
|
|
243
|
-
else lines.push(options.name);
|
|
258
|
+
if (page.brief) lines.push(`${require_roff.escapeHyphens(require_roff.escapeRoff(options.name))} \\- ${require_roff.formatMessageAsRoff(page.brief)}`);
|
|
259
|
+
else lines.push(require_roff.escapeHyphens(require_roff.escapeRoff(options.name)));
|
|
244
260
|
if (page.usage) {
|
|
245
261
|
lines.push(".SH SYNOPSIS");
|
|
246
|
-
lines.push(`.B ${options.name}`);
|
|
262
|
+
lines.push(`.B ${require_roff.escapeHyphens(require_roff.escapeRoff(options.name))}`);
|
|
247
263
|
const usageStr = formatUsageAsRoff(page.usage);
|
|
248
264
|
if (usageStr) lines.push(usageStr);
|
|
249
265
|
}
|
|
@@ -256,7 +272,7 @@ function formatDocPageAsMan(page, options) {
|
|
|
256
272
|
const content = formatDocSectionEntries(section);
|
|
257
273
|
if (content === "") continue;
|
|
258
274
|
const title = section.title?.toUpperCase() ?? "OPTIONS";
|
|
259
|
-
lines.push(`.SH ${title}`);
|
|
275
|
+
lines.push(`.SH "${require_roff.escapeRequestArg(title)}"`);
|
|
260
276
|
lines.push(content);
|
|
261
277
|
}
|
|
262
278
|
if (options.environment && options.environment.entries.length > 0) {
|
|
@@ -292,7 +308,7 @@ function formatDocPageAsMan(page, options) {
|
|
|
292
308
|
lines.push(".SH SEE ALSO");
|
|
293
309
|
const refs = options.seeAlso.map((ref, i) => {
|
|
294
310
|
const suffix = i < options.seeAlso.length - 1 ? "," : "";
|
|
295
|
-
return `.BR ${ref.name} (${ref.section})${suffix}`;
|
|
311
|
+
return `.BR ${require_roff.escapeHyphens(require_roff.escapeRoff(ref.name))} (${ref.section})${suffix}`;
|
|
296
312
|
});
|
|
297
313
|
lines.push(refs.join("\n"));
|
|
298
314
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Message } from "@optique/core/message";
|
|
2
|
-
import { UsageTerm } from "@optique/core/usage";
|
|
3
2
|
import { DocPage, DocSection } from "@optique/core/doc";
|
|
3
|
+
import { UsageTerm } from "@optique/core/usage";
|
|
4
4
|
|
|
5
5
|
//#region src/man.d.ts
|
|
6
6
|
|
|
@@ -121,6 +121,9 @@ declare function formatUsageTermAsRoff(term: UsageTerm): string;
|
|
|
121
121
|
* @param page The documentation page to format.
|
|
122
122
|
* @param options The man page options.
|
|
123
123
|
* @returns The complete man page in roff format.
|
|
124
|
+
* @throws {TypeError} If the program name is empty.
|
|
125
|
+
* @throws {RangeError} If the section number is not a valid man page section
|
|
126
|
+
* (1–8).
|
|
124
127
|
* @since 0.10.0
|
|
125
128
|
*/
|
|
126
129
|
declare function formatDocPageAsMan(page: DocPage, options: ManPageOptions): string;
|
package/dist/man.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_man = require('./man-
|
|
2
|
-
require('./roff-
|
|
1
|
+
const require_man = require('./man-DFKETOWN.cjs');
|
|
2
|
+
require('./roff-Cl0vekdg.cjs');
|
|
3
3
|
|
|
4
4
|
exports.formatDateForMan = require_man.formatDateForMan;
|
|
5
5
|
exports.formatDocPageAsMan = require_man.formatDocPageAsMan;
|
package/dist/man.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-
|
|
1
|
+
import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-xPX8GhXq.cjs";
|
|
2
2
|
export { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff };
|
package/dist/man.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-
|
|
1
|
+
import { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-CGKLHWkS.js";
|
|
2
2
|
export { ManPageOptions, ManPageSection, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff };
|
package/dist/man.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./roff-
|
|
2
|
-
import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-
|
|
1
|
+
import "./roff-CwBRpWCo.js";
|
|
2
|
+
import { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-BBDifH_Y.js";
|
|
3
3
|
|
|
4
4
|
export { formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff };
|
|
@@ -15,6 +15,38 @@ import { Message } from "@optique/core/message";
|
|
|
15
15
|
* @since 0.10.0
|
|
16
16
|
*/
|
|
17
17
|
declare function escapeRoff(text: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Escapes roff-sensitive characters inside a quoted value in body text.
|
|
20
|
+
* Handles backslashes and double quotes so the value can be safely
|
|
21
|
+
* placed between literal `"` delimiters in roff text output (e.g.,
|
|
22
|
+
* `value()` / `values()` message terms).
|
|
23
|
+
*
|
|
24
|
+
* This function is *not* safe for roff request arguments such as
|
|
25
|
+
* `.SH "..."`, where groff performs an extra level of escape
|
|
26
|
+
* interpretation. Use {@link escapeRequestArg} for that purpose.
|
|
27
|
+
*
|
|
28
|
+
* @param text The raw value text.
|
|
29
|
+
* @returns The escaped text safe for use inside roff double quotes
|
|
30
|
+
* in body text.
|
|
31
|
+
* @since 1.0.0
|
|
32
|
+
*/
|
|
33
|
+
declare function escapeQuotedValue(text: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Escapes roff-sensitive characters inside a quoted roff request argument
|
|
36
|
+
* (e.g., `.SH "..."`). Unlike {@link escapeQuotedValue}, this function
|
|
37
|
+
* replaces backslashes with the `\(rs` glyph instead of `\\`, because
|
|
38
|
+
* groff performs an extra level of escape interpretation on request
|
|
39
|
+
* arguments — `\\` would still be parsed as an escape prefix.
|
|
40
|
+
*
|
|
41
|
+
* Line breaks (`\r\n`, `\r`, `\n`) are normalized to spaces because a
|
|
42
|
+
* raw newline would split the request line and cause the remainder to be
|
|
43
|
+
* parsed as new roff input.
|
|
44
|
+
*
|
|
45
|
+
* @param text The raw argument text.
|
|
46
|
+
* @returns The escaped text safe for use inside a quoted roff request.
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
*/
|
|
49
|
+
declare function escapeRequestArg(text: string): string;
|
|
18
50
|
/**
|
|
19
51
|
* Escapes hyphens in option names to prevent line breaks.
|
|
20
52
|
*
|
|
@@ -62,4 +94,4 @@ declare function escapeHyphens(text: string): string;
|
|
|
62
94
|
*/
|
|
63
95
|
declare function formatMessageAsRoff(msg: Message): string;
|
|
64
96
|
//#endregion
|
|
65
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
97
|
+
export { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
//#region src/roff.ts
|
|
2
3
|
/**
|
|
3
4
|
* Escapes backslashes in text for roff.
|
|
@@ -40,6 +41,42 @@ function escapeRoff(text) {
|
|
|
40
41
|
return escapeLineStarts(escapeBackslashes(text));
|
|
41
42
|
}
|
|
42
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
|
+
/**
|
|
43
80
|
* Escapes hyphens in option names to prevent line breaks.
|
|
44
81
|
*
|
|
45
82
|
* In roff, a regular hyphen (`-`) can be used as a line break point.
|
|
@@ -68,10 +105,10 @@ function formatTermAsRoff(term) {
|
|
|
68
105
|
case "optionName": return `\\fB${escapeHyphens(term.optionName)}\\fR`;
|
|
69
106
|
case "optionNames": return term.optionNames.map((name) => `\\fB${escapeHyphens(name)}\\fR`).join(", ");
|
|
70
107
|
case "metavar": return `\\fI${escapeBackslashes(term.metavar)}\\fR`;
|
|
71
|
-
case "value": return `"${
|
|
108
|
+
case "value": return `"${escapeQuotedValue(term.value)}"`;
|
|
72
109
|
case "values":
|
|
73
110
|
if (term.values.length === 0) return "";
|
|
74
|
-
return term.values.map((v) => `"${
|
|
111
|
+
return term.values.map((v) => `"${escapeQuotedValue(v)}"`).join(" ");
|
|
75
112
|
case "envVar": return `\\fB${escapeBackslashes(term.envVar)}\\fR`;
|
|
76
113
|
case "commandLine": return `\\fB${escapeHyphens(escapeBackslashes(term.commandLine))}\\fR`;
|
|
77
114
|
case "lineBreak": return "\n";
|
|
@@ -122,4 +159,33 @@ function formatMessageAsRoff(msg) {
|
|
|
122
159
|
}
|
|
123
160
|
|
|
124
161
|
//#endregion
|
|
125
|
-
|
|
162
|
+
Object.defineProperty(exports, 'escapeHyphens', {
|
|
163
|
+
enumerable: true,
|
|
164
|
+
get: function () {
|
|
165
|
+
return escapeHyphens;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
Object.defineProperty(exports, 'escapeQuotedValue', {
|
|
169
|
+
enumerable: true,
|
|
170
|
+
get: function () {
|
|
171
|
+
return escapeQuotedValue;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
Object.defineProperty(exports, 'escapeRequestArg', {
|
|
175
|
+
enumerable: true,
|
|
176
|
+
get: function () {
|
|
177
|
+
return escapeRequestArg;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
Object.defineProperty(exports, 'escapeRoff', {
|
|
181
|
+
enumerable: true,
|
|
182
|
+
get: function () {
|
|
183
|
+
return escapeRoff;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
Object.defineProperty(exports, 'formatMessageAsRoff', {
|
|
187
|
+
enumerable: true,
|
|
188
|
+
get: function () {
|
|
189
|
+
return formatMessageAsRoff;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
//#region src/roff.ts
|
|
3
2
|
/**
|
|
4
3
|
* Escapes backslashes in text for roff.
|
|
@@ -41,6 +40,42 @@ function escapeRoff(text) {
|
|
|
41
40
|
return escapeLineStarts(escapeBackslashes(text));
|
|
42
41
|
}
|
|
43
42
|
/**
|
|
43
|
+
* Escapes roff-sensitive characters inside a quoted value in body text.
|
|
44
|
+
* Handles backslashes and double quotes so the value can be safely
|
|
45
|
+
* placed between literal `"` delimiters in roff text output (e.g.,
|
|
46
|
+
* `value()` / `values()` message terms).
|
|
47
|
+
*
|
|
48
|
+
* This function is *not* safe for roff request arguments such as
|
|
49
|
+
* `.SH "..."`, where groff performs an extra level of escape
|
|
50
|
+
* interpretation. Use {@link escapeRequestArg} for that purpose.
|
|
51
|
+
*
|
|
52
|
+
* @param text The raw value text.
|
|
53
|
+
* @returns The escaped text safe for use inside roff double quotes
|
|
54
|
+
* in body text.
|
|
55
|
+
* @since 1.0.0
|
|
56
|
+
*/
|
|
57
|
+
function escapeQuotedValue(text) {
|
|
58
|
+
return escapeBackslashes(text).replace(/"/g, "\\(dq");
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Escapes roff-sensitive characters inside a quoted roff request argument
|
|
62
|
+
* (e.g., `.SH "..."`). Unlike {@link escapeQuotedValue}, this function
|
|
63
|
+
* replaces backslashes with the `\(rs` glyph instead of `\\`, because
|
|
64
|
+
* groff performs an extra level of escape interpretation on request
|
|
65
|
+
* arguments — `\\` would still be parsed as an escape prefix.
|
|
66
|
+
*
|
|
67
|
+
* Line breaks (`\r\n`, `\r`, `\n`) are normalized to spaces because a
|
|
68
|
+
* raw newline would split the request line and cause the remainder to be
|
|
69
|
+
* parsed as new roff input.
|
|
70
|
+
*
|
|
71
|
+
* @param text The raw argument text.
|
|
72
|
+
* @returns The escaped text safe for use inside a quoted roff request.
|
|
73
|
+
* @since 1.0.0
|
|
74
|
+
*/
|
|
75
|
+
function escapeRequestArg(text) {
|
|
76
|
+
return text.replace(/\r\n|\r|\n/g, " ").replace(/\\/g, "\\(rs").replace(/"/g, "\\(dq");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
44
79
|
* Escapes hyphens in option names to prevent line breaks.
|
|
45
80
|
*
|
|
46
81
|
* In roff, a regular hyphen (`-`) can be used as a line break point.
|
|
@@ -69,10 +104,10 @@ function formatTermAsRoff(term) {
|
|
|
69
104
|
case "optionName": return `\\fB${escapeHyphens(term.optionName)}\\fR`;
|
|
70
105
|
case "optionNames": return term.optionNames.map((name) => `\\fB${escapeHyphens(name)}\\fR`).join(", ");
|
|
71
106
|
case "metavar": return `\\fI${escapeBackslashes(term.metavar)}\\fR`;
|
|
72
|
-
case "value": return `"${
|
|
107
|
+
case "value": return `"${escapeQuotedValue(term.value)}"`;
|
|
73
108
|
case "values":
|
|
74
109
|
if (term.values.length === 0) return "";
|
|
75
|
-
return term.values.map((v) => `"${
|
|
110
|
+
return term.values.map((v) => `"${escapeQuotedValue(v)}"`).join(" ");
|
|
76
111
|
case "envVar": return `\\fB${escapeBackslashes(term.envVar)}\\fR`;
|
|
77
112
|
case "commandLine": return `\\fB${escapeHyphens(escapeBackslashes(term.commandLine))}\\fR`;
|
|
78
113
|
case "lineBreak": return "\n";
|
|
@@ -123,21 +158,4 @@ function formatMessageAsRoff(msg) {
|
|
|
123
158
|
}
|
|
124
159
|
|
|
125
160
|
//#endregion
|
|
126
|
-
|
|
127
|
-
enumerable: true,
|
|
128
|
-
get: function () {
|
|
129
|
-
return escapeHyphens;
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
Object.defineProperty(exports, 'escapeRoff', {
|
|
133
|
-
enumerable: true,
|
|
134
|
-
get: function () {
|
|
135
|
-
return escapeRoff;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
Object.defineProperty(exports, 'formatMessageAsRoff', {
|
|
139
|
-
enumerable: true,
|
|
140
|
-
get: function () {
|
|
141
|
-
return formatMessageAsRoff;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
161
|
+
export { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
|
@@ -15,6 +15,38 @@ import { Message } from "@optique/core/message";
|
|
|
15
15
|
* @since 0.10.0
|
|
16
16
|
*/
|
|
17
17
|
declare function escapeRoff(text: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Escapes roff-sensitive characters inside a quoted value in body text.
|
|
20
|
+
* Handles backslashes and double quotes so the value can be safely
|
|
21
|
+
* placed between literal `"` delimiters in roff text output (e.g.,
|
|
22
|
+
* `value()` / `values()` message terms).
|
|
23
|
+
*
|
|
24
|
+
* This function is *not* safe for roff request arguments such as
|
|
25
|
+
* `.SH "..."`, where groff performs an extra level of escape
|
|
26
|
+
* interpretation. Use {@link escapeRequestArg} for that purpose.
|
|
27
|
+
*
|
|
28
|
+
* @param text The raw value text.
|
|
29
|
+
* @returns The escaped text safe for use inside roff double quotes
|
|
30
|
+
* in body text.
|
|
31
|
+
* @since 1.0.0
|
|
32
|
+
*/
|
|
33
|
+
declare function escapeQuotedValue(text: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Escapes roff-sensitive characters inside a quoted roff request argument
|
|
36
|
+
* (e.g., `.SH "..."`). Unlike {@link escapeQuotedValue}, this function
|
|
37
|
+
* replaces backslashes with the `\(rs` glyph instead of `\\`, because
|
|
38
|
+
* groff performs an extra level of escape interpretation on request
|
|
39
|
+
* arguments — `\\` would still be parsed as an escape prefix.
|
|
40
|
+
*
|
|
41
|
+
* Line breaks (`\r\n`, `\r`, `\n`) are normalized to spaces because a
|
|
42
|
+
* raw newline would split the request line and cause the remainder to be
|
|
43
|
+
* parsed as new roff input.
|
|
44
|
+
*
|
|
45
|
+
* @param text The raw argument text.
|
|
46
|
+
* @returns The escaped text safe for use inside a quoted roff request.
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
*/
|
|
49
|
+
declare function escapeRequestArg(text: string): string;
|
|
18
50
|
/**
|
|
19
51
|
* Escapes hyphens in option names to prevent line breaks.
|
|
20
52
|
*
|
|
@@ -62,4 +94,4 @@ declare function escapeHyphens(text: string): string;
|
|
|
62
94
|
*/
|
|
63
95
|
declare function formatMessageAsRoff(msg: Message): string;
|
|
64
96
|
//#endregion
|
|
65
|
-
export { escapeHyphens, escapeRoff, formatMessageAsRoff };
|
|
97
|
+
export { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff };
|
package/dist/roff.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
const require_roff = require('./roff-
|
|
1
|
+
const require_roff = require('./roff-Cl0vekdg.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 { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-C_87xXP6.cjs";
|
|
2
|
+
export { 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 { escapeHyphens, escapeQuotedValue, escapeRequestArg, escapeRoff, formatMessageAsRoff } from "./roff-DlmeL3KB.js";
|
|
2
|
+
export { 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-CwBRpWCo.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": "1.0.0-dev.
|
|
3
|
+
"version": "1.0.0-dev.885+3300ebe1",
|
|
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": "1.0.0-dev.
|
|
88
|
-
"@optique/run": "1.0.0-dev.
|
|
87
|
+
"@optique/core": "1.0.0-dev.885+3300ebe1",
|
|
88
|
+
"@optique/run": "1.0.0-dev.885+3300ebe1"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@types/node": "^20.19.9",
|