politty 0.3.3 → 0.4.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/docs/index.cjs +201 -197
- package/dist/docs/index.cjs.map +1 -1
- package/dist/docs/index.d.cts +17 -9
- package/dist/docs/index.d.cts.map +1 -1
- package/dist/docs/index.d.ts +17 -9
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +198 -195
- package/dist/docs/index.js.map +1 -1
- package/package.json +6 -6
package/dist/docs/index.cjs
CHANGED
|
@@ -8,6 +8,77 @@ node_fs = require_subcommand_router.__toESM(node_fs);
|
|
|
8
8
|
let node_path = require("node:path");
|
|
9
9
|
node_path = require_subcommand_router.__toESM(node_path);
|
|
10
10
|
|
|
11
|
+
//#region src/docs/types.ts
|
|
12
|
+
/**
|
|
13
|
+
* Environment variable name for update mode
|
|
14
|
+
*/
|
|
15
|
+
const UPDATE_GOLDEN_ENV = "POLITTY_DOCS_UPDATE";
|
|
16
|
+
/**
|
|
17
|
+
* All section types in rendering order
|
|
18
|
+
*/
|
|
19
|
+
const SECTION_TYPES = [
|
|
20
|
+
"heading",
|
|
21
|
+
"description",
|
|
22
|
+
"usage",
|
|
23
|
+
"arguments",
|
|
24
|
+
"options",
|
|
25
|
+
"subcommands",
|
|
26
|
+
"examples",
|
|
27
|
+
"notes"
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Marker prefix for command section markers in generated documentation
|
|
31
|
+
* Format: <!-- politty:command:<scope>:<type>:start --> ... <!-- politty:command:<scope>:<type>:end -->
|
|
32
|
+
*/
|
|
33
|
+
const SECTION_MARKER_PREFIX = "politty:command";
|
|
34
|
+
/**
|
|
35
|
+
* Generate start marker for a command section
|
|
36
|
+
*/
|
|
37
|
+
function sectionStartMarker(type, scope) {
|
|
38
|
+
return `<!-- ${SECTION_MARKER_PREFIX}:${scope}:${type}:start -->`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate end marker for a command section
|
|
42
|
+
*/
|
|
43
|
+
function sectionEndMarker(type, scope) {
|
|
44
|
+
return `<!-- ${SECTION_MARKER_PREFIX}:${scope}:${type}:end -->`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Marker prefix for global options sections in generated documentation
|
|
48
|
+
* Format: <!-- politty:global-options:start --> ... <!-- politty:global-options:end -->
|
|
49
|
+
*/
|
|
50
|
+
const GLOBAL_OPTIONS_MARKER_PREFIX = "politty:global-options";
|
|
51
|
+
/**
|
|
52
|
+
* Generate start marker for a global options section
|
|
53
|
+
*/
|
|
54
|
+
function globalOptionsStartMarker() {
|
|
55
|
+
return `<!-- ${GLOBAL_OPTIONS_MARKER_PREFIX}:start -->`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Generate end marker for a global options section
|
|
59
|
+
*/
|
|
60
|
+
function globalOptionsEndMarker() {
|
|
61
|
+
return `<!-- ${GLOBAL_OPTIONS_MARKER_PREFIX}:end -->`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Marker prefix for index sections in generated documentation
|
|
65
|
+
* Format: <!-- politty:index:<scope>:start --> ... <!-- politty:index:<scope>:end -->
|
|
66
|
+
*/
|
|
67
|
+
const INDEX_MARKER_PREFIX = "politty:index";
|
|
68
|
+
/**
|
|
69
|
+
* Generate start marker for an index section
|
|
70
|
+
*/
|
|
71
|
+
function indexStartMarker(scope) {
|
|
72
|
+
return `<!-- ${INDEX_MARKER_PREFIX}:${scope}:start -->`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Generate end marker for an index section
|
|
76
|
+
*/
|
|
77
|
+
function indexEndMarker(scope) {
|
|
78
|
+
return `<!-- ${INDEX_MARKER_PREFIX}:${scope}:end -->`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
11
82
|
//#region src/docs/default-renderers.ts
|
|
12
83
|
/**
|
|
13
84
|
* Escape markdown special characters in table cells
|
|
@@ -69,15 +140,34 @@ function formatEnvInfo(env) {
|
|
|
69
140
|
return ` [env: ${(Array.isArray(env) ? env : [env]).join(", ")}]`;
|
|
70
141
|
}
|
|
71
142
|
/**
|
|
72
|
-
*
|
|
143
|
+
* Resolve placeholder for an option (uses kebab-case cliName)
|
|
144
|
+
*/
|
|
145
|
+
function resolvePlaceholder(opt) {
|
|
146
|
+
return opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Format option name for table display (e.g., `--dry-run` or `--port <PORT>`)
|
|
150
|
+
*/
|
|
151
|
+
function formatOptionName(opt) {
|
|
152
|
+
const placeholder = resolvePlaceholder(opt);
|
|
153
|
+
return opt.type === "boolean" ? `\`--${opt.cliName}\`` : `\`--${opt.cliName} <${placeholder}>\``;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Format option flags for list display (uses kebab-case cliName)
|
|
73
157
|
*/
|
|
74
158
|
function formatOptionFlags(opt) {
|
|
75
|
-
const
|
|
76
|
-
const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
|
|
159
|
+
const placeholder = resolvePlaceholder(opt);
|
|
77
160
|
const longFlag = opt.type === "boolean" ? `--${opt.cliName}` : `--${opt.cliName} <${placeholder}>`;
|
|
78
|
-
if (opt.alias)
|
|
79
|
-
|
|
80
|
-
|
|
161
|
+
if (opt.alias) return `\`-${opt.alias}\`, \`${longFlag}\``;
|
|
162
|
+
return `\`${longFlag}\``;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Format env variable names for table display
|
|
166
|
+
*/
|
|
167
|
+
function formatEnvNames(env) {
|
|
168
|
+
if (!env) return "-";
|
|
169
|
+
if (Array.isArray(env)) return env.map((e) => `\`${e}\``).join(", ");
|
|
170
|
+
return `\`${env}\``;
|
|
81
171
|
}
|
|
82
172
|
/**
|
|
83
173
|
* Render options as markdown table
|
|
@@ -105,14 +195,13 @@ function renderOptionsTable(info) {
|
|
|
105
195
|
lines.push("|--------|-------|-------------|----------|---------|");
|
|
106
196
|
}
|
|
107
197
|
for (const opt of info.options) {
|
|
108
|
-
const
|
|
109
|
-
const optionName = opt.type === "boolean" ? `\`--${opt.cliName}\`` : `\`--${opt.cliName} <${placeholder}>\``;
|
|
198
|
+
const optionName = formatOptionName(opt);
|
|
110
199
|
const alias = opt.alias ? `\`-${opt.alias}\`` : "-";
|
|
111
200
|
const desc = escapeTableCell$2(opt.description ?? "");
|
|
112
201
|
const required = opt.required ? "Yes" : "No";
|
|
113
202
|
const defaultVal = formatDefaultValue$1(opt.defaultValue);
|
|
114
203
|
if (hasEnv) {
|
|
115
|
-
const envNames =
|
|
204
|
+
const envNames = formatEnvNames(opt.env);
|
|
116
205
|
lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} | ${envNames} |`);
|
|
117
206
|
} else lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} |`);
|
|
118
207
|
}
|
|
@@ -199,14 +288,13 @@ function renderOptionsTableFromArray(options) {
|
|
|
199
288
|
lines.push("|--------|-------|-------------|----------|---------|");
|
|
200
289
|
}
|
|
201
290
|
for (const opt of options) {
|
|
202
|
-
const
|
|
203
|
-
const optionName = opt.type === "boolean" ? `\`--${opt.cliName}\`` : `\`--${opt.cliName} <${placeholder}>\``;
|
|
291
|
+
const optionName = formatOptionName(opt);
|
|
204
292
|
const alias = opt.alias ? `\`-${opt.alias}\`` : "-";
|
|
205
293
|
const desc = escapeTableCell$2(opt.description ?? "");
|
|
206
294
|
const required = opt.required ? "Yes" : "No";
|
|
207
295
|
const defaultVal = formatDefaultValue$1(opt.defaultValue);
|
|
208
296
|
if (hasEnv) {
|
|
209
|
-
const envNames =
|
|
297
|
+
const envNames = formatEnvNames(opt.env);
|
|
210
298
|
lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} | ${envNames} |`);
|
|
211
299
|
} else lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} |`);
|
|
212
300
|
}
|
|
@@ -322,17 +410,23 @@ function renderExamplesDefault(examples, results, opts) {
|
|
|
322
410
|
return lines.join("\n");
|
|
323
411
|
}
|
|
324
412
|
/**
|
|
413
|
+
* Wrap content with section markers
|
|
414
|
+
*/
|
|
415
|
+
function wrapWithMarker(type, scope, content) {
|
|
416
|
+
return `${sectionStartMarker(type, scope)}\n${content}\n${sectionEndMarker(type, scope)}`;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
325
419
|
* Create command renderer with options
|
|
326
420
|
*/
|
|
327
421
|
function createCommandRenderer(options = {}) {
|
|
328
422
|
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;
|
|
329
423
|
return (info) => {
|
|
330
|
-
const
|
|
424
|
+
const sections = [];
|
|
425
|
+
const scope = info.commandPath;
|
|
331
426
|
const effectiveLevel = Math.min(headingLevel + (info.depth - 1), 6);
|
|
332
427
|
const h = "#".repeat(effectiveLevel);
|
|
333
428
|
const title = info.commandPath || info.name;
|
|
334
|
-
|
|
335
|
-
lines.push("");
|
|
429
|
+
sections.push(wrapWithMarker("heading", scope, `${h} ${title}`));
|
|
336
430
|
if (info.description) {
|
|
337
431
|
const context = {
|
|
338
432
|
content: info.description,
|
|
@@ -340,10 +434,7 @@ function createCommandRenderer(options = {}) {
|
|
|
340
434
|
info
|
|
341
435
|
};
|
|
342
436
|
const content = customRenderDescription ? customRenderDescription(context) : context.content;
|
|
343
|
-
if (content)
|
|
344
|
-
lines.push(content);
|
|
345
|
-
lines.push("");
|
|
346
|
-
}
|
|
437
|
+
if (content) sections.push(wrapWithMarker("description", scope, content));
|
|
347
438
|
}
|
|
348
439
|
{
|
|
349
440
|
const context = {
|
|
@@ -352,10 +443,7 @@ function createCommandRenderer(options = {}) {
|
|
|
352
443
|
info
|
|
353
444
|
};
|
|
354
445
|
const content = customRenderUsage ? customRenderUsage(context) : context.content;
|
|
355
|
-
if (content)
|
|
356
|
-
lines.push(content);
|
|
357
|
-
lines.push("");
|
|
358
|
-
}
|
|
446
|
+
if (content) sections.push(wrapWithMarker("usage", scope, content));
|
|
359
447
|
}
|
|
360
448
|
if (info.positionalArgs.length > 0) {
|
|
361
449
|
const renderArgs = (args, opts) => {
|
|
@@ -371,10 +459,7 @@ function createCommandRenderer(options = {}) {
|
|
|
371
459
|
info
|
|
372
460
|
};
|
|
373
461
|
const content = customRenderArguments ? customRenderArguments(context) : renderArgs(context.args);
|
|
374
|
-
if (content)
|
|
375
|
-
lines.push(content);
|
|
376
|
-
lines.push("");
|
|
377
|
-
}
|
|
462
|
+
if (content) sections.push(wrapWithMarker("arguments", scope, content));
|
|
378
463
|
}
|
|
379
464
|
if (info.options.length > 0) {
|
|
380
465
|
const renderOpts = (opts, renderOpts) => {
|
|
@@ -390,10 +475,7 @@ function createCommandRenderer(options = {}) {
|
|
|
390
475
|
info
|
|
391
476
|
};
|
|
392
477
|
const content = customRenderOptions ? customRenderOptions(context) : renderOpts(context.options);
|
|
393
|
-
if (content)
|
|
394
|
-
lines.push(content);
|
|
395
|
-
lines.push("");
|
|
396
|
-
}
|
|
478
|
+
if (content) sections.push(wrapWithMarker("options", scope, content));
|
|
397
479
|
}
|
|
398
480
|
if (info.subCommands.length > 0) {
|
|
399
481
|
const effectiveAnchors = generateAnchors && includeSubcommandDetails;
|
|
@@ -410,10 +492,7 @@ function createCommandRenderer(options = {}) {
|
|
|
410
492
|
info
|
|
411
493
|
};
|
|
412
494
|
const content = customRenderSubcommands ? customRenderSubcommands(context) : renderSubs(context.subcommands);
|
|
413
|
-
if (content)
|
|
414
|
-
lines.push(content);
|
|
415
|
-
lines.push("");
|
|
416
|
-
}
|
|
495
|
+
if (content) sections.push(wrapWithMarker("subcommands", scope, content));
|
|
417
496
|
}
|
|
418
497
|
if (info.examples && info.examples.length > 0) {
|
|
419
498
|
const renderEx = (examples, results, opts) => {
|
|
@@ -432,10 +511,7 @@ function createCommandRenderer(options = {}) {
|
|
|
432
511
|
info
|
|
433
512
|
};
|
|
434
513
|
const content = customRenderExamples ? customRenderExamples(context) : renderEx(context.examples, context.results);
|
|
435
|
-
if (content)
|
|
436
|
-
lines.push(content);
|
|
437
|
-
lines.push("");
|
|
438
|
-
}
|
|
514
|
+
if (content) sections.push(wrapWithMarker("examples", scope, content));
|
|
439
515
|
}
|
|
440
516
|
if (info.notes) {
|
|
441
517
|
const context = {
|
|
@@ -444,10 +520,7 @@ function createCommandRenderer(options = {}) {
|
|
|
444
520
|
info
|
|
445
521
|
};
|
|
446
522
|
const content = customRenderNotes ? customRenderNotes(context) : context.content;
|
|
447
|
-
if (content)
|
|
448
|
-
lines.push(content);
|
|
449
|
-
lines.push("");
|
|
450
|
-
}
|
|
523
|
+
if (content) sections.push(wrapWithMarker("notes", scope, content));
|
|
451
524
|
}
|
|
452
525
|
{
|
|
453
526
|
const context = {
|
|
@@ -456,14 +529,9 @@ function createCommandRenderer(options = {}) {
|
|
|
456
529
|
info
|
|
457
530
|
};
|
|
458
531
|
const content = customRenderFooter ? customRenderFooter(context) : context.content;
|
|
459
|
-
if (content)
|
|
460
|
-
lines.push(content);
|
|
461
|
-
lines.push("");
|
|
462
|
-
}
|
|
532
|
+
if (content) sections.push(content);
|
|
463
533
|
}
|
|
464
|
-
|
|
465
|
-
lines.push("");
|
|
466
|
-
return lines.join("\n");
|
|
534
|
+
return sections.join("\n\n") + "\n";
|
|
467
535
|
};
|
|
468
536
|
}
|
|
469
537
|
/**
|
|
@@ -936,64 +1004,6 @@ async function renderCommandIndex(command, categories, options) {
|
|
|
936
1004
|
return sections.join("\n\n");
|
|
937
1005
|
}
|
|
938
1006
|
|
|
939
|
-
//#endregion
|
|
940
|
-
//#region src/docs/types.ts
|
|
941
|
-
/**
|
|
942
|
-
* Environment variable name for update mode
|
|
943
|
-
*/
|
|
944
|
-
const UPDATE_GOLDEN_ENV = "POLITTY_DOCS_UPDATE";
|
|
945
|
-
/**
|
|
946
|
-
* Marker prefix for command sections in generated documentation
|
|
947
|
-
* Format: <!-- politty:command:<path>:start --> ... <!-- politty:command:<path>:end -->
|
|
948
|
-
*/
|
|
949
|
-
const COMMAND_MARKER_PREFIX = "politty:command";
|
|
950
|
-
/**
|
|
951
|
-
* Generate start marker for a command section
|
|
952
|
-
*/
|
|
953
|
-
function commandStartMarker(commandPath) {
|
|
954
|
-
return `<!-- ${COMMAND_MARKER_PREFIX}:${commandPath}:start -->`;
|
|
955
|
-
}
|
|
956
|
-
/**
|
|
957
|
-
* Generate end marker for a command section
|
|
958
|
-
*/
|
|
959
|
-
function commandEndMarker(commandPath) {
|
|
960
|
-
return `<!-- ${COMMAND_MARKER_PREFIX}:${commandPath}:end -->`;
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Marker prefix for global options sections in generated documentation
|
|
964
|
-
* Format: <!-- politty:global-options:start --> ... <!-- politty:global-options:end -->
|
|
965
|
-
*/
|
|
966
|
-
const GLOBAL_OPTIONS_MARKER_PREFIX = "politty:global-options";
|
|
967
|
-
/**
|
|
968
|
-
* Generate start marker for a global options section
|
|
969
|
-
*/
|
|
970
|
-
function globalOptionsStartMarker() {
|
|
971
|
-
return `<!-- ${GLOBAL_OPTIONS_MARKER_PREFIX}:start -->`;
|
|
972
|
-
}
|
|
973
|
-
/**
|
|
974
|
-
* Generate end marker for a global options section
|
|
975
|
-
*/
|
|
976
|
-
function globalOptionsEndMarker() {
|
|
977
|
-
return `<!-- ${GLOBAL_OPTIONS_MARKER_PREFIX}:end -->`;
|
|
978
|
-
}
|
|
979
|
-
/**
|
|
980
|
-
* Marker prefix for index sections in generated documentation
|
|
981
|
-
* Format: <!-- politty:index:start --> ... <!-- politty:index:end -->
|
|
982
|
-
*/
|
|
983
|
-
const INDEX_MARKER_PREFIX = "politty:index";
|
|
984
|
-
/**
|
|
985
|
-
* Generate start marker for an index section
|
|
986
|
-
*/
|
|
987
|
-
function indexStartMarker() {
|
|
988
|
-
return `<!-- ${INDEX_MARKER_PREFIX}:start -->`;
|
|
989
|
-
}
|
|
990
|
-
/**
|
|
991
|
-
* Generate end marker for an index section
|
|
992
|
-
*/
|
|
993
|
-
function indexEndMarker() {
|
|
994
|
-
return `<!-- ${INDEX_MARKER_PREFIX}:end -->`;
|
|
995
|
-
}
|
|
996
|
-
|
|
997
1007
|
//#endregion
|
|
998
1008
|
//#region src/docs/golden-test.ts
|
|
999
1009
|
/**
|
|
@@ -1084,16 +1094,8 @@ function matchesIgnorePattern(path, ignorePattern) {
|
|
|
1084
1094
|
*/
|
|
1085
1095
|
function expandCommandPaths(commandPaths, allCommands) {
|
|
1086
1096
|
const expanded = /* @__PURE__ */ new Set();
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
for (const match of matches) {
|
|
1090
|
-
expanded.add(match);
|
|
1091
|
-
for (const path of allCommands.keys()) if (isSubcommandOf(path, match)) expanded.add(path);
|
|
1092
|
-
}
|
|
1093
|
-
} else {
|
|
1094
|
-
if (allCommands.has(cmdPath)) expanded.add(cmdPath);
|
|
1095
|
-
for (const path of allCommands.keys()) if (isSubcommandOf(path, cmdPath)) expanded.add(path);
|
|
1096
|
-
}
|
|
1097
|
+
const resolved = commandPaths.flatMap((cmdPath) => containsWildcard(cmdPath) ? expandWildcardPattern(cmdPath, allCommands) : [cmdPath]);
|
|
1098
|
+
for (const cmdPath of resolved) for (const existingPath of allCommands.keys()) if (isSubcommandOf(existingPath, cmdPath)) expanded.add(existingPath);
|
|
1097
1099
|
return Array.from(expanded);
|
|
1098
1100
|
}
|
|
1099
1101
|
/**
|
|
@@ -1236,55 +1238,52 @@ function processFileHeader(existingContent, fileConfig, updateMode) {
|
|
|
1236
1238
|
wasUpdated: true
|
|
1237
1239
|
};
|
|
1238
1240
|
}
|
|
1241
|
+
function formatCommandPath(commandPath) {
|
|
1242
|
+
return commandPath === "" ? "<root>" : commandPath;
|
|
1243
|
+
}
|
|
1239
1244
|
/**
|
|
1240
|
-
* Extract a
|
|
1241
|
-
* Returns the content between start and end markers (including markers)
|
|
1245
|
+
* Extract a section marker's content from document content.
|
|
1246
|
+
* Returns the content between start and end markers (including markers).
|
|
1242
1247
|
*/
|
|
1243
|
-
function
|
|
1244
|
-
|
|
1245
|
-
const endMarker = commandEndMarker(commandPath);
|
|
1246
|
-
const startIndex = content.indexOf(startMarker);
|
|
1247
|
-
if (startIndex === -1) return null;
|
|
1248
|
-
const endIndex = content.indexOf(endMarker, startIndex);
|
|
1249
|
-
if (endIndex === -1) return null;
|
|
1250
|
-
return content.slice(startIndex, endIndex + endMarker.length);
|
|
1248
|
+
function extractSectionMarker(content, type, scope) {
|
|
1249
|
+
return extractMarkerSection(content, sectionStartMarker(type, scope), sectionEndMarker(type, scope));
|
|
1251
1250
|
}
|
|
1252
1251
|
/**
|
|
1253
|
-
*
|
|
1252
|
+
* Replace a section marker's content in document content.
|
|
1253
|
+
* Returns updated content, or null if marker not found.
|
|
1254
1254
|
*/
|
|
1255
|
-
function
|
|
1256
|
-
|
|
1257
|
-
const paths = [];
|
|
1258
|
-
for (const match of content.matchAll(markerPattern)) paths.push(match[1] ?? "");
|
|
1259
|
-
return paths;
|
|
1255
|
+
function replaceSectionMarker(content, type, scope, newContent) {
|
|
1256
|
+
return replaceMarkerSection(content, sectionStartMarker(type, scope), sectionEndMarker(type, scope), newContent);
|
|
1260
1257
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1258
|
+
/**
|
|
1259
|
+
* Collect all section types that have markers for a given command path.
|
|
1260
|
+
*/
|
|
1261
|
+
function collectSectionMarkers(content, commandPath) {
|
|
1262
|
+
const found = [];
|
|
1263
|
+
for (const type of SECTION_TYPES) if (extractSectionMarker(content, type, commandPath) !== null) found.push(type);
|
|
1264
|
+
return found;
|
|
1263
1265
|
}
|
|
1264
1266
|
/**
|
|
1265
|
-
*
|
|
1266
|
-
* Returns the updated content with the new section
|
|
1267
|
+
* Collect all command paths that have any section markers in the content.
|
|
1267
1268
|
*/
|
|
1268
|
-
function
|
|
1269
|
-
const
|
|
1270
|
-
const
|
|
1271
|
-
const
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
if (endIndex === -1) return null;
|
|
1275
|
-
return content.slice(0, startIndex) + newSection + content.slice(endIndex + endMarker.length);
|
|
1269
|
+
function collectSectionMarkerPaths(content) {
|
|
1270
|
+
const sectionTypes = SECTION_TYPES.join("|");
|
|
1271
|
+
const markerPattern = new RegExp(`<!--\\s*politty:command:(.*?):(?:${sectionTypes}):start\\s*-->`, "g");
|
|
1272
|
+
const paths = /* @__PURE__ */ new Set();
|
|
1273
|
+
for (const match of content.matchAll(markerPattern)) paths.add(match[1] ?? "");
|
|
1274
|
+
return Array.from(paths);
|
|
1276
1275
|
}
|
|
1277
1276
|
/**
|
|
1278
|
-
* Insert
|
|
1279
|
-
*
|
|
1277
|
+
* Insert command section markers at the correct position based on specified order.
|
|
1278
|
+
* Uses the heading marker of adjacent commands as reference points.
|
|
1280
1279
|
*/
|
|
1281
|
-
function
|
|
1280
|
+
function insertCommandSections(content, commandPath, newSection, specifiedOrder) {
|
|
1282
1281
|
const targetIndex = specifiedOrder.indexOf(commandPath);
|
|
1283
1282
|
if (targetIndex === -1) return content.trimEnd() + "\n\n" + newSection + "\n";
|
|
1284
1283
|
for (let i = targetIndex + 1; i < specifiedOrder.length; i++) {
|
|
1285
1284
|
const nextCmd = specifiedOrder[i];
|
|
1286
1285
|
if (nextCmd === void 0) continue;
|
|
1287
|
-
const nextMarker =
|
|
1286
|
+
const nextMarker = sectionStartMarker("heading", nextCmd);
|
|
1288
1287
|
const nextIndex = content.indexOf(nextMarker);
|
|
1289
1288
|
if (nextIndex !== -1) {
|
|
1290
1289
|
let insertPos = nextIndex;
|
|
@@ -1296,11 +1295,15 @@ function insertCommandSection(content, commandPath, newSection, specifiedOrder)
|
|
|
1296
1295
|
for (let i = targetIndex - 1; i >= 0; i--) {
|
|
1297
1296
|
const prevCmd = specifiedOrder[i];
|
|
1298
1297
|
if (prevCmd === void 0) continue;
|
|
1299
|
-
const
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
const
|
|
1303
|
-
|
|
1298
|
+
const prevMarkers = collectSectionMarkers(content, prevCmd);
|
|
1299
|
+
if (prevMarkers.length > 0) {
|
|
1300
|
+
const lastType = prevMarkers[prevMarkers.length - 1];
|
|
1301
|
+
const prevEndMarker = sectionEndMarker(lastType, prevCmd);
|
|
1302
|
+
const prevEndIndex = content.indexOf(prevEndMarker);
|
|
1303
|
+
if (prevEndIndex !== -1) {
|
|
1304
|
+
const insertPos = prevEndIndex + prevEndMarker.length;
|
|
1305
|
+
return content.slice(0, insertPos) + "\n" + newSection + content.slice(insertPos);
|
|
1306
|
+
}
|
|
1304
1307
|
}
|
|
1305
1308
|
}
|
|
1306
1309
|
return content.trimEnd() + "\n" + newSection + "\n";
|
|
@@ -1451,9 +1454,9 @@ function generateGlobalOptionsSection(config) {
|
|
|
1451
1454
|
/**
|
|
1452
1455
|
* Generate index section content with markers
|
|
1453
1456
|
*/
|
|
1454
|
-
async function generateIndexSection(categories, command, options) {
|
|
1455
|
-
const startMarker = indexStartMarker();
|
|
1456
|
-
const endMarker = indexEndMarker();
|
|
1457
|
+
async function generateIndexSection(categories, command, scope, options) {
|
|
1458
|
+
const startMarker = indexStartMarker(scope);
|
|
1459
|
+
const endMarker = indexEndMarker(scope);
|
|
1457
1460
|
return [
|
|
1458
1461
|
startMarker,
|
|
1459
1462
|
await renderCommandIndex(command, categories, options),
|
|
@@ -1514,13 +1517,13 @@ async function processGlobalOptionsMarker(existingContent, globalOptionsConfig,
|
|
|
1514
1517
|
* Returns result with updated content and any diffs.
|
|
1515
1518
|
* If the marker is not present in the file, the section is silently skipped.
|
|
1516
1519
|
*/
|
|
1517
|
-
async function processIndexMarker(existingContent, categories, command, updateMode, formatter, indexOptions) {
|
|
1520
|
+
async function processIndexMarker(existingContent, categories, command, scope, updateMode, formatter, indexOptions) {
|
|
1518
1521
|
let content = existingContent;
|
|
1519
1522
|
const diffs = [];
|
|
1520
1523
|
let hasError = false;
|
|
1521
1524
|
let wasUpdated = false;
|
|
1522
|
-
const startMarker = indexStartMarker();
|
|
1523
|
-
const endMarker = indexEndMarker();
|
|
1525
|
+
const startMarker = indexStartMarker(scope);
|
|
1526
|
+
const endMarker = indexEndMarker(scope);
|
|
1524
1527
|
const hasStartMarker = content.includes(startMarker);
|
|
1525
1528
|
const hasEndMarker = content.includes(endMarker);
|
|
1526
1529
|
if (!hasStartMarker && !hasEndMarker) return {
|
|
@@ -1550,7 +1553,7 @@ async function processIndexMarker(existingContent, categories, command, updateMo
|
|
|
1550
1553
|
wasUpdated
|
|
1551
1554
|
};
|
|
1552
1555
|
}
|
|
1553
|
-
const generatedSection = await applyFormatter(await generateIndexSection(categories, command, indexOptions), formatter);
|
|
1556
|
+
const generatedSection = await applyFormatter(await generateIndexSection(categories, command, scope, indexOptions), formatter);
|
|
1554
1557
|
if (existingSection !== generatedSection) if (updateMode) {
|
|
1555
1558
|
const updated = replaceMarkerSection(content, startMarker, endMarker, generatedSection);
|
|
1556
1559
|
if (updated) {
|
|
@@ -1598,21 +1601,16 @@ function findTargetCommandsInFile(targetCommands, filePath, files, allCommands,
|
|
|
1598
1601
|
return Array.from(expandedTargets);
|
|
1599
1602
|
}
|
|
1600
1603
|
/**
|
|
1601
|
-
* Generate a single command section
|
|
1604
|
+
* Generate a single command section (already contains section markers from renderer)
|
|
1602
1605
|
*/
|
|
1603
1606
|
function generateCommandSection(cmdPath, allCommands, render, filePath, fileMap) {
|
|
1604
1607
|
const info = allCommands.get(cmdPath);
|
|
1605
1608
|
if (!info) return null;
|
|
1606
|
-
|
|
1609
|
+
return render({
|
|
1607
1610
|
...info,
|
|
1608
1611
|
filePath,
|
|
1609
1612
|
fileMap
|
|
1610
1613
|
});
|
|
1611
|
-
return [
|
|
1612
|
-
commandStartMarker(cmdPath),
|
|
1613
|
-
renderedSection,
|
|
1614
|
-
commandEndMarker(cmdPath)
|
|
1615
|
-
].join("\n");
|
|
1616
1614
|
}
|
|
1617
1615
|
/**
|
|
1618
1616
|
* Generate markdown for a file containing multiple commands
|
|
@@ -1701,12 +1699,13 @@ async function generateDoc(config) {
|
|
|
1701
1699
|
for (const targetCommand of fileTargetCommands) {
|
|
1702
1700
|
const rawSection = generateCommandSection(targetCommand, allCommands, render, filePath, fileMap);
|
|
1703
1701
|
if (!rawSection) throw new Error(`Target command "${targetCommand}" not found in commands`);
|
|
1704
|
-
const
|
|
1705
|
-
const generatedSection = await applyFormatter(header ? `${header}\n${rawSection}` : rawSection, formatter);
|
|
1702
|
+
const generatedSection = await applyFormatter(rawSection, formatter);
|
|
1706
1703
|
if (!existingContent) {
|
|
1707
1704
|
if (updateMode) {
|
|
1708
|
-
|
|
1709
|
-
|
|
1705
|
+
const header = targetCommand === "" && fileConfig ? generateFileHeader(fileConfig) : null;
|
|
1706
|
+
const fullContent = header ? `${header}\n${generatedSection}` : generatedSection;
|
|
1707
|
+
writeFile(filePath, fullContent);
|
|
1708
|
+
existingContent = fullContent;
|
|
1710
1709
|
fileStatus = "created";
|
|
1711
1710
|
} else {
|
|
1712
1711
|
hasError = true;
|
|
@@ -1715,32 +1714,35 @@ async function generateDoc(config) {
|
|
|
1715
1714
|
}
|
|
1716
1715
|
continue;
|
|
1717
1716
|
}
|
|
1718
|
-
const
|
|
1719
|
-
|
|
1720
|
-
if (!generatedSectionOnly) throw new Error(`Generated content does not contain section for command "${targetCommand}"`);
|
|
1721
|
-
if (!existingSection) {
|
|
1717
|
+
const existingMarkers = collectSectionMarkers(existingContent, targetCommand);
|
|
1718
|
+
if (existingMarkers.length === 0) {
|
|
1722
1719
|
if (updateMode) {
|
|
1723
|
-
existingContent =
|
|
1720
|
+
existingContent = insertCommandSections(existingContent, targetCommand, generatedSection, specifiedCommands);
|
|
1724
1721
|
writeFile(filePath, existingContent);
|
|
1725
1722
|
if (fileStatus !== "created") fileStatus = "updated";
|
|
1726
1723
|
} else {
|
|
1727
1724
|
hasError = true;
|
|
1728
1725
|
fileStatus = "diff";
|
|
1729
|
-
diffs.push(`Existing file does not contain section for command "${targetCommand}"`);
|
|
1726
|
+
diffs.push(`Existing file does not contain section markers for command "${targetCommand}"`);
|
|
1730
1727
|
}
|
|
1731
1728
|
continue;
|
|
1732
1729
|
}
|
|
1733
|
-
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1730
|
+
for (const sectionType of existingMarkers) {
|
|
1731
|
+
const existingSection = extractSectionMarker(existingContent, sectionType, targetCommand);
|
|
1732
|
+
const generatedSectionPart = extractSectionMarker(generatedSection, sectionType, targetCommand);
|
|
1733
|
+
if (!existingSection || !generatedSectionPart) continue;
|
|
1734
|
+
if (existingSection !== generatedSectionPart) if (updateMode) {
|
|
1735
|
+
const updated = replaceSectionMarker(existingContent, sectionType, targetCommand, generatedSectionPart);
|
|
1736
|
+
if (updated) {
|
|
1737
|
+
existingContent = updated;
|
|
1738
|
+
writeFile(filePath, existingContent);
|
|
1739
|
+
if (fileStatus !== "created") fileStatus = "updated";
|
|
1740
|
+
} else throw new Error(`Failed to replace ${sectionType} section for command "${targetCommand}"`);
|
|
1741
|
+
} else {
|
|
1742
|
+
hasError = true;
|
|
1743
|
+
fileStatus = "diff";
|
|
1744
|
+
diffs.push(formatDiff(existingSection, generatedSectionPart));
|
|
1745
|
+
}
|
|
1744
1746
|
}
|
|
1745
1747
|
}
|
|
1746
1748
|
} else {
|
|
@@ -1782,10 +1784,10 @@ async function generateDoc(config) {
|
|
|
1782
1784
|
if (headerResult.diff) rootDocDiffs.push(headerResult.diff);
|
|
1783
1785
|
if (headerResult.hasError) hasError = true;
|
|
1784
1786
|
if (headerResult.wasUpdated) markerUpdated = true;
|
|
1785
|
-
const
|
|
1786
|
-
if (
|
|
1787
|
+
const unexpectedSectionPaths = Array.from(new Set(collectSectionMarkerPaths(content)));
|
|
1788
|
+
if (unexpectedSectionPaths.length > 0) {
|
|
1787
1789
|
hasError = true;
|
|
1788
|
-
rootDocDiffs.push(`Found unexpected
|
|
1790
|
+
rootDocDiffs.push(`Found unexpected section markers in rootDoc: ${unexpectedSectionPaths.map((commandPath) => `"${formatCommandPath(commandPath)}"`).join(", ")}.`);
|
|
1789
1791
|
}
|
|
1790
1792
|
const normalizedGlobalOptions = normalizeGlobalOptions(rootDoc.globalOptions);
|
|
1791
1793
|
if (normalizedGlobalOptions) {
|
|
@@ -1796,7 +1798,8 @@ async function generateDoc(config) {
|
|
|
1796
1798
|
if (globalOptionsResult.wasUpdated) markerUpdated = true;
|
|
1797
1799
|
}
|
|
1798
1800
|
const derivedCategories = deriveIndexFromFiles(files, rootDocFilePath, allCommands, ignores);
|
|
1799
|
-
const
|
|
1801
|
+
const indexScope = node_path.relative(process.cwd(), rootDocFilePath);
|
|
1802
|
+
const indexResult = await processIndexMarker(content, derivedCategories, command, indexScope, updateMode, formatter, rootDoc.index);
|
|
1800
1803
|
content = indexResult.content;
|
|
1801
1804
|
rootDocDiffs.push(...indexResult.diffs);
|
|
1802
1805
|
if (indexResult.hasError) hasError = true;
|
|
@@ -1848,15 +1851,14 @@ function initDocFile(config, fileSystem) {
|
|
|
1848
1851
|
}
|
|
1849
1852
|
|
|
1850
1853
|
//#endregion
|
|
1851
|
-
exports.COMMAND_MARKER_PREFIX = COMMAND_MARKER_PREFIX;
|
|
1852
1854
|
exports.GLOBAL_OPTIONS_MARKER_PREFIX = GLOBAL_OPTIONS_MARKER_PREFIX;
|
|
1853
1855
|
exports.INDEX_MARKER_PREFIX = INDEX_MARKER_PREFIX;
|
|
1856
|
+
exports.SECTION_MARKER_PREFIX = SECTION_MARKER_PREFIX;
|
|
1857
|
+
exports.SECTION_TYPES = SECTION_TYPES;
|
|
1854
1858
|
exports.UPDATE_GOLDEN_ENV = UPDATE_GOLDEN_ENV;
|
|
1855
1859
|
exports.assertDocMatch = assertDocMatch;
|
|
1856
1860
|
exports.buildCommandInfo = buildCommandInfo;
|
|
1857
1861
|
exports.collectAllCommands = collectAllCommands;
|
|
1858
|
-
exports.commandEndMarker = commandEndMarker;
|
|
1859
|
-
exports.commandStartMarker = commandStartMarker;
|
|
1860
1862
|
exports.compareWithExisting = compareWithExisting;
|
|
1861
1863
|
exports.createCommandRenderer = createCommandRenderer;
|
|
1862
1864
|
exports.defaultRenderers = defaultRenderers;
|
|
@@ -1883,5 +1885,7 @@ exports.renderSubcommandsTable = renderSubcommandsTable;
|
|
|
1883
1885
|
exports.renderSubcommandsTableFromArray = renderSubcommandsTableFromArray;
|
|
1884
1886
|
exports.renderUsage = renderUsage;
|
|
1885
1887
|
exports.resolveLazyCommand = require_subcommand_router.resolveLazyCommand;
|
|
1888
|
+
exports.sectionEndMarker = sectionEndMarker;
|
|
1889
|
+
exports.sectionStartMarker = sectionStartMarker;
|
|
1886
1890
|
exports.writeFile = writeFile;
|
|
1887
1891
|
//# sourceMappingURL=index.cjs.map
|