@redpanda-data/docs-extensions-and-macros 4.12.6 → 4.13.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.
Files changed (61) hide show
  1. package/README.adoc +33 -1064
  2. package/bin/doc-tools-mcp.js +720 -0
  3. package/bin/doc-tools.js +1050 -50
  4. package/bin/mcp-tools/antora.js +153 -0
  5. package/bin/mcp-tools/cache.js +89 -0
  6. package/bin/mcp-tools/cloud-regions.js +127 -0
  7. package/bin/mcp-tools/content-review.js +196 -0
  8. package/bin/mcp-tools/crd-docs.js +153 -0
  9. package/bin/mcp-tools/frontmatter.js +138 -0
  10. package/bin/mcp-tools/generated-docs-review.js +887 -0
  11. package/bin/mcp-tools/helm-docs.js +152 -0
  12. package/bin/mcp-tools/index.js +245 -0
  13. package/bin/mcp-tools/job-queue.js +468 -0
  14. package/bin/mcp-tools/mcp-validation.js +266 -0
  15. package/bin/mcp-tools/metrics-docs.js +146 -0
  16. package/bin/mcp-tools/openapi.js +174 -0
  17. package/bin/mcp-tools/prompt-discovery.js +283 -0
  18. package/bin/mcp-tools/property-docs.js +157 -0
  19. package/bin/mcp-tools/rpcn-docs.js +113 -0
  20. package/bin/mcp-tools/rpk-docs.js +141 -0
  21. package/bin/mcp-tools/telemetry.js +211 -0
  22. package/bin/mcp-tools/utils.js +131 -0
  23. package/bin/mcp-tools/versions.js +168 -0
  24. package/cli-utils/convert-doc-links.js +1 -1
  25. package/cli-utils/github-token.js +58 -0
  26. package/cli-utils/self-managed-docs-branch.js +2 -2
  27. package/cli-utils/setup-mcp.js +313 -0
  28. package/docker-compose/25.1/transactions.md +1 -1
  29. package/docker-compose/transactions.md +1 -1
  30. package/extensions/DEVELOPMENT.adoc +464 -0
  31. package/extensions/README.adoc +124 -0
  32. package/extensions/REFERENCE.adoc +768 -0
  33. package/extensions/USER_GUIDE.adoc +339 -0
  34. package/extensions/generate-rp-connect-info.js +3 -4
  35. package/extensions/version-fetcher/get-latest-console-version.js +38 -27
  36. package/extensions/version-fetcher/get-latest-redpanda-version.js +65 -54
  37. package/extensions/version-fetcher/retry-util.js +88 -0
  38. package/extensions/version-fetcher/set-latest-version.js +6 -3
  39. package/macros/DEVELOPMENT.adoc +377 -0
  40. package/macros/README.adoc +105 -0
  41. package/macros/REFERENCE.adoc +222 -0
  42. package/macros/USER_GUIDE.adoc +220 -0
  43. package/macros/rp-connect-components.js +6 -6
  44. package/package.json +12 -3
  45. package/tools/bundle-openapi.js +20 -10
  46. package/tools/cloud-regions/generate-cloud-regions.js +1 -1
  47. package/tools/fetch-from-github.js +18 -4
  48. package/tools/gen-rpk-ascii.py +3 -1
  49. package/tools/generate-cli-docs.js +325 -0
  50. package/tools/get-console-version.js +4 -2
  51. package/tools/get-redpanda-version.js +4 -2
  52. package/tools/metrics/metrics.py +19 -7
  53. package/tools/property-extractor/Makefile +7 -1
  54. package/tools/property-extractor/cloud_config.py +4 -4
  55. package/tools/property-extractor/constant_resolver.py +11 -11
  56. package/tools/property-extractor/property_extractor.py +18 -16
  57. package/tools/property-extractor/topic_property_extractor.py +2 -2
  58. package/tools/property-extractor/transformers.py +7 -7
  59. package/tools/property-extractor/type_definition_extractor.py +4 -4
  60. package/tools/redpanda-connect/README.adoc +1 -1
  61. package/tools/redpanda-connect/generate-rpcn-connector-docs.js +5 -3
@@ -0,0 +1,464 @@
1
+ = Antora Extensions Development Guide
2
+ :toc:
3
+ :toclevels: 3
4
+
5
+ Guide for developing new Antora extensions.
6
+
7
+ Antora extensions are Node.js modules that hook into the Antora build pipeline to modify, enhance, or generate content. Extensions can run at different stages of the build process and access the content catalog, component descriptors, and more.
8
+
9
+ == Extension architecture
10
+
11
+ Antora extensions are JavaScript modules that export a `register` function. This function receives a context object that provides access to the Antora build lifecycle and APIs.
12
+
13
+ === Extension lifecycle
14
+
15
+ Extensions register event listeners that execute at specific points in the Antora build:
16
+
17
+ . **contentAggregated** - After content is collected but before conversion
18
+ . **uiLoaded** - After UI bundle is loaded
19
+ . **contentClassified** - After content is organized by component/module
20
+ . **documentsConverted** - After AsciiDoc conversion to HTML
21
+ . **beforePublish** - Before site is written to disk
22
+ . **sitepublished** - After site is published
23
+
24
+ === Extension structure
25
+
26
+ Basic extension structure:
27
+
28
+ [,javascript]
29
+ ----
30
+ module.exports.register = function ({ config }) {
31
+ // Extension logic here
32
+ }
33
+ ----
34
+
35
+ With event listeners:
36
+
37
+ [,javascript]
38
+ ----
39
+ module.exports.register = function ({ config }) {
40
+ this
41
+ .on('contentAggregated', ({ contentAggregate }) => {
42
+ // Process aggregated content
43
+ })
44
+ .on('documentsConverted', ({ contentCatalog }) => {
45
+ // Process converted documents
46
+ })
47
+ }
48
+ ----
49
+
50
+ == Creating a new extension
51
+
52
+ === Create the file
53
+
54
+ Create a new JavaScript file in the `extensions/` directory:
55
+
56
+ [,bash]
57
+ ----
58
+ touch extensions/my-extension.js
59
+ ----
60
+
61
+ === Implement the register function
62
+
63
+ [,javascript]
64
+ ----
65
+ /**
66
+ * My Extension - Does something useful
67
+ *
68
+ * Configuration options:
69
+ * - option1: Description of option1
70
+ * - option2: Description of option2
71
+ */
72
+ module.exports.register = function ({ config }) {
73
+ const logger = this.getLogger('my-extension')
74
+
75
+ // Access configuration
76
+ const option1 = config.option1 || 'default-value'
77
+ const option2 = config.option2
78
+
79
+ // Validate configuration
80
+ if (!option2) {
81
+ logger.error('option2 is required')
82
+ return
83
+ }
84
+
85
+ // Register event listeners
86
+ this.on('contentClassified', ({ contentCatalog }) => {
87
+ logger.info('Processing content...')
88
+
89
+ // Your extension logic here
90
+ const pages = contentCatalog.getPages()
91
+
92
+ pages.forEach(page => {
93
+ // Do something with each page
94
+ logger.debug(`Processing ${page.src.relative}`)
95
+ })
96
+
97
+ logger.info('Processing complete')
98
+ })
99
+ }
100
+ ----
101
+
102
+ === Add to playbook
103
+
104
+ Test your extension by adding it to a playbook:
105
+
106
+ [,yaml]
107
+ ----
108
+ antora:
109
+ extensions:
110
+ - require: './extensions/my-extension.js'
111
+ option1: value1
112
+ option2: value2
113
+ ----
114
+
115
+ === Test
116
+
117
+ Run Antora and verify your extension works:
118
+
119
+ [,bash]
120
+ ----
121
+ npx antora local-antora-playbook.yml
122
+ ----
123
+
124
+ == Common patterns
125
+
126
+ === Accessing content
127
+
128
+ Get all pages:
129
+
130
+ [,javascript]
131
+ ----
132
+ this.on('contentClassified', ({ contentCatalog }) => {
133
+ const pages = contentCatalog.getPages()
134
+
135
+ pages.forEach(page => {
136
+ console.log(page.src.relative)
137
+ console.log(page.asciidoc) // AsciiDoc content
138
+ console.log(page.contents) // Converted HTML
139
+ })
140
+ })
141
+ ----
142
+
143
+ Filter pages by component:
144
+
145
+ [,javascript]
146
+ ----
147
+ const pages = contentCatalog.getPages(page =>
148
+ page.src.component === 'redpanda'
149
+ )
150
+ ----
151
+
152
+ === Creating new pages
153
+
154
+ Add a generated page to the catalog:
155
+
156
+ [,javascript]
157
+ ----
158
+ this.on('contentClassified', ({ contentCatalog }) => {
159
+ const newPage = contentCatalog.addFile({
160
+ contents: Buffer.from('<h1>Generated Page</h1>'),
161
+ src: {
162
+ component: 'redpanda',
163
+ version: '1.0',
164
+ module: 'ROOT',
165
+ family: 'page',
166
+ relative: 'generated-page.adoc'
167
+ },
168
+ out: {
169
+ path: 'generated-page.html'
170
+ },
171
+ pub: {
172
+ url: '/generated-page.html'
173
+ }
174
+ })
175
+
176
+ // Set page attributes
177
+ newPage.asciidoc = {
178
+ attributes: {
179
+ 'page-title': 'Generated Page'
180
+ }
181
+ }
182
+ })
183
+ ----
184
+
185
+ === Modifying pages
186
+
187
+ Update page content:
188
+
189
+ [,javascript]
190
+ ----
191
+ this.on('documentsConverted', ({ contentCatalog }) => {
192
+ const pages = contentCatalog.getPages()
193
+
194
+ pages.forEach(page => {
195
+ if (page.asciidoc) {
196
+ // Modify AsciiDoc attributes
197
+ page.asciidoc.attributes['custom-attr'] = 'value'
198
+
199
+ // Modify HTML content
200
+ page.contents = Buffer.from(
201
+ page.contents.toString().replace(/old/g, 'new')
202
+ )
203
+ }
204
+ })
205
+ })
206
+ ----
207
+
208
+ === Working with components
209
+
210
+ Access component descriptors:
211
+
212
+ [,javascript]
213
+ ----
214
+ this.on('contentAggregated', ({ contentAggregate }) => {
215
+ contentAggregate.forEach(aggregate => {
216
+ const { name, version, title } = aggregate
217
+ console.log(`Component: ${name} v${version}`)
218
+
219
+ // Access component files
220
+ aggregate.files.forEach(file => {
221
+ console.log(file.path)
222
+ })
223
+ })
224
+ })
225
+ ----
226
+
227
+ === Reading external data
228
+
229
+ Load external files or fetch data:
230
+
231
+ [,javascript]
232
+ ----
233
+ const fs = require('fs')
234
+ const path = require('path')
235
+
236
+ module.exports.register = function ({ config }) {
237
+ this.on('contentClassified', ({ contentCatalog, playbook }) => {
238
+ const dataPath = path.join(playbook.dir, 'data', 'my-data.json')
239
+ const data = JSON.parse(fs.readFileSync(dataPath, 'utf8'))
240
+
241
+ // Use data to generate or modify content
242
+ })
243
+ }
244
+ ----
245
+
246
+ Fetch data from APIs:
247
+
248
+ [,javascript]
249
+ ----
250
+ const https = require('https')
251
+
252
+ function fetchData(url) {
253
+ return new Promise((resolve, reject) => {
254
+ https.get(url, (res) => {
255
+ let data = ''
256
+ res.on('data', chunk => data += chunk)
257
+ res.on('end', () => resolve(JSON.parse(data)))
258
+ res.on('error', reject)
259
+ })
260
+ })
261
+ }
262
+
263
+ module.exports.register = function ({ config }) {
264
+ this.on('contentClassified', async ({ contentCatalog }) => {
265
+ const data = await fetchData('https://api.example.com/data')
266
+ // Process data
267
+ })
268
+ }
269
+ ----
270
+
271
+ === Logging
272
+
273
+ Use the logger for debugging:
274
+
275
+ [,javascript]
276
+ ----
277
+ const logger = this.getLogger('my-extension')
278
+
279
+ logger.error('Critical error message')
280
+ logger.warn('Warning message')
281
+ logger.info('Informational message')
282
+ logger.debug('Debug message')
283
+ ----
284
+
285
+ Set log level in playbook:
286
+
287
+ [,yaml]
288
+ ----
289
+ runtime:
290
+ log:
291
+ level: debug
292
+ ----
293
+
294
+ === Environment variables
295
+
296
+ Access environment variables:
297
+
298
+ [,javascript]
299
+ ----
300
+ module.exports.register = function ({ config }) {
301
+ const apiKey = process.env.API_KEY || config.api_key
302
+
303
+ if (!apiKey) {
304
+ this.getLogger('my-extension').error('API_KEY not set')
305
+ return
306
+ }
307
+
308
+ // Use apiKey
309
+ }
310
+ ----
311
+
312
+ == Best practices
313
+
314
+ === Error handling
315
+
316
+ Always handle errors gracefully:
317
+
318
+ [,javascript]
319
+ ----
320
+ this.on('contentClassified', ({ contentCatalog }) => {
321
+ try {
322
+ // Extension logic
323
+ } catch (err) {
324
+ const logger = this.getLogger('my-extension')
325
+ logger.error(`Error: ${err.message}`)
326
+ logger.debug(err.stack)
327
+ // Don't throw - let build continue
328
+ }
329
+ })
330
+ ----
331
+
332
+ === Performance
333
+
334
+ * Cache expensive operations
335
+ * Use async/await for I/O operations
336
+ * Avoid processing files multiple times
337
+ * Filter content early to reduce iterations
338
+
339
+ [,javascript]
340
+ ----
341
+ // Good: Filter early
342
+ const relevantPages = contentCatalog.getPages(page =>
343
+ page.src.component === 'redpanda' && page.asciidoc
344
+ )
345
+
346
+ relevantPages.forEach(page => {
347
+ // Process only relevant pages
348
+ })
349
+
350
+ // Bad: Filter during iteration
351
+ const allPages = contentCatalog.getPages()
352
+ allPages.forEach(page => {
353
+ if (page.src.component === 'redpanda' && page.asciidoc) {
354
+ // Process
355
+ }
356
+ })
357
+ ----
358
+
359
+ === Testing
360
+
361
+ Test extensions independently:
362
+
363
+ [,javascript]
364
+ ----
365
+ // extensions/__tests__/my-extension.test.js
366
+ const myExtension = require('../my-extension')
367
+
368
+ describe('my-extension', () => {
369
+ test('registers correctly', () => {
370
+ const context = {
371
+ on: jest.fn(),
372
+ getLogger: jest.fn(() => ({
373
+ info: jest.fn(),
374
+ error: jest.fn()
375
+ }))
376
+ }
377
+
378
+ myExtension.register.call(context, { config: {} })
379
+
380
+ expect(context.on).toHaveBeenCalled()
381
+ })
382
+ })
383
+ ----
384
+
385
+ === Documentation
386
+
387
+ Document your extension:
388
+
389
+ [,javascript]
390
+ ----
391
+ /**
392
+ * My Extension
393
+ *
394
+ * Description of what the extension does.
395
+ *
396
+ * Configuration:
397
+ * @param {string} option1 - Description of option1
398
+ * @param {boolean} option2 - Description of option2 (required)
399
+ *
400
+ * Environment variables:
401
+ * - MY_VAR: Description
402
+ *
403
+ * Example:
404
+ * antora:
405
+ * extensions:
406
+ * - require: './extensions/my-extension.js'
407
+ * option1: value
408
+ * option2: true
409
+ */
410
+ module.exports.register = function ({ config }) {
411
+ // Implementation
412
+ }
413
+ ----
414
+
415
+ === Code organization
416
+
417
+ For complex extensions, split into modules:
418
+
419
+ ----
420
+ extensions/
421
+ my-extension/
422
+ index.js # Main extension file
423
+ processor.js # Processing logic
424
+ generator.js # Content generation
425
+ utils.js # Utility functions
426
+ ----
427
+
428
+ == Debugging
429
+
430
+ === Enable debug logging
431
+
432
+ [,bash]
433
+ ----
434
+ ANTORA_LOG_LEVEL=debug npx antora playbook.yml
435
+ ----
436
+
437
+ === Use console.log sparingly
438
+
439
+ Prefer the logger:
440
+
441
+ [,javascript]
442
+ ----
443
+ // Good
444
+ const logger = this.getLogger('my-extension')
445
+ logger.debug('Debug info')
446
+
447
+ // Avoid
448
+ console.log('Debug info')
449
+ ----
450
+
451
+ === Inspect objects
452
+
453
+ [,javascript]
454
+ ----
455
+ const util = require('util')
456
+
457
+ console.log(util.inspect(object, { depth: null, colors: true }))
458
+ ----
459
+
460
+ == Related documentation
461
+
462
+ * link:USER_GUIDE.adoc[User guide] - How to use extensions
463
+ * link:REFERENCE.adoc[Reference] - Complete extension documentation
464
+ * https://docs.antora.org/antora/latest/extend/extensions/[Antora Extensions API]
@@ -0,0 +1,124 @@
1
+ = Antora Extensions
2
+ :toc:
3
+ :toclevels: 2
4
+
5
+ Documentation for Antora extensions that enhance the documentation build process.
6
+
7
+ == What are Antora extensions?
8
+
9
+ Antora extensions are Node.js modules that extend Antora's capabilities during the documentation site build. These extensions can modify content, generate new pages, integrate with external services, and customize the build pipeline.
10
+
11
+ == Documentation
12
+
13
+ link:USER_GUIDE.adoc[**User guide**]:: How to use and configure Antora extensions in your playbook
14
+ +
15
+ * Installation and setup
16
+ * Configuring extensions
17
+ * Common usage patterns
18
+ * Troubleshooting
19
+
20
+ link:REFERENCE.adoc[**Reference**]:: Complete reference for all available extensions
21
+ +
22
+ * Extension descriptions
23
+ * Configuration options
24
+ * Environment variables
25
+ * Examples for each extension
26
+
27
+ link:DEVELOPMENT.adoc[**Development guide**]:: How to develop new Antora extensions
28
+ +
29
+ * Extension architecture
30
+ * Creating new extensions
31
+ * Testing and debugging
32
+ * Best practices
33
+
34
+ == Quickstart
35
+
36
+ === Install the package
37
+
38
+ [,bash]
39
+ ----
40
+ npm i @redpanda-data/docs-extensions-and-macros
41
+ ----
42
+
43
+ === Configure in your playbook
44
+
45
+ [,yaml]
46
+ ----
47
+ antora:
48
+ extensions:
49
+ - '@redpanda-data/docs-extensions-and-macros/extensions/version-fetcher/set-latest-version'
50
+ ----
51
+
52
+ IMPORTANT: Extensions must be registered under the `antora.extensions` key in your playbook, not `asciidoc.extensions`.
53
+
54
+ == Available extensions
55
+
56
+ === Version management
57
+ * **set-latest-version** - Automatically fetch latest versions from GitHub releases
58
+
59
+ === Content generation
60
+ * **generate-index-data** - Generate searchable indexes from content
61
+ * **generate-rp-connect-categories** - Generate Redpanda Connect component categories
62
+ * **generate-rp-connect-info** - Generate Redpanda Connect component information
63
+
64
+ === Navigation
65
+ * **unlisted-pages** - Manage pages that appear in navigation but aren't listed
66
+ * **produce-redirects** - Generate redirect configurations
67
+ * **unpublish-pages** - Mark pages as unpublished
68
+
69
+ === Integrations
70
+ * **algolia-indexer** - Index content for Algolia search
71
+ * **compute-end-of-life** - Calculate and display EOL information
72
+ * **find-related-docs** - Find and link related documentation
73
+ * **find-related-labs** - Find and link related lab exercises
74
+
75
+ === File processing
76
+ * **archive-attachments** - Archive file attachments
77
+ * **replace-attributes-in-attachments** - Replace AsciiDoc attributes in attached files
78
+ * **collect-bloblang-samples** - Collect Bloblang code samples
79
+
80
+ === Content enhancement
81
+ * **add-global-attributes** - Add attributes globally to all pages
82
+ * **add-pages-to-root** - Add pages to the root navigation
83
+ * **process-context-switcher** - Handle context-dependent content
84
+ * **validate-attributes** - Validate AsciiDoc attributes
85
+
86
+ See link:REFERENCE.adoc[Reference documentation] for complete details on each extension.
87
+
88
+ == Common use cases
89
+
90
+ === Automatically update version numbers
91
+
92
+ [,yaml]
93
+ ----
94
+ antora:
95
+ extensions:
96
+ - '@redpanda-data/docs-extensions-and-macros/extensions/version-fetcher/set-latest-version'
97
+ ----
98
+
99
+ === Enable Algolia search
100
+
101
+ [,yaml]
102
+ ----
103
+ antora:
104
+ extensions:
105
+ - require: '@redpanda-data/docs-extensions-and-macros/extensions/algolia-indexer'
106
+ algolia_app_id: YOUR_APP_ID
107
+ algolia_api_key: YOUR_API_KEY
108
+ algolia_index_name: YOUR_INDEX
109
+ ----
110
+
111
+ === Generate redirects
112
+
113
+ [,yaml]
114
+ ----
115
+ antora:
116
+ extensions:
117
+ - '@redpanda-data/docs-extensions-and-macros/extensions/produce-redirects.js'
118
+ ----
119
+
120
+ == Support
121
+
122
+ * link:USER_GUIDE.adoc#troubleshooting[Troubleshooting guide]
123
+ * https://github.com/redpanda-data/docs-extensions-and-macros/issues[Report issues]
124
+ * https://docs.antora.org/antora/latest/extend/extensions/[Antora Extensions Documentation]