@optique/man 0.10.0-dev.0
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/LICENSE +20 -0
- package/README.md +113 -0
- package/dist/cli.cjs +319 -0
- package/dist/cli.d.cts +7 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +319 -0
- package/dist/generator-DFTQgmHv.cjs +104 -0
- package/dist/generator-DQks_OLj.js +58 -0
- package/dist/index.cjs +13 -0
- package/dist/index.d.cts +162 -0
- package/dist/index.d.ts +162 -0
- package/dist/index.js +5 -0
- package/dist/man-BMb0Vyt9.d.cts +127 -0
- package/dist/man-BmhJz56F.js +218 -0
- package/dist/man-K9LPAprq.cjs +235 -0
- package/dist/man-tclTvdWs.d.ts +127 -0
- package/dist/man.cjs +6 -0
- package/dist/man.d.cts +2 -0
- package/dist/man.d.ts +2 -0
- package/dist/man.js +4 -0
- package/dist/roff-CK3-yKaY.d.ts +64 -0
- package/dist/roff-Cs3_UBG5.d.cts +64 -0
- package/dist/roff-DzxoXJIL.cjs +140 -0
- package/dist/roff-i3JSYqke.js +122 -0
- package/dist/roff.cjs +5 -0
- package/dist/roff.d.cts +2 -0
- package/dist/roff.d.ts +2 -0
- package/dist/roff.js +3 -0
- package/package.json +104 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./roff-i3JSYqke.js";
|
|
3
|
+
import "./man-BmhJz56F.js";
|
|
4
|
+
import { generateManPageAsync } from "./generator-DQks_OLj.js";
|
|
5
|
+
import { object } from "@optique/core/constructs";
|
|
6
|
+
import { argument, option } from "@optique/core/primitives";
|
|
7
|
+
import { choice, string } from "@optique/core/valueparser";
|
|
8
|
+
import { optional, withDefault } from "@optique/core/modifiers";
|
|
9
|
+
import { commandLine, message, metavar, optionName } from "@optique/core/message";
|
|
10
|
+
import { defineProgram } from "@optique/core/program";
|
|
11
|
+
import { printError, runSync } from "@optique/run";
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { writeFile } from "node:fs/promises";
|
|
14
|
+
import { basename, extname, resolve } from "node:path";
|
|
15
|
+
import process from "node:process";
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
17
|
+
|
|
18
|
+
//#region deno.json
|
|
19
|
+
var name = "@optique/man";
|
|
20
|
+
var version = "0.10.0";
|
|
21
|
+
var license = "MIT";
|
|
22
|
+
var exports = {
|
|
23
|
+
".": "./src/index.ts",
|
|
24
|
+
"./roff": "./src/roff.ts",
|
|
25
|
+
"./man": "./src/man.ts",
|
|
26
|
+
"./cli": "./src/cli.ts"
|
|
27
|
+
};
|
|
28
|
+
var imports = { "tsx/esm/api": "npm:tsx@^4.21.0/esm/api" };
|
|
29
|
+
var exclude = ["dist/", "tsdown.config.ts"];
|
|
30
|
+
var tasks = {
|
|
31
|
+
"build": "pnpm build",
|
|
32
|
+
"test": "deno test",
|
|
33
|
+
"test:node": {
|
|
34
|
+
"dependencies": ["build"],
|
|
35
|
+
"command": "node --experimental-transform-types --test"
|
|
36
|
+
},
|
|
37
|
+
"test:bun": {
|
|
38
|
+
"dependencies": ["build"],
|
|
39
|
+
"command": "bun test"
|
|
40
|
+
},
|
|
41
|
+
"test-all": { "dependencies": [
|
|
42
|
+
"test",
|
|
43
|
+
"test:node",
|
|
44
|
+
"test:bun"
|
|
45
|
+
] }
|
|
46
|
+
};
|
|
47
|
+
var deno_default = {
|
|
48
|
+
name,
|
|
49
|
+
version,
|
|
50
|
+
license,
|
|
51
|
+
exports,
|
|
52
|
+
imports,
|
|
53
|
+
exclude,
|
|
54
|
+
tasks
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/cli.ts
|
|
59
|
+
const EXIT_FILE_NOT_FOUND = 1;
|
|
60
|
+
const EXIT_EXPORT_NOT_FOUND = 2;
|
|
61
|
+
const EXIT_NOT_PROGRAM_OR_PARSER = 3;
|
|
62
|
+
const EXIT_TSX_REQUIRED = 4;
|
|
63
|
+
const EXIT_GENERATION_FAILED = 5;
|
|
64
|
+
const EXIT_WRITE_FAILED = 6;
|
|
65
|
+
const sectionValues = [
|
|
66
|
+
1,
|
|
67
|
+
2,
|
|
68
|
+
3,
|
|
69
|
+
4,
|
|
70
|
+
5,
|
|
71
|
+
6,
|
|
72
|
+
7,
|
|
73
|
+
8
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* CLI program definition for optique-man.
|
|
77
|
+
*/
|
|
78
|
+
const cliProgram = defineProgram({
|
|
79
|
+
parser: object({
|
|
80
|
+
file: argument(string({ metavar: "FILE" }), { description: message`Path to a TypeScript or JavaScript file that exports
|
|
81
|
+
a ${metavar("PROGRAM")} or ${metavar("PARSER")} to generate a man page from.` }),
|
|
82
|
+
section: option("-s", "--section", choice(sectionValues, { metavar: "SECTION" }), { description: message`Man page section number (${"1"}-${"8"}). Common sections:
|
|
83
|
+
|
|
84
|
+
${"1"} User commands
|
|
85
|
+
${"5"} File formats
|
|
86
|
+
${"8"} System administration` }),
|
|
87
|
+
exportName: withDefault(option("-e", "--export", string({ metavar: "NAME" }), { description: message`JavaScript export name to use. The export must be
|
|
88
|
+
a ${metavar("PROGRAM")} (from ${commandLine("defineProgram()")}) or
|
|
89
|
+
a ${metavar("PARSER")}. If not specified, the default export is used.` }), "default"),
|
|
90
|
+
output: optional(option("-o", "--output", string({ metavar: "PATH" }), { description: message`Output file path. If not specified, the man page
|
|
91
|
+
is written to stdout.` })),
|
|
92
|
+
name: optional(option("--name", string({ metavar: "NAME" }), { description: message`Program name to use in the man page header.
|
|
93
|
+
If not specified, inferred from the ${metavar("PROGRAM")} metadata
|
|
94
|
+
or the input file name.` })),
|
|
95
|
+
date: optional(option("--date", string({ metavar: "DATE" }), { description: message`Date to display in the man page footer.
|
|
96
|
+
Defaults to the current date.` })),
|
|
97
|
+
versionString: optional(option("--version-string", string({ metavar: "VERSION" }), { description: message`Version string for the man page footer
|
|
98
|
+
(e.g., ${"MyApp 1.0.0"}). Overrides the version from
|
|
99
|
+
${metavar("PROGRAM")} metadata if provided.` })),
|
|
100
|
+
manual: optional(option("--manual", string({ metavar: "TITLE" }), { description: message`Manual name for the man page header
|
|
101
|
+
(e.g., ${"User Commands"}).` }))
|
|
102
|
+
}),
|
|
103
|
+
metadata: {
|
|
104
|
+
name: "optique-man",
|
|
105
|
+
version: deno_default.version,
|
|
106
|
+
brief: message`Generate Unix man pages from Optique parsers`,
|
|
107
|
+
description: message`Generates a Unix man page from an Optique
|
|
108
|
+
${metavar("PROGRAM")} or ${metavar("PARSER")} exported from a TypeScript
|
|
109
|
+
or JavaScript file.
|
|
110
|
+
|
|
111
|
+
The input file should export a ${metavar("PROGRAM")} (created with
|
|
112
|
+
${commandLine("defineProgram()")}) or a ${metavar("PARSER")}. When using
|
|
113
|
+
a ${metavar("PROGRAM")}, metadata like name, version, author, and examples
|
|
114
|
+
are automatically extracted.`,
|
|
115
|
+
examples: message`Generate a man page for section ${"1"} (user commands):
|
|
116
|
+
|
|
117
|
+
${commandLine("optique-man ./src/cli.ts -s 1")}
|
|
118
|
+
|
|
119
|
+
Use a named export instead of the default export:
|
|
120
|
+
|
|
121
|
+
${commandLine("optique-man ./src/cli.ts -s 1 -e myProgram")}
|
|
122
|
+
|
|
123
|
+
Write output to a file:
|
|
124
|
+
|
|
125
|
+
${commandLine("optique-man ./src/cli.ts -s 1 -o myapp.1")}
|
|
126
|
+
|
|
127
|
+
Override the program name:
|
|
128
|
+
|
|
129
|
+
${commandLine("optique-man ./src/cli.ts -s 1 --name myapp")}`,
|
|
130
|
+
bugs: message`Report bugs to: <https://github.com/dahlia/optique/issues>.`
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* Gets the Node.js major and minor version numbers.
|
|
135
|
+
* @returns A tuple of [major, minor] or null if not running on Node.js.
|
|
136
|
+
*/
|
|
137
|
+
function getNodeMajorMinor() {
|
|
138
|
+
if (typeof process === "undefined" || !process.versions?.node) return null;
|
|
139
|
+
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
140
|
+
return [major, minor];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Checks if Node.js natively supports TypeScript via type stripping.
|
|
144
|
+
* Node.js 25.2.0+ has type stripping enabled by default.
|
|
145
|
+
* @returns true if native TypeScript is supported.
|
|
146
|
+
*/
|
|
147
|
+
function nodeSupportsNativeTypeScript() {
|
|
148
|
+
const version$1 = getNodeMajorMinor();
|
|
149
|
+
if (version$1 == null) return false;
|
|
150
|
+
const [major, minor] = version$1;
|
|
151
|
+
return major > 25 || major === 25 && minor >= 2;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Error handler for file not found.
|
|
155
|
+
*/
|
|
156
|
+
function fileNotFoundError(filePath) {
|
|
157
|
+
printError(message`File ${filePath} not found.
|
|
158
|
+
|
|
159
|
+
Make sure the file path is correct and the file exists.`, { exitCode: EXIT_FILE_NOT_FOUND });
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Error handler for export not found.
|
|
163
|
+
*/
|
|
164
|
+
function exportNotFoundError(filePath, exportName, availableExports) {
|
|
165
|
+
const exportDisplay = exportName === "default" ? "default export" : `export ${exportName}`;
|
|
166
|
+
let suggestion;
|
|
167
|
+
if (availableExports.length > 0) suggestion = message`
|
|
168
|
+
|
|
169
|
+
Available exports: ${availableExports.join(", ")}.
|
|
170
|
+
Use ${optionName("-e")} to specify one of these exports.`;
|
|
171
|
+
else suggestion = message`
|
|
172
|
+
|
|
173
|
+
The file has no exports. Make sure it exports a Program or Parser.`;
|
|
174
|
+
printError(message`No ${exportDisplay} found in ${filePath}.${suggestion}`, { exitCode: EXIT_EXPORT_NOT_FOUND });
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Error handler for invalid export type.
|
|
178
|
+
*/
|
|
179
|
+
function notProgramOrParserError(filePath, exportName, actualType) {
|
|
180
|
+
const exportDisplay = exportName === "default" ? "default export" : `export ${exportName}`;
|
|
181
|
+
printError(message`The ${exportDisplay} in ${filePath} is not a Program or Parser.
|
|
182
|
+
|
|
183
|
+
Got type: ${actualType}
|
|
184
|
+
|
|
185
|
+
The export should be created with ${commandLine("defineProgram()")} or be
|
|
186
|
+
an Optique parser (e.g., from ${commandLine("object()")},
|
|
187
|
+
${commandLine("command()")}, etc.).`, { exitCode: EXIT_NOT_PROGRAM_OR_PARSER });
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Error handler for missing tsx.
|
|
191
|
+
*/
|
|
192
|
+
function tsxRequiredError(filePath) {
|
|
193
|
+
const version$1 = getNodeMajorMinor();
|
|
194
|
+
const versionStr = version$1 ? `${version$1[0]}.${version$1[1]}` : "unknown";
|
|
195
|
+
printError(message`TypeScript file ${filePath} cannot be loaded on Node.js ${versionStr}.
|
|
196
|
+
|
|
197
|
+
Install tsx as a dev dependency:
|
|
198
|
+
|
|
199
|
+
${commandLine("npm install -D tsx")}
|
|
200
|
+
|
|
201
|
+
Or upgrade to Node.js 25.2.0 or later, which supports TypeScript natively.
|
|
202
|
+
|
|
203
|
+
Alternatively, use a pre-compiled JavaScript file instead.`, { exitCode: EXIT_TSX_REQUIRED });
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Error handler for man page generation failure.
|
|
207
|
+
*/
|
|
208
|
+
function generationError(error) {
|
|
209
|
+
printError(message`Failed to generate man page: ${error.message}`, { exitCode: EXIT_GENERATION_FAILED });
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Error handler for file write failure.
|
|
213
|
+
*/
|
|
214
|
+
function writeError(outputPath, error) {
|
|
215
|
+
printError(message`Failed to write to ${outputPath}: ${error.message}
|
|
216
|
+
|
|
217
|
+
Make sure you have write permission and the parent directory exists.`, { exitCode: EXIT_WRITE_FAILED });
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Imports a module from the given file path.
|
|
221
|
+
* Handles TypeScript files on Node.js by using tsx if needed.
|
|
222
|
+
*/
|
|
223
|
+
async function importModule(filePath) {
|
|
224
|
+
const absolutePath = resolve(filePath);
|
|
225
|
+
if (!existsSync(absolutePath)) fileNotFoundError(filePath);
|
|
226
|
+
const isTypeScript = /\.[mc]?ts$/.test(filePath);
|
|
227
|
+
if (typeof globalThis.Deno !== "undefined") return await import(absolutePath);
|
|
228
|
+
if (typeof globalThis.Bun !== "undefined") return await import(absolutePath);
|
|
229
|
+
if (isTypeScript && !nodeSupportsNativeTypeScript()) try {
|
|
230
|
+
const tsx = await import("tsx/esm/api");
|
|
231
|
+
tsx.register();
|
|
232
|
+
} catch {
|
|
233
|
+
tsxRequiredError(filePath);
|
|
234
|
+
}
|
|
235
|
+
const fileUrl = pathToFileURL(absolutePath).href;
|
|
236
|
+
return await import(fileUrl);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Checks if a value is a Program object.
|
|
240
|
+
*/
|
|
241
|
+
function isProgram(value) {
|
|
242
|
+
return value != null && typeof value === "object" && "parser" in value && "metadata" in value && typeof value.metadata === "object" && value.metadata != null;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Checks if a value is a Parser object.
|
|
246
|
+
*/
|
|
247
|
+
function isParser(value) {
|
|
248
|
+
return value != null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "$mode" in value && "usage" in value;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Infers the program name from a file path.
|
|
252
|
+
*/
|
|
253
|
+
function inferNameFromPath(filePath) {
|
|
254
|
+
const base = basename(filePath);
|
|
255
|
+
const ext = extname(base);
|
|
256
|
+
return base.slice(0, -ext.length);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Gets available exports from a module.
|
|
260
|
+
*/
|
|
261
|
+
function getAvailableExports(mod) {
|
|
262
|
+
return Object.keys(mod).filter((key) => key !== "__esModule");
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Describes the type of a value for error messages.
|
|
266
|
+
*/
|
|
267
|
+
function describeType(value) {
|
|
268
|
+
if (value === null) return "null";
|
|
269
|
+
if (value === void 0) return "undefined";
|
|
270
|
+
if (Array.isArray(value)) return "array";
|
|
271
|
+
return typeof value;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Main CLI entry point.
|
|
275
|
+
*/
|
|
276
|
+
async function main() {
|
|
277
|
+
const args = runSync(cliProgram, {
|
|
278
|
+
help: "option",
|
|
279
|
+
version: {
|
|
280
|
+
value: deno_default.version,
|
|
281
|
+
mode: "option"
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
const mod = await importModule(args.file);
|
|
285
|
+
const target = args.exportName === "default" ? mod.default : mod[args.exportName];
|
|
286
|
+
if (target === void 0) exportNotFoundError(args.file, args.exportName, getAvailableExports(mod));
|
|
287
|
+
if (!isProgram(target) && !isParser(target)) notProgramOrParserError(args.file, args.exportName, describeType(target));
|
|
288
|
+
const name$1 = args.name ?? (isProgram(target) ? target.metadata.name : null) ?? inferNameFromPath(args.file);
|
|
289
|
+
let manPage;
|
|
290
|
+
try {
|
|
291
|
+
if (isProgram(target)) manPage = await generateManPageAsync(target, {
|
|
292
|
+
section: args.section,
|
|
293
|
+
name: args.name,
|
|
294
|
+
date: args.date,
|
|
295
|
+
version: args.versionString,
|
|
296
|
+
manual: args.manual
|
|
297
|
+
});
|
|
298
|
+
else manPage = await generateManPageAsync(target, {
|
|
299
|
+
name: name$1,
|
|
300
|
+
section: args.section,
|
|
301
|
+
date: args.date,
|
|
302
|
+
version: args.versionString,
|
|
303
|
+
manual: args.manual
|
|
304
|
+
});
|
|
305
|
+
} catch (error) {
|
|
306
|
+
generationError(error instanceof Error ? error : new Error(String(error)));
|
|
307
|
+
}
|
|
308
|
+
if (args.output) try {
|
|
309
|
+
await writeFile(args.output, manPage, "utf-8");
|
|
310
|
+
} catch (error) {
|
|
311
|
+
writeError(args.output, error instanceof Error ? error : new Error(String(error)));
|
|
312
|
+
}
|
|
313
|
+
else console.log(manPage);
|
|
314
|
+
}
|
|
315
|
+
const isMain = "main" in import.meta ? import.meta.main : process.argv[1] === fileURLToPath(import.meta.url);
|
|
316
|
+
if (isMain) main();
|
|
317
|
+
|
|
318
|
+
//#endregion
|
|
319
|
+
export { main };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
const require_man = require('./man-K9LPAprq.cjs');
|
|
25
|
+
const __optique_core_parser = __toESM(require("@optique/core/parser"));
|
|
26
|
+
|
|
27
|
+
//#region src/generator.ts
|
|
28
|
+
/**
|
|
29
|
+
* Checks if the given value is a {@link Program} object.
|
|
30
|
+
*/
|
|
31
|
+
function isProgram(value) {
|
|
32
|
+
return typeof value === "object" && value !== null && "parser" in value && "metadata" in value;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extracts parser and merged options from a parser or program.
|
|
36
|
+
*/
|
|
37
|
+
function extractParserAndOptions(parserOrProgram, options) {
|
|
38
|
+
if (isProgram(parserOrProgram)) {
|
|
39
|
+
const { metadata } = parserOrProgram;
|
|
40
|
+
const programOptions = options;
|
|
41
|
+
return {
|
|
42
|
+
parser: parserOrProgram.parser,
|
|
43
|
+
mergedOptions: {
|
|
44
|
+
name: programOptions.name ?? metadata.name,
|
|
45
|
+
section: programOptions.section,
|
|
46
|
+
date: programOptions.date,
|
|
47
|
+
version: programOptions.version ?? metadata.version,
|
|
48
|
+
manual: programOptions.manual,
|
|
49
|
+
author: programOptions.author ?? metadata.author,
|
|
50
|
+
bugs: programOptions.bugs ?? metadata.bugs,
|
|
51
|
+
examples: programOptions.examples ?? metadata.examples,
|
|
52
|
+
seeAlso: programOptions.seeAlso,
|
|
53
|
+
environment: programOptions.environment,
|
|
54
|
+
files: programOptions.files,
|
|
55
|
+
exitStatus: programOptions.exitStatus
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
parser: parserOrProgram,
|
|
61
|
+
mergedOptions: options
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function generateManPageSync(parserOrProgram, options) {
|
|
65
|
+
const { parser, mergedOptions } = extractParserAndOptions(parserOrProgram, options);
|
|
66
|
+
const docPage = (0, __optique_core_parser.getDocPageSync)(parser) ?? { sections: [] };
|
|
67
|
+
return require_man.formatDocPageAsMan(docPage, mergedOptions);
|
|
68
|
+
}
|
|
69
|
+
async function generateManPageAsync(parserOrProgram, options) {
|
|
70
|
+
const { parser, mergedOptions } = extractParserAndOptions(parserOrProgram, options);
|
|
71
|
+
const docPage = await (0, __optique_core_parser.getDocPageAsync)(parser) ?? { sections: [] };
|
|
72
|
+
return require_man.formatDocPageAsMan(docPage, mergedOptions);
|
|
73
|
+
}
|
|
74
|
+
function generateManPage(parserOrProgram, options) {
|
|
75
|
+
const { parser, mergedOptions } = extractParserAndOptions(parserOrProgram, options);
|
|
76
|
+
if (parser.$mode === "async") return generateManPageAsync(parser, mergedOptions);
|
|
77
|
+
return generateManPageSync(parser, mergedOptions);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
Object.defineProperty(exports, '__toESM', {
|
|
82
|
+
enumerable: true,
|
|
83
|
+
get: function () {
|
|
84
|
+
return __toESM;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
Object.defineProperty(exports, 'generateManPage', {
|
|
88
|
+
enumerable: true,
|
|
89
|
+
get: function () {
|
|
90
|
+
return generateManPage;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
Object.defineProperty(exports, 'generateManPageAsync', {
|
|
94
|
+
enumerable: true,
|
|
95
|
+
get: function () {
|
|
96
|
+
return generateManPageAsync;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
Object.defineProperty(exports, 'generateManPageSync', {
|
|
100
|
+
enumerable: true,
|
|
101
|
+
get: function () {
|
|
102
|
+
return generateManPageSync;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { formatDocPageAsMan } from "./man-BmhJz56F.js";
|
|
2
|
+
import { getDocPageAsync, getDocPageSync } from "@optique/core/parser";
|
|
3
|
+
|
|
4
|
+
//#region src/generator.ts
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the given value is a {@link Program} object.
|
|
7
|
+
*/
|
|
8
|
+
function isProgram(value) {
|
|
9
|
+
return typeof value === "object" && value !== null && "parser" in value && "metadata" in value;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Extracts parser and merged options from a parser or program.
|
|
13
|
+
*/
|
|
14
|
+
function extractParserAndOptions(parserOrProgram, options) {
|
|
15
|
+
if (isProgram(parserOrProgram)) {
|
|
16
|
+
const { metadata } = parserOrProgram;
|
|
17
|
+
const programOptions = options;
|
|
18
|
+
return {
|
|
19
|
+
parser: parserOrProgram.parser,
|
|
20
|
+
mergedOptions: {
|
|
21
|
+
name: programOptions.name ?? metadata.name,
|
|
22
|
+
section: programOptions.section,
|
|
23
|
+
date: programOptions.date,
|
|
24
|
+
version: programOptions.version ?? metadata.version,
|
|
25
|
+
manual: programOptions.manual,
|
|
26
|
+
author: programOptions.author ?? metadata.author,
|
|
27
|
+
bugs: programOptions.bugs ?? metadata.bugs,
|
|
28
|
+
examples: programOptions.examples ?? metadata.examples,
|
|
29
|
+
seeAlso: programOptions.seeAlso,
|
|
30
|
+
environment: programOptions.environment,
|
|
31
|
+
files: programOptions.files,
|
|
32
|
+
exitStatus: programOptions.exitStatus
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
parser: parserOrProgram,
|
|
38
|
+
mergedOptions: options
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function generateManPageSync(parserOrProgram, options) {
|
|
42
|
+
const { parser, mergedOptions } = extractParserAndOptions(parserOrProgram, options);
|
|
43
|
+
const docPage = getDocPageSync(parser) ?? { sections: [] };
|
|
44
|
+
return formatDocPageAsMan(docPage, mergedOptions);
|
|
45
|
+
}
|
|
46
|
+
async function generateManPageAsync(parserOrProgram, options) {
|
|
47
|
+
const { parser, mergedOptions } = extractParserAndOptions(parserOrProgram, options);
|
|
48
|
+
const docPage = await getDocPageAsync(parser) ?? { sections: [] };
|
|
49
|
+
return formatDocPageAsMan(docPage, mergedOptions);
|
|
50
|
+
}
|
|
51
|
+
function generateManPage(parserOrProgram, options) {
|
|
52
|
+
const { parser, mergedOptions } = extractParserAndOptions(parserOrProgram, options);
|
|
53
|
+
if (parser.$mode === "async") return generateManPageAsync(parser, mergedOptions);
|
|
54
|
+
return generateManPageSync(parser, mergedOptions);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { generateManPage, generateManPageAsync, generateManPageSync };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const require_generator = require('./generator-DFTQgmHv.cjs');
|
|
2
|
+
const require_roff = require('./roff-DzxoXJIL.cjs');
|
|
3
|
+
const require_man = require('./man-K9LPAprq.cjs');
|
|
4
|
+
|
|
5
|
+
exports.escapeHyphens = require_roff.escapeHyphens;
|
|
6
|
+
exports.escapeRoff = require_roff.escapeRoff;
|
|
7
|
+
exports.formatDateForMan = require_man.formatDateForMan;
|
|
8
|
+
exports.formatDocPageAsMan = require_man.formatDocPageAsMan;
|
|
9
|
+
exports.formatMessageAsRoff = require_roff.formatMessageAsRoff;
|
|
10
|
+
exports.formatUsageTermAsRoff = require_man.formatUsageTermAsRoff;
|
|
11
|
+
exports.generateManPage = require_generator.generateManPage;
|
|
12
|
+
exports.generateManPageAsync = require_generator.generateManPageAsync;
|
|
13
|
+
exports.generateManPageSync = require_generator.generateManPageSync;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { escapeHyphens, escapeRoff, formatMessageAsRoff } from "./roff-Cs3_UBG5.cjs";
|
|
2
|
+
import { ManPageOptions, formatDateForMan, formatDocPageAsMan, formatUsageTermAsRoff } from "./man-BMb0Vyt9.cjs";
|
|
3
|
+
import { Mode, ModeValue, Parser } from "@optique/core/parser";
|
|
4
|
+
import { Program } from "@optique/core/program";
|
|
5
|
+
|
|
6
|
+
//#region src/generator.d.ts
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Options for generating a man page from a parser.
|
|
10
|
+
* Extends {@link ManPageOptions} with the same configuration.
|
|
11
|
+
* @since 0.10.0
|
|
12
|
+
*/
|
|
13
|
+
interface GenerateManPageOptions extends ManPageOptions {}
|
|
14
|
+
/**
|
|
15
|
+
* Options for generating a man page from a {@link Program}.
|
|
16
|
+
*
|
|
17
|
+
* This interface omits `name`, `version`, `author`, `bugs`, and `examples`
|
|
18
|
+
* from {@link ManPageOptions} since they are extracted from the program's
|
|
19
|
+
* metadata. You can still override them by providing values in this options
|
|
20
|
+
* object.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.11.0
|
|
23
|
+
*/
|
|
24
|
+
interface GenerateManPageProgramOptions extends Partial<Omit<ManPageOptions, "section">>, Pick<ManPageOptions, "section"> {}
|
|
25
|
+
/**
|
|
26
|
+
* Generates a man page from a parser synchronously.
|
|
27
|
+
*
|
|
28
|
+
* This function extracts documentation from the parser's structure
|
|
29
|
+
* and formats it as a complete man page in roff format.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { generateManPageSync } from "@optique/man";
|
|
34
|
+
* import { object, option, flag } from "@optique/core/primitives";
|
|
35
|
+
* import { string } from "@optique/core/valueparser";
|
|
36
|
+
*
|
|
37
|
+
* const parser = object({
|
|
38
|
+
* verbose: flag("-v", "--verbose"),
|
|
39
|
+
* config: option("-c", "--config", string()),
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* const manPage = generateManPageSync(parser, {
|
|
43
|
+
* name: "myapp",
|
|
44
|
+
* section: 1,
|
|
45
|
+
* version: "1.0.0",
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* console.log(manPage);
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @param parser The parser to generate documentation from.
|
|
52
|
+
* @param options The man page generation options.
|
|
53
|
+
* @returns The complete man page in roff format.
|
|
54
|
+
* @since 0.10.0
|
|
55
|
+
* @since 0.11.0 Added support for {@link Program} objects.
|
|
56
|
+
*/
|
|
57
|
+
declare function generateManPageSync<T>(program: Program<"sync", T>, options: GenerateManPageProgramOptions): string;
|
|
58
|
+
declare function generateManPageSync(parser: Parser<"sync", unknown, unknown>, options: GenerateManPageOptions): string;
|
|
59
|
+
/**
|
|
60
|
+
* Generates a man page from a parser asynchronously.
|
|
61
|
+
*
|
|
62
|
+
* This function extracts documentation from the parser's structure
|
|
63
|
+
* and formats it as a complete man page in roff format. It supports
|
|
64
|
+
* both sync and async parsers.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* import { generateManPageAsync } from "@optique/man";
|
|
69
|
+
* import { object, option } from "@optique/core/primitives";
|
|
70
|
+
* import { string } from "@optique/core/valueparser";
|
|
71
|
+
*
|
|
72
|
+
* const parser = object({
|
|
73
|
+
* config: option("-c", "--config", string()),
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* const manPage = await generateManPageAsync(parser, {
|
|
77
|
+
* name: "myapp",
|
|
78
|
+
* section: 1,
|
|
79
|
+
* });
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @param parser The parser to generate documentation from.
|
|
83
|
+
* @param options The man page generation options.
|
|
84
|
+
* @returns A promise that resolves to the complete man page in roff format.
|
|
85
|
+
* @since 0.10.0
|
|
86
|
+
* @since 0.11.0 Added support for {@link Program} objects.
|
|
87
|
+
*/
|
|
88
|
+
declare function generateManPageAsync<M extends Mode, T>(program: Program<M, T>, options: GenerateManPageProgramOptions): Promise<string>;
|
|
89
|
+
declare function generateManPageAsync<M extends Mode>(parser: Parser<M, unknown, unknown>, options: GenerateManPageOptions): Promise<string>;
|
|
90
|
+
/**
|
|
91
|
+
* Generates a man page from a parser or program.
|
|
92
|
+
*
|
|
93
|
+
* This function extracts documentation from the parser's structure
|
|
94
|
+
* and formats it as a complete man page in roff format.
|
|
95
|
+
*
|
|
96
|
+
* For sync parsers, it returns the man page directly.
|
|
97
|
+
* For async parsers, it returns a Promise that resolves to the man page.
|
|
98
|
+
*
|
|
99
|
+
* @example Parser-based API
|
|
100
|
+
* ```typescript
|
|
101
|
+
* import { generateManPage } from "@optique/man";
|
|
102
|
+
* import { object, option, flag } from "@optique/core/primitives";
|
|
103
|
+
* import { string, integer } from "@optique/core/valueparser";
|
|
104
|
+
* import { message } from "@optique/core/message";
|
|
105
|
+
*
|
|
106
|
+
* const parser = object({
|
|
107
|
+
* verbose: flag("-v", "--verbose", {
|
|
108
|
+
* description: message`Enable verbose output.`,
|
|
109
|
+
* }),
|
|
110
|
+
* port: option("-p", "--port", integer(), {
|
|
111
|
+
* description: message`Port to listen on.`,
|
|
112
|
+
* }),
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* const manPage = generateManPage(parser, {
|
|
116
|
+
* name: "myapp",
|
|
117
|
+
* section: 1,
|
|
118
|
+
* version: "1.0.0",
|
|
119
|
+
* date: new Date(),
|
|
120
|
+
* author: message`Hong Minhee`,
|
|
121
|
+
* });
|
|
122
|
+
*
|
|
123
|
+
* // Write to file
|
|
124
|
+
* import { writeFileSync } from "node:fs";
|
|
125
|
+
* writeFileSync("myapp.1", manPage);
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @example Program-based API
|
|
129
|
+
* ```typescript
|
|
130
|
+
* import { generateManPage } from "@optique/man";
|
|
131
|
+
* import { defineProgram } from "@optique/core/program";
|
|
132
|
+
* import { object, flag } from "@optique/core/primitives";
|
|
133
|
+
* import { message } from "@optique/core/message";
|
|
134
|
+
*
|
|
135
|
+
* const prog = defineProgram({
|
|
136
|
+
* parser: object({
|
|
137
|
+
* verbose: flag("-v", "--verbose"),
|
|
138
|
+
* }),
|
|
139
|
+
* metadata: {
|
|
140
|
+
* name: "myapp",
|
|
141
|
+
* version: "1.0.0",
|
|
142
|
+
* author: message`Hong Minhee`,
|
|
143
|
+
* },
|
|
144
|
+
* });
|
|
145
|
+
*
|
|
146
|
+
* // Metadata is automatically extracted from the program
|
|
147
|
+
* const manPage = generateManPage(prog, { section: 1 });
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @param parserOrProgram The parser or program to generate documentation from.
|
|
151
|
+
* @param options The man page generation options.
|
|
152
|
+
* @returns The complete man page in roff format, or a Promise for async parsers.
|
|
153
|
+
* @since 0.10.0
|
|
154
|
+
* @since 0.11.0 Added support for {@link Program} objects.
|
|
155
|
+
*/
|
|
156
|
+
declare function generateManPage<T>(program: Program<"sync", T>, options: GenerateManPageProgramOptions): string;
|
|
157
|
+
declare function generateManPage<T>(program: Program<"async", T>, options: GenerateManPageProgramOptions): Promise<string>;
|
|
158
|
+
declare function generateManPage(parser: Parser<"sync", unknown, unknown>, options: GenerateManPageOptions): string;
|
|
159
|
+
declare function generateManPage(parser: Parser<"async", unknown, unknown>, options: GenerateManPageOptions): Promise<string>;
|
|
160
|
+
declare function generateManPage<M extends Mode>(parser: Parser<M, unknown, unknown>, options: GenerateManPageOptions): ModeValue<M, string>;
|
|
161
|
+
//#endregion
|
|
162
|
+
export { type GenerateManPageOptions, type GenerateManPageProgramOptions, type ManPageOptions, escapeHyphens, escapeRoff, formatDateForMan, formatDocPageAsMan, formatMessageAsRoff, formatUsageTermAsRoff, generateManPage, generateManPageAsync, generateManPageSync };
|