@redpanda-data/docs-extensions-and-macros 5.0.4 → 5.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/bin/doc-tools-mcp.js +30 -2
- package/bin/doc-tools.js +260 -51
- package/bin/mcp-tools/rpk-docs.js +109 -39
- package/extensions/version-fetcher/set-latest-version.js +0 -131
- package/package.json +2 -2
- package/tools/rpk-docs/DEPRECATION-SCANNING.md +192 -0
- package/tools/rpk-docs/extract-conditional-content.js +169 -0
- package/tools/rpk-docs/extract-overrides.js +566 -0
- package/tools/rpk-docs/generate-rpk-docs.js +2433 -0
- package/tools/rpk-docs/helpers/index.js +458 -0
- package/tools/rpk-docs/report-delta.js +479 -0
- package/tools/rpk-docs/rpk-docs-handler.js +1650 -0
- package/tools/rpk-docs/scan-deprecated-commands.js +295 -0
- package/tools/rpk-docs/templates/command.hbs +576 -0
- package/tools/rpk-docs/templates/content-item.hbs +106 -0
- package/tools/rpk-docs/templates/subsection.hbs +37 -0
- package/tools/rpk-docs/validate-output.js +414 -0
- package/tools/rpk-docs/validate-overrides.js +624 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Diff generator for rpk command documentation
|
|
5
|
+
* Compares two rpk command trees and generates a detailed diff report
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Deep equality check that handles object key ordering
|
|
10
|
+
* Objects with same keys in different order are considered equal
|
|
11
|
+
* @param {*} a - First value
|
|
12
|
+
* @param {*} b - Second value
|
|
13
|
+
* @returns {boolean} True if values are deeply equal
|
|
14
|
+
*/
|
|
15
|
+
function deepEqual(a, b) {
|
|
16
|
+
// Handle primitives and null/undefined
|
|
17
|
+
if (a === b) return true
|
|
18
|
+
if (a == null || b == null) return a === b
|
|
19
|
+
if (typeof a !== typeof b) return false
|
|
20
|
+
|
|
21
|
+
// Handle arrays
|
|
22
|
+
if (Array.isArray(a)) {
|
|
23
|
+
if (!Array.isArray(b) || a.length !== b.length) return false
|
|
24
|
+
return a.every((item, i) => deepEqual(item, b[i]))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Handle objects
|
|
28
|
+
if (typeof a === 'object') {
|
|
29
|
+
const keysA = Object.keys(a).sort()
|
|
30
|
+
const keysB = Object.keys(b).sort()
|
|
31
|
+
if (keysA.length !== keysB.length) return false
|
|
32
|
+
if (!keysA.every((key, i) => key === keysB[i])) return false
|
|
33
|
+
return keysA.every(key => deepEqual(a[key], b[key]))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Primitives that aren't strictly equal
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Flatten command tree into a map of path -> command
|
|
42
|
+
* @param {Object} node - Tree node
|
|
43
|
+
* @param {string} parentPath - Parent command path
|
|
44
|
+
* @returns {Map} Map of command path to command object
|
|
45
|
+
*/
|
|
46
|
+
function flattenToMap(node, parentPath = '') {
|
|
47
|
+
const result = new Map()
|
|
48
|
+
|
|
49
|
+
// Defensive check for missing or invalid node
|
|
50
|
+
if (!node || typeof node !== 'object') {
|
|
51
|
+
return result
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Validate node.name exists and is a non-empty string
|
|
55
|
+
const nodeName = node.name
|
|
56
|
+
if (typeof nodeName !== 'string' || nodeName.trim() === '') {
|
|
57
|
+
// Skip nodes without valid names but still process children
|
|
58
|
+
if (node.commands && Array.isArray(node.commands)) {
|
|
59
|
+
for (const child of node.commands) {
|
|
60
|
+
const childMap = flattenToMap(child, parentPath)
|
|
61
|
+
for (const [path, cmd] of childMap) {
|
|
62
|
+
result.set(path, cmd)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const currentPath = parentPath ? `${parentPath} ${nodeName}` : nodeName
|
|
70
|
+
result.set(currentPath, node)
|
|
71
|
+
|
|
72
|
+
if (node.commands && Array.isArray(node.commands)) {
|
|
73
|
+
for (const child of node.commands) {
|
|
74
|
+
const childMap = flattenToMap(child, currentPath)
|
|
75
|
+
for (const [path, cmd] of childMap) {
|
|
76
|
+
result.set(path, cmd)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return result
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get flags as a map of name -> flag
|
|
86
|
+
* @param {Object} command - Command object
|
|
87
|
+
* @returns {Map} Map of flag name to flag object
|
|
88
|
+
*/
|
|
89
|
+
function getFlagsMap(command) {
|
|
90
|
+
const flags = command.flags || []
|
|
91
|
+
return new Map(flags.map(f => [f.name, f]))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Compare two flags and find differences
|
|
96
|
+
* @param {Object} oldFlag - Old flag object
|
|
97
|
+
* @param {Object} newFlag - New flag object
|
|
98
|
+
* @returns {Object|null} Differences or null if identical
|
|
99
|
+
*/
|
|
100
|
+
function compareFlags(oldFlag, newFlag) {
|
|
101
|
+
// Defensive checks for missing flags
|
|
102
|
+
if (!oldFlag || !newFlag) {
|
|
103
|
+
return null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const changes = {}
|
|
107
|
+
|
|
108
|
+
if (oldFlag.type !== newFlag.type) {
|
|
109
|
+
changes.type = { old: oldFlag.type, new: newFlag.type }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!deepEqual(oldFlag.default, newFlag.default)) {
|
|
113
|
+
changes.default = { old: oldFlag.default, new: newFlag.default }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (oldFlag.description !== newFlag.description) {
|
|
117
|
+
changes.description = { old: oldFlag.description, new: newFlag.description }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (oldFlag.required !== newFlag.required) {
|
|
121
|
+
changes.required = { old: oldFlag.required, new: newFlag.required }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return Object.keys(changes).length > 0 ? changes : null
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generate diff between two rpk command trees
|
|
129
|
+
* @param {Object} oldTree - Old command tree
|
|
130
|
+
* @param {Object} newTree - New command tree
|
|
131
|
+
* @param {Object} options - Options
|
|
132
|
+
* @returns {Object} Diff report
|
|
133
|
+
*/
|
|
134
|
+
function generateRpkDiff(oldTree, newTree, options = {}) {
|
|
135
|
+
const { oldVersion = 'old', newVersion = 'new' } = options
|
|
136
|
+
|
|
137
|
+
const oldCommands = flattenToMap(oldTree)
|
|
138
|
+
const newCommands = flattenToMap(newTree)
|
|
139
|
+
|
|
140
|
+
const oldPaths = new Set(oldCommands.keys())
|
|
141
|
+
const newPaths = new Set(newCommands.keys())
|
|
142
|
+
|
|
143
|
+
// Find new commands
|
|
144
|
+
const newCommandPaths = [...newPaths].filter(p => !oldPaths.has(p))
|
|
145
|
+
const newCommandsDetails = newCommandPaths.map(path => {
|
|
146
|
+
const cmd = newCommands.get(path)
|
|
147
|
+
return {
|
|
148
|
+
path,
|
|
149
|
+
name: cmd.name,
|
|
150
|
+
description: cmd.description || '',
|
|
151
|
+
introducedInVersion: newVersion
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// Find removed commands
|
|
156
|
+
const removedCommandPaths = [...oldPaths].filter(p => !newPaths.has(p))
|
|
157
|
+
const removedCommandsDetails = removedCommandPaths.map(path => {
|
|
158
|
+
const cmd = oldCommands.get(path)
|
|
159
|
+
return {
|
|
160
|
+
path,
|
|
161
|
+
name: cmd.name,
|
|
162
|
+
description: cmd.description || '',
|
|
163
|
+
removedInVersion: newVersion
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
// Find flag changes in existing commands
|
|
168
|
+
const newFlags = []
|
|
169
|
+
const removedFlags = []
|
|
170
|
+
const changedDefaults = []
|
|
171
|
+
const descriptionChanges = []
|
|
172
|
+
|
|
173
|
+
for (const path of newPaths) {
|
|
174
|
+
if (!oldPaths.has(path)) continue // Skip new commands
|
|
175
|
+
|
|
176
|
+
const oldCmd = oldCommands.get(path)
|
|
177
|
+
const newCmd = newCommands.get(path)
|
|
178
|
+
|
|
179
|
+
const oldFlags = getFlagsMap(oldCmd)
|
|
180
|
+
const newFlagsMap = getFlagsMap(newCmd)
|
|
181
|
+
|
|
182
|
+
// Find new flags
|
|
183
|
+
for (const [flagName, flag] of newFlagsMap) {
|
|
184
|
+
if (!oldFlags.has(flagName)) {
|
|
185
|
+
newFlags.push({
|
|
186
|
+
commandPath: path,
|
|
187
|
+
flagName,
|
|
188
|
+
type: flag.type,
|
|
189
|
+
description: flag.description,
|
|
190
|
+
default: flag.default,
|
|
191
|
+
introducedInVersion: newVersion
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Find removed flags
|
|
197
|
+
for (const [flagName, flag] of oldFlags) {
|
|
198
|
+
if (!newFlagsMap.has(flagName)) {
|
|
199
|
+
removedFlags.push({
|
|
200
|
+
commandPath: path,
|
|
201
|
+
flagName,
|
|
202
|
+
type: flag.type,
|
|
203
|
+
description: flag.description,
|
|
204
|
+
removedInVersion: newVersion
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Find changed flags
|
|
210
|
+
for (const [flagName, newFlag] of newFlagsMap) {
|
|
211
|
+
if (!oldFlags.has(flagName)) continue
|
|
212
|
+
|
|
213
|
+
const oldFlag = oldFlags.get(flagName)
|
|
214
|
+
const changes = compareFlags(oldFlag, newFlag)
|
|
215
|
+
|
|
216
|
+
if (changes) {
|
|
217
|
+
if (changes.default) {
|
|
218
|
+
changedDefaults.push({
|
|
219
|
+
commandPath: path,
|
|
220
|
+
flagName,
|
|
221
|
+
oldDefault: changes.default.old,
|
|
222
|
+
newDefault: changes.default.new
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Check command description changes
|
|
229
|
+
if (oldCmd.description !== newCmd.description) {
|
|
230
|
+
descriptionChanges.push({
|
|
231
|
+
path,
|
|
232
|
+
type: 'command',
|
|
233
|
+
oldDescription: oldCmd.description,
|
|
234
|
+
newDescription: newCmd.description
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
comparison: {
|
|
241
|
+
oldVersion,
|
|
242
|
+
newVersion,
|
|
243
|
+
timestamp: new Date().toISOString()
|
|
244
|
+
},
|
|
245
|
+
summary: {
|
|
246
|
+
newCommands: newCommandsDetails.length,
|
|
247
|
+
removedCommands: removedCommandsDetails.length,
|
|
248
|
+
newFlags: newFlags.length,
|
|
249
|
+
removedFlags: removedFlags.length,
|
|
250
|
+
changedDefaults: changedDefaults.length,
|
|
251
|
+
descriptionChanges: descriptionChanges.length
|
|
252
|
+
},
|
|
253
|
+
details: {
|
|
254
|
+
newCommands: newCommandsDetails,
|
|
255
|
+
removedCommands: removedCommandsDetails,
|
|
256
|
+
newFlags,
|
|
257
|
+
removedFlags,
|
|
258
|
+
changedDefaults,
|
|
259
|
+
descriptionChanges
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Print a human-readable diff report to console
|
|
266
|
+
* @param {Object} diff - Diff object from generateRpkDiff
|
|
267
|
+
*/
|
|
268
|
+
function printDiffReport(diff) {
|
|
269
|
+
console.log('\n=== rpk Documentation Diff Report ===')
|
|
270
|
+
console.log(`Comparing ${diff.comparison.oldVersion} → ${diff.comparison.newVersion}`)
|
|
271
|
+
console.log(`Generated: ${diff.comparison.timestamp}\n`)
|
|
272
|
+
|
|
273
|
+
console.log('Summary:')
|
|
274
|
+
console.log(` New commands: ${diff.summary.newCommands}`)
|
|
275
|
+
console.log(` Deprecated commands: ${diff.summary.removedCommands}`)
|
|
276
|
+
console.log(` New flags: ${diff.summary.newFlags}`)
|
|
277
|
+
console.log(` Deprecated flags: ${diff.summary.removedFlags}`)
|
|
278
|
+
console.log(` Changed defaults: ${diff.summary.changedDefaults}`)
|
|
279
|
+
console.log(` Description changes: ${diff.summary.descriptionChanges}`)
|
|
280
|
+
|
|
281
|
+
if (diff.details.newCommands.length > 0) {
|
|
282
|
+
console.log('\nNew Commands:')
|
|
283
|
+
for (const cmd of diff.details.newCommands) {
|
|
284
|
+
console.log(` + ${cmd.path}`)
|
|
285
|
+
if (cmd.description) {
|
|
286
|
+
const shortDesc = cmd.description.split('\n')[0].substring(0, 60)
|
|
287
|
+
console.log(` ${shortDesc}${cmd.description.length > 60 ? '...' : ''}`)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (diff.details.removedCommands.length > 0) {
|
|
293
|
+
console.log('\nDeprecated Commands (no longer in command tree):')
|
|
294
|
+
for (const cmd of diff.details.removedCommands) {
|
|
295
|
+
console.log(` ⚠ ${cmd.path}`)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (diff.details.newFlags.length > 0) {
|
|
300
|
+
console.log('\nNew Flags:')
|
|
301
|
+
for (const flag of diff.details.newFlags) {
|
|
302
|
+
console.log(` + ${flag.commandPath} --${flag.flagName} (${flag.type})`)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (diff.details.removedFlags.length > 0) {
|
|
307
|
+
console.log('\nDeprecated Flags (no longer in command tree):')
|
|
308
|
+
for (const flag of diff.details.removedFlags) {
|
|
309
|
+
console.log(` ⚠ ${flag.commandPath} --${flag.flagName}`)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (diff.details.changedDefaults.length > 0) {
|
|
314
|
+
console.log('\nChanged Defaults:')
|
|
315
|
+
for (const change of diff.details.changedDefaults) {
|
|
316
|
+
console.log(` ~ ${change.commandPath} --${change.flagName}`)
|
|
317
|
+
console.log(` ${JSON.stringify(change.oldDefault)} → ${JSON.stringify(change.newDefault)}`)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
console.log('')
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Generate markdown summary for PR description
|
|
326
|
+
* @param {Object} diff - Diff object
|
|
327
|
+
* @returns {string} Markdown content
|
|
328
|
+
*/
|
|
329
|
+
function generateMarkdownSummary(diff) {
|
|
330
|
+
const lines = []
|
|
331
|
+
|
|
332
|
+
lines.push(`## rpk Documentation Changes`)
|
|
333
|
+
lines.push(``)
|
|
334
|
+
lines.push(`**Version:** ${diff.comparison.oldVersion} → ${diff.comparison.newVersion}`)
|
|
335
|
+
lines.push(``)
|
|
336
|
+
|
|
337
|
+
lines.push(`### Summary`)
|
|
338
|
+
lines.push(``)
|
|
339
|
+
lines.push(`| Category | Count |`)
|
|
340
|
+
lines.push(`|----------|-------|`)
|
|
341
|
+
lines.push(`| New commands | ${diff.summary.newCommands} |`)
|
|
342
|
+
lines.push(`| Deprecated commands | ${diff.summary.removedCommands} |`)
|
|
343
|
+
lines.push(`| New flags | ${diff.summary.newFlags} |`)
|
|
344
|
+
lines.push(`| Deprecated flags | ${diff.summary.removedFlags} |`)
|
|
345
|
+
lines.push(`| Changed defaults | ${diff.summary.changedDefaults} |`)
|
|
346
|
+
lines.push(``)
|
|
347
|
+
|
|
348
|
+
if (diff.details.newCommands.length > 0) {
|
|
349
|
+
lines.push(`### New Commands`)
|
|
350
|
+
lines.push(``)
|
|
351
|
+
for (const cmd of diff.details.newCommands) {
|
|
352
|
+
lines.push(`- \`${cmd.path}\``)
|
|
353
|
+
}
|
|
354
|
+
lines.push(``)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (diff.details.removedCommands.length > 0) {
|
|
358
|
+
lines.push(`### Deprecated Commands`)
|
|
359
|
+
lines.push(``)
|
|
360
|
+
lines.push(`> Commands no longer in the active command tree. These may still work but are deprecated.`)
|
|
361
|
+
lines.push(``)
|
|
362
|
+
for (const cmd of diff.details.removedCommands) {
|
|
363
|
+
lines.push(`- ~~\`${cmd.path}\`~~`)
|
|
364
|
+
}
|
|
365
|
+
lines.push(``)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (diff.details.newFlags.length > 0 && diff.details.newFlags.length <= 20) {
|
|
369
|
+
lines.push(`### New Flags`)
|
|
370
|
+
lines.push(``)
|
|
371
|
+
for (const flag of diff.details.newFlags) {
|
|
372
|
+
lines.push(`- \`${flag.commandPath}\`: \`--${flag.flagName}\` (${flag.type})`)
|
|
373
|
+
}
|
|
374
|
+
lines.push(``)
|
|
375
|
+
} else if (diff.details.newFlags.length > 20) {
|
|
376
|
+
lines.push(`### New Flags`)
|
|
377
|
+
lines.push(``)
|
|
378
|
+
lines.push(`${diff.details.newFlags.length} new flags added. See diff JSON for details.`)
|
|
379
|
+
lines.push(``)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return lines.join('\n')
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Convert command path to xref path
|
|
387
|
+
* @param {string} commandPath - Command path like "rpk cluster info"
|
|
388
|
+
* @returns {string} Xref path like "rpk-cluster/rpk-cluster-info.adoc"
|
|
389
|
+
*/
|
|
390
|
+
function commandPathToXref(commandPath) {
|
|
391
|
+
const parts = commandPath.split(' ')
|
|
392
|
+
if (parts.length === 1) {
|
|
393
|
+
return `rpk.adoc`
|
|
394
|
+
}
|
|
395
|
+
const dashified = commandPath.replace(/ /g, '-')
|
|
396
|
+
if (parts.length === 2) {
|
|
397
|
+
return `${dashified}.adoc`
|
|
398
|
+
}
|
|
399
|
+
// For deeper commands: rpk cluster info -> rpk-cluster/rpk-cluster-info.adoc
|
|
400
|
+
const parentDir = parts.slice(0, 2).join('-')
|
|
401
|
+
return `${parentDir}/${dashified}.adoc`
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Generate AsciiDoc content for what's-new file
|
|
406
|
+
* @param {Object} diff - Diff object from generateRpkDiff
|
|
407
|
+
* @param {Object} options - Options
|
|
408
|
+
* @param {string} options.version - Version string to display
|
|
409
|
+
* @returns {string} AsciiDoc content
|
|
410
|
+
*/
|
|
411
|
+
function generateWhatsNewSection(diff, options = {}) {
|
|
412
|
+
const lines = []
|
|
413
|
+
const version = options.version || diff.comparison.newVersion
|
|
414
|
+
|
|
415
|
+
// Check if there are any changes worth documenting
|
|
416
|
+
const hasNewCommands = diff.details.newCommands.length > 0
|
|
417
|
+
const hasNewFlags = diff.details.newFlags.length > 0
|
|
418
|
+
const hasChangedDefaults = diff.details.changedDefaults.length > 0
|
|
419
|
+
|
|
420
|
+
if (!hasNewCommands && !hasNewFlags && !hasChangedDefaults) {
|
|
421
|
+
return '' // No changes to document
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
lines.push(`== Redpanda CLI`)
|
|
425
|
+
lines.push(``)
|
|
426
|
+
|
|
427
|
+
if (hasNewCommands) {
|
|
428
|
+
lines.push(`=== New commands`)
|
|
429
|
+
lines.push(``)
|
|
430
|
+
for (const cmd of diff.details.newCommands) {
|
|
431
|
+
const xrefPath = commandPathToXref(cmd.path)
|
|
432
|
+
const desc = cmd.description ? ` - ${cmd.description}` : ''
|
|
433
|
+
lines.push(`* xref:reference:rpk/${xrefPath}[\`${cmd.path}\`]${desc}`)
|
|
434
|
+
}
|
|
435
|
+
lines.push(``)
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (hasNewFlags) {
|
|
439
|
+
lines.push(`=== New flags`)
|
|
440
|
+
lines.push(``)
|
|
441
|
+
// Group flags by command
|
|
442
|
+
const flagsByCommand = {}
|
|
443
|
+
for (const flag of diff.details.newFlags) {
|
|
444
|
+
if (!flagsByCommand[flag.commandPath]) {
|
|
445
|
+
flagsByCommand[flag.commandPath] = []
|
|
446
|
+
}
|
|
447
|
+
flagsByCommand[flag.commandPath].push(flag)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
for (const [cmdPath, flags] of Object.entries(flagsByCommand)) {
|
|
451
|
+
const xrefPath = commandPathToXref(cmdPath)
|
|
452
|
+
const flagList = flags.map(f => `\`--${f.flagName}\``).join(', ')
|
|
453
|
+
lines.push(`* xref:reference:rpk/${xrefPath}[\`${cmdPath}\`]: Added ${flagList}`)
|
|
454
|
+
}
|
|
455
|
+
lines.push(``)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (hasChangedDefaults) {
|
|
459
|
+
lines.push(`=== Changed defaults`)
|
|
460
|
+
lines.push(``)
|
|
461
|
+
for (const change of diff.details.changedDefaults) {
|
|
462
|
+
const xrefPath = commandPathToXref(change.commandPath)
|
|
463
|
+
lines.push(`* xref:reference:rpk/${xrefPath}[\`${change.commandPath}\`]: \`--${change.flagName}\` default changed from \`${change.oldDefault}\` to \`${change.newDefault}\``)
|
|
464
|
+
}
|
|
465
|
+
lines.push(``)
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return lines.join('\n')
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
module.exports = {
|
|
472
|
+
generateRpkDiff,
|
|
473
|
+
printDiffReport,
|
|
474
|
+
generateMarkdownSummary,
|
|
475
|
+
generateWhatsNewSection,
|
|
476
|
+
flattenToMap,
|
|
477
|
+
getFlagsMap,
|
|
478
|
+
compareFlags
|
|
479
|
+
}
|