@redpanda-data/docs-extensions-and-macros 3.10.0 → 3.11.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/README.adoc +123 -21
- package/extensions/generate-index-data.js +193 -0
- package/macros/rp-connect-components.js +1 -1
- package/package.json +2 -1
package/README.adoc
CHANGED
|
@@ -52,6 +52,24 @@ The `collect-bloblang-samples` extension processes Bloblang examples from YAML f
|
|
|
52
52
|
|
|
53
53
|
It validates, sorts, and attaches the processed examples as a JSON object to the Antora page attributes. The extension ensures examples have unique titles, mandatory fields (`input` and `mapping`), and are sorted in alphabetical order.
|
|
54
54
|
|
|
55
|
+
The processed examples are added as JSON to the `page-bloblang-samples` attribute. For example:
|
|
56
|
+
|
|
57
|
+
[,json]
|
|
58
|
+
----
|
|
59
|
+
{
|
|
60
|
+
"hello-world.yaml": {
|
|
61
|
+
"title": "Hello world",
|
|
62
|
+
"input": "{\n \"message\": \"hello world\"\n}\n",
|
|
63
|
+
"mapping": "root.message = this.message.uppercase()\n"
|
|
64
|
+
},
|
|
65
|
+
"array-processing.yaml": {
|
|
66
|
+
"title": "Array processing",
|
|
67
|
+
"input": "{\n \"numbers\": [1, 2, 3, 4, 5]\n}\n",
|
|
68
|
+
"mapping": "root.even_numbers = this.numbers.filter(n -> n % 2 == 0)"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
----
|
|
72
|
+
|
|
55
73
|
==== Environment variables
|
|
56
74
|
|
|
57
75
|
This extension does not require any environment variables.
|
|
@@ -82,26 +100,6 @@ mapping: |
|
|
|
82
100
|
root.message = this.message.uppercase()
|
|
83
101
|
----
|
|
84
102
|
|
|
85
|
-
==== Sample output
|
|
86
|
-
|
|
87
|
-
The processed examples are added as JSON to the `page-bloblang-samples` attribute. For example:
|
|
88
|
-
|
|
89
|
-
[,json]
|
|
90
|
-
----
|
|
91
|
-
{
|
|
92
|
-
"hello-world.yaml": {
|
|
93
|
-
"title": "Hello world",
|
|
94
|
-
"input": "{\n \"message\": \"hello world\"\n}\n",
|
|
95
|
-
"mapping": "root.message = this.message.uppercase()\n"
|
|
96
|
-
},
|
|
97
|
-
"array-processing.yaml": {
|
|
98
|
-
"title": "Array processing",
|
|
99
|
-
"input": "{\n \"numbers\": [1, 2, 3, 4, 5]\n}\n",
|
|
100
|
-
"mapping": "root.even_numbers = this.numbers.filter(n -> n % 2 == 0)"
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
----
|
|
104
|
-
|
|
105
103
|
=== Add pages to root
|
|
106
104
|
|
|
107
105
|
The `add-pages-to-root` extension allows you to copy files from your Antora content catalog to the root of the site during the build process. This is particularly useful for files like `llms.txt` or any custom files that need to be directly accessible at the site's root level.
|
|
@@ -183,7 +181,7 @@ This extension does not require any environment variables.
|
|
|
183
181
|
|
|
184
182
|
There are no configurable options for this extension.
|
|
185
183
|
|
|
186
|
-
==== Registration
|
|
184
|
+
==== Registration example
|
|
187
185
|
|
|
188
186
|
```yaml
|
|
189
187
|
antora:
|
|
@@ -191,6 +189,110 @@ antora:
|
|
|
191
189
|
- require: '@redpanda-data/docs-extensions-and-macros/extensions/generate-rp-connect-categories'
|
|
192
190
|
```
|
|
193
191
|
|
|
192
|
+
=== Generate index data
|
|
193
|
+
|
|
194
|
+
The `generate-index-data` extension creates structured index data about doc pages based on configurable filters. The indexed data is saved to a specified attribute in all component versions, enabling the dynamic generation of categorized links and descriptions within your docs using UI templates.
|
|
195
|
+
|
|
196
|
+
This extension allows you to define multiple indexing criteria, such as component, URL filter, and environment type.
|
|
197
|
+
|
|
198
|
+
The generated data is an array of objects, where each object represents a component version. Each object contains the following properties:
|
|
199
|
+
|
|
200
|
+
- `component` (string):
|
|
201
|
+
The name of the Antora component.
|
|
202
|
+
|
|
203
|
+
- `version` (string):
|
|
204
|
+
The version of the component.
|
|
205
|
+
|
|
206
|
+
- `pages` (array):
|
|
207
|
+
A list of pages that match the indexing criteria. Each page contains:
|
|
208
|
+
** `title` (string): The title of the doc page.
|
|
209
|
+
** `url` (string): The URL of the doc page relative to the site root.
|
|
210
|
+
** `description` (string): A brief description sourced from the `:description:` attribute in the AsciiDoc file. Defaults to an empty string if not provided.
|
|
211
|
+
|
|
212
|
+
Example:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
[
|
|
216
|
+
{
|
|
217
|
+
"component": "ROOT",
|
|
218
|
+
"version": "24.3",
|
|
219
|
+
"pages": [
|
|
220
|
+
{
|
|
221
|
+
"title": "Manage Debug Bundles in Redpanda Console",
|
|
222
|
+
"url": "/current/console/ui/generate-bundle/",
|
|
223
|
+
"description": "Learn how to generate, download, and delete debug bundles in Redpanda Console for comprehensive cluster diagnostics."
|
|
224
|
+
},
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
==== Environment variables
|
|
231
|
+
|
|
232
|
+
This extension does not require any environment variables.
|
|
233
|
+
|
|
234
|
+
==== Configuration options
|
|
235
|
+
|
|
236
|
+
The extension accepts the following options in the Antora playbook.
|
|
237
|
+
|
|
238
|
+
NOTE: Ensure filters are well-defined to minimize unnecessary processing. Avoid overly broad configurations in `data.sets`.
|
|
239
|
+
|
|
240
|
+
- `data.sets` (required): An object defining one or more indexing configurations. Each configuration (or set) accepts the following options:
|
|
241
|
+
|
|
242
|
+
** `component` (string, required): The Antora component to search for pages.
|
|
243
|
+
|
|
244
|
+
** `attribute_name` (string, required): The attribute name to assign the generated index data. This allows pages and templates to reference the index.
|
|
245
|
+
|
|
246
|
+
** `filter` (string, optional): A substring to match within page URLs.
|
|
247
|
+
|
|
248
|
+
** `env_type` (string, optional): Matches pages with environment-specific attributes (e.g., Docker, Kubernetes).
|
|
249
|
+
|
|
250
|
+
** `output_file` (string, optional): Save the generated index data as a JSON file at the specified path. If not provided, no file is created.
|
|
251
|
+
|
|
252
|
+
==== Example configuration
|
|
253
|
+
|
|
254
|
+
Here's an example configuration to enable the generate-index-data-extension:
|
|
255
|
+
|
|
256
|
+
```yaml
|
|
257
|
+
antora:
|
|
258
|
+
extensions:
|
|
259
|
+
- require: '@redpanda-data/docs-extensions-and-macros/extensions/generate-index-data-extension'
|
|
260
|
+
data:
|
|
261
|
+
sets:
|
|
262
|
+
console_ui:
|
|
263
|
+
component: ROOT # Search the ROOT component
|
|
264
|
+
filter: console/ui # Filter pages containing this substring in their URL
|
|
265
|
+
attribute_name: console-ui-index # Save the result in this attribute
|
|
266
|
+
output_file: redpanda-labs/console-ui-index.json # Save data to this file
|
|
267
|
+
docker_labs:
|
|
268
|
+
component: redpanda-labs
|
|
269
|
+
filter: docker-compose
|
|
270
|
+
env_type: Docker
|
|
271
|
+
attribute_name: docker-labs-index
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
==== Use the generated data
|
|
275
|
+
|
|
276
|
+
The index data can be referenced in AsciiDoc pages by specifying the following required attributes:
|
|
277
|
+
|
|
278
|
+
```asciidoc
|
|
279
|
+
= CONSOLE UI
|
|
280
|
+
:page-index-data: console-ui-index <1>
|
|
281
|
+
:page-role: index-list <2>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
<1> The attribute whose data you want to display on the page. This must match an attribute configured in the extension.
|
|
285
|
+
<2> The page role. This role specfies the UI template that renders the data in the `page-index-data` on the page.
|
|
286
|
+
|
|
287
|
+
You can optionally display pages only if they match the component and version of the current Asciidoc page by adding the `:page-match-component-version:` attribute.
|
|
288
|
+
|
|
289
|
+
```asciidoc
|
|
290
|
+
= CONSOLE UI
|
|
291
|
+
:page-index-data: console-ui-index
|
|
292
|
+
:page-role: index-list
|
|
293
|
+
:page-match-component-version: ''
|
|
294
|
+
```
|
|
295
|
+
|
|
194
296
|
=== Redpanda Connect tag modifier
|
|
195
297
|
|
|
196
298
|
This extension updates the playbook to use the latest release tag for the Redpanda Connect documentation. It ensures that the Redpanda Connect documentation is always pulled from the latest release tag available on GitHub.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const _ = require('lodash');
|
|
3
|
+
|
|
4
|
+
module.exports.register = function ({ config }) {
|
|
5
|
+
const logger = this.getLogger('generate-index-data-extension');
|
|
6
|
+
|
|
7
|
+
this.on('documentsConverted', async ({ contentCatalog, siteCatalog }) => {
|
|
8
|
+
// Ensure data.sets exists and is an object
|
|
9
|
+
const setsConfig = _.get(config, 'data.sets', {});
|
|
10
|
+
if (!setsConfig || Object.keys(setsConfig).length === 0) {
|
|
11
|
+
logger.info('No index sets defined in the configuration. Skipping index data generation.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
// Process each defined index set
|
|
17
|
+
for (const [setName, setParams] of Object.entries(setsConfig)) {
|
|
18
|
+
logger.info(`Processing index set: ${setName}`);
|
|
19
|
+
const { component, filter, env_type, output_file, attribute_name } = setParams;
|
|
20
|
+
|
|
21
|
+
// Validate required parameters
|
|
22
|
+
const requiredParams = ['component', 'attribute_name'];
|
|
23
|
+
|
|
24
|
+
const missingParams = requiredParams.filter(param => !setParams[param]);
|
|
25
|
+
|
|
26
|
+
if (missingParams.length > 0) {
|
|
27
|
+
logger.warn(`One or more required parameters are missing: ${missingParams.join(', ')} for set "${setName}". Skipping.`);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Gather items based on the target version
|
|
32
|
+
const items = gatherItems(contentCatalog, {
|
|
33
|
+
component,
|
|
34
|
+
filter,
|
|
35
|
+
env_type,
|
|
36
|
+
}, logger);
|
|
37
|
+
|
|
38
|
+
if (!items.length) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const uniqueItems = deduplicateAndSortItems(items);
|
|
43
|
+
await addDataAttributeToComponents(uniqueItems, contentCatalog, attribute_name, logger);
|
|
44
|
+
if (output_file) createIndexFile(uniqueItems, siteCatalog, output_file, logger);
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.error(`Failed to generate indexes: ${error.stack}`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Gathers items (pages) from the contentCatalog based on the provided setParams.
|
|
54
|
+
* setParams should contain:
|
|
55
|
+
* - component (string, required): Component name to search
|
|
56
|
+
* - filter (string, optional): A substring to match in the URL or other criteria
|
|
57
|
+
* - env_type (string, optional): Deployment type to match ('Docker', 'Kubernetes', 'Linux', 'Redpanda Cloud')
|
|
58
|
+
*/
|
|
59
|
+
function gatherItems(contentCatalog, setParams, logger) {
|
|
60
|
+
const { component, filter, env_type } = setParams;
|
|
61
|
+
|
|
62
|
+
// Find the component in the catalog
|
|
63
|
+
const componentObj = contentCatalog.getComponents().find(comp => comp.name === component);
|
|
64
|
+
if (!componentObj) {
|
|
65
|
+
logger.warn(`Component "${component}" not found in the content catalog.`);
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const result = [];
|
|
70
|
+
|
|
71
|
+
// Iterate through all versions of the component
|
|
72
|
+
componentObj.versions.forEach(versionObj => {
|
|
73
|
+
const versionPages = contentCatalog.findBy({ component, family: 'page', version: versionObj.version });
|
|
74
|
+
|
|
75
|
+
logger.debug(`Gathering pages for component "${component}" version "${versionObj.version}". Found ${versionPages.length} pages.`);
|
|
76
|
+
|
|
77
|
+
// Filter pages based on criteria
|
|
78
|
+
const matchedPages = versionPages.filter(page => {
|
|
79
|
+
const deploymentType = getDeploymentType(page.asciidoc.attributes);
|
|
80
|
+
const urlMatches = filter ? page.pub.url.includes(filter) : true;
|
|
81
|
+
const envMatches = env_type ? (deploymentType === env_type) : true;
|
|
82
|
+
|
|
83
|
+
return urlMatches && envMatches;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Map matched pages to the desired structure
|
|
87
|
+
const pages = matchedPages.map(page => ({
|
|
88
|
+
title: page.asciidoc.doctitle,
|
|
89
|
+
url: page.pub.url,
|
|
90
|
+
description: page.asciidoc.attributes.description || ''
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
// Add the component and version structure, even if pages is empty
|
|
94
|
+
result.push({
|
|
95
|
+
component,
|
|
96
|
+
version: versionObj.version,
|
|
97
|
+
pages
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
logger.debug(`Processed ${pages.length} pages for version "${versionObj.version}".`);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
logger.debug(`Completed gathering items for component "${component}".`);
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Deduplicates items by their URL and returns them in alphabetical order by title.
|
|
109
|
+
*/
|
|
110
|
+
function deduplicateAndSortItems(items) {
|
|
111
|
+
return items.map(item => {
|
|
112
|
+
const seenUrls = new Set();
|
|
113
|
+
|
|
114
|
+
// Deduplicate pages by URL
|
|
115
|
+
const deduplicatedPages = item.pages.filter(page => {
|
|
116
|
+
if (seenUrls.has(page.url)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
seenUrls.add(page.url);
|
|
120
|
+
return true;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Sort pages alphabetically by title
|
|
124
|
+
const sortedPages = deduplicatedPages.sort((a, b) => {
|
|
125
|
+
const titleA = a.title.toLowerCase();
|
|
126
|
+
const titleB = b.title.toLowerCase();
|
|
127
|
+
if (titleA < titleB) return -1;
|
|
128
|
+
if (titleA > titleB) return 1;
|
|
129
|
+
return 0;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
...item,
|
|
134
|
+
pages: sortedPages
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Add the gathered data as an attribute to all components.
|
|
141
|
+
*
|
|
142
|
+
* @param {Array} data - The deduplicated items to set as an attribute.
|
|
143
|
+
* @param {Object} contentCatalog - The content catalog from Antora.
|
|
144
|
+
* @param {string} attributeName - The name of the attribute to set.
|
|
145
|
+
* @param {Object} logger - The Antora logger.
|
|
146
|
+
*/
|
|
147
|
+
async function addDataAttributeToComponents(data, contentCatalog, attributeName, logger) {
|
|
148
|
+
try {
|
|
149
|
+
const jsonData = JSON.stringify(data, null, 2);
|
|
150
|
+
const components = await contentCatalog.getComponents();
|
|
151
|
+
|
|
152
|
+
components.forEach(component => {
|
|
153
|
+
component.versions.forEach(({ name, asciidoc }) => {
|
|
154
|
+
asciidoc.attributes[attributeName] = jsonData;
|
|
155
|
+
logger.debug(`Set attribute "${attributeName}" on component "${name}".`);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
logger.info(`Added "${attributeName}" attribute to relevant component versions.`);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
logger.error(`Failed to add data attribute "${attributeName}": ${error.message}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create a JSON file in the output with the given data.
|
|
167
|
+
*/
|
|
168
|
+
function createIndexFile(data, siteCatalog, outputFile, logger) {
|
|
169
|
+
if (!outputFile) {
|
|
170
|
+
logger.info('No output_file specified, skipping JSON file creation.');
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const jsonData = JSON.stringify(data, null, 2);
|
|
175
|
+
siteCatalog.addFile({
|
|
176
|
+
contents: Buffer.from(jsonData, 'utf8'),
|
|
177
|
+
out: {
|
|
178
|
+
path: outputFile
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
logger.info(`Created "${outputFile}" with indexed data.`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Determine the deployment type from AsciiDoc attributes.
|
|
186
|
+
*/
|
|
187
|
+
function getDeploymentType(attributes) {
|
|
188
|
+
return attributes['env-kubernetes'] ? 'Kubernetes'
|
|
189
|
+
: attributes['env-linux'] ? 'Linux'
|
|
190
|
+
: attributes['env-docker'] ? 'Docker'
|
|
191
|
+
: attributes['env-cloud'] ? 'Redpanda Cloud'
|
|
192
|
+
: attributes['page-cloud'] ? 'Redpanda Cloud' : '';
|
|
193
|
+
}
|
|
@@ -704,7 +704,7 @@ module.exports.register = function (registry, context) {
|
|
|
704
704
|
const requiresEnterprise = componentRows.some(row => row.is_licensed.toLowerCase() === 'yes');
|
|
705
705
|
if (requiresEnterprise) {
|
|
706
706
|
enterpriseLicenseInfo = `
|
|
707
|
-
<p><strong>License</strong>: This component requires an <a href="https://redpanda.com/
|
|
707
|
+
<p><strong>License</strong>: This component requires an <a href="https://docs.redpanda.com/redpanda-connect/get-started/licensing/" target="_blank">Enterprise license</a>. To upgrade, go to the <a href="https://www.redpanda.com/upgrade" target="_blank" rel="noopener">Redpanda website</a>.</p>`;
|
|
708
708
|
}
|
|
709
709
|
}
|
|
710
710
|
const isCloudSupported = componentRows.some(row => row.is_cloud_supported === 'y');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redpanda-data/docs-extensions-and-macros",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "Antora extensions and macros developed for Redpanda documentation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antora",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"./extensions/add-pages-to-root": "./extensions/add-pages-to-root.js",
|
|
34
34
|
"./extensions/collect-bloblang-samples": "./extensions/collect-bloblang-samples.js",
|
|
35
35
|
"./extensions/generate-rp-connect-categories": "./extensions/generate-rp-connect-categories.js",
|
|
36
|
+
"./extensions/generate-index-data": "./extensions/generate-index-data.js",
|
|
36
37
|
"./extensions/generate-rp-connect-info": "./extensions/generate-rp-connect-info.js",
|
|
37
38
|
"./extensions/add-global-attributes": "./extensions/add-global-attributes.js",
|
|
38
39
|
"./extensions/version-fetcher/set-latest-version": "./extensions/version-fetcher/set-latest-version.js",
|