@redpanda-data/docs-extensions-and-macros 4.17.3 → 5.0.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.
@@ -17,14 +17,11 @@ const LLMS_DIRECTIVE_BASE = 'For the complete documentation index, see [llms.txt
17
17
  * @returns {string} Formatted markdown blockquote directive
18
18
  */
19
19
  function formatLlmsDirective(componentName) {
20
- const feedbackInstructions = `
21
- >
22
- > **Agent Feedback**: If you encounter incorrect, outdated, or confusing documentation, submit feedback via \`POST https://docs.redpanda.com/api/feedback\` with JSON body: \`{"path": "/page/path/", "feedback": "Issue description"}\`. Only submit when you have specific, actionable feedback.`;
23
20
 
24
21
  if (componentName) {
25
- return `> ${LLMS_DIRECTIVE_BASE}. Component-specific: [${componentName}-full.txt](/${componentName}-full.txt)${feedbackInstructions}`;
22
+ return `> ${LLMS_DIRECTIVE_BASE}. Component-specific: [${componentName}-full.txt](/${componentName}-full.txt)`;
26
23
  }
27
- return `> ${LLMS_DIRECTIVE_BASE}${feedbackInstructions}`;
24
+ return `> ${LLMS_DIRECTIVE_BASE}`;
28
25
  }
29
26
 
30
27
  /**
@@ -107,42 +107,67 @@ function generateIndex (playbook, contentCatalog, { indexLatestOnly = false, exc
107
107
 
108
108
  // Start handling the article content
109
109
  const article = root.querySelector('article.doc')
110
+ let documentTitle, titles, intro, text, isLandingPage
111
+
110
112
  if (!article) {
111
- logger.warn(`Page is not an article...skipping ${page.pub.url}`)
112
- continue
113
- }
113
+ // Check if this is a landing page we should index with metadata
114
+ const pageRole = page.asciidoc?.attributes?.['page-role'] || ''
115
+ const pageLayout = page.asciidoc?.attributes?.['page-layout'] || ''
116
+ const isUmbrellaPage = ['home', 'component-home-v3', 'data-platform'].includes(pageRole) ||
117
+ ['home', 'component-home-v3', 'data-platform'].includes(pageLayout)
118
+
119
+ if (!isUmbrellaPage) {
120
+ logger.warn(`Page is not an article...skipping ${page.pub.url}`)
121
+ continue
122
+ }
114
123
 
115
- // Handle titles
116
- const h1 = article.querySelector('h1')
117
- if (!h1) {
118
- logger.warn(`No H1 in ${page.pub.url}...skipping`)
119
- continue
120
- }
121
- const documentTitle = h1.text
122
- h1.remove()
123
-
124
- const titles = []
125
- article.querySelectorAll('h2,h3,h4,h5,h6').forEach((title) => {
126
- const id = title.getAttribute('id')
127
- if (id) {
128
- titles.push({
129
- t: title.text,
130
- h: id
131
- })
124
+ // Index landing page using metadata
125
+ isLandingPage = true
126
+ const h1 = root.querySelector('h1') || root.querySelector('.hero-title') || root.querySelector('title')
127
+ documentTitle = h1 ? decode(h1.text || h1.textContent || '') : component.title || cname
128
+ titles = []
129
+
130
+ // Get description from meta tag or page attribute
131
+ const metaDesc = root.querySelector('meta[name="description"]')
132
+ intro = metaDesc ? metaDesc.getAttribute('content') :
133
+ page.asciidoc?.attributes?.description || ''
134
+ text = intro
135
+ logger.info(`Indexing landing page: ${page.pub.url}`)
136
+ } else {
137
+ isLandingPage = false
138
+
139
+ // Handle titles
140
+ const h1 = article.querySelector('h1')
141
+ if (!h1) {
142
+ logger.warn(`No H1 in ${page.pub.url}...skipping`)
143
+ continue
144
+ }
145
+ documentTitle = h1.text
146
+ h1.remove()
147
+
148
+ titles = []
149
+ article.querySelectorAll('h2,h3,h4,h5,h6').forEach((title) => {
150
+ const id = title.getAttribute('id')
151
+ if (id) {
152
+ titles.push({
153
+ t: title.text,
154
+ h: id
155
+ })
156
+ }
157
+ title.remove()
158
+ })
159
+
160
+ // Exclude elements within the article that should not be indexed
161
+ for (const excl of excludes) {
162
+ if (!excl) continue
163
+ article.querySelectorAll(excl).forEach((e) => e.remove())
132
164
  }
133
- title.remove()
134
- })
135
165
 
136
- // Exclude elements within the article that should not be indexed
137
- for (const excl of excludes) {
138
- if (!excl) continue
139
- article.querySelectorAll(excl).forEach((e) => e.remove())
166
+ // FIXED: Handle potential null intro element
167
+ const introElement = article.querySelector('p')
168
+ intro = introElement ? decode(introElement.rawText) : ''
140
169
  }
141
170
 
142
- // FIXED: Handle potential null intro element
143
- const introElement = article.querySelector('p')
144
- const intro = introElement ? decode(introElement.rawText) : ''
145
-
146
171
  // Establish structure in the Algolia index
147
172
  if (!(cname in algolia)) algolia[cname] = {}
148
173
  if (!(version in algolia[cname])) algolia[cname][version] = []
@@ -150,10 +175,12 @@ function generateIndex (playbook, contentCatalog, { indexLatestOnly = false, exc
150
175
  // Check if this is a properties reference page (or has many titles)
151
176
  const isPropertiesPage = page.pub.url.includes('/properties/') || titles.length > 30
152
177
 
153
- // Handle the article text
154
- let text = ''
178
+ // Handle the article text (skip for landing pages - already set above)
179
+ if (!isLandingPage) {
180
+ text = ''
181
+ }
155
182
 
156
- if (!isPropertiesPage) {
183
+ if (!isLandingPage && !isPropertiesPage && article) {
157
184
  // For normal pages, index full text content
158
185
  const contentElements = article.querySelectorAll('p, table, li')
159
186
  let contentText = ''
@@ -186,44 +213,62 @@ function generateIndex (playbook, contentCatalog, { indexLatestOnly = false, exc
186
213
  .replace(/\r/g, ' ')
187
214
  .replace(/\s+/g, ' ')
188
215
  .trim()
189
- } else {
216
+ } else if (!isLandingPage && isPropertiesPage) {
190
217
  // For long pages, only use intro as text (property names are already in titles array)
191
218
  text = intro
192
219
  logger.info(`Skipping full text indexing for long page: ${page.pub.url} (${titles.length} properties)`)
193
220
  }
221
+ // For landing pages, text is already set above
194
222
 
195
223
  let tag
196
224
  const title = (component.title || '').trim()
197
- if (title.toLowerCase() === 'home') {
198
- // Collect all unique component titles except 'home', 'shared', 'search'
225
+ const titleLower = title.toLowerCase()
226
+
227
+ // Umbrella components that should include multiple product tags
228
+ const UMBRELLA_COMPONENTS = ['home', 'data platform', 'self-managed']
229
+
230
+ if (UMBRELLA_COMPONENTS.includes(titleLower)) {
231
+ // Collect all unique component titles except umbrella/utility components
199
232
  const componentsList = typeof contentCatalog.getComponents === 'function'
200
233
  ? contentCatalog.getComponents()
201
234
  : Array.isArray(contentCatalog.components)
202
235
  ? contentCatalog.components
203
236
  : Object.values(contentCatalog.components || contentCatalog._components || {})
204
237
 
205
- // Find the latest version for Self-Managed (component title: 'Self-Managed')
206
- let selfManagedLatestVersion
207
- const selfManaged = componentsList.find(c => (c.title || '').trim().toLowerCase() === 'self-managed')
208
- if (selfManaged?.latest?.version) {
209
- selfManagedLatestVersion = selfManaged.latest.version
210
- if (selfManagedLatestVersion && !/^v/.test(selfManagedLatestVersion)) {
211
- selfManagedLatestVersion = 'v' + selfManagedLatestVersion
238
+ // Find the latest version for Streaming
239
+ let streamingLatestVersion
240
+ const streaming = componentsList.find(c => (c.title || '').trim().toLowerCase() === 'streaming')
241
+ if (streaming?.latest?.version) {
242
+ streamingLatestVersion = streaming.latest.version
243
+ if (streamingLatestVersion && !/^v/.test(streamingLatestVersion)) {
244
+ streamingLatestVersion = 'v' + streamingLatestVersion
212
245
  }
213
246
  }
214
247
 
215
- const allComponentTitles = componentsList
216
- .map(c => (c.title || '').trim())
217
- .filter(t => t && !['home', 'shared', 'search'].includes(t.toLowerCase()))
218
-
219
- if (!allComponentTitles.length) {
220
- throw new Error('No component titles found for "home" page. Indexing aborted.')
248
+ // Filter components based on umbrella type
249
+ let filteredTitles
250
+ if (titleLower === 'home') {
251
+ // Home includes all main products
252
+ filteredTitles = componentsList
253
+ .map(c => (c.title || '').trim())
254
+ .filter(t => t && !['home', 'shared', 'search', 'data platform', 'self-managed'].includes(t.toLowerCase()))
255
+ } else if (titleLower === 'data platform') {
256
+ // Data Platform includes Cloud, Streaming, Connect
257
+ filteredTitles = ['Cloud', 'Streaming', 'Connect']
258
+ } else if (titleLower === 'self-managed') {
259
+ // Self-Managed includes Streaming, Connect
260
+ filteredTitles = ['Streaming', 'Connect']
221
261
  }
222
262
 
223
- tag = [...new Set(allComponentTitles)]
224
- // For Self-Managed, append v<latest-version> to the tag
225
- if (selfManagedLatestVersion) {
226
- tag = tag.map(t => t.toLowerCase() === 'self-managed' ? `${t} ${selfManagedLatestVersion}` : t)
263
+ if (!filteredTitles || !filteredTitles.length) {
264
+ // Fallback to component title
265
+ tag = title
266
+ } else {
267
+ tag = [...new Set(filteredTitles)]
268
+ // For Streaming, append v<latest-version> to the tag
269
+ if (streamingLatestVersion) {
270
+ tag = tag.map(t => t.toLowerCase() === 'streaming' ? `${t} ${streamingLatestVersion}` : t)
271
+ }
227
272
  }
228
273
  } else {
229
274
  tag = `${title}${version ? ' v' + version : ''}`
@@ -261,7 +306,7 @@ function generateIndex (playbook, contentCatalog, { indexLatestOnly = false, exc
261
306
  unixTimestamp: unixTimestamp
262
307
  }
263
308
 
264
- if (component.name !== 'redpanda-labs') {
309
+ if (component.name !== 'labs') {
265
310
  indexItem.product = component.title
266
311
  indexItem.breadcrumbs = breadcrumbs
267
312
  indexItem.type = 'Doc'
@@ -53,21 +53,21 @@ module.exports.register = function () {
53
53
  };
54
54
 
55
55
  // Fetch examples from both components
56
- const examples = contentCatalog.findBy({ component: 'redpanda-connect', family: 'example' });
56
+ const examples = contentCatalog.findBy({ component: 'connect', family: 'example' });
57
57
  const previewExamples = contentCatalog.findBy({ component: 'preview', family: 'example' });
58
58
 
59
- if (!examples.length) logger.warn(`No examples found in the 'redpanda-connect' component.`);
59
+ if (!examples.length) logger.warn(`No examples found in the 'connect' component.`);
60
60
 
61
61
  // Get components
62
- const connect = contentCatalog.getComponents().find((c) => c.name === 'redpanda-connect');
62
+ const connect = contentCatalog.getComponents().find((c) => c.name === 'connect');
63
63
  const preview = contentCatalog.getComponents().find((c) => c.name === 'preview');
64
64
 
65
65
  if (connect) {
66
- const connectSamples = collectExamples(examples, 'redpanda-connect');
66
+ const connectSamples = collectExamples(examples, 'connect');
67
67
  connect.latest.asciidoc.attributes['page-bloblang-samples'] = JSON.stringify(connectSamples);
68
- logger.debug(`Bloblang samples added to 'redpanda-connect': ${JSON.stringify(connectSamples, null, 2)}`);
68
+ logger.debug(`Bloblang samples added to 'connect': ${JSON.stringify(connectSamples, null, 2)}`);
69
69
  } else {
70
- logger.warn(`Component 'redpanda-connect' not found.`);
70
+ logger.warn(`Component 'connect' not found.`);
71
71
  }
72
72
 
73
73
  if (preview) {
@@ -13,10 +13,10 @@ module.exports.register = function ({ config }) {
13
13
  return;
14
14
  }
15
15
 
16
- eolConfigs.forEach(({ component: componentName, supported_months, warning_weeks, eol_doc, upgrade_doc }) => {
16
+ eolConfigs.forEach(({ component: componentName, supported_months, warning_weeks, eol_doc, upgrade_doc, whats_new_doc }) => {
17
17
  if (!eol_doc || !upgrade_doc) {
18
18
  logger.error(
19
- `End-of-life configuration for component "${component}" is missing required attributes. ` +
19
+ `End-of-life configuration for component "${componentName}" is missing required attributes. ` +
20
20
  `Ensure both "eol_doc" and "upgrade_doc" are specified.`
21
21
  );
22
22
  return;
@@ -40,14 +40,18 @@ module.exports.register = function ({ config }) {
40
40
  if (releaseDate) {
41
41
  // Pass resolved configuration to calculateEOL
42
42
  const eolInfo = calculateEOL(releaseDate, resolvedEOLMonths, resolvedWarningWeeks, logger);
43
- Object.assign(asciidoc.attributes, {
43
+ const attrs = {
44
44
  'page-is-nearing-eol': eolInfo.isNearingEOL.toString(),
45
45
  'page-is-past-eol': eolInfo.isPastEOL.toString(),
46
46
  'page-eol-date': eolInfo.eolDate,
47
47
  'page-eol-doc': eol_doc,
48
48
  'page-upgrade-doc': upgrade_doc,
49
49
  'page-support-months': resolvedEOLMonths,
50
- });
50
+ };
51
+ if (whats_new_doc) {
52
+ attrs['page-whats-new-doc'] = whats_new_doc;
53
+ }
54
+ Object.assign(asciidoc.attributes, attrs);
51
55
  } else {
52
56
  logger.warn(`No release date found for component: ${componentName}. Make sure to set {page-release-date} in the antora.yml of the component version ${version}.`);
53
57
  }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Antora extension to redirect home page when agentic-data-plane component doesn't exist
3
+ *
4
+ * When the agentic-data-plane component is not included in the build, this extension
5
+ * programmatically adds an alias to the home page that redirects to the data-platform
6
+ * landing page. This leverages Antora's standard redirect facility (Netlify, etc.).
7
+ */
8
+
9
+ 'use strict'
10
+
11
+ module.exports.register = function () {
12
+ const logger = this.getLogger('conditional-home-redirect')
13
+ let shouldRedirect = false
14
+
15
+ // Check if ADP exists during content aggregation
16
+ this.on('contentAggregated', ({ contentAggregate }) => {
17
+ const adpComponent = contentAggregate.find(c => c.name === 'agentic-data-plane')
18
+ shouldRedirect = !adpComponent
19
+ if (shouldRedirect) {
20
+ logger.info('agentic-data-plane not found, will create redirect after publish')
21
+ } else {
22
+ logger.info('agentic-data-plane found, no redirect needed')
23
+ }
24
+ })
25
+
26
+ // Create redirect files AFTER site is published
27
+ this.on('sitePublished', ({ playbook }) => {
28
+ if (!shouldRedirect) return
29
+
30
+ const fs = require('fs')
31
+ const path = require('path')
32
+
33
+ // Get absolute output directory
34
+ const outputDir = path.resolve(playbook.output.dir || 'build/site')
35
+ logger.debug(`Output directory: ${outputDir}`)
36
+
37
+ // Check redirect facility
38
+ const redirectFacility = playbook.urls.redirectFacility || 'netlify'
39
+ logger.debug(`Redirect facility: ${redirectFacility}`)
40
+
41
+ if (redirectFacility === 'netlify') {
42
+ // Add to _redirects file
43
+ const redirectsPath = path.join(outputDir, '_redirects')
44
+ const redirectRule = '/home/ /data-platform/ 301\n/home/index.html /data-platform/index.html 301\n'
45
+
46
+ try {
47
+ let existingRedirects = ''
48
+ if (fs.existsSync(redirectsPath)) {
49
+ existingRedirects = fs.readFileSync(redirectsPath, 'utf8')
50
+ logger.debug(`Found existing _redirects file with ${existingRedirects.split('\\n').length} lines`)
51
+ } else {
52
+ logger.debug('No existing _redirects file, creating new one')
53
+ }
54
+
55
+ // Prepend our redirect to the top (higher priority)
56
+ fs.writeFileSync(redirectsPath, redirectRule + existingRedirects)
57
+ logger.info('Added home -> data-platform redirect to _redirects')
58
+ } catch (err) {
59
+ logger.error(`Failed to write redirects file: ${err.message}`)
60
+ }
61
+ }
62
+
63
+ // Create a static HTML redirect at /home/index.html
64
+ const homeDir = path.join(outputDir, 'home')
65
+ const homeIndexPath = path.join(homeDir, 'index.html')
66
+
67
+ const redirectHtml = `<!DOCTYPE html>
68
+ <meta charset="utf-8">
69
+ <link rel="canonical" href="../data-platform/">
70
+ <script>location="../data-platform/"</script>
71
+ <meta http-equiv="refresh" content="0; url=../data-platform/">
72
+ <meta name="robots" content="noindex">
73
+ <title>Redirect Notice</title>
74
+ <h1>Redirecting to Data Platform</h1>
75
+ <p>The Redpanda documentation home page is being redirected. You will be forwarded to <a href="../data-platform/">Data Platform</a> automatically.</p>`
76
+
77
+ try {
78
+ // Ensure directory exists
79
+ if (!fs.existsSync(homeDir)) {
80
+ fs.mkdirSync(homeDir, { recursive: true })
81
+ }
82
+
83
+ // Overwrite the home page with redirect HTML
84
+ fs.writeFileSync(homeIndexPath, redirectHtml)
85
+ logger.info(`Overwrote home page with redirect at ${homeIndexPath}`)
86
+ } catch (err) {
87
+ logger.error(`Failed to create redirect HTML: ${err.message}`)
88
+ }
89
+ })
90
+ }
@@ -51,7 +51,8 @@ function generateFrontmatter(page) {
51
51
  'title',
52
52
  'navtitle',
53
53
  'description',
54
- 'categories',
54
+ // Note: 'categories' removed - it's a massive object (all Connect components)
55
+ // that bloats frontmatter. Only include on pages that specifically need it.
55
56
  'page-component-name',
56
57
  'page-component-title',
57
58
  'page-component-version',
@@ -75,10 +76,25 @@ function generateFrontmatter(page) {
75
76
  'latest-connect-version',
76
77
  ]
77
78
 
79
+ // Blocklist of large data attributes that should never be in frontmatter
80
+ // These are component-level data used by macros but shouldn't pollute markdown
81
+ const blockedAttributes = [
82
+ 'categories', // Massive nested object with all Connect components
83
+ 'connectCategoriesData', // Raw Connect categories data
84
+ 'flatComponentsData', // Flattened Connect component data
85
+ 'driverSupportData', // SQL driver support matrix
86
+ 'cacheSupportData', // Cache support matrix
87
+ 'csvData', // Raw CSV data from generate-rp-connect-info
88
+ 'commercialNamesMap', // Commercial names mapping
89
+ ]
90
+
78
91
  // Add allowed page attributes to frontmatter
79
92
  Object.keys(attrs).forEach(key => {
80
93
  const value = attrs[key]
81
94
 
95
+ // Skip blocked attributes (large data objects)
96
+ if (blockedAttributes.includes(key)) return
97
+
82
98
  // Allow all learning-objective-* attributes (learning-objective-1, -2, -3, etc.)
83
99
  const isLearningObjective = key.startsWith('learning-objective-')
84
100
 
@@ -222,6 +238,12 @@ module.exports.register = function () {
222
238
  'nav-expand',
223
239
  'banner-container',
224
240
  'markdown-dropdown',
241
+ 'version-selector', // Version dropdown (not relevant for LLMs)
242
+ 'component-indicator', // Component header bar
243
+ 'product-switcher', // Product switcher dropdown
244
+ 'breadcrumb', // Breadcrumb navigation
245
+ 'chat-panel', // AI chat interface
246
+ 'kapa', // Kapa AI widget
225
247
  ]
226
248
  return toRemove.some(
227
249
  (x) => classAttr.includes(x) || idAttr.includes(x)
@@ -12,10 +12,10 @@ module.exports.register = function ({ config }) {
12
12
 
13
13
  // Retrieve all documents and labs from the latest versions of each component
14
14
  const allDocs = [];
15
- const allLabs = contentCatalog.findBy({ component: 'redpanda-labs', family: 'page', version: latestVersions['redpanda-labs'] });
15
+ const allLabs = contentCatalog.findBy({ component: 'labs', family: 'page', version: latestVersions['labs'] });
16
16
 
17
17
  Object.keys(latestVersions).forEach(component => {
18
- if (component === 'redpanda-labs') return;
18
+ if (component === 'labs') return;
19
19
  allDocs.push(...contentCatalog.findBy({ component, family: 'page', version: latestVersions[component] }));
20
20
  });
21
21
  allLabs.forEach((labPage) => {
@@ -26,7 +26,7 @@ module.exports.register = function ({ config }) {
26
26
  if (!pageCategories) return;
27
27
  const sourceCategoryList = pageCategories.split(',').map(c => c.trim());
28
28
  const sourceDeploymentType = getDeploymentType(sourceAttributes);
29
- const docs = contentCatalog.findBy({ component: 'ROOT', family: 'page', version: latestVersions['ROOT'] });
29
+ const docs = contentCatalog.findBy({ component: 'streaming', family: 'page', version: latestVersions['streaming'] });
30
30
 
31
31
  allDocs.forEach((docPage) => {
32
32
  const related = findRelated(docPage, sourceCategoryList, sourceDeploymentType, logger);
@@ -12,7 +12,7 @@ module.exports.register = function ({ config }) {
12
12
  if (!pageCategories) return;
13
13
  const sourceCategoryList = pageCategories.split(',').map(c => c.trim());
14
14
  const sourceDeploymentType = getDeploymentType(sourceAttributes)
15
- const labs = contentCatalog.findBy({ component: 'redpanda-labs', family: 'page' });
15
+ const labs = contentCatalog.findBy({ component: 'labs', family: 'page' });
16
16
  labs.forEach((labPage) => {
17
17
  const related = findRelated(labPage, sourceCategoryList, sourceDeploymentType, logger)
18
18
  related && relatedLabs.push(related)
@@ -145,15 +145,15 @@ module.exports.register = function ({ config }) {
145
145
  const fieldOnlyTemplate = handlebars.compile(`{{{${helperName} children}}}`)
146
146
 
147
147
  this.on('contentClassified', ({ contentCatalog, siteCatalog }) => {
148
- const component = contentCatalog.getComponent('redpanda-connect')
148
+ const component = contentCatalog.getComponent('connect')
149
149
  if (!component) {
150
- logger.warn('redpanda-connect component not found. Skipping field-only page generation.')
150
+ logger.warn('connect component not found. Skipping field-only page generation.')
151
151
  return
152
152
  }
153
153
 
154
154
  const componentVersion = component.latest
155
155
  if (!componentVersion) {
156
- logger.warn('No latest version found for redpanda-connect component.')
156
+ logger.warn('No latest version found for connect component.')
157
157
  return
158
158
  }
159
159
 
@@ -161,7 +161,7 @@ module.exports.register = function ({ config }) {
161
161
  // Look for any versioned JSON attachment in the components module
162
162
  // (i.e. modules/components/attachments/connect-X.Y.Z.json)
163
163
  const attachments = contentCatalog.findBy({
164
- component: 'redpanda-connect',
164
+ component: 'connect',
165
165
  version: componentVersion.version,
166
166
  module: 'components',
167
167
  family: 'attachment'
@@ -203,7 +203,7 @@ module.exports.register = function ({ config }) {
203
203
  const attachment = matchingAttachments[0]?.file
204
204
 
205
205
  if (!attachment) {
206
- logger.warn('No JSON attachment found in the components module of the redpanda-connect content catalog. Skipping field-only page generation.')
206
+ logger.warn('No JSON attachment found in the components module of the connect content catalog. Skipping field-only page generation.')
207
207
  return
208
208
  }
209
209
 
@@ -218,7 +218,7 @@ module.exports.register = function ({ config }) {
218
218
  let pagesGenerated = 0
219
219
 
220
220
  // Get origin from first existing page in component (for git metadata)
221
- const existingPages = contentCatalog.getPages((page) => page.src.component === 'redpanda-connect')
221
+ const existingPages = contentCatalog.getPages((page) => page.src.component === 'connect')
222
222
  const origin = existingPages.length > 0 ? existingPages[0].src.origin : { type: 'generated' }
223
223
 
224
224
  // Iterate over each type (inputs, outputs, processors, etc.)
@@ -266,7 +266,7 @@ module.exports.register = function ({ config }) {
266
266
  contents: contentBuffer,
267
267
  stat: stat,
268
268
  src: {
269
- component: 'redpanda-connect',
269
+ component: 'connect',
270
270
  version: componentVersion.version,
271
271
  module: 'components',
272
272
  family: 'page',
@@ -14,10 +14,10 @@ module.exports.register = function ({ config }) {
14
14
  const logger = this.getLogger('redpanda-connect-category-aggregation-extension')
15
15
 
16
16
  this.on('contentClassified', ({ contentCatalog }) => {
17
- const redpandaConnect = contentCatalog.getComponents().find(component => component.name === 'redpanda-connect')
17
+ const redpandaConnect = contentCatalog.getComponents().find(component => component.name === 'connect')
18
18
 
19
19
  if (!redpandaConnect || !redpandaConnect.latest) {
20
- logger.warn('Could not find the redpanda-connect component. Skipping category creation.')
20
+ logger.warn('Could not find the connect component. Skipping category creation.')
21
21
  return
22
22
  }
23
23
 
@@ -25,12 +25,12 @@ module.exports.register = function ({ config }) {
25
25
  const csvData = redpandaConnect.latest.asciidoc.attributes.csvData
26
26
 
27
27
  if (!descriptions) {
28
- logger.error('No categories attribute found in redpanda-connect component')
28
+ logger.error('No categories attribute found in connect component')
29
29
  return
30
30
  }
31
31
 
32
32
  if (!csvData || !csvData.data) {
33
- logger.error('No csvData attribute found in redpanda-connect component.')
33
+ logger.error('No csvData attribute found in connect component.')
34
34
  logger.error('Ensure generate-rp-connect-info extension is listed BEFORE this extension in your playbook.')
35
35
  return
36
36
  }
@@ -61,7 +61,7 @@ module.exports.register = function ({ config }) {
61
61
  }
62
62
 
63
63
  try {
64
- const files = contentCatalog.findBy({ component: 'redpanda-connect', family: 'page' })
64
+ const files = contentCatalog.findBy({ component: 'connect', family: 'page' })
65
65
 
66
66
  for (const file of files) {
67
67
  // Prefer using page.asciidoc.attributes when available
@@ -36,12 +36,12 @@ module.exports.register = function ({ config }) {
36
36
  })
37
37
 
38
38
  async function processContent (contentCatalog) {
39
- const redpandaConnect = contentCatalog.getComponents().find(component => component.name === 'redpanda-connect')
40
- const redpandaCloud = contentCatalog.getComponents().find(component => component.name === 'redpanda-cloud')
39
+ const redpandaConnect = contentCatalog.getComponents().find(component => component.name === 'connect')
40
+ const redpandaCloud = contentCatalog.getComponents().find(component => component.name === 'cloud-data-platform')
41
41
  const preview = contentCatalog.getComponents().find(component => component.name === 'preview')
42
42
 
43
43
  if (!redpandaConnect) {
44
- logger.warn('redpanda-connect component not found, skipping CSV enrichment')
44
+ logger.warn('connect component not found, skipping CSV enrichment')
45
45
  return
46
46
  }
47
47
 
@@ -141,7 +141,7 @@ module.exports.register = function ({ config }) {
141
141
  const stem = file.src.stem
142
142
  const filePath = file.path
143
143
 
144
- if (component === 'redpanda-connect') {
144
+ if (component === 'connect') {
145
145
  // Store by stem, but only for connector doc paths
146
146
  if (isConnectorDocPath(filePath, file)) {
147
147
  const type = extractTypeFromPath(filePath)
@@ -150,7 +150,7 @@ module.exports.register = function ({ config }) {
150
150
  connectPages.set(key, file)
151
151
  }
152
152
  }
153
- } else if (component === 'redpanda-cloud') {
153
+ } else if (component === 'cloud-data-platform') {
154
154
  // Cloud docs have a specific path pattern
155
155
  const cloudMatch = filePath.match(/connect\/components\/([^/]+)s\/([^/]+)\.adoc$/)
156
156
  if (cloudMatch) {
@@ -280,7 +280,7 @@ module.exports.register = function ({ config }) {
280
280
  const { component, relative, module: moduleName } = page.src
281
281
 
282
282
  // Only process Redpanda Connect and Cloud component pages
283
- if (component !== 'redpanda-connect' && component !== 'redpanda-cloud') continue
283
+ if (component !== 'connect' && component !== 'cloud-data-platform') continue
284
284
 
285
285
  // Match component documentation pages:
286
286
  // 1. Cloud-style paths: connect/components/processors/archive.adoc
@@ -20,7 +20,7 @@ module.exports.register = function ({ config }) {
20
20
  }
21
21
  }
22
22
  } catch (error) {
23
- console.error('Failed to update playbook with the latest Redpanda Connect tag:', error);
23
+ logger.error('Failed to update playbook with the latest Redpanda Connect tag:', error);
24
24
  }
25
25
  });
26
26
  }