@redpanda-data/docs-extensions-and-macros 5.2.0 → 5.2.2

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.js CHANGED
@@ -26,6 +26,7 @@ const {
26
26
  diffDirs,
27
27
  generatePropertyComparisonReport,
28
28
  updatePropertyOverridesWithVersion,
29
+ updatePropertiesJsonWithVersion,
29
30
  cleanupOldDiffs
30
31
  } = require('../cli-utils/diff-utils')
31
32
 
@@ -1002,6 +1003,12 @@ automation
1002
1003
 
1003
1004
  if (overridesPath && fs.existsSync(overridesPath)) {
1004
1005
  updatePropertyOverridesWithVersion(overridesPath, diffData, newTag)
1006
+ // The overrides were baked into the extracted JSON during Phase 1,
1007
+ // before the stamp above existed. Stamp the JSON too, so the
1008
+ // AsciiDoc generated in Phase 3 shows "Introduced in" for
1009
+ // properties new in this release instead of one release late.
1010
+ const extractedJsonPath = path.resolve(outputDir, 'attachments', `redpanda-properties-${newTag}.json`)
1011
+ updatePropertiesJsonWithVersion(extractedJsonPath, diffData, newTag)
1005
1012
  }
1006
1013
  }
1007
1014
  } catch (err) {
@@ -193,6 +193,88 @@ function updatePropertyOverridesWithVersion (overridesPath, diffData, newTag) {
193
193
  }
194
194
  }
195
195
 
196
+ /**
197
+ * Stamp version information for new properties directly into an extracted
198
+ * properties JSON file (redpanda-properties-<tag>.json).
199
+ *
200
+ * Overrides are baked into this JSON during extraction, which happens before
201
+ * updatePropertyOverridesWithVersion stamps new properties into the overrides
202
+ * file — so without this step the AsciiDoc rendered from the JSON misses the
203
+ * "Introduced in" line for properties added in the release being generated
204
+ * (it would only appear on the next release's run).
205
+ *
206
+ * @param {string} jsonPath - Path to the extracted properties JSON file
207
+ * @param {object} diffData - Diff data from property comparison
208
+ * @param {string} newTag - Version tag for new properties (e.g., "v26.1.13")
209
+ */
210
+ function updatePropertiesJsonWithVersion (jsonPath, diffData, newTag) {
211
+ try {
212
+ const newProperties = diffData.details?.newProperties || []
213
+ if (newProperties.length === 0) return
214
+ if (!fs.existsSync(jsonPath)) {
215
+ console.warn(`Warning: Cannot stamp versions: ${jsonPath} does not exist`)
216
+ return
217
+ }
218
+
219
+ // The stamp is a textual insertion, NOT a parse/re-serialize round-trip:
220
+ // JSON.stringify would corrupt values JavaScript numbers cannot represent
221
+ // (uint64 maxima like 18446744073709551615) and reformat floats (0.0 → 0)
222
+ // throughout the Python-generated file.
223
+ let raw = fs.readFileSync(jsonPath, 'utf8')
224
+ const indentUnit = (raw.match(/^([ \t]+)"/m) || [null, ' '])[1]
225
+
226
+ let stampedCount = 0
227
+ newProperties.forEach(prop => {
228
+ const updated = insertVersionIntoRawJson(raw, prop.name, newTag, indentUnit)
229
+ if (updated) {
230
+ raw = updated
231
+ stampedCount++
232
+ }
233
+ })
234
+
235
+ if (stampedCount > 0) {
236
+ JSON.parse(raw) // validate the surgical edits before touching the file
237
+ fs.writeFileSync(jsonPath, raw, 'utf8')
238
+ console.log(`Done: Stamped "Introduced in ${newTag}" on ${stampedCount} new ${stampedCount === 1 ? 'property' : 'properties'} in ${path.basename(jsonPath)}`)
239
+ }
240
+ } catch (error) {
241
+ console.error(`Warning: Failed to stamp versions into properties JSON: ${error.message}`)
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Insert a `"version": "<newTag>",` field at the top of one property's object
247
+ * in the raw JSON text, leaving every other byte untouched.
248
+ *
249
+ * @param {string} raw - Full JSON file content
250
+ * @param {string} propName - Property key to stamp
251
+ * @param {string} newTag - Version tag to insert
252
+ * @param {string} indentUnit - One level of the file's indentation
253
+ * @returns {string|null} Updated content, or null when the property was not
254
+ * found or already carries a version field.
255
+ */
256
+ function insertVersionIntoRawJson (raw, propName, newTag, indentUnit) {
257
+ // Anchor the search to the top-level "properties" section when present, so
258
+ // an identically named key elsewhere (e.g. under "definitions") is not hit.
259
+ const sectionMatch = raw.match(new RegExp(`^${indentUnit}"properties": \\{`, 'm'))
260
+ const searchFrom = sectionMatch ? raw.indexOf(sectionMatch[0]) : 0
261
+
262
+ const escapedName = propName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
263
+ const keyMatch = new RegExp(`^([ \t]+)"${escapedName}": \\{[ \t]*$`, 'm').exec(raw.slice(searchFrom))
264
+ if (!keyMatch) return null
265
+
266
+ const keyIndent = keyMatch[1]
267
+ const objStart = searchFrom + keyMatch.index + keyMatch[0].length
268
+
269
+ // Skip when the object already has a version field (scan up to its closing brace).
270
+ const close = new RegExp(`^${keyIndent}\\}`, 'm').exec(raw.slice(objStart))
271
+ const objBody = raw.slice(objStart, close ? objStart + close.index : raw.length)
272
+ if (new RegExp(`^${keyIndent}${indentUnit}"version":`, 'm').test(objBody)) return null
273
+
274
+ const insertion = `\n${keyIndent}${indentUnit}"version": ${JSON.stringify(newTag)},`
275
+ return raw.slice(0, objStart) + insertion + raw.slice(objStart)
276
+ }
277
+
196
278
  /**
197
279
  * Create a unified diff patch between two directories and clean them up.
198
280
  *
@@ -269,5 +351,6 @@ module.exports = {
269
351
  cleanupOldDiffs,
270
352
  generatePropertyComparisonReport,
271
353
  updatePropertyOverridesWithVersion,
354
+ updatePropertiesJsonWithVersion,
272
355
  diffDirs
273
356
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "5.2.0",
3
+ "version": "5.2.2",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -1692,13 +1692,18 @@ function formatExamples(text) {
1692
1692
  i++
1693
1693
  } else if (isIndented) {
1694
1694
  // Command line — collect all consecutive command lines into one code block
1695
- // (stops at a blank line or a comment line)
1696
- result.push('[,bash]')
1697
- result.push('----')
1695
+ // (stops at a blank line or a comment line). Dedent by the run's minimum
1696
+ // indent rather than trimming each line, so multi-line commands with
1697
+ // backslash continuations keep their relative indentation.
1698
+ const run = []
1698
1699
  while (i < lines.length && /^\s{2,}\S/.test(lines[i]) && !lines[i].trim().startsWith('#')) {
1699
- result.push(lines[i].trim())
1700
+ run.push(lines[i])
1700
1701
  i++
1701
1702
  }
1703
+ const minIndent = Math.min(...run.map(l => l.match(/^\s*/)[0].length))
1704
+ result.push('[,bash]')
1705
+ result.push('----')
1706
+ run.forEach(l => result.push(l.slice(minIndent)))
1702
1707
  result.push('----')
1703
1708
  } else if (/^\s*`rpk .+`\s*$/.test(line)) {
1704
1709
  // Inline backticked command on its own line - convert to code block
@@ -14,7 +14,7 @@ const { validateDirectory, formatResults } = require('./validate-output')
14
14
  /**
15
15
  * Known rpk plugins that are managed separately (have install/uninstall commands)
16
16
  */
17
- const KNOWN_PLUGINS = ['ai', 'check', 'connect', 'oxla']
17
+ const KNOWN_PLUGINS = ['ai', 'check', 'connect', 'k8s', 'oxla']
18
18
 
19
19
  /**
20
20
  * Parse Go version from 'go version' output
@@ -497,6 +497,13 @@ function fetchRpkTreeFromLinuxSource(sourcePath) {
497
497
  } else if (stderr.includes('unknown command') || stderr.includes('Error: unknown command')) {
498
498
  console.log(` - ${plugin} is not an installable plugin`)
499
499
  } else {
500
+ // A failed install is non-fatal: generation continues, but this
501
+ // plugin's commands will be absent from the tree. Expected for `k8s`
502
+ // during the 26.2 beta window — `rpk k8s install` finds no `latest`
503
+ // release because the plugin publisher's stableVersionRe only promotes
504
+ // pure X.Y.Z versions, so k8s commands only appear at GA. A pre-GA
505
+ // regen that omits `rpk k8s` pages is this, not a generator bug.
506
+ // See redpanda-data/docs#1801.
500
507
  console.warn(` ✗ Failed to install ${plugin}: ${stderr || stdout}`)
501
508
  }
502
509
  }