politty 0.4.4 → 0.4.7
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/{arg-registry-BUUhZ7JR.d.ts → arg-registry-2m40k1Et.d.ts} +1 -1
- package/dist/{arg-registry-BUUhZ7JR.d.ts.map → arg-registry-2m40k1Et.d.ts.map} +1 -1
- package/dist/augment.d.ts +1 -1
- package/dist/completion/index.cjs +16 -168
- package/dist/completion/index.d.cts +2 -77
- package/dist/completion/index.d.ts +2 -77
- package/dist/completion/index.js +3 -154
- package/dist/{zsh-DR47Ccac.cjs → completion-Df0eZ70u.cjs} +230 -18
- package/dist/completion-Df0eZ70u.cjs.map +1 -0
- package/dist/{zsh-XbRzR8FW.js → completion-_AnQsWh9.js} +202 -8
- package/dist/completion-_AnQsWh9.js.map +1 -0
- package/dist/docs/index.cjs +274 -28
- package/dist/docs/index.cjs.map +1 -1
- package/dist/docs/index.d.cts +62 -7
- package/dist/docs/index.d.cts.map +1 -1
- package/dist/docs/index.d.ts +62 -7
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +269 -29
- package/dist/docs/index.js.map +1 -1
- package/dist/{value-completion-resolver-C9LTGr0O.d.ts → index-BA0GkZQx.d.cts} +83 -4
- package/dist/index-BA0GkZQx.d.cts.map +1 -0
- package/dist/{value-completion-resolver-BQgHsX7b.d.cts → index-rMDe9hp1.d.ts} +83 -4
- package/dist/index-rMDe9hp1.d.ts.map +1 -0
- package/dist/index.cjs +8 -7
- package/dist/index.d.cts +67 -13
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +68 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -5
- package/dist/{lazy-BEDnSR0m.cjs → lazy-DHlvJiQQ.cjs} +44 -8
- package/dist/lazy-DHlvJiQQ.cjs.map +1 -0
- package/dist/{lazy-BrEg8SgI.js → lazy-DSyfzR-F.js} +38 -8
- package/dist/lazy-DSyfzR-F.js.map +1 -0
- package/dist/{runner-C4fSHJMe.cjs → runner-Cn6Oq4ZZ.cjs} +453 -26
- package/dist/runner-Cn6Oq4ZZ.cjs.map +1 -0
- package/dist/{runner-D6k4BgB4.js → runner-D4ByDT5I.js} +453 -26
- package/dist/runner-D4ByDT5I.js.map +1 -0
- package/dist/{schema-extractor-DFaAZzaY.d.cts → schema-extractor-BoWkcP9a.d.cts} +48 -2
- package/dist/schema-extractor-BoWkcP9a.d.cts.map +1 -0
- package/dist/{schema-extractor-n9288WJ6.d.ts → schema-extractor-DoDO4M_i.d.ts} +49 -3
- package/dist/schema-extractor-DoDO4M_i.d.ts.map +1 -0
- package/dist/{subcommand-router-CAzBsLSI.js → subcommand-router-CKuy6D2b.js} +2 -2
- package/dist/{subcommand-router-CAzBsLSI.js.map → subcommand-router-CKuy6D2b.js.map} +1 -1
- package/dist/{subcommand-router-ZjNjFaUL.cjs → subcommand-router-sZHhUP7b.cjs} +2 -2
- package/dist/{subcommand-router-ZjNjFaUL.cjs.map → subcommand-router-sZHhUP7b.cjs.map} +1 -1
- package/package.json +9 -9
- package/dist/completion/index.cjs.map +0 -1
- package/dist/completion/index.d.cts.map +0 -1
- package/dist/completion/index.d.ts.map +0 -1
- package/dist/completion/index.js.map +0 -1
- package/dist/lazy-BEDnSR0m.cjs.map +0 -1
- package/dist/lazy-BrEg8SgI.js.map +0 -1
- package/dist/runner-C4fSHJMe.cjs.map +0 -1
- package/dist/runner-D6k4BgB4.js.map +0 -1
- package/dist/schema-extractor-DFaAZzaY.d.cts.map +0 -1
- package/dist/schema-extractor-n9288WJ6.d.ts.map +0 -1
- package/dist/value-completion-resolver-BQgHsX7b.d.cts.map +0 -1
- package/dist/value-completion-resolver-C9LTGr0O.d.ts.map +0 -1
- package/dist/zsh-DR47Ccac.cjs.map +0 -1
- package/dist/zsh-XbRzR8FW.js.map +0 -1
package/dist/docs/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as getExtractedFields, i as extractFields } from "../lazy-
|
|
2
|
-
import { i as createLogCollector, n as resolveLazyCommand } from "../subcommand-router-
|
|
1
|
+
import { a as getExtractedFields, i as extractFields } from "../lazy-DSyfzR-F.js";
|
|
2
|
+
import { i as createLogCollector, n as resolveLazyCommand } from "../subcommand-router-CKuy6D2b.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { isDeepStrictEqual } from "node:util";
|
|
5
5
|
import * as fs from "node:fs";
|
|
@@ -58,6 +58,26 @@ function globalOptionsEndMarker() {
|
|
|
58
58
|
return `<!-- ${GLOBAL_OPTIONS_MARKER_PREFIX}:end -->`;
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
+
* Marker prefix for root header sections in generated documentation
|
|
62
|
+
*/
|
|
63
|
+
const ROOT_HEADER_MARKER_PREFIX = "politty:root-header";
|
|
64
|
+
function rootHeaderStartMarker() {
|
|
65
|
+
return `<!-- ${ROOT_HEADER_MARKER_PREFIX}:start -->`;
|
|
66
|
+
}
|
|
67
|
+
function rootHeaderEndMarker() {
|
|
68
|
+
return `<!-- ${ROOT_HEADER_MARKER_PREFIX}:end -->`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Marker prefix for root footer sections in generated documentation
|
|
72
|
+
*/
|
|
73
|
+
const ROOT_FOOTER_MARKER_PREFIX = "politty:root-footer";
|
|
74
|
+
function rootFooterStartMarker() {
|
|
75
|
+
return `<!-- ${ROOT_FOOTER_MARKER_PREFIX}:start -->`;
|
|
76
|
+
}
|
|
77
|
+
function rootFooterEndMarker() {
|
|
78
|
+
return `<!-- ${ROOT_FOOTER_MARKER_PREFIX}:end -->`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
61
81
|
* Marker prefix for index sections in generated documentation
|
|
62
82
|
* Format: <!-- politty:index:<scope>:start --> ... <!-- politty:index:<scope>:end -->
|
|
63
83
|
*/
|
|
@@ -298,6 +318,68 @@ function renderOptionsTableFromArray(options) {
|
|
|
298
318
|
return lines.join("\n");
|
|
299
319
|
}
|
|
300
320
|
/**
|
|
321
|
+
* Render union/xor options as markdown with variant grouping
|
|
322
|
+
*/
|
|
323
|
+
function renderUnionOptionsMarkdown(extracted, style = "table") {
|
|
324
|
+
const unionOptions = extracted.unionOptions ?? [];
|
|
325
|
+
if (unionOptions.length === 0) return "";
|
|
326
|
+
const sections = [];
|
|
327
|
+
const allFieldNames = /* @__PURE__ */ new Set();
|
|
328
|
+
for (const option of unionOptions) for (const field of option.fields) allFieldNames.add(field.name);
|
|
329
|
+
const commonFieldNames = /* @__PURE__ */ new Set();
|
|
330
|
+
for (const fieldName of allFieldNames) if (unionOptions.every((o) => o.fields.some((f) => f.name === fieldName))) commonFieldNames.add(fieldName);
|
|
331
|
+
const commonFields = extracted.fields.filter((f) => commonFieldNames.has(f.name) && !f.positional);
|
|
332
|
+
if (commonFields.length > 0) sections.push(style === "table" ? renderOptionsTableFromArray(commonFields) : renderOptionsListFromArray(commonFields));
|
|
333
|
+
sections.push("> One of the following option groups is required:");
|
|
334
|
+
for (let i = 0; i < unionOptions.length; i++) {
|
|
335
|
+
const option = unionOptions[i];
|
|
336
|
+
if (!option) continue;
|
|
337
|
+
const uniqueFields = option.fields.filter((f) => !commonFieldNames.has(f.name) && !f.positional);
|
|
338
|
+
if (uniqueFields.length === 0) continue;
|
|
339
|
+
const label = option.description ?? `Variant ${i + 1}`;
|
|
340
|
+
const rendered = style === "table" ? renderOptionsTableFromArray(uniqueFields) : renderOptionsListFromArray(uniqueFields);
|
|
341
|
+
sections.push(`**${label}:**\n\n${rendered}`);
|
|
342
|
+
}
|
|
343
|
+
return sections.join("\n\n");
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Render discriminatedUnion options as markdown with variant grouping
|
|
347
|
+
*/
|
|
348
|
+
function renderDiscriminatedUnionOptionsMarkdown(extracted, style = "table") {
|
|
349
|
+
const discriminator = extracted.discriminator;
|
|
350
|
+
const variants = extracted.variants ?? [];
|
|
351
|
+
if (!discriminator || variants.length === 0) return "";
|
|
352
|
+
const sections = [];
|
|
353
|
+
const allFieldNames = /* @__PURE__ */ new Set();
|
|
354
|
+
for (const variant of variants) for (const field of variant.fields) allFieldNames.add(field.name);
|
|
355
|
+
const commonFieldNames = /* @__PURE__ */ new Set();
|
|
356
|
+
for (const fieldName of allFieldNames) {
|
|
357
|
+
if (fieldName === discriminator) continue;
|
|
358
|
+
if (variants.every((v) => v.fields.some((f) => f.name === fieldName))) commonFieldNames.add(fieldName);
|
|
359
|
+
}
|
|
360
|
+
const discriminatorField = extracted.fields.find((f) => f.name === discriminator);
|
|
361
|
+
const variantValues = variants.map((v) => v.discriminatorValue).join("\\|");
|
|
362
|
+
const topFields = [];
|
|
363
|
+
if (discriminatorField) topFields.push({
|
|
364
|
+
...discriminatorField,
|
|
365
|
+
placeholder: variantValues
|
|
366
|
+
});
|
|
367
|
+
for (const fieldName of commonFieldNames) {
|
|
368
|
+
const field = extracted.fields.find((f) => f.name === fieldName);
|
|
369
|
+
if (field && !field.positional) topFields.push(field);
|
|
370
|
+
}
|
|
371
|
+
if (topFields.length > 0) sections.push(style === "table" ? renderOptionsTableFromArray(topFields) : renderOptionsListFromArray(topFields));
|
|
372
|
+
for (const variant of variants) {
|
|
373
|
+
const uniqueFields = variant.fields.filter((f) => f.name !== discriminator && !commonFieldNames.has(f.name) && !f.positional);
|
|
374
|
+
if (uniqueFields.length === 0) continue;
|
|
375
|
+
const descSuffix = variant.description ? ` ${variant.description}` : "";
|
|
376
|
+
const label = `**When \`${discriminator}\` = \`${variant.discriminatorValue}\`:**${descSuffix}`;
|
|
377
|
+
const rendered = style === "table" ? renderOptionsTableFromArray(uniqueFields) : renderOptionsListFromArray(uniqueFields);
|
|
378
|
+
sections.push(`${label}\n\n${rendered}`);
|
|
379
|
+
}
|
|
380
|
+
return sections.join("\n\n");
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
301
383
|
* Render options from array as list
|
|
302
384
|
*/
|
|
303
385
|
function renderOptionsListFromArray(options) {
|
|
@@ -413,8 +495,13 @@ function wrapWithMarker(type, scope, content) {
|
|
|
413
495
|
return `${sectionStartMarker(type, scope)}\n${content}\n${sectionEndMarker(type, scope)}`;
|
|
414
496
|
}
|
|
415
497
|
/**
|
|
416
|
-
*
|
|
498
|
+
* Generate a "See Global Options" link for subcommand documentation.
|
|
499
|
+
* Returns null for root command or when no global options exist.
|
|
417
500
|
*/
|
|
501
|
+
function getGlobalOptionsLink(info) {
|
|
502
|
+
if (!info.hasGlobalOptions || info.commandPath === "") return null;
|
|
503
|
+
return `See [Global Options](${info.rootDocPath && info.filePath && info.filePath !== info.rootDocPath ? `${getRelativePath(info.filePath, info.rootDocPath)}#global-options` : "#global-options"}) for options available to all commands.`;
|
|
504
|
+
}
|
|
418
505
|
function createCommandRenderer(options = {}) {
|
|
419
506
|
const { headingLevel = 1, optionStyle = "table", generateAnchors = true, includeSubcommandDetails = true, renderDescription: customRenderDescription, renderUsage: customRenderUsage, renderArguments: customRenderArguments, renderOptions: customRenderOptions, renderSubcommands: customRenderSubcommands, renderNotes: customRenderNotes, renderFooter: customRenderFooter, renderExamples: customRenderExamples } = options;
|
|
420
507
|
return (info) => {
|
|
@@ -462,7 +549,11 @@ function createCommandRenderer(options = {}) {
|
|
|
462
549
|
const renderOpts = (opts, renderOpts) => {
|
|
463
550
|
const style = renderOpts?.style ?? optionStyle;
|
|
464
551
|
const withHeading = renderOpts?.withHeading ?? true;
|
|
465
|
-
const
|
|
552
|
+
const extracted = info.extracted;
|
|
553
|
+
let content;
|
|
554
|
+
if (extracted && (extracted.schemaType === "union" || extracted.schemaType === "xor") && extracted.unionOptions) content = renderUnionOptionsMarkdown(extracted, style);
|
|
555
|
+
else if (extracted && extracted.schemaType === "discriminatedUnion" && extracted.discriminator) content = renderDiscriminatedUnionOptionsMarkdown(extracted, style);
|
|
556
|
+
else content = style === "table" ? renderOptionsTableFromArray(opts) : renderOptionsListFromArray(opts);
|
|
466
557
|
return withHeading ? `**Options**\n\n${content}` : content;
|
|
467
558
|
};
|
|
468
559
|
const context = {
|
|
@@ -474,6 +565,10 @@ function createCommandRenderer(options = {}) {
|
|
|
474
565
|
const content = customRenderOptions ? customRenderOptions(context) : renderOpts(context.options);
|
|
475
566
|
if (content) sections.push(wrapWithMarker("options", scope, content));
|
|
476
567
|
}
|
|
568
|
+
{
|
|
569
|
+
const globalLink = getGlobalOptionsLink(info);
|
|
570
|
+
if (globalLink) sections.push(globalLink);
|
|
571
|
+
}
|
|
477
572
|
if (info.subCommands.length > 0) {
|
|
478
573
|
const effectiveAnchors = generateAnchors && includeSubcommandDetails;
|
|
479
574
|
const renderSubs = (subs, opts) => {
|
|
@@ -720,7 +815,7 @@ async function executeSingleExample(example, rootCommand, commandPath) {
|
|
|
720
815
|
collector.start();
|
|
721
816
|
let success = true;
|
|
722
817
|
try {
|
|
723
|
-
const { runCommand } = await import("../runner-
|
|
818
|
+
const { runCommand } = await import("../runner-D4ByDT5I.js").then((n) => n.r);
|
|
724
819
|
const result = await runCommand(rootCommand, argv);
|
|
725
820
|
success = result.success;
|
|
726
821
|
if (!result.success && result.error) console.error(result.error.message);
|
|
@@ -1124,7 +1219,7 @@ function resolveConfiguredCommandPaths(fileConfigRaw, allCommands, ignores) {
|
|
|
1124
1219
|
return {
|
|
1125
1220
|
fileConfig,
|
|
1126
1221
|
specifiedCommands,
|
|
1127
|
-
commandPaths: filterIgnoredCommands(expandCommandPaths(specifiedCommands, allCommands), ignores),
|
|
1222
|
+
commandPaths: filterIgnoredCommands(fileConfig.noExpand ? specifiedCommands.filter((p) => allCommands.has(p)) : expandCommandPaths(specifiedCommands, allCommands), ignores),
|
|
1128
1223
|
topLevelCommands: filterIgnoredCommands(resolveTopLevelCommands(specifiedCommands, allCommands), ignores)
|
|
1129
1224
|
};
|
|
1130
1225
|
}
|
|
@@ -1444,6 +1539,7 @@ function generateGlobalOptionsSection(config) {
|
|
|
1444
1539
|
const endMarker = globalOptionsEndMarker();
|
|
1445
1540
|
return [
|
|
1446
1541
|
startMarker,
|
|
1542
|
+
"<a id=\"global-options\"></a>",
|
|
1447
1543
|
renderArgsTable(config.args, config.options),
|
|
1448
1544
|
endMarker
|
|
1449
1545
|
].join("\n");
|
|
@@ -1470,7 +1566,7 @@ function normalizeDocPathForComparison(filePath) {
|
|
|
1470
1566
|
* Process global options marker in file content
|
|
1471
1567
|
* Returns result with updated content and any diffs
|
|
1472
1568
|
*/
|
|
1473
|
-
async function processGlobalOptionsMarker(existingContent, globalOptionsConfig, updateMode, formatter) {
|
|
1569
|
+
async function processGlobalOptionsMarker(existingContent, globalOptionsConfig, updateMode, formatter, autoInsertIfMissing) {
|
|
1474
1570
|
let content = existingContent;
|
|
1475
1571
|
const diffs = [];
|
|
1476
1572
|
let hasError = false;
|
|
@@ -1480,6 +1576,16 @@ async function processGlobalOptionsMarker(existingContent, globalOptionsConfig,
|
|
|
1480
1576
|
const generatedSection = await applyFormatter(generateGlobalOptionsSection(globalOptionsConfig), formatter);
|
|
1481
1577
|
const existingSection = extractMarkerSection(content, startMarker, endMarker);
|
|
1482
1578
|
if (!existingSection) {
|
|
1579
|
+
if (updateMode && autoInsertIfMissing) {
|
|
1580
|
+
content = content.trimEnd() + "\n\n" + generatedSection + "\n";
|
|
1581
|
+
wasUpdated = true;
|
|
1582
|
+
return {
|
|
1583
|
+
content,
|
|
1584
|
+
diffs,
|
|
1585
|
+
hasError,
|
|
1586
|
+
wasUpdated
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1483
1589
|
hasError = true;
|
|
1484
1590
|
diffs.push(`Global options marker not found in file. Expected markers:\n${startMarker}\n...\n${endMarker}`);
|
|
1485
1591
|
return {
|
|
@@ -1510,6 +1616,61 @@ async function processGlobalOptionsMarker(existingContent, globalOptionsConfig,
|
|
|
1510
1616
|
};
|
|
1511
1617
|
}
|
|
1512
1618
|
/**
|
|
1619
|
+
* Process a static content marker (root-header or root-footer).
|
|
1620
|
+
* Inserts/updates the marker section with the given content.
|
|
1621
|
+
*/
|
|
1622
|
+
async function processStaticMarker(existingContent, markerLabel, startMarker, endMarker, rawContent, updateMode, formatter, autoInsertIfMissing) {
|
|
1623
|
+
let content = existingContent;
|
|
1624
|
+
const diffs = [];
|
|
1625
|
+
let hasError = false;
|
|
1626
|
+
let wasUpdated = false;
|
|
1627
|
+
const generatedSection = [
|
|
1628
|
+
startMarker,
|
|
1629
|
+
await applyFormatter(rawContent, formatter),
|
|
1630
|
+
endMarker
|
|
1631
|
+
].join("\n");
|
|
1632
|
+
const existingSection = extractMarkerSection(content, startMarker, endMarker);
|
|
1633
|
+
if (!existingSection) {
|
|
1634
|
+
if (updateMode && autoInsertIfMissing) {
|
|
1635
|
+
content = content.trimEnd() + "\n\n" + generatedSection + "\n";
|
|
1636
|
+
wasUpdated = true;
|
|
1637
|
+
return {
|
|
1638
|
+
content,
|
|
1639
|
+
diffs,
|
|
1640
|
+
hasError,
|
|
1641
|
+
wasUpdated
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
hasError = true;
|
|
1645
|
+
diffs.push(`${markerLabel} marker not found in file. Expected markers:\n${startMarker}\n...\n${endMarker}`);
|
|
1646
|
+
return {
|
|
1647
|
+
content,
|
|
1648
|
+
diffs,
|
|
1649
|
+
hasError,
|
|
1650
|
+
wasUpdated
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
if (existingSection !== generatedSection) if (updateMode) {
|
|
1654
|
+
const updated = replaceMarkerSection(content, startMarker, endMarker, generatedSection);
|
|
1655
|
+
if (updated) {
|
|
1656
|
+
content = updated;
|
|
1657
|
+
wasUpdated = true;
|
|
1658
|
+
} else {
|
|
1659
|
+
hasError = true;
|
|
1660
|
+
diffs.push(`Failed to replace ${markerLabel} section`);
|
|
1661
|
+
}
|
|
1662
|
+
} else {
|
|
1663
|
+
hasError = true;
|
|
1664
|
+
diffs.push(formatDiff(existingSection, generatedSection));
|
|
1665
|
+
}
|
|
1666
|
+
return {
|
|
1667
|
+
content,
|
|
1668
|
+
diffs,
|
|
1669
|
+
hasError,
|
|
1670
|
+
wasUpdated
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1513
1674
|
* Process index marker in file content
|
|
1514
1675
|
* Returns result with updated content and any diffs.
|
|
1515
1676
|
* If the marker is not present in the file, the section is silently skipped.
|
|
@@ -1600,26 +1761,29 @@ function findTargetCommandsInFile(targetCommands, filePath, files, allCommands,
|
|
|
1600
1761
|
/**
|
|
1601
1762
|
* Generate a single command section (already contains section markers from renderer)
|
|
1602
1763
|
*/
|
|
1603
|
-
function generateCommandSection(cmdPath, allCommands, render, filePath, fileMap) {
|
|
1764
|
+
function generateCommandSection(cmdPath, allCommands, render, filePath, fileMap, rootDocPath, hasGlobalOptions) {
|
|
1604
1765
|
const info = allCommands.get(cmdPath);
|
|
1605
1766
|
if (!info) return null;
|
|
1606
|
-
|
|
1767
|
+
const enriched = {
|
|
1607
1768
|
...info,
|
|
1608
1769
|
filePath,
|
|
1609
|
-
fileMap
|
|
1610
|
-
|
|
1770
|
+
fileMap,
|
|
1771
|
+
rootDocPath
|
|
1772
|
+
};
|
|
1773
|
+
if (hasGlobalOptions !== void 0) enriched.hasGlobalOptions = hasGlobalOptions;
|
|
1774
|
+
return render(enriched);
|
|
1611
1775
|
}
|
|
1612
1776
|
/**
|
|
1613
1777
|
* Generate markdown for a file containing multiple commands
|
|
1614
1778
|
* Each command section is wrapped with markers for partial validation
|
|
1615
1779
|
*/
|
|
1616
|
-
function generateFileMarkdown(commandPaths, allCommands, render, filePath, fileMap, specifiedOrder, fileConfig) {
|
|
1780
|
+
function generateFileMarkdown(commandPaths, allCommands, render, filePath, fileMap, specifiedOrder, fileConfig, rootDocPath, hasGlobalOptions) {
|
|
1617
1781
|
const sections = [];
|
|
1618
1782
|
const header = fileConfig ? generateFileHeader(fileConfig) : null;
|
|
1619
1783
|
if (header) sections.push(header);
|
|
1620
1784
|
const sortedPaths = sortDepthFirst(commandPaths, specifiedOrder ?? []);
|
|
1621
1785
|
for (const cmdPath of sortedPaths) {
|
|
1622
|
-
const section = generateCommandSection(cmdPath, allCommands, render, filePath, fileMap);
|
|
1786
|
+
const section = generateCommandSection(cmdPath, allCommands, render, filePath, fileMap, rootDocPath, hasGlobalOptions);
|
|
1623
1787
|
if (section) sections.push(section);
|
|
1624
1788
|
}
|
|
1625
1789
|
return `${sections.join("\n")}\n`;
|
|
@@ -1648,16 +1812,72 @@ async function executeConfiguredExamples(allCommands, examplesConfig, rootComman
|
|
|
1648
1812
|
}
|
|
1649
1813
|
}
|
|
1650
1814
|
/**
|
|
1815
|
+
* Convert PathConfig to FileMapping with explicit command paths.
|
|
1816
|
+
* Uses noExpand to prevent subcommand expansion since paths are pre-resolved.
|
|
1817
|
+
*/
|
|
1818
|
+
function pathToFiles(pathConfig, allCommands) {
|
|
1819
|
+
if (typeof pathConfig === "string") return {
|
|
1820
|
+
files: { [pathConfig]: Array.from(allCommands.keys()) },
|
|
1821
|
+
rootDocPath: pathConfig
|
|
1822
|
+
};
|
|
1823
|
+
const { root, commands = {} } = pathConfig;
|
|
1824
|
+
const files = {};
|
|
1825
|
+
const assignedToOtherFiles = /* @__PURE__ */ new Set();
|
|
1826
|
+
const sortedEntries = Object.entries(commands).sort(([a], [b]) => b.split(" ").length - a.split(" ").length);
|
|
1827
|
+
for (const [cmdPath, filePath] of sortedEntries) {
|
|
1828
|
+
if (!files[filePath]) files[filePath] = {
|
|
1829
|
+
commands: [],
|
|
1830
|
+
noExpand: true
|
|
1831
|
+
};
|
|
1832
|
+
const fc = files[filePath];
|
|
1833
|
+
for (const existingPath of allCommands.keys()) if ((existingPath === cmdPath || existingPath.startsWith(cmdPath + " ")) && !assignedToOtherFiles.has(existingPath)) {
|
|
1834
|
+
fc.commands.push(existingPath);
|
|
1835
|
+
assignedToOtherFiles.add(existingPath);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
files[root] = {
|
|
1839
|
+
commands: Array.from(allCommands.keys()).filter((p) => !assignedToOtherFiles.has(p)),
|
|
1840
|
+
noExpand: true
|
|
1841
|
+
};
|
|
1842
|
+
return {
|
|
1843
|
+
files,
|
|
1844
|
+
rootDocPath: root
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
/**
|
|
1651
1848
|
* Generate documentation from command definition
|
|
1652
1849
|
*/
|
|
1653
1850
|
async function generateDoc(config) {
|
|
1654
|
-
const { command,
|
|
1851
|
+
const { command, ignores = [], format = {}, formatter, examples: examplesConfig, targetCommands, globalArgs } = config;
|
|
1852
|
+
const allCommands = await collectAllCommands(command);
|
|
1853
|
+
let files;
|
|
1854
|
+
let usingPathConfig = false;
|
|
1855
|
+
let resolvedRootDocPath;
|
|
1856
|
+
if (config.path !== void 0) {
|
|
1857
|
+
if (config.files !== void 0) throw new Error("Cannot specify both \"path\" and \"files\". Use one or the other.");
|
|
1858
|
+
const converted = pathToFiles(config.path, allCommands);
|
|
1859
|
+
files = converted.files;
|
|
1860
|
+
resolvedRootDocPath = converted.rootDocPath;
|
|
1861
|
+
usingPathConfig = true;
|
|
1862
|
+
} else if (config.files !== void 0) files = config.files;
|
|
1863
|
+
else throw new Error("Either \"path\" or \"files\" must be specified.");
|
|
1864
|
+
let rootDoc = config.rootDoc;
|
|
1865
|
+
if (!rootDoc && usingPathConfig && (globalArgs || config.rootInfo)) rootDoc = { path: resolvedRootDocPath };
|
|
1866
|
+
if (globalArgs && rootDoc && !rootDoc.globalOptions) {
|
|
1867
|
+
const optionFields = extractFields(globalArgs).fields.filter((f) => !f.positional);
|
|
1868
|
+
if (optionFields.length > 0) {
|
|
1869
|
+
const globalShape = Object.fromEntries(optionFields.map((f) => [f.name, f.schema]));
|
|
1870
|
+
rootDoc = {
|
|
1871
|
+
...rootDoc,
|
|
1872
|
+
globalOptions: globalShape
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1655
1876
|
const updateMode = isUpdateMode();
|
|
1656
|
-
if (rootDoc) {
|
|
1877
|
+
if (rootDoc && !usingPathConfig) {
|
|
1657
1878
|
const normalizedRootDocPath = normalizeDocPathForComparison(rootDoc.path);
|
|
1658
1879
|
if (Object.keys(files).some((filePath) => normalizeDocPathForComparison(filePath) === normalizedRootDocPath)) throw new Error(`rootDoc.path "${rootDoc.path}" must not also appear as a key in files.`);
|
|
1659
1880
|
}
|
|
1660
|
-
const allCommands = await collectAllCommands(command);
|
|
1661
1881
|
if (examplesConfig) await executeConfiguredExamples(allCommands, examplesConfig, command);
|
|
1662
1882
|
const hasTargetCommands = targetCommands !== void 0 && targetCommands.length > 0;
|
|
1663
1883
|
if (hasTargetCommands) {
|
|
@@ -1691,11 +1911,13 @@ async function generateDoc(config) {
|
|
|
1691
1911
|
headingLevel: adjustedHeadingLevel
|
|
1692
1912
|
});
|
|
1693
1913
|
const render = fileConfig.render ?? fileRenderer;
|
|
1694
|
-
|
|
1914
|
+
const isRootDocFile = usingPathConfig && rootDoc && normalizeDocPathForComparison(filePath) === normalizeDocPathForComparison(rootDoc.path);
|
|
1915
|
+
if (hasTargetCommands || isRootDocFile) {
|
|
1695
1916
|
let existingContent = readFile(filePath);
|
|
1696
1917
|
const sortedCommandPaths = sortDepthFirst(commandPaths, specifiedCommands);
|
|
1697
|
-
|
|
1698
|
-
|
|
1918
|
+
const effectiveTargetCommands = hasTargetCommands ? fileTargetCommands : commandPaths;
|
|
1919
|
+
for (const targetCommand of effectiveTargetCommands) {
|
|
1920
|
+
const rawSection = generateCommandSection(targetCommand, allCommands, render, filePath, fileMap, rootDoc?.path, globalOptionDefinitions.size > 0);
|
|
1699
1921
|
if (!rawSection) throw new Error(`Target command "${targetCommand}" not found in commands`);
|
|
1700
1922
|
const generatedSection = await applyFormatter(rawSection, formatter);
|
|
1701
1923
|
if (!existingContent) {
|
|
@@ -1744,7 +1966,7 @@ async function generateDoc(config) {
|
|
|
1744
1966
|
}
|
|
1745
1967
|
}
|
|
1746
1968
|
} else {
|
|
1747
|
-
const generatedMarkdown = await applyFormatter(generateFileMarkdown(commandPaths, allCommands, render, filePath, fileMap, specifiedCommands, fileConfig), formatter);
|
|
1969
|
+
const generatedMarkdown = await applyFormatter(generateFileMarkdown(commandPaths, allCommands, render, filePath, fileMap, specifiedCommands, fileConfig, rootDoc?.path, globalOptionDefinitions.size > 0), formatter);
|
|
1748
1970
|
const comparison = compareWithExisting(generatedMarkdown, filePath);
|
|
1749
1971
|
if (comparison.match) {} else if (updateMode) {
|
|
1750
1972
|
writeFile(filePath, generatedMarkdown);
|
|
@@ -1774,22 +1996,33 @@ async function generateDoc(config) {
|
|
|
1774
1996
|
} else {
|
|
1775
1997
|
let content = existingContent;
|
|
1776
1998
|
let markerUpdated = false;
|
|
1777
|
-
const
|
|
1999
|
+
const rootInfo = config.rootInfo;
|
|
2000
|
+
const rootDocFileConfig = { title: rootInfo?.title ?? command.name };
|
|
1778
2001
|
if (rootDoc.headingLevel !== void 0) rootDocFileConfig.headingLevel = rootDoc.headingLevel;
|
|
1779
|
-
|
|
2002
|
+
const rootDescription = rootInfo?.description ?? command.description;
|
|
2003
|
+
if (rootDescription !== void 0) rootDocFileConfig.description = rootDescription;
|
|
1780
2004
|
const headerResult = processFileHeader(content, rootDocFileConfig, updateMode);
|
|
1781
2005
|
content = headerResult.content;
|
|
1782
2006
|
if (headerResult.diff) rootDocDiffs.push(headerResult.diff);
|
|
1783
2007
|
if (headerResult.hasError) hasError = true;
|
|
1784
2008
|
if (headerResult.wasUpdated) markerUpdated = true;
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
rootDocDiffs.push(
|
|
2009
|
+
if (rootInfo?.header) {
|
|
2010
|
+
const headerMarkerResult = await processStaticMarker(content, "Root header", rootHeaderStartMarker(), rootHeaderEndMarker(), rootInfo.header, updateMode, formatter, usingPathConfig);
|
|
2011
|
+
content = headerMarkerResult.content;
|
|
2012
|
+
rootDocDiffs.push(...headerMarkerResult.diffs);
|
|
2013
|
+
if (headerMarkerResult.hasError) hasError = true;
|
|
2014
|
+
if (headerMarkerResult.wasUpdated) markerUpdated = true;
|
|
2015
|
+
}
|
|
2016
|
+
if (!usingPathConfig) {
|
|
2017
|
+
const unexpectedSectionPaths = Array.from(new Set(collectSectionMarkerPaths(content)));
|
|
2018
|
+
if (unexpectedSectionPaths.length > 0) {
|
|
2019
|
+
hasError = true;
|
|
2020
|
+
rootDocDiffs.push(`Found unexpected section markers in rootDoc: ${unexpectedSectionPaths.map((commandPath) => `"${formatCommandPath(commandPath)}"`).join(", ")}.`);
|
|
2021
|
+
}
|
|
1789
2022
|
}
|
|
1790
2023
|
const normalizedGlobalOptions = normalizeGlobalOptions(rootDoc.globalOptions);
|
|
1791
2024
|
if (normalizedGlobalOptions) {
|
|
1792
|
-
const globalOptionsResult = await processGlobalOptionsMarker(content, normalizedGlobalOptions, updateMode, formatter);
|
|
2025
|
+
const globalOptionsResult = await processGlobalOptionsMarker(content, normalizedGlobalOptions, updateMode, formatter, usingPathConfig);
|
|
1793
2026
|
content = globalOptionsResult.content;
|
|
1794
2027
|
rootDocDiffs.push(...globalOptionsResult.diffs);
|
|
1795
2028
|
if (globalOptionsResult.hasError) hasError = true;
|
|
@@ -1802,6 +2035,13 @@ async function generateDoc(config) {
|
|
|
1802
2035
|
rootDocDiffs.push(...indexResult.diffs);
|
|
1803
2036
|
if (indexResult.hasError) hasError = true;
|
|
1804
2037
|
if (indexResult.wasUpdated) markerUpdated = true;
|
|
2038
|
+
if (rootInfo?.footer) {
|
|
2039
|
+
const footerMarkerResult = await processStaticMarker(content, "Root footer", rootFooterStartMarker(), rootFooterEndMarker(), rootInfo.footer, updateMode, formatter, usingPathConfig);
|
|
2040
|
+
content = footerMarkerResult.content;
|
|
2041
|
+
rootDocDiffs.push(...footerMarkerResult.diffs);
|
|
2042
|
+
if (footerMarkerResult.hasError) hasError = true;
|
|
2043
|
+
if (footerMarkerResult.wasUpdated) markerUpdated = true;
|
|
2044
|
+
}
|
|
1805
2045
|
if (updateMode && markerUpdated) {
|
|
1806
2046
|
writeFile(rootDocFilePath, content);
|
|
1807
2047
|
if (rootDocStatus === "match") rootDocStatus = "updated";
|
|
@@ -1845,9 +2085,9 @@ async function assertDocMatch(config) {
|
|
|
1845
2085
|
function initDocFile(config, fileSystem) {
|
|
1846
2086
|
if (!isUpdateMode()) return;
|
|
1847
2087
|
if (typeof config === "string") deleteFile(config, fileSystem);
|
|
1848
|
-
else for (const filePath of Object.keys(config.files)) deleteFile(filePath, fileSystem);
|
|
2088
|
+
else if (config.files) for (const filePath of Object.keys(config.files)) deleteFile(filePath, fileSystem);
|
|
1849
2089
|
}
|
|
1850
2090
|
|
|
1851
2091
|
//#endregion
|
|
1852
|
-
export { GLOBAL_OPTIONS_MARKER_PREFIX, INDEX_MARKER_PREFIX, SECTION_MARKER_PREFIX, SECTION_TYPES, UPDATE_GOLDEN_ENV, assertDocMatch, buildCommandInfo, collectAllCommands, compareWithExisting, createCommandRenderer, defaultRenderers, executeExamples, formatDiff, generateDoc, globalOptionsEndMarker, globalOptionsStartMarker, indexEndMarker, indexStartMarker, initDocFile, renderArgsTable, renderArgumentsList, renderArgumentsListFromArray, renderArgumentsTable, renderArgumentsTableFromArray, renderCommandIndex, renderExamplesDefault, renderOptionsList, renderOptionsListFromArray, renderOptionsTable, renderOptionsTableFromArray, renderSubcommandsTable, renderSubcommandsTableFromArray, renderUsage, resolveLazyCommand, sectionEndMarker, sectionStartMarker, writeFile };
|
|
2092
|
+
export { GLOBAL_OPTIONS_MARKER_PREFIX, INDEX_MARKER_PREFIX, ROOT_FOOTER_MARKER_PREFIX, ROOT_HEADER_MARKER_PREFIX, SECTION_MARKER_PREFIX, SECTION_TYPES, UPDATE_GOLDEN_ENV, assertDocMatch, buildCommandInfo, collectAllCommands, compareWithExisting, createCommandRenderer, defaultRenderers, executeExamples, formatDiff, generateDoc, globalOptionsEndMarker, globalOptionsStartMarker, indexEndMarker, indexStartMarker, initDocFile, renderArgsTable, renderArgumentsList, renderArgumentsListFromArray, renderArgumentsTable, renderArgumentsTableFromArray, renderCommandIndex, renderExamplesDefault, renderOptionsList, renderOptionsListFromArray, renderOptionsTable, renderOptionsTableFromArray, renderSubcommandsTable, renderSubcommandsTableFromArray, renderUsage, resolveLazyCommand, rootFooterEndMarker, rootFooterStartMarker, rootHeaderEndMarker, rootHeaderStartMarker, sectionEndMarker, sectionStartMarker, writeFile };
|
|
1853
2093
|
//# sourceMappingURL=index.js.map
|