mdat-plugin-cli-help 2.0.1 → 2.1.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/dist/index.js +299 -15
- package/package.json +10 -7
- package/readme.md +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineConfig, getContextMetadata } from "mdat";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { execa } from "execa";
|
|
4
4
|
import { createLogger, injectionHelper } from "lognow";
|
|
5
5
|
import { CstParser, Lexer, createToken } from "chevrotain";
|
|
6
6
|
import path from "node:path";
|
|
@@ -134,6 +134,277 @@ function setLogger(logger) {
|
|
|
134
134
|
log = injectionHelper(logger);
|
|
135
135
|
}
|
|
136
136
|
//#endregion
|
|
137
|
+
//#region src/utilities/parsers/commander.ts
|
|
138
|
+
const flag$2 = createToken({
|
|
139
|
+
name: "flag",
|
|
140
|
+
pattern: /--[\w-]+/
|
|
141
|
+
});
|
|
142
|
+
const alias$2 = createToken({
|
|
143
|
+
name: "alias",
|
|
144
|
+
pattern: /-[A-Z]/i
|
|
145
|
+
});
|
|
146
|
+
const comma$2 = createToken({
|
|
147
|
+
group: Lexer.SKIPPED,
|
|
148
|
+
name: "comma",
|
|
149
|
+
pattern: /,/
|
|
150
|
+
});
|
|
151
|
+
const word$2 = createToken({
|
|
152
|
+
name: "word",
|
|
153
|
+
pattern: /\S+/
|
|
154
|
+
});
|
|
155
|
+
const argument$2 = createToken({
|
|
156
|
+
name: "argument",
|
|
157
|
+
pattern: /<\S+>|\[\S+\]/
|
|
158
|
+
});
|
|
159
|
+
const defaultInfoParens = createToken({
|
|
160
|
+
name: "defaultInfoParens",
|
|
161
|
+
pattern: /\(default:\s.+?\)/
|
|
162
|
+
});
|
|
163
|
+
const whiteSpace$2 = createToken({
|
|
164
|
+
group: Lexer.SKIPPED,
|
|
165
|
+
name: "whiteSpace",
|
|
166
|
+
pattern: /\s/
|
|
167
|
+
});
|
|
168
|
+
const usagePrefix = createToken({
|
|
169
|
+
group: Lexer.SKIPPED,
|
|
170
|
+
name: "usagePrefix",
|
|
171
|
+
pattern: /Usage:\s/
|
|
172
|
+
});
|
|
173
|
+
const startProgramDescription$1 = createToken({
|
|
174
|
+
group: Lexer.SKIPPED,
|
|
175
|
+
name: "startProgramDescription",
|
|
176
|
+
pattern: /\n\n/,
|
|
177
|
+
push_mode: "PROGRAM_DESCRIPTION_MODE"
|
|
178
|
+
});
|
|
179
|
+
const programDescription$2 = createToken({
|
|
180
|
+
name: "programDescription",
|
|
181
|
+
pattern: /.+/
|
|
182
|
+
});
|
|
183
|
+
const endProgramDescription$1 = createToken({
|
|
184
|
+
group: Lexer.SKIPPED,
|
|
185
|
+
name: "endProgramDescription",
|
|
186
|
+
pattern: /\n\n/,
|
|
187
|
+
pop_mode: true
|
|
188
|
+
});
|
|
189
|
+
const startOptionsSection$1 = createToken({
|
|
190
|
+
name: "startOptionsSection",
|
|
191
|
+
pattern: /Options:\n/,
|
|
192
|
+
push_mode: "SECTION_MODE"
|
|
193
|
+
});
|
|
194
|
+
const startCommandsSection$1 = createToken({
|
|
195
|
+
name: "startCommandsSection",
|
|
196
|
+
pattern: /Commands:\n/,
|
|
197
|
+
push_mode: "SECTION_MODE"
|
|
198
|
+
});
|
|
199
|
+
const startRow$2 = createToken({
|
|
200
|
+
name: "startRow",
|
|
201
|
+
pattern: / {2,}/,
|
|
202
|
+
push_mode: "ROW_MODE"
|
|
203
|
+
});
|
|
204
|
+
const rowDescription$2 = createToken({
|
|
205
|
+
name: "rowDescription",
|
|
206
|
+
pattern: / {2}\w.+? {2}/
|
|
207
|
+
});
|
|
208
|
+
const rowDescriptionTerminal$1 = createToken({
|
|
209
|
+
name: "rowDescriptionTerminal",
|
|
210
|
+
pattern: / {2}\w[^(\n]+(?=\(default:)| {2}\w.+/
|
|
211
|
+
});
|
|
212
|
+
const endRow$2 = createToken({
|
|
213
|
+
group: Lexer.SKIPPED,
|
|
214
|
+
name: "endRow",
|
|
215
|
+
pattern: /\n/,
|
|
216
|
+
pop_mode: true
|
|
217
|
+
});
|
|
218
|
+
const endSection$1 = createToken({
|
|
219
|
+
group: Lexer.SKIPPED,
|
|
220
|
+
name: "endSection",
|
|
221
|
+
pattern: /\n+/,
|
|
222
|
+
pop_mode: true
|
|
223
|
+
});
|
|
224
|
+
const lexer$2 = new Lexer({
|
|
225
|
+
defaultMode: "DEFAULT_MODE",
|
|
226
|
+
modes: {
|
|
227
|
+
DEFAULT_MODE: [
|
|
228
|
+
startOptionsSection$1,
|
|
229
|
+
startCommandsSection$1,
|
|
230
|
+
usagePrefix,
|
|
231
|
+
startProgramDescription$1,
|
|
232
|
+
argument$2,
|
|
233
|
+
word$2,
|
|
234
|
+
whiteSpace$2
|
|
235
|
+
],
|
|
236
|
+
PROGRAM_DESCRIPTION_MODE: [endProgramDescription$1, programDescription$2],
|
|
237
|
+
ROW_MODE: [
|
|
238
|
+
endRow$2,
|
|
239
|
+
comma$2,
|
|
240
|
+
defaultInfoParens,
|
|
241
|
+
rowDescription$2,
|
|
242
|
+
rowDescriptionTerminal$1,
|
|
243
|
+
flag$2,
|
|
244
|
+
alias$2,
|
|
245
|
+
argument$2,
|
|
246
|
+
word$2,
|
|
247
|
+
whiteSpace$2
|
|
248
|
+
],
|
|
249
|
+
SECTION_MODE: [startRow$2, endSection$1]
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
const allTokens$2 = [
|
|
253
|
+
flag$2,
|
|
254
|
+
alias$2,
|
|
255
|
+
comma$2,
|
|
256
|
+
word$2,
|
|
257
|
+
argument$2,
|
|
258
|
+
defaultInfoParens,
|
|
259
|
+
whiteSpace$2,
|
|
260
|
+
usagePrefix,
|
|
261
|
+
startProgramDescription$1,
|
|
262
|
+
programDescription$2,
|
|
263
|
+
endProgramDescription$1,
|
|
264
|
+
startOptionsSection$1,
|
|
265
|
+
startCommandsSection$1,
|
|
266
|
+
startRow$2,
|
|
267
|
+
rowDescription$2,
|
|
268
|
+
rowDescriptionTerminal$1,
|
|
269
|
+
endRow$2,
|
|
270
|
+
endSection$1
|
|
271
|
+
];
|
|
272
|
+
var CliParser$2 = class extends CstParser {
|
|
273
|
+
sectionRow = this.RULE("sectionRow", () => {
|
|
274
|
+
this.CONSUME(startRow$2);
|
|
275
|
+
this.MANY(() => {
|
|
276
|
+
this.OR([
|
|
277
|
+
{ ALT: () => this.CONSUME(argument$2) },
|
|
278
|
+
{ ALT: () => this.CONSUME(alias$2) },
|
|
279
|
+
{ ALT: () => this.CONSUME(flag$2) },
|
|
280
|
+
{ ALT: () => this.CONSUME(rowDescription$2, { LABEL: "description" }) },
|
|
281
|
+
{ ALT: () => this.CONSUME(rowDescriptionTerminal$1, { LABEL: "description" }) },
|
|
282
|
+
{ ALT: () => this.CONSUME(defaultInfoParens) },
|
|
283
|
+
{ ALT: () => this.CONSUME(word$2, { LABEL: "commandName" }) }
|
|
284
|
+
]);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
commandsSection = this.RULE("commandsSection", () => {
|
|
288
|
+
this.CONSUME(startCommandsSection$1);
|
|
289
|
+
this.MANY1(() => {
|
|
290
|
+
this.SUBRULE1(this.sectionRow);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
optionsSection = this.RULE("optionsSection", () => {
|
|
294
|
+
this.CONSUME(startOptionsSection$1);
|
|
295
|
+
this.MANY2(() => {
|
|
296
|
+
this.SUBRULE2(this.sectionRow);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
programHelp = this.RULE("programHelp", () => {
|
|
300
|
+
this.AT_LEAST_ONE(() => {
|
|
301
|
+
this.CONSUME(word$2, { LABEL: "commandName" });
|
|
302
|
+
});
|
|
303
|
+
this.MANY1(() => {
|
|
304
|
+
this.CONSUME(argument$2);
|
|
305
|
+
});
|
|
306
|
+
this.OPTION(() => {
|
|
307
|
+
this.CONSUME(programDescription$2, { LABEL: "description" });
|
|
308
|
+
});
|
|
309
|
+
this.OPTION1(() => {
|
|
310
|
+
this.SUBRULE(this.optionsSection);
|
|
311
|
+
});
|
|
312
|
+
this.OPTION2(() => {
|
|
313
|
+
this.SUBRULE(this.commandsSection);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
constructor() {
|
|
317
|
+
super(allTokens$2);
|
|
318
|
+
this.performSelfAnalysis();
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
const parser$2 = new CliParser$2();
|
|
322
|
+
var CliHelpToObjectVisitor$2 = class extends parser$2.getBaseCstVisitorConstructor() {
|
|
323
|
+
constructor() {
|
|
324
|
+
super();
|
|
325
|
+
this.validateVisitor();
|
|
326
|
+
}
|
|
327
|
+
commandsSection(context) {
|
|
328
|
+
return context.sectionRow.map((entry) => this.visit(entry));
|
|
329
|
+
}
|
|
330
|
+
optionsSection(context) {
|
|
331
|
+
return context.sectionRow.map((entry) => this.visit(entry));
|
|
332
|
+
}
|
|
333
|
+
programHelp(context) {
|
|
334
|
+
const { command: commandName, subcommand: subcommandName } = getCommandParts(this.getString(context.commandName));
|
|
335
|
+
return {
|
|
336
|
+
arguments: this.getArray(context.argument),
|
|
337
|
+
commandName,
|
|
338
|
+
commands: context.commandsSection ? this.visit(context.commandsSection) : void 0,
|
|
339
|
+
description: this.getString(context.description),
|
|
340
|
+
options: context.optionsSection ? this.visit(context.optionsSection) : void 0,
|
|
341
|
+
subcommandName
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
sectionRow(context) {
|
|
345
|
+
return {
|
|
346
|
+
aliases: this.getArray(context.alias),
|
|
347
|
+
arguments: this.getArray(context.argument),
|
|
348
|
+
commandName: this.getString(context.commandName),
|
|
349
|
+
defaultValue: this.cleanDefault(this.getString(context.defaultInfoParens)),
|
|
350
|
+
description: this.trimDescription(this.getString(context.description)),
|
|
351
|
+
flags: this.getArray(context.flag)
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Clean a Commander default value: strip `(default: ...)` wrapper, env info, and quotes.
|
|
356
|
+
*/
|
|
357
|
+
cleanDefault(text) {
|
|
358
|
+
if (text === void 0) return void 0;
|
|
359
|
+
let cleaned = text.replaceAll(/^\(default:\s*/g, "").replaceAll(/\)$/g, "").trim();
|
|
360
|
+
cleaned = cleaned.replaceAll(/,\s*env:\s*\S+$/g, "").trim();
|
|
361
|
+
cleaned = cleaned.replaceAll(/^["']|["']$/g, "");
|
|
362
|
+
return cleaned || void 0;
|
|
363
|
+
}
|
|
364
|
+
getArray(context) {
|
|
365
|
+
if (context === void 0) return void 0;
|
|
366
|
+
return context.map((entry) => entry.image);
|
|
367
|
+
}
|
|
368
|
+
getString(context) {
|
|
369
|
+
if (context === void 0) return void 0;
|
|
370
|
+
return context.map((entry) => entry.image).join(" ");
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Trim leading/trailing whitespace from description text.
|
|
374
|
+
*/
|
|
375
|
+
trimDescription(text) {
|
|
376
|
+
if (text === void 0) return void 0;
|
|
377
|
+
return text.trim() || void 0;
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
const visitor$2 = new CliHelpToObjectVisitor$2();
|
|
381
|
+
/**
|
|
382
|
+
* Converts an unstructured help string emitted from a CLI tool built with the
|
|
383
|
+
* `Commander` CLI library and turn it into a structured POJO describing the
|
|
384
|
+
* command.
|
|
385
|
+
*/
|
|
386
|
+
function helpStringToObject$3(helpString) {
|
|
387
|
+
if (!helpString.trimStart().startsWith("Usage:")) throw new Error("Not a Commander-format help string (must start with \"Usage:\")");
|
|
388
|
+
const lexingResult = lexer$2.tokenize(helpString);
|
|
389
|
+
if (lexingResult.errors.length > 0) throw new Error(`Errors lexing CLI command: ${JSON.stringify(lexingResult.errors, void 0, 2)}`);
|
|
390
|
+
parser$2.input = lexingResult.tokens;
|
|
391
|
+
const cst = parser$2.programHelp();
|
|
392
|
+
if (parser$2.errors.length > 0) throw new Error(`Errors parsing CLI command help text: ${JSON.stringify(parser$2.errors, void 0, 2)}`);
|
|
393
|
+
let programInfo;
|
|
394
|
+
try {
|
|
395
|
+
programInfo = visitor$2.visit(cst);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
if (error instanceof Error) throw new TypeError(`Errors visiting CLI command help text: ${String(error)}`);
|
|
398
|
+
}
|
|
399
|
+
if (programInfo === void 0) throw new Error("Could not parse help string");
|
|
400
|
+
if (programInfo.commands) {
|
|
401
|
+
programInfo.commands = programInfo.commands.filter((cmd) => cmd.commandName !== void 0 || cmd.description !== void 0);
|
|
402
|
+
for (const cmd of programInfo.commands) if (cmd.commandName && !cmd.parentCommandName) cmd.parentCommandName = programInfo.commandName;
|
|
403
|
+
if (programInfo.commands.length === 0) programInfo.commands = void 0;
|
|
404
|
+
}
|
|
405
|
+
return programInfo;
|
|
406
|
+
}
|
|
407
|
+
//#endregion
|
|
137
408
|
//#region src/utilities/parsers/meow.ts
|
|
138
409
|
const flag$1 = createToken({
|
|
139
410
|
name: "flag",
|
|
@@ -674,6 +945,7 @@ function helpStringToObject$1(helpString) {
|
|
|
674
945
|
//#endregion
|
|
675
946
|
//#region src/utilities/parsers/index.ts
|
|
676
947
|
var parsers_default = {
|
|
948
|
+
commander: helpStringToObject$3,
|
|
677
949
|
yargs: helpStringToObject$1,
|
|
678
950
|
meow: helpStringToObject$2
|
|
679
951
|
};
|
|
@@ -720,26 +992,32 @@ function helpStringToObject(helpString) {
|
|
|
720
992
|
//#region src/utilities/get-help-markdown.ts
|
|
721
993
|
/**
|
|
722
994
|
* Get help output from a CLI command and return it as markdown
|
|
995
|
+
*
|
|
996
|
+
* @param cliCommand - The executable path (may contain spaces, e.g. on Windows)
|
|
997
|
+
* @param helpFlag - The flag to pass to get help output
|
|
998
|
+
* @param depth - Max recursion depth for subcommands
|
|
723
999
|
*/
|
|
724
1000
|
async function getHelpMarkdown(cliCommand, helpFlag = "--help", depth) {
|
|
725
|
-
|
|
1001
|
+
return getHelpMarkdownInternal(cliCommand, [], helpFlag, depth ?? Number.MAX_SAFE_INTEGER);
|
|
1002
|
+
}
|
|
1003
|
+
async function getHelpMarkdownInternal(executable, subcommands, helpFlag, depth) {
|
|
1004
|
+
const rawHelpString = await getHelpString(executable, [...subcommands, helpFlag]);
|
|
726
1005
|
const programInfo = helpStringToObject(rawHelpString);
|
|
727
1006
|
if (programInfo === void 0) {
|
|
728
1007
|
log.warn(`Falling back to basic cli help text output.`);
|
|
729
1008
|
return renderHelpMarkdownBasic(rawHelpString);
|
|
730
1009
|
}
|
|
731
|
-
return renderHelpMarkdownObject(
|
|
1010
|
+
return renderHelpMarkdownObject(executable, subcommands, helpFlag, depth, programInfo);
|
|
732
1011
|
}
|
|
733
|
-
async function renderHelpMarkdownObject(
|
|
1012
|
+
async function renderHelpMarkdownObject(executable, subcommands, helpFlag, depth, programInfo) {
|
|
734
1013
|
if (depth <= 0) {
|
|
735
1014
|
log.warn(`Max CLI command help depth reached, stopping recursion`);
|
|
736
1015
|
return "";
|
|
737
1016
|
}
|
|
738
1017
|
let markdown = helpObjectToMarkdown(programInfo, depth);
|
|
739
|
-
const baseCommand = cliCommand.split(" ")[0];
|
|
740
1018
|
if (programInfo.commands) for (const command of programInfo.commands) {
|
|
741
1019
|
if (!command.parentCommandName || !command.commandName) continue;
|
|
742
|
-
const subCommandHelp = await
|
|
1020
|
+
const subCommandHelp = await getHelpMarkdownInternal(executable, [...subcommands, command.commandName], helpFlag, depth - 1);
|
|
743
1021
|
if (subCommandHelp === "") return markdown;
|
|
744
1022
|
markdown += `\n\n${subCommandHelp}`;
|
|
745
1023
|
}
|
|
@@ -753,19 +1031,21 @@ function renderHelpMarkdownBasic(rawHelpString) {
|
|
|
753
1031
|
}
|
|
754
1032
|
/**
|
|
755
1033
|
* Run the CLI help command and return the output, throw if there's no output
|
|
1034
|
+
*
|
|
1035
|
+
* @returns The full help string from the resolved command
|
|
756
1036
|
* @throws {TypeError} If there's an error running the CLI help command
|
|
757
|
-
* @returns the full help string from the resolved command
|
|
758
1037
|
*/
|
|
759
|
-
async function getHelpString(
|
|
1038
|
+
async function getHelpString(command, args) {
|
|
1039
|
+
const displayCommand = `${command} ${args.join(" ")}`;
|
|
760
1040
|
let rawHelpString;
|
|
761
1041
|
try {
|
|
762
|
-
const { stderr, stdout } = await
|
|
1042
|
+
const { stderr, stdout } = await execa(command, args, { preferLocal: true });
|
|
763
1043
|
rawHelpString = stdout;
|
|
764
1044
|
if (rawHelpString === void 0 || rawHelpString === "") rawHelpString = stderr;
|
|
765
1045
|
} catch (error) {
|
|
766
|
-
if (error instanceof Error) throw new TypeError(`Error running CLI help command: "${
|
|
1046
|
+
if (error instanceof Error) throw new TypeError(`Error running CLI help command: "${displayCommand}"\n${error.message}\n`);
|
|
767
1047
|
}
|
|
768
|
-
if (rawHelpString === void 0 || rawHelpString === "") throw new Error(`No result from running CLI help command: "${
|
|
1048
|
+
if (rawHelpString === void 0 || rawHelpString === "") throw new Error(`No result from running CLI help command: "${displayCommand}"\n`);
|
|
769
1049
|
return rawHelpString;
|
|
770
1050
|
}
|
|
771
1051
|
//#endregion
|
|
@@ -823,10 +1103,14 @@ function looksLikePath(maybePath) {
|
|
|
823
1103
|
return parsed.root !== "" || parsed.dir !== "";
|
|
824
1104
|
}
|
|
825
1105
|
async function ensureExecutable(filePath) {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1106
|
+
if (path.isAbsolute(filePath)) {
|
|
1107
|
+
if (await isExecutable(filePath)) return filePath;
|
|
1108
|
+
throw new Error(`The cli-help rule noticed that "${filePath}" is not executable.`);
|
|
1109
|
+
}
|
|
1110
|
+
if (await which(filePath, { nothrow: true }) !== null) return filePath;
|
|
1111
|
+
const packagePath = await getCommandPathFromPackage(filePath);
|
|
1112
|
+
if (packagePath !== void 0 && await isExecutable(packagePath)) return packagePath;
|
|
1113
|
+
throw new Error(`The cli-help rule noticed that "${filePath}" is not executable.`);
|
|
830
1114
|
}
|
|
831
1115
|
async function getCommandPathFromPackage(commandName) {
|
|
832
1116
|
const { nodePackageJson } = await getContextMetadata();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdat-plugin-cli-help",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Mdat plugin to generate tabular help documentation for CLI tools in Markdown files.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -38,20 +38,23 @@
|
|
|
38
38
|
"@types/which": "^3.0.4",
|
|
39
39
|
"chevrotain": "^12.0.0",
|
|
40
40
|
"execa": "^9.6.1",
|
|
41
|
-
"lognow": "^0.6.
|
|
41
|
+
"lognow": "^0.6.1",
|
|
42
42
|
"type-fest": "^5.5.0",
|
|
43
43
|
"which": "^6.0.1",
|
|
44
44
|
"zod": "^4.3.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@kitschpatrol/shared-config": "^7.
|
|
47
|
+
"@kitschpatrol/shared-config": "^7.1.0",
|
|
48
48
|
"@types/node": "~22.17.2",
|
|
49
|
+
"@types/yargs": "^17.0.35",
|
|
49
50
|
"bumpp": "^11.0.1",
|
|
50
|
-
"
|
|
51
|
+
"commander": "^14.0.3",
|
|
52
|
+
"mdat": "^2.2.0",
|
|
51
53
|
"meow": "^14.1.0",
|
|
52
54
|
"tsdown": "^0.21.7",
|
|
53
55
|
"typescript": "~5.9.3",
|
|
54
|
-
"vitest": "^4.1.2"
|
|
56
|
+
"vitest": "^4.1.2",
|
|
57
|
+
"yargs": "^18.0.0"
|
|
55
58
|
},
|
|
56
59
|
"peerDependencies": {
|
|
57
60
|
"mdat": "^2.0.0"
|
|
@@ -66,8 +69,8 @@
|
|
|
66
69
|
}
|
|
67
70
|
},
|
|
68
71
|
"scripts": {
|
|
69
|
-
"bench": "vitest bench --no-file-parallelism --compare test/benchmarks/baseline.json",
|
|
70
|
-
"bench:baseline": "vitest bench --no-file-parallelism --outputJson test/benchmarks/baseline.json",
|
|
72
|
+
"bench": "vitest bench --run --no-file-parallelism --compare test/benchmarks/baseline.json",
|
|
73
|
+
"bench:baseline": "vitest bench --run --no-file-parallelism --outputJson test/benchmarks/baseline.json",
|
|
71
74
|
"build": "tsdown --no-fixed-extension --tsconfig tsconfig.build.json",
|
|
72
75
|
"clean": "git rm -f pnpm-lock.yaml ; git clean -fdX",
|
|
73
76
|
"fix": "ksc fix",
|
package/readme.md
CHANGED
|
@@ -26,7 +26,7 @@ This plugin automatically transforms a CLI command's `--help` output into nicely
|
|
|
26
26
|
|
|
27
27
|
The rule also recursively calls `--help` on any subcommands found for inclusion in the output.
|
|
28
28
|
|
|
29
|
-
Currently, the rule can
|
|
29
|
+
Currently, the rule can parse help output in the format provided by [Commander](https://github.com/tj/commander.js)-, [Yargs](https://yargs.js.org)-, and [Meow](https://github.com/sindresorhus/meow)-based tools. If parsing fails, the rule will fall back to show the raw help output in a regular code block instead.
|
|
30
30
|
|
|
31
31
|
## Getting started
|
|
32
32
|
|