@redpanda-data/docs-extensions-and-macros 4.10.0 → 4.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/doc-tools.js +23 -3
- package/package.json +1 -1
- package/tools/property-extractor/Makefile +3 -2
- package/tools/property-extractor/generate-handlebars-docs.js +255 -74
- package/tools/property-extractor/property_extractor.py +285 -40
- package/tools/property-extractor/templates/property-cloud.hbs +2 -3
- package/tools/property-extractor/templates/property-page-with-includes.hbs +17 -0
- package/tools/property-extractor/templates/property.hbs +4 -5
- package/tools/property-extractor/transformers.py +240 -36
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>
|
|
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', '
|
|
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);
|
|
@@ -1111,6 +1115,22 @@ automation
|
|
|
1111
1115
|
} else {
|
|
1112
1116
|
env.OUTPUT_JSON_DIR = path.resolve(outputDir, 'examples');
|
|
1113
1117
|
env.OUTPUT_AUTOGENERATED_DIR = path.resolve(outputDir);
|
|
1118
|
+
// Set property files to go to properties subdirectory
|
|
1119
|
+
env.OUTPUT_ASCIIDOC_DIR = path.resolve(outputDir, 'pages', 'properties');
|
|
1120
|
+
}
|
|
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
|
+
}
|
|
1114
1134
|
}
|
|
1115
1135
|
|
|
1116
1136
|
const r = spawnSync('make', args, { cwd, stdio: 'inherit', env });
|
package/package.json
CHANGED
|
@@ -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
|
|
@@ -111,10 +112,10 @@ generate-docs: node-deps
|
|
|
111
112
|
@# Use the enhanced properties file (with overrides) for documentation generation if it exists
|
|
112
113
|
@if [ -f "$(TOOL_ROOT)/gen/$(TAG)-properties.json" ]; then \
|
|
113
114
|
cd $(TOOL_ROOT) && \
|
|
114
|
-
node generate-handlebars-docs.js "gen/$(TAG)-properties.json" "$(
|
|
115
|
+
node generate-handlebars-docs.js "gen/$(TAG)-properties.json" "$(OUTPUT_ASCIIDOC_DIR)"; \
|
|
115
116
|
else \
|
|
116
117
|
cd $(TOOL_ROOT) && \
|
|
117
|
-
node generate-handlebars-docs.js "gen/properties-output.json" "$(
|
|
118
|
+
node generate-handlebars-docs.js "gen/properties-output.json" "$(OUTPUT_ASCIIDOC_DIR)"; \
|
|
118
119
|
fi
|
|
119
120
|
@echo "📄 Copying properties JSON files to $(OUTPUT_JSON_DIR)…"
|
|
120
121
|
@if [ -f "$(TOOL_ROOT)/gen/$(TAG)-properties.json" ]; then \
|
|
@@ -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,7 +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
|
|
80
|
+
filter: (prop) => prop.config_scope === 'cluster' && !prop.is_deprecated && !isObjectStorageProperty(prop)
|
|
64
81
|
}
|
|
65
82
|
],
|
|
66
83
|
filename: 'cluster-properties.adoc'
|
|
@@ -75,15 +92,7 @@ NOTE: Some object storage properties require that you restart the cluster for an
|
|
|
75
92
|
sectionIntro: 'Object storage properties should only be set if you enable xref:manage:tiered-storage.adoc[Tiered Storage].',
|
|
76
93
|
groups: [
|
|
77
94
|
{
|
|
78
|
-
filter: (prop) => prop
|
|
79
|
-
prop.name.includes('cloud_storage') ||
|
|
80
|
-
prop.name.includes('s3_') ||
|
|
81
|
-
prop.name.includes('azure_') ||
|
|
82
|
-
prop.name.includes('gcs_') ||
|
|
83
|
-
prop.name.includes('archival_') ||
|
|
84
|
-
prop.name.includes('remote_') ||
|
|
85
|
-
prop.name.includes('tiered_')
|
|
86
|
-
) && !prop.is_deprecated
|
|
95
|
+
filter: (prop) => isObjectStorageProperty(prop) && !prop.is_deprecated
|
|
87
96
|
}
|
|
88
97
|
],
|
|
89
98
|
filename: 'object-storage-properties.adoc'
|
|
@@ -197,39 +206,165 @@ function registerPartials(hasCloudSupport = false) {
|
|
|
197
206
|
* Generates documentation for a specific property type
|
|
198
207
|
*/
|
|
199
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';
|
|
200
298
|
const templatePath = getTemplatePath(
|
|
201
|
-
path.join(__dirname, 'templates',
|
|
202
|
-
'
|
|
299
|
+
path.join(__dirname, 'templates', `${templateName}.hbs`),
|
|
300
|
+
'TEMPLATE_PROPERTY'
|
|
203
301
|
);
|
|
204
302
|
const template = handlebars.compile(fs.readFileSync(templatePath, 'utf8'));
|
|
205
303
|
|
|
206
|
-
//
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
title: group.title,
|
|
214
|
-
intro: group.intro,
|
|
215
|
-
properties: filteredProperties,
|
|
216
|
-
template: group.template || 'property' // Default to 'property' template
|
|
217
|
-
};
|
|
218
|
-
}).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'));
|
|
219
311
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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': []
|
|
223
322
|
};
|
|
224
323
|
|
|
225
|
-
|
|
226
|
-
|
|
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;
|
|
227
343
|
|
|
228
|
-
|
|
229
|
-
|
|
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
|
+
});
|
|
230
365
|
|
|
231
|
-
console.log(`✅ Generated ${
|
|
232
|
-
return
|
|
366
|
+
console.log(`✅ Generated consolidated property partials in ${partialsDir} (${totalCount} total properties)`);
|
|
367
|
+
return totalCount;
|
|
233
368
|
}
|
|
234
369
|
|
|
235
370
|
/**
|
|
@@ -269,7 +404,19 @@ function generateDeprecatedDocs(properties, outputDir) {
|
|
|
269
404
|
};
|
|
270
405
|
|
|
271
406
|
const output = template(data);
|
|
272
|
-
|
|
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
|
+
}
|
|
273
420
|
|
|
274
421
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
275
422
|
fs.writeFileSync(outputPath, output, 'utf8');
|
|
@@ -330,26 +477,68 @@ function generateAllDocs(inputFile, outputDir) {
|
|
|
330
477
|
let totalObjectStorageProperties = 0;
|
|
331
478
|
let totalTopicProperties = 0;
|
|
332
479
|
|
|
333
|
-
// Generate
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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)`);
|
|
337
496
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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;
|
|
342
518
|
}
|
|
343
519
|
|
|
344
|
-
// Generate
|
|
345
|
-
|
|
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
|
+
}
|
|
346
532
|
|
|
347
|
-
// Generate
|
|
348
|
-
const
|
|
349
|
-
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);
|
|
350
535
|
|
|
351
|
-
//
|
|
352
|
-
|
|
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}`);
|
|
353
542
|
|
|
354
543
|
console.log(`📊 Generation Summary:`);
|
|
355
544
|
console.log(` Total properties read: ${Object.keys(properties).length}`);
|
|
@@ -358,6 +547,9 @@ function generateAllDocs(inputFile, outputDir) {
|
|
|
358
547
|
console.log(` Total Object Storage properties: ${totalObjectStorageProperties}`);
|
|
359
548
|
console.log(` Total Topic properties: ${totalTopicProperties}`);
|
|
360
549
|
console.log(` Total Deprecated properties: ${deprecatedCount}`);
|
|
550
|
+
if (partialsCount > 0) {
|
|
551
|
+
console.log(` Total Property partials: ${partialsCount}`);
|
|
552
|
+
}
|
|
361
553
|
|
|
362
554
|
return {
|
|
363
555
|
totalProperties: Object.keys(properties).length,
|
|
@@ -365,7 +557,8 @@ function generateAllDocs(inputFile, outputDir) {
|
|
|
365
557
|
clusterProperties: totalClusterProperties,
|
|
366
558
|
objectStorageProperties: totalObjectStorageProperties,
|
|
367
559
|
topicProperties: totalTopicProperties,
|
|
368
|
-
deprecatedProperties: deprecatedCount
|
|
560
|
+
deprecatedProperties: deprecatedCount,
|
|
561
|
+
propertyPartials: partialsCount
|
|
369
562
|
};
|
|
370
563
|
}
|
|
371
564
|
|
|
@@ -373,9 +566,6 @@ function generateAllDocs(inputFile, outputDir) {
|
|
|
373
566
|
* Generate error reports for properties with missing or invalid data
|
|
374
567
|
*/
|
|
375
568
|
function generateErrorReports(properties, outputDir) {
|
|
376
|
-
const errorDir = path.join(outputDir, 'error');
|
|
377
|
-
fs.mkdirSync(errorDir, { recursive: true });
|
|
378
|
-
|
|
379
569
|
const emptyDescriptions = [];
|
|
380
570
|
const deprecatedProperties = [];
|
|
381
571
|
|
|
@@ -388,34 +578,25 @@ function generateErrorReports(properties, outputDir) {
|
|
|
388
578
|
}
|
|
389
579
|
});
|
|
390
580
|
|
|
391
|
-
//
|
|
581
|
+
// Add these arrays to the properties JSON file
|
|
392
582
|
const totalProperties = Object.keys(properties).length;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
emptyDescriptions.join('\n'),
|
|
398
|
-
'utf8'
|
|
399
|
-
);
|
|
400
|
-
const percentage = totalProperties > 0 ? ((emptyDescriptions.length / totalProperties) * 100).toFixed(2) : '0.00';
|
|
401
|
-
console.log(`You have ${emptyDescriptions.length} properties with empty description. Percentage of errors: ${percentage}%. Data written in 'empty_description.txt'.`);
|
|
402
|
-
}
|
|
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}%.`);
|
|
403
587
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
);
|
|
410
|
-
const percentage = totalProperties > 0 ? ((deprecatedProperties.length / totalProperties) * 100).toFixed(2) : '0.00';
|
|
411
|
-
console.log(`You have ${deprecatedProperties.length} deprecated properties. Percentage of errors: ${percentage}%. Data written in 'deprecated_properties.txt'.`);
|
|
412
|
-
}
|
|
588
|
+
// Return the arrays sorted for deterministic output
|
|
589
|
+
return {
|
|
590
|
+
empty_descriptions: emptyDescriptions.sort(),
|
|
591
|
+
deprecated_properties: deprecatedProperties.sort()
|
|
592
|
+
};
|
|
413
593
|
}
|
|
414
594
|
|
|
415
595
|
module.exports = {
|
|
416
596
|
generateAllDocs,
|
|
417
597
|
generatePropertyDocs,
|
|
418
598
|
generateDeprecatedDocs,
|
|
599
|
+
generatePropertyPartials,
|
|
419
600
|
PROPERTY_CONFIG
|
|
420
601
|
};
|
|
421
602
|
|