@redpanda-data/docs-extensions-and-macros 4.10.1 → 4.10.3

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
@@ -1032,17 +1032,20 @@ automation
1032
1032
 
1033
1033
  automation
1034
1034
  .command('property-docs')
1035
- .description('Generate JSON and AsciiDoc documentation for Redpanda configuration properties')
1035
+ .description('Generate JSON and AsciiDoc documentation for Redpanda configuration properties. By default, only extracts properties to JSON. Use --generate-partials to create consolidated AsciiDoc partials (including deprecated properties). Use --generate-pages to create complete property pages that include the partials using AsciiDoc includes.')
1036
1036
  .option('--tag <tag>', 'Git tag or branch to extract from', 'dev')
1037
- .option('--diff <oldTag>', 'Also diff autogenerated properties from <oldTag> <tag>')
1037
+ .option('--diff <oldTag>', 'Also diff autogenerated properties from <oldTag> to <tag>')
1038
1038
  .option('--overrides <path>', 'Optional JSON file with property description overrides')
1039
1039
  .option('--output-dir <dir>', 'Where to write all generated files', 'modules/reference')
1040
- .option('--cloud-support', 'Enable cloud support metadata by fetching configuration from the cloudv2 repository (requires GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN)')
1040
+ .option('--cloud-support', 'Add AsciiDoc tags to generated property docs to indicate which ones are supported in Redpanda Cloud. This data is fetched from the cloudv2 repository so requires a GitHub token with repo permissions. Set the token as an environment variable using GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN')
1041
1041
  .option('--template-property-page <path>', 'Custom Handlebars template for property page layout')
1042
1042
  .option('--template-property <path>', 'Custom Handlebars template for individual property sections')
1043
1043
  .option('--template-topic-property <path>', 'Custom Handlebars template for individual topic property sections')
1044
1044
  .option('--template-deprecated <path>', 'Custom Handlebars template for deprecated properties page')
1045
1045
  .option('--template-deprecated-property <path>', 'Custom Handlebars template for individual deprecated property sections')
1046
+ .option('--generate-partials', 'Generate consolidated property partials (cluster-properties.adoc, topic-properties.adoc, etc.) in the partials directory')
1047
+ .option('--partials-dir <path>', 'Directory for property partials (relative to output-dir)', 'partials')
1048
+ .option('--generate-pages', 'Generate complete property pages that include the partials using AsciiDoc includes')
1046
1049
  .action((options) => {
1047
1050
  verifyPropertyDependencies();
1048
1051
 
@@ -1091,6 +1094,7 @@ automation
1091
1094
  }
1092
1095
  if (templates.propertyPage) {
1093
1096
  env.TEMPLATE_PROPERTY_PAGE = path.resolve(templates.propertyPage);
1097
+ env.TEMPLATE_PROPERTY_PAGE_WITH_INCLUDES = env.TEMPLATE_PROPERTY_PAGE;
1094
1098
  }
1095
1099
  if (templates.property) {
1096
1100
  env.TEMPLATE_PROPERTY = path.resolve(templates.property);
@@ -1115,6 +1119,20 @@ automation
1115
1119
  env.OUTPUT_ASCIIDOC_DIR = path.resolve(outputDir, 'pages', 'properties');
1116
1120
  }
1117
1121
 
1122
+ // Set partials generation options
1123
+ if (options.generatePartials) {
1124
+ env.GENERATE_PARTIALS = '1';
1125
+ env.OUTPUT_PARTIALS_DIR = path.resolve(outputDir, options.partialsDir || 'partials');
1126
+ }
1127
+
1128
+ // Set page generation options
1129
+ if (options.generatePages) {
1130
+ env.GENERATE_PAGES = '1';
1131
+ if (templates.propertyPage) {
1132
+ env.TEMPLATE_PROPERTY_PAGE_WITH_INCLUDES = env.TEMPLATE_PROPERTY_PAGE;
1133
+ }
1134
+ }
1135
+
1118
1136
  const r = spawnSync('make', args, { cwd, stdio: 'inherit', env });
1119
1137
  if (r.error) {
1120
1138
  console.error(`❌ ${r.error.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "4.10.1",
3
+ "version": "4.10.3",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -28,6 +28,7 @@ TREE_SITTER := npx tree-sitter
28
28
  OUTPUT_AUTOGENERATED_DIR ?= $(REPO_ROOT)/modules/reference
29
29
  OUTPUT_ASCIIDOC_DIR ?= $(OUTPUT_AUTOGENERATED_DIR)/pages
30
30
  OUTPUT_JSON_DIR ?= $(OUTPUT_AUTOGENERATED_DIR)/examples
31
+ OUTPUT_PARTIALS_DIR ?= $(OUTPUT_AUTOGENERATED_DIR)/partials
31
32
 
32
33
  # --- Main build: venv, fetch code, build parser, extract & docgen ---
33
34
  build: venv redpanda-git treesitter
@@ -27,6 +27,23 @@ Object.entries(helpers).forEach(([name, fn]) => {
27
27
  handlebars.registerHelper(name, fn);
28
28
  });
29
29
 
30
+ /**
31
+ * Determines if a property is related to object storage.
32
+ * @param {Object} prop - The property object
33
+ * @returns {boolean} True if the property is object storage related
34
+ */
35
+ function isObjectStorageProperty(prop) {
36
+ return prop.name && (
37
+ prop.name.includes('cloud_storage') ||
38
+ prop.name.includes('s3_') ||
39
+ prop.name.includes('azure_') ||
40
+ prop.name.includes('gcs_') ||
41
+ prop.name.includes('archival_') ||
42
+ prop.name.includes('remote_') ||
43
+ prop.name.includes('tiered_')
44
+ );
45
+ }
46
+
30
47
  /**
31
48
  * Configuration mapping for different property types
32
49
  */
@@ -60,17 +77,7 @@ NOTE: Some cluster properties require that you restart the cluster for any updat
60
77
  sectionTitle: 'Cluster configuration',
61
78
  groups: [
62
79
  {
63
- filter: (prop) => prop.config_scope === 'cluster' && !prop.is_deprecated && !(
64
- prop.name && (
65
- prop.name.includes('cloud_storage') ||
66
- prop.name.includes('s3_') ||
67
- prop.name.includes('azure_') ||
68
- prop.name.includes('gcs_') ||
69
- prop.name.includes('archival_') ||
70
- prop.name.includes('remote_') ||
71
- prop.name.includes('tiered_')
72
- )
73
- )
80
+ filter: (prop) => prop.config_scope === 'cluster' && !prop.is_deprecated && !isObjectStorageProperty(prop)
74
81
  }
75
82
  ],
76
83
  filename: 'cluster-properties.adoc'
@@ -85,15 +92,7 @@ NOTE: Some object storage properties require that you restart the cluster for an
85
92
  sectionIntro: 'Object storage properties should only be set if you enable xref:manage:tiered-storage.adoc[Tiered Storage].',
86
93
  groups: [
87
94
  {
88
- filter: (prop) => prop.name && (
89
- prop.name.includes('cloud_storage') ||
90
- prop.name.includes('s3_') ||
91
- prop.name.includes('azure_') ||
92
- prop.name.includes('gcs_') ||
93
- prop.name.includes('archival_') ||
94
- prop.name.includes('remote_') ||
95
- prop.name.includes('tiered_')
96
- ) && !prop.is_deprecated
95
+ filter: (prop) => isObjectStorageProperty(prop) && !prop.is_deprecated
97
96
  }
98
97
  ],
99
98
  filename: 'object-storage-properties.adoc'
@@ -207,39 +206,165 @@ function registerPartials(hasCloudSupport = false) {
207
206
  * Generates documentation for a specific property type
208
207
  */
209
208
  function generatePropertyDocs(properties, config, outputDir) {
209
+ // Check if partials are being generated to determine which template to use
210
+ const useIncludes = process.env.GENERATE_PARTIALS === '1';
211
+
212
+ let templatePath;
213
+ if (useIncludes) {
214
+ // Use the include-based template when partials are also being generated
215
+ templatePath = getTemplatePath(
216
+ path.join(__dirname, 'templates', 'property-page-with-includes.hbs'),
217
+ 'TEMPLATE_PROPERTY_PAGE_WITH_INCLUDES'
218
+ );
219
+ } else {
220
+ // Use the standard template for full content
221
+ templatePath = getTemplatePath(
222
+ path.join(__dirname, 'templates', 'property-page.hbs'),
223
+ 'TEMPLATE_PROPERTY_PAGE'
224
+ );
225
+ }
226
+
227
+ const template = handlebars.compile(fs.readFileSync(templatePath, 'utf8'));
228
+
229
+ if (useIncludes) {
230
+ // For include-based pages, we need minimal data - just page metadata and filename for include
231
+ const data = {
232
+ ...config,
233
+ filename: config.filename.replace('.adoc', '') // Remove .adoc extension for include
234
+ };
235
+
236
+ const output = template(data);
237
+ const outputPath = path.join(outputDir, config.filename);
238
+
239
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
240
+ fs.writeFileSync(outputPath, output, 'utf8');
241
+
242
+ console.log(`✅ Generated include-based page ${outputPath}`);
243
+
244
+ // Count properties for this type
245
+ const typeCount = Object.values(properties).filter(prop => {
246
+ return config.groups.some(group => group.filter(prop));
247
+ }).length;
248
+
249
+ return typeCount;
250
+ } else {
251
+ // Filter and group properties according to configuration
252
+ const groups = config.groups.map(group => {
253
+ const filteredProperties = Object.values(properties)
254
+ .filter(prop => group.filter(prop))
255
+ .sort((a, b) => String(a.name || '').localeCompare(String(b.name || '')));
256
+
257
+ return {
258
+ title: group.title,
259
+ intro: group.intro,
260
+ properties: filteredProperties,
261
+ template: group.template || 'property' // Default to 'property' template
262
+ };
263
+ }).filter(group => group.properties.length > 0);
264
+
265
+ const data = {
266
+ ...config,
267
+ groups
268
+ };
269
+
270
+ const output = template(data);
271
+ const outputPath = path.join(outputDir, config.filename);
272
+
273
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
274
+ fs.writeFileSync(outputPath, output, 'utf8');
275
+
276
+ console.log(`✅ Generated full content page ${outputPath}`);
277
+ return groups.reduce((total, group) => total + group.properties.length, 0);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Generate consolidated AsciiDoc partials for properties grouped by type.
283
+ *
284
+ * Creates separate .adoc files for each property type (cluster-properties.adoc,
285
+ * topic-properties.adoc, object-storage-properties.adoc, broker-properties.adoc)
286
+ * containing all properties of that type using the appropriate templates.
287
+ *
288
+ * @param {Object} properties - Map of properties (property name → property object).
289
+ * @param {string} partialsDir - Directory where consolidated property files will be written.
290
+ * @param {boolean} [hasCloudSupport=false] - If true, use cloud-aware templates.
291
+ * @returns {number} The total number of properties included in the consolidated partials.
292
+ */
293
+ function generatePropertyPartials(properties, partialsDir, hasCloudSupport = false) {
294
+ console.log(`📝 Generating consolidated property partials in ${partialsDir}…`);
295
+
296
+ // Use the appropriate template based on cloud support
297
+ const templateName = hasCloudSupport ? 'property-cloud' : 'property';
210
298
  const templatePath = getTemplatePath(
211
- path.join(__dirname, 'templates', 'property-page.hbs'),
212
- 'TEMPLATE_PROPERTY_PAGE'
299
+ path.join(__dirname, 'templates', `${templateName}.hbs`),
300
+ 'TEMPLATE_PROPERTY'
213
301
  );
214
302
  const template = handlebars.compile(fs.readFileSync(templatePath, 'utf8'));
215
303
 
216
- // Filter and group properties according to configuration
217
- const groups = config.groups.map(group => {
218
- const filteredProperties = Object.values(properties)
219
- .filter(prop => group.filter(prop))
220
- .sort((a, b) => String(a.name || '').localeCompare(String(b.name || '')));
221
-
222
- return {
223
- title: group.title,
224
- intro: group.intro,
225
- properties: filteredProperties,
226
- template: group.template || 'property' // Default to 'property' template
227
- };
228
- }).filter(group => group.properties.length > 0);
304
+ // Use the topic property template for topic properties
305
+ const topicTemplateName = hasCloudSupport ? 'topic-property-cloud' : 'topic-property';
306
+ const topicTemplatePath = getTemplatePath(
307
+ path.join(__dirname, 'templates', `${topicTemplateName}.hbs`),
308
+ 'TEMPLATE_TOPIC_PROPERTY'
309
+ );
310
+ const topicTemplate = handlebars.compile(fs.readFileSync(topicTemplatePath, 'utf8'));
229
311
 
230
- const data = {
231
- ...config,
232
- groups
312
+ // Create the main partials directory
313
+ const propertiesPartialsDir = path.join(partialsDir, 'properties');
314
+ fs.mkdirSync(propertiesPartialsDir, { recursive: true });
315
+
316
+ // Group properties by type
317
+ const propertyGroups = {
318
+ cluster: [],
319
+ topic: [],
320
+ broker: [],
321
+ 'object-storage': []
233
322
  };
234
323
 
235
- const output = template(data);
236
- const outputPath = path.join(outputDir, config.filename);
324
+ // Categorize properties
325
+ Object.values(properties).forEach(prop => {
326
+ if (!prop.name || !prop.config_scope) return; // Skip properties without names or scope
327
+
328
+ if (prop.config_scope === 'topic') {
329
+ propertyGroups.topic.push(prop);
330
+ } else if (prop.config_scope === 'broker') {
331
+ propertyGroups.broker.push(prop);
332
+ } else if (prop.config_scope === 'cluster') {
333
+ // Check if it's an object storage property
334
+ if (isObjectStorageProperty(prop)) {
335
+ propertyGroups['object-storage'].push(prop);
336
+ } else {
337
+ propertyGroups.cluster.push(prop);
338
+ }
339
+ }
340
+ });
341
+
342
+ let totalCount = 0;
237
343
 
238
- fs.mkdirSync(path.dirname(outputPath), { recursive: true });
239
- fs.writeFileSync(outputPath, output, 'utf8');
344
+ // Generate consolidated partials for each property type
345
+ Object.entries(propertyGroups).forEach(([type, props]) => {
346
+ if (props.length === 0) return;
347
+
348
+ // Sort properties by name
349
+ props.sort((a, b) => String(a.name || '').localeCompare(String(b.name || '')));
350
+
351
+ // Choose the appropriate template based on property type
352
+ const selectedTemplate = type === 'topic' ? topicTemplate : template;
353
+
354
+ // Generate content for all properties of this type
355
+ const content = props.map(prop => selectedTemplate(prop)).join('\n');
356
+
357
+ // Write the consolidated file
358
+ const filename = `${type}-properties.adoc`;
359
+ const outputPath = path.join(propertiesPartialsDir, filename);
360
+ fs.writeFileSync(outputPath, content, 'utf8');
361
+
362
+ console.log(`✅ Generated ${outputPath} with ${props.length} properties`);
363
+ totalCount += props.length;
364
+ });
240
365
 
241
- console.log(`✅ Generated ${outputPath}`);
242
- return groups.reduce((total, group) => total + group.properties.length, 0);
366
+ console.log(`✅ Generated consolidated property partials in ${partialsDir} (${totalCount} total properties)`);
367
+ return totalCount;
243
368
  }
244
369
 
245
370
  /**
@@ -279,8 +404,19 @@ function generateDeprecatedDocs(properties, outputDir) {
279
404
  };
280
405
 
281
406
  const output = template(data);
282
- // Navigate back from pages/properties to reference, then into partials/deprecated
283
- const outputPath = path.join(path.dirname(path.dirname(outputDir)), 'partials', 'deprecated', 'deprecated-properties.adoc');
407
+
408
+ // Determine the correct path for deprecated properties
409
+ let outputPath;
410
+ if (process.env.OUTPUT_PARTIALS_DIR) {
411
+ // Use the explicitly set partials directory
412
+ outputPath = path.join(process.env.OUTPUT_PARTIALS_DIR, 'deprecated', 'deprecated-properties.adoc');
413
+ } else if (outputDir.includes('pages/properties')) {
414
+ // Fallback: Navigate back from pages/properties to reference, then into partials/deprecated
415
+ outputPath = path.join(path.dirname(path.dirname(outputDir)), 'partials', 'deprecated', 'deprecated-properties.adoc');
416
+ } else {
417
+ // Fallback: Direct path when outputDir is the base directory
418
+ outputPath = path.join(outputDir, 'partials', 'deprecated', 'deprecated-properties.adoc');
419
+ }
284
420
 
285
421
  fs.mkdirSync(path.dirname(outputPath), { recursive: true });
286
422
  fs.writeFileSync(outputPath, output, 'utf8');
@@ -341,26 +477,68 @@ function generateAllDocs(inputFile, outputDir) {
341
477
  let totalObjectStorageProperties = 0;
342
478
  let totalTopicProperties = 0;
343
479
 
344
- // Generate each type of documentation
345
- for (const [type, config] of Object.entries(PROPERTY_CONFIG)) {
346
- const count = generatePropertyDocs(properties, config, outputDir);
347
- totalProperties += count;
480
+ // Generate complete property pages only if requested
481
+ if (process.env.GENERATE_PAGES === '1') {
482
+ console.log(`📄 Generating complete property pages...`);
483
+
484
+ // Generate each type of documentation
485
+ for (const [type, config] of Object.entries(PROPERTY_CONFIG)) {
486
+ const count = generatePropertyDocs(properties, config, outputDir);
487
+ totalProperties += count;
488
+
489
+ if (type === 'broker') totalBrokerProperties = count;
490
+ else if (type === 'cluster') totalClusterProperties = count;
491
+ else if (type === 'object-storage') totalObjectStorageProperties = count;
492
+ else if (type === 'topic') totalTopicProperties = count;
493
+ }
494
+ } else {
495
+ console.log(`📄 Skipping complete property pages (use --generate-pages to enable)`);
348
496
 
349
- if (type === 'broker') totalBrokerProperties = count;
350
- else if (type === 'cluster') totalClusterProperties = count;
351
- else if (type === 'object-storage') totalObjectStorageProperties = count;
352
- else if (type === 'topic') totalTopicProperties = count;
497
+ // Still count properties for summary
498
+ Object.values(properties).forEach(prop => {
499
+ if (prop.config_scope === 'broker' && !prop.is_deprecated) totalBrokerProperties++;
500
+ else if (prop.config_scope === 'cluster' && !prop.is_deprecated) {
501
+ if (prop.name && (
502
+ prop.name.includes('cloud_storage') ||
503
+ prop.name.includes('s3_') ||
504
+ prop.name.includes('azure_') ||
505
+ prop.name.includes('gcs_') ||
506
+ prop.name.includes('archival_') ||
507
+ prop.name.includes('remote_') ||
508
+ prop.name.includes('tiered_')
509
+ )) {
510
+ totalObjectStorageProperties++;
511
+ } else {
512
+ totalClusterProperties++;
513
+ }
514
+ }
515
+ else if (prop.config_scope === 'topic' && !prop.is_deprecated) totalTopicProperties++;
516
+ });
517
+ totalProperties = totalBrokerProperties + totalClusterProperties + totalObjectStorageProperties + totalTopicProperties;
353
518
  }
354
519
 
355
- // Generate deprecated properties documentation
356
- const deprecatedCount = generateDeprecatedDocs(properties, outputDir);
520
+ // Generate individual property partials if requested
521
+ let partialsCount = 0;
522
+ let deprecatedCount = 0;
523
+ if (process.env.GENERATE_PARTIALS === '1' && process.env.OUTPUT_PARTIALS_DIR) {
524
+ // Generate deprecated properties documentation
525
+ deprecatedCount = generateDeprecatedDocs(properties, outputDir);
526
+
527
+ partialsCount = generatePropertyPartials(properties, process.env.OUTPUT_PARTIALS_DIR, hasCloudSupport);
528
+ } else {
529
+ console.log(`📄 Skipping property partials (use --generate-partials to enable)`);
530
+ console.log(`📄 Skipping deprecated properties documentation (use --generate-partials to enable)`);
531
+ }
357
532
 
358
- // Generate summary file
359
- const allPropertiesContent = Object.keys(properties).sort().join('\n');
360
- fs.writeFileSync(path.join(outputDir, 'all_properties.txt'), allPropertiesContent, 'utf8');
533
+ // Generate error reports and add to input JSON output
534
+ const errorReport = generateErrorReports(properties, outputDir);
361
535
 
362
- // Generate error reports
363
- generateErrorReports(properties, outputDir);
536
+ // Add error arrays directly to the input file so they're included when copied
537
+ const inputData = JSON.parse(fs.readFileSync(inputFile, 'utf8'));
538
+ inputData.empty_descriptions = errorReport.empty_descriptions;
539
+ inputData.deprecated_properties = errorReport.deprecated_properties;
540
+ fs.writeFileSync(inputFile, JSON.stringify(inputData, null, 2), 'utf8');
541
+ console.log(`📝 Added error arrays to ${inputFile}`);
364
542
 
365
543
  console.log(`📊 Generation Summary:`);
366
544
  console.log(` Total properties read: ${Object.keys(properties).length}`);
@@ -369,6 +547,9 @@ function generateAllDocs(inputFile, outputDir) {
369
547
  console.log(` Total Object Storage properties: ${totalObjectStorageProperties}`);
370
548
  console.log(` Total Topic properties: ${totalTopicProperties}`);
371
549
  console.log(` Total Deprecated properties: ${deprecatedCount}`);
550
+ if (partialsCount > 0) {
551
+ console.log(` Total Property partials: ${partialsCount}`);
552
+ }
372
553
 
373
554
  return {
374
555
  totalProperties: Object.keys(properties).length,
@@ -376,7 +557,8 @@ function generateAllDocs(inputFile, outputDir) {
376
557
  clusterProperties: totalClusterProperties,
377
558
  objectStorageProperties: totalObjectStorageProperties,
378
559
  topicProperties: totalTopicProperties,
379
- deprecatedProperties: deprecatedCount
560
+ deprecatedProperties: deprecatedCount,
561
+ propertyPartials: partialsCount
380
562
  };
381
563
  }
382
564
 
@@ -384,9 +566,6 @@ function generateAllDocs(inputFile, outputDir) {
384
566
  * Generate error reports for properties with missing or invalid data
385
567
  */
386
568
  function generateErrorReports(properties, outputDir) {
387
- const errorDir = path.join(outputDir, 'error');
388
- fs.mkdirSync(errorDir, { recursive: true });
389
-
390
569
  const emptyDescriptions = [];
391
570
  const deprecatedProperties = [];
392
571
 
@@ -399,34 +578,25 @@ function generateErrorReports(properties, outputDir) {
399
578
  }
400
579
  });
401
580
 
402
- // Write error reports
581
+ // Add these arrays to the properties JSON file
403
582
  const totalProperties = Object.keys(properties).length;
404
-
405
- if (emptyDescriptions.length > 0) {
406
- fs.writeFileSync(
407
- path.join(errorDir, 'empty_description.txt'),
408
- emptyDescriptions.join('\n'),
409
- 'utf8'
410
- );
411
- const percentage = totalProperties > 0 ? ((emptyDescriptions.length / totalProperties) * 100).toFixed(2) : '0.00';
412
- console.log(`You have ${emptyDescriptions.length} properties with empty description. Percentage of errors: ${percentage}%. Data written in 'empty_description.txt'.`);
413
- }
583
+ const percentageEmpty = totalProperties > 0 ? ((emptyDescriptions.length / totalProperties) * 100).toFixed(2) : '0.00';
584
+ const percentageDeprecated = totalProperties > 0 ? ((deprecatedProperties.length / totalProperties) * 100).toFixed(2) : '0.00';
585
+ console.log(`You have ${emptyDescriptions.length} properties with empty description. Percentage of errors: ${percentageEmpty}%.`);
586
+ console.log(`You have ${deprecatedProperties.length} deprecated properties. Percentage of errors: ${percentageDeprecated}%.`);
414
587
 
415
- if (deprecatedProperties.length > 0) {
416
- fs.writeFileSync(
417
- path.join(errorDir, 'deprecated_properties.txt'),
418
- deprecatedProperties.join('\n'),
419
- 'utf8'
420
- );
421
- const percentage = totalProperties > 0 ? ((deprecatedProperties.length / totalProperties) * 100).toFixed(2) : '0.00';
422
- console.log(`You have ${deprecatedProperties.length} deprecated properties. Percentage of errors: ${percentage}%. Data written in 'deprecated_properties.txt'.`);
423
- }
588
+ // Return the arrays sorted for deterministic output
589
+ return {
590
+ empty_descriptions: emptyDescriptions.sort(),
591
+ deprecated_properties: deprecatedProperties.sort()
592
+ };
424
593
  }
425
594
 
426
595
  module.exports = {
427
596
  generateAllDocs,
428
597
  generatePropertyDocs,
429
598
  generateDeprecatedDocs,
599
+ generatePropertyPartials,
430
600
  PROPERTY_CONFIG
431
601
  };
432
602
 
@@ -877,15 +877,18 @@ def add_config_scope(properties):
877
877
  if prop.get("is_topic_property", False):
878
878
  prop["config_scope"] = "topic"
879
879
  else:
880
- # For override-created properties, preserve existing config_scope if set
881
- if prop.get("defined_in") == "override" and prop.get("config_scope") is not None:
882
- # Keep the existing config_scope from override
880
+ # Skip config_scope assignment if it's already been set by an override
881
+ if prop.get("config_scope") is not None:
882
+ # Keep the existing config_scope from override or previous assignment
883
883
  pass
884
884
  else:
885
885
  defined_in = prop.get("defined_in", "")
886
886
  if defined_in == "src/v/config/configuration.cc":
887
887
  prop["config_scope"] = "cluster"
888
- elif defined_in == "src/v/config/node_config.cc":
888
+ elif defined_in in ["src/v/config/node_config.cc",
889
+ "src/v/pandaproxy/rest/configuration.cc",
890
+ "src/v/kafka/client/configuration.cc",
891
+ "src/v/pandaproxy/schema_registry/configuration.cc"]:
889
892
  prop["config_scope"] = "broker"
890
893
  else:
891
894
  prop["config_scope"] = None
@@ -1,3 +1,4 @@
1
+ {{#unless is_deprecated}}
1
2
  {{#if cloud_supported}}
2
3
  // tag::redpanda-cloud[]
3
4
  {{/if}}
@@ -20,8 +21,9 @@ ifndef::env-cloud[]
20
21
  endif::[]
21
22
  {{/if}}
22
23
  {{#if cloud_byoc_only}}
23
-
24
+ ifdef::env-cloud[]
24
25
  NOTE: This property is available only in Redpanda Cloud BYOC deployments.
26
+ endif::[]
25
27
  {{/if}}
26
28
  {{#if units}}
27
29
 
@@ -71,9 +73,7 @@ ifndef::env-cloud[]
71
73
  endif::[]
72
74
  {{/if}}
73
75
 
74
- // tag::self-managed-only[]
75
76
  *Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
76
- // end::self-managed-only[]
77
77
  {{#if example}}
78
78
 
79
79
  {{{renderPropertyExample this}}}
@@ -92,14 +92,9 @@ endif::[]
92
92
  *Aliases:* {{join aliases ", "}}
93
93
  // end::self-managed-only[]
94
94
  {{/if}}
95
- {{#if is_deprecated}}
96
95
 
97
- [WARNING]
98
- ====
99
- This property is deprecated.
100
- ====
101
- {{/if}}
102
96
  ---
103
97
  {{#if cloud_supported}}
104
98
  // end::redpanda-cloud[]
105
99
  {{/if}}
100
+ {{/unless}}
@@ -0,0 +1,17 @@
1
+ = {{pageTitle}}
2
+ {{#if pageAliases}}
3
+ :page-aliases: {{join pageAliases ", "}}
4
+ {{/if}}
5
+ :description: {{description}}
6
+
7
+ {{{intro}}}
8
+
9
+ {{#if sectionTitle}}
10
+ == {{sectionTitle}}
11
+ {{/if}}
12
+
13
+ {{#if sectionIntro}}
14
+ {{{sectionIntro}}}
15
+ {{/if}}
16
+
17
+ include::reference:partial$properties/{{filename}}.adoc[]
@@ -1,3 +1,4 @@
1
+ {{#unless is_deprecated}}
1
2
  === {{name}}
2
3
 
3
4
  {{#if version}}
@@ -58,28 +59,22 @@ endif::[]
58
59
 
59
60
  {{/if}}
60
61
  *Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
61
-
62
62
  {{#if example}}
63
+
63
64
  {{{renderPropertyExample this}}}
64
65
  {{/if}}
65
-
66
66
  {{#if related_topics}}
67
+
67
68
  *Related topics:*
68
69
 
69
70
  {{#each related_topics}}
70
71
  * {{{this}}}
71
72
  {{/each}}
72
73
  {{/if}}
73
-
74
74
  {{#if aliases}}
75
- *Aliases:* {{join aliases ", "}}
76
-
77
- {{/if}}
78
- {{#if is_deprecated}}
79
- [WARNING]
80
- ====
81
- This property is deprecated.
82
- ====
83
75
 
76
+ *Aliases:* {{join aliases ", "}}
84
77
  {{/if}}
85
78
  ---
79
+ {{/unless}}
80
+
@@ -1,3 +1,4 @@
1
+ {{#unless is_deprecated}}
1
2
  {{#if cloud_supported}}
2
3
  // tag::redpanda-cloud[]
3
4
  {{/if}}
@@ -84,14 +85,10 @@ endif::[]
84
85
  *Aliases:* {{join aliases ", "}}
85
86
  // end::self-managed-only[]
86
87
  {{/if}}
87
- {{#if is_deprecated}}
88
88
 
89
- [WARNING]
90
- ====
91
- This property is deprecated.
92
- ====
93
- {{/if}}
94
89
  ---
95
90
  {{#if cloud_supported}}
96
91
  // end::redpanda-cloud[]
97
92
  {{/if}}
93
+
94
+ {{/unless}}
@@ -1,3 +1,4 @@
1
+ {{#unless is_deprecated}}
1
2
  === {{name}}
2
3
  {{#if version}}
3
4
 
@@ -63,11 +64,6 @@ endif::[]
63
64
 
64
65
  *Aliases:* {{join aliases ", "}}
65
66
  {{/if}}
66
- {{#if is_deprecated}}
67
67
 
68
- [WARNING]
69
- ====
70
- This property is deprecated.
71
- ====
72
- {{/if}}
73
68
  ---
69
+ {{/unless}}