@redpanda-data/docs-extensions-and-macros 4.6.1 → 4.6.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 +26 -18
- package/extensions/generate-rp-connect-info.js +31 -13
- package/macros/badge.js +21 -0
- package/package.json +3 -2
- package/tools/redpanda-connect/generate-rpcn-connector-docs.js +64 -12
- package/tools/redpanda-connect/helpers/renderConnectFields.js +46 -51
- package/tools/redpanda-connect/helpers/renderLeafField.js +40 -17
- package/tools/redpanda-connect/helpers/renderYamlList.js +20 -6
- package/macros/enterprise-label.js +0 -11
package/bin/doc-tools.js
CHANGED
|
@@ -546,22 +546,27 @@ automation
|
|
|
546
546
|
}
|
|
547
547
|
|
|
548
548
|
if (options.draftMissing) {
|
|
549
|
-
console.log('⏳ Drafting missing connectors
|
|
549
|
+
console.log('⏳ Drafting missing connectors…');
|
|
550
550
|
try {
|
|
551
551
|
const connectorList = await parseCSVConnectors(options.csv, console);
|
|
552
|
-
const validConnectors = connectorList.filter(
|
|
552
|
+
const validConnectors = connectorList.filter(r => r.name && r.type);
|
|
553
553
|
|
|
554
|
-
const
|
|
554
|
+
const roots = {
|
|
555
|
+
pages: path.resolve(process.cwd(), 'modules/components/pages'),
|
|
556
|
+
partials:path.resolve(process.cwd(), 'modules/components/partials/components'),
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
// find any connector that has NO .adoc under pages/TYPEs or partials/TYPEs
|
|
555
560
|
const allMissing = validConnectors.filter(({ name, type }) => {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
return !fs.existsSync(expected);
|
|
561
|
+
const relPath = path.join(`${type}s`, `${name}.adoc`);
|
|
562
|
+
const existsInAny = Object.values(roots).some(root =>
|
|
563
|
+
fs.existsSync(path.join(root, relPath))
|
|
564
|
+
);
|
|
565
|
+
return !existsInAny;
|
|
562
566
|
});
|
|
563
567
|
|
|
564
|
-
|
|
568
|
+
// still skip sql_driver
|
|
569
|
+
const missingConnectors = allMissing.filter(c => !c.name.includes('sql_driver'));
|
|
565
570
|
|
|
566
571
|
if (missingConnectors.length === 0) {
|
|
567
572
|
console.log('✅ All connectors (excluding sql_drivers) already have docs—nothing to draft.');
|
|
@@ -572,17 +577,20 @@ automation
|
|
|
572
577
|
});
|
|
573
578
|
console.log('');
|
|
574
579
|
|
|
580
|
+
// build your filtered JSON as before…
|
|
575
581
|
const rawData = fs.readFileSync(dataFile, 'utf8');
|
|
576
582
|
const dataObj = JSON.parse(rawData);
|
|
577
|
-
|
|
578
583
|
const filteredDataObj = {};
|
|
584
|
+
|
|
579
585
|
for (const [key, arr] of Object.entries(dataObj)) {
|
|
580
586
|
if (!Array.isArray(arr)) {
|
|
581
587
|
filteredDataObj[key] = arr;
|
|
582
588
|
continue;
|
|
583
589
|
}
|
|
584
590
|
filteredDataObj[key] = arr.filter(component =>
|
|
585
|
-
missingConnectors.some(
|
|
591
|
+
missingConnectors.some(
|
|
592
|
+
m => m.name === component.name && `${m.type}s` === key
|
|
593
|
+
)
|
|
586
594
|
);
|
|
587
595
|
}
|
|
588
596
|
|
|
@@ -590,12 +598,12 @@ automation
|
|
|
590
598
|
fs.writeFileSync(tempDataPath, JSON.stringify(filteredDataObj, null, 2), 'utf8');
|
|
591
599
|
|
|
592
600
|
const draftResult = await generateRpcnConnectorDocs({
|
|
593
|
-
data:
|
|
594
|
-
overrides:
|
|
595
|
-
template:
|
|
596
|
-
templateFields:
|
|
597
|
-
templateExamples:
|
|
598
|
-
templateIntro:
|
|
601
|
+
data: tempDataPath,
|
|
602
|
+
overrides: options.overrides,
|
|
603
|
+
template: options.templateMain,
|
|
604
|
+
templateFields: options.templateFields,
|
|
605
|
+
templateExamples:options.templateExamples,
|
|
606
|
+
templateIntro: options.templateIntro,
|
|
599
607
|
writeFullDrafts: true
|
|
600
608
|
});
|
|
601
609
|
|
|
@@ -115,40 +115,58 @@ module.exports.register = function ({ config }) {
|
|
|
115
115
|
let redpandaConnectUrl = '';
|
|
116
116
|
let redpandaCloudUrl = '';
|
|
117
117
|
|
|
118
|
+
function isConnectorDocPath (filePath, type) {
|
|
119
|
+
const dirsToCheck = [
|
|
120
|
+
`pages/${type}s/`,
|
|
121
|
+
`partials/components/${type}s/`
|
|
122
|
+
];
|
|
123
|
+
return dirsToCheck.some(dir => filePath.includes(dir));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isCloudDoc(file, connector, type) {
|
|
127
|
+
return (
|
|
128
|
+
file.src.component === 'redpanda-cloud' &&
|
|
129
|
+
file.path.includes(`connect/components/${type}s/${connector}.adoc`)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
118
133
|
// Look for both Redpanda Connect and Cloud URLs
|
|
119
134
|
for (const file of pages) {
|
|
120
|
-
const component = file.src
|
|
121
|
-
const filePath = file.
|
|
135
|
+
const { component } = file.src; // such as 'redpanda-connect'
|
|
136
|
+
const { path: filePath } = file; // such as modules/.../pages/sinks/foo.adoc
|
|
122
137
|
|
|
123
138
|
if (
|
|
124
139
|
component === 'redpanda-connect' &&
|
|
125
140
|
filePath.endsWith(`/${connector}.adoc`) &&
|
|
126
|
-
filePath
|
|
141
|
+
isConnectorDocPath(filePath, type)
|
|
127
142
|
) {
|
|
128
143
|
redpandaConnectUrl = file.pub.url;
|
|
129
144
|
}
|
|
130
145
|
|
|
131
|
-
//
|
|
132
|
-
if
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
filePath.endsWith(`/${connector}.adoc`) &&
|
|
136
|
-
filePath.includes(`${type}s/`)
|
|
137
|
-
) {
|
|
146
|
+
// -------------------------------------------------
|
|
147
|
+
// Redpanda Cloud (only if cloud supported)
|
|
148
|
+
// -------------------------------------------------
|
|
149
|
+
if (is_cloud_supported === 'y' && isCloudDoc(file, connector, type)) {
|
|
138
150
|
redpandaCloudUrl = file.pub.url;
|
|
139
151
|
}
|
|
140
152
|
}
|
|
141
153
|
|
|
142
|
-
// Log a warning if neither URL was found and the component is not deprecated
|
|
143
154
|
if (
|
|
144
155
|
deprecated !== 'y' &&
|
|
145
156
|
!connector.includes('sql_driver') &&
|
|
146
157
|
!redpandaConnectUrl &&
|
|
147
|
-
(
|
|
158
|
+
!(is_cloud_supported === 'y' && redpandaCloudUrl)
|
|
148
159
|
) {
|
|
149
|
-
logger.warn(`
|
|
160
|
+
logger.warn(`Self-Managed docs missing for: ${connector} of type: ${type}`);
|
|
150
161
|
}
|
|
151
162
|
|
|
163
|
+
if (
|
|
164
|
+
is_cloud_supported === 'y' &&
|
|
165
|
+
!redpandaCloudUrl &&
|
|
166
|
+
redpandaConnectUrl
|
|
167
|
+
) {
|
|
168
|
+
logger.warn(`Cloud docs missing for: ${connector} of type: ${type}`);
|
|
169
|
+
}
|
|
152
170
|
|
|
153
171
|
// Return the translated and enriched row
|
|
154
172
|
return {
|
package/macros/badge.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports.register = function (registry) {
|
|
4
|
+
registry.inlineMacro(function () {
|
|
5
|
+
const self = this;
|
|
6
|
+
self.named('badge');
|
|
7
|
+
self.process((parent, target, attrs) => {
|
|
8
|
+
const label = attrs.label || 'label';
|
|
9
|
+
const className = `badge--${label.toLowerCase().replace(/\s+/g, '-')}`;
|
|
10
|
+
const isLarge = attrs.size === 'large';
|
|
11
|
+
const sizeClass = isLarge ? 'badge--large' : '';
|
|
12
|
+
const tooltip = attrs.tooltip;
|
|
13
|
+
const tooltipAttr = tooltip ? ` data-tooltip="${tooltip}"` : '';
|
|
14
|
+
|
|
15
|
+
// Add brackets if not large
|
|
16
|
+
const renderedLabel = isLarge ? label : `(${label})`;
|
|
17
|
+
|
|
18
|
+
return `<span class="badge ${className} ${sizeClass}"${tooltipAttr}>${renderedLabel}</span>`;
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redpanda-data/docs-extensions-and-macros",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.3",
|
|
4
4
|
"description": "Antora extensions and macros developed for Redpanda documentation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antora",
|
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
"./macros/glossary": "./macros/glossary.js",
|
|
58
58
|
"./macros/rp-connect-components": "./macros/rp-connect-components.js",
|
|
59
59
|
"./macros/config-ref": "./macros/config-ref.js",
|
|
60
|
-
"./macros/helm-ref": "./macros/helm-ref.js"
|
|
60
|
+
"./macros/helm-ref": "./macros/helm-ref.js",
|
|
61
|
+
"./macros/badge": "./macros/badge.js"
|
|
61
62
|
},
|
|
62
63
|
"files": [
|
|
63
64
|
"extensions",
|
|
@@ -35,47 +35,99 @@ function registerPartial(name, filePath) {
|
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Deep-merge `overrides` into `target`. Only 'description', 'type',
|
|
38
|
-
*
|
|
38
|
+
* 'annotated_field', 'examples', and known nested fields are overridden.
|
|
39
39
|
*/
|
|
40
40
|
function mergeOverrides(target, overrides) {
|
|
41
41
|
if (!overrides || typeof overrides !== 'object') return target;
|
|
42
42
|
if (!target || typeof target !== 'object') {
|
|
43
43
|
throw new Error('Target must be a valid object');
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
const scalarKeys = ['description', 'type', 'annotated_field', 'version'];
|
|
47
|
+
|
|
45
48
|
for (const key in overrides) {
|
|
49
|
+
// === Handle annotated_options ===
|
|
50
|
+
if (key === 'annotated_options' && Array.isArray(overrides[key]) && Array.isArray(target[key])) {
|
|
51
|
+
const overrideMap = new Map(overrides[key].map(([name, desc]) => [name, desc]));
|
|
52
|
+
|
|
53
|
+
target[key] = target[key].map(([name, desc]) => {
|
|
54
|
+
if (overrideMap.has(name)) {
|
|
55
|
+
return [name, overrideMap.get(name)];
|
|
56
|
+
}
|
|
57
|
+
return [name, desc];
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const existingNames = new Set(target[key].map(([name]) => name));
|
|
61
|
+
for (const [name, desc] of overrides[key]) {
|
|
62
|
+
if (!existingNames.has(name)) {
|
|
63
|
+
target[key].push([name, desc]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// === Handle examples ===
|
|
70
|
+
if (key === 'examples' && Array.isArray(overrides[key]) && Array.isArray(target[key])) {
|
|
71
|
+
const overrideMap = new Map(overrides[key].map(o => [o.title, o]));
|
|
72
|
+
|
|
73
|
+
target[key] = target[key].map(example => {
|
|
74
|
+
const override = overrideMap.get(example.title);
|
|
75
|
+
if (override) {
|
|
76
|
+
return {
|
|
77
|
+
...example,
|
|
78
|
+
...(override.summary && { summary: override.summary }),
|
|
79
|
+
...(override.config && { config: override.config }),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return example;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const existingTitles = new Set(target[key].map(e => e.title));
|
|
86
|
+
for (const example of overrides[key]) {
|
|
87
|
+
if (!existingTitles.has(example.title)) {
|
|
88
|
+
target[key].push(example);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// === Merge arrays of objects with .name ===
|
|
46
95
|
if (Array.isArray(target[key]) && Array.isArray(overrides[key])) {
|
|
47
|
-
// Merge two parallel arrays by matching items on `.name`
|
|
48
96
|
target[key] = target[key].map(item => {
|
|
49
97
|
const overrideItem = overrides[key].find(o => o.name === item.name);
|
|
50
98
|
if (overrideItem) {
|
|
51
|
-
|
|
52
|
-
['description', 'type'].forEach(field => {
|
|
99
|
+
scalarKeys.forEach(field => {
|
|
53
100
|
if (Object.hasOwn(overrideItem, field)) {
|
|
54
101
|
item[field] = overrideItem[field];
|
|
55
102
|
}
|
|
56
103
|
});
|
|
57
|
-
// Copy through selfManagedOnly flag
|
|
58
104
|
if (Object.hasOwn(overrideItem, 'selfManagedOnly')) {
|
|
59
105
|
item.selfManagedOnly = overrideItem.selfManagedOnly;
|
|
60
106
|
}
|
|
61
|
-
|
|
62
|
-
item = mergeOverrides(item, overrideItem);
|
|
107
|
+
return mergeOverrides(item, overrideItem);
|
|
63
108
|
}
|
|
64
109
|
return item;
|
|
65
110
|
});
|
|
66
|
-
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// === Merge nested objects ===
|
|
115
|
+
if (
|
|
67
116
|
typeof target[key] === 'object' &&
|
|
68
117
|
typeof overrides[key] === 'object' &&
|
|
69
118
|
!Array.isArray(target[key]) &&
|
|
70
119
|
!Array.isArray(overrides[key])
|
|
71
120
|
) {
|
|
72
|
-
// Deep-merge plain objects
|
|
73
121
|
target[key] = mergeOverrides(target[key], overrides[key]);
|
|
74
|
-
|
|
75
|
-
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// === Overwrite scalar keys ===
|
|
126
|
+
if (scalarKeys.includes(key) && Object.hasOwn(overrides, key)) {
|
|
76
127
|
target[key] = overrides[key];
|
|
77
128
|
}
|
|
78
129
|
}
|
|
130
|
+
|
|
79
131
|
return target;
|
|
80
132
|
}
|
|
81
133
|
|
|
@@ -185,7 +237,7 @@ async function generateRpcnConnectorDocs(options) {
|
|
|
185
237
|
partialFiles.push(path.relative(process.cwd(), fPath));
|
|
186
238
|
}
|
|
187
239
|
|
|
188
|
-
if (examplesOut.trim()) {
|
|
240
|
+
if (examplesOut.trim() && type !== 'bloblang-functions' && type !== 'bloblang-methods') {
|
|
189
241
|
const ePath = path.join(examplesOutRoot, type, `${name}.adoc`);
|
|
190
242
|
fs.mkdirSync(path.dirname(ePath), { recursive: true });
|
|
191
243
|
fs.writeFileSync(ePath, examplesOut);
|
|
@@ -26,7 +26,7 @@ module.exports = function renderConnectFields(children, prefix = '') {
|
|
|
26
26
|
sorted.forEach(child => {
|
|
27
27
|
if (child.is_deprecated || !child.name) return;
|
|
28
28
|
|
|
29
|
-
// Normalize type
|
|
29
|
+
// Normalize type: arrays and unknown-map as object
|
|
30
30
|
let displayType;
|
|
31
31
|
if (child.type === 'string' && child.kind === 'array') {
|
|
32
32
|
displayType = 'array';
|
|
@@ -56,27 +56,49 @@ module.exports = function renderConnectFields(children, prefix = '') {
|
|
|
56
56
|
|
|
57
57
|
block += `*Type*: \`${displayType}\`\n\n`;
|
|
58
58
|
|
|
59
|
-
// Default
|
|
60
|
-
if (child.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
block += `*Default*:
|
|
64
|
-
}
|
|
59
|
+
// Default value
|
|
60
|
+
if (child.default !== undefined) {
|
|
61
|
+
// Empty array
|
|
62
|
+
if (Array.isArray(child.default) && child.default.length === 0) {
|
|
63
|
+
block += `*Default*: \`[]\`\n\n`;
|
|
64
|
+
}
|
|
65
|
+
// Empty object
|
|
66
|
+
else if (
|
|
67
|
+
child.default !== null &&
|
|
68
|
+
typeof child.default === 'object' &&
|
|
69
|
+
!Array.isArray(child.default) &&
|
|
70
|
+
Object.keys(child.default).length === 0
|
|
71
|
+
) {
|
|
72
|
+
block += `*Default*: \`{}\`\n\n`;
|
|
73
|
+
}
|
|
74
|
+
// Complex object/array
|
|
75
|
+
else if (typeof child.default === 'object') {
|
|
65
76
|
const defYaml = yaml.stringify(child.default).trim();
|
|
66
77
|
block += `*Default*:\n[source,yaml]\n----\n${defYaml}\n----\n\n`;
|
|
67
78
|
}
|
|
79
|
+
// Primitive
|
|
80
|
+
else {
|
|
81
|
+
const display = typeof child.default === 'string'
|
|
82
|
+
? (child.default.startsWith('"') && child.default.endsWith('"')
|
|
83
|
+
? child.default
|
|
84
|
+
: child.default === ''
|
|
85
|
+
? '""'
|
|
86
|
+
: child.default)
|
|
87
|
+
: String(child.default);
|
|
88
|
+
block += `*Default*: \`${display}\`\n\n`;
|
|
89
|
+
}
|
|
68
90
|
}
|
|
69
91
|
|
|
70
|
-
// Annotated options
|
|
92
|
+
// Annotated options table
|
|
71
93
|
if (child.annotated_options && child.annotated_options.length) {
|
|
72
|
-
block += `[cols
|
|
94
|
+
block += `[cols="1m,2a"]\n|===\n|Option |Summary\n\n`;
|
|
73
95
|
child.annotated_options.forEach(([opt, summary]) => {
|
|
74
96
|
block += `|${opt}\n|${summary}\n\n`;
|
|
75
97
|
});
|
|
76
98
|
block += `|===\n\n`;
|
|
77
99
|
}
|
|
78
100
|
|
|
79
|
-
//
|
|
101
|
+
// Simple options list
|
|
80
102
|
if (child.options && child.options.length) {
|
|
81
103
|
block += `*Options*: ${child.options.map(opt => `\`${opt}\``).join(', ')}\n\n`;
|
|
82
104
|
}
|
|
@@ -84,54 +106,27 @@ module.exports = function renderConnectFields(children, prefix = '') {
|
|
|
84
106
|
// Examples
|
|
85
107
|
if (child.examples && child.examples.length) {
|
|
86
108
|
block += `[source,yaml]\n----\n# Examples:\n`;
|
|
87
|
-
if (child.
|
|
88
|
-
|
|
89
|
-
block += renderYamlList(child.name, child.examples);
|
|
90
|
-
} else {
|
|
91
|
-
child.examples.forEach(example => {
|
|
92
|
-
if (typeof example === 'string' && example.includes('\n')) {
|
|
93
|
-
block += `${child.name}: |-\n`;
|
|
94
|
-
block += example.split('\n').map(line => ' ' + line).join('\n') + '\n';
|
|
95
|
-
} else {
|
|
96
|
-
block += `${child.name}: \`${example}\`\n`;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
block += '\n';
|
|
100
|
-
}
|
|
101
|
-
} else if (child.type === 'processor') {
|
|
102
|
-
if (child.kind === 'array') {
|
|
103
|
-
block += renderYamlList(child.name, child.examples);
|
|
104
|
-
} else {
|
|
105
|
-
child.examples.forEach(example => {
|
|
106
|
-
block += `${child.name}: \`${String(example)}\`\n`;
|
|
107
|
-
});
|
|
108
|
-
block += '\n';
|
|
109
|
-
}
|
|
110
|
-
} else if (child.type === 'object') {
|
|
111
|
-
if (child.kind === 'array') {
|
|
112
|
-
block += renderYamlList(child.name, child.examples);
|
|
113
|
-
} else {
|
|
114
|
-
child.examples.forEach(example => {
|
|
115
|
-
if (typeof example === 'object') {
|
|
116
|
-
const snippet = yaml.stringify(example).trim();
|
|
117
|
-
block += `${child.name}:\n`;
|
|
118
|
-
block += snippet.split('\n').map(line => ' ' + line).join('\n') + '\n';
|
|
119
|
-
} else {
|
|
120
|
-
block += `${child.name}: \`${String(example)}\`\n`;
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
block += '\n';
|
|
124
|
-
}
|
|
109
|
+
if (child.kind === 'array') {
|
|
110
|
+
block += renderYamlList(child.name, child.examples);
|
|
125
111
|
} else {
|
|
126
112
|
child.examples.forEach(example => {
|
|
127
|
-
|
|
113
|
+
if (typeof example === 'object') {
|
|
114
|
+
const snippet = yaml.stringify(example).trim();
|
|
115
|
+
block += `${child.name}:\n`;
|
|
116
|
+
block += snippet.split('\n').map(line => ' ' + line).join('\n') + '\n';
|
|
117
|
+
} else if (typeof example === 'string' && example.includes('\n')) {
|
|
118
|
+
block += `${child.name}: |-\n`;
|
|
119
|
+
block += example.split('\n').map(line => ' ' + line).join('\n') + '\n';
|
|
120
|
+
} else {
|
|
121
|
+
// Primitive values
|
|
122
|
+
block += `${child.name}: ${example}\n`;
|
|
123
|
+
}
|
|
128
124
|
});
|
|
129
|
-
block += '\n';
|
|
130
125
|
}
|
|
131
126
|
block += `----\n\n`;
|
|
132
127
|
}
|
|
133
128
|
|
|
134
|
-
// Nested
|
|
129
|
+
// Nested children
|
|
135
130
|
if (child.children && child.children.length) {
|
|
136
131
|
block += renderConnectFields(child.children, currentPath);
|
|
137
132
|
}
|
|
@@ -31,34 +31,57 @@ module.exports = function renderLeafField(field, indentLevel) {
|
|
|
31
31
|
|
|
32
32
|
// If a default is provided, use it:
|
|
33
33
|
if (field.default !== undefined) {
|
|
34
|
-
//
|
|
34
|
+
// Empty array inline
|
|
35
|
+
if (Array.isArray(field.default) && field.default.length === 0) {
|
|
36
|
+
return `${indent}${name}: []`;
|
|
37
|
+
}
|
|
38
|
+
// Empty object inline
|
|
39
|
+
if (
|
|
40
|
+
field.default !== null &&
|
|
41
|
+
typeof field.default === 'object' &&
|
|
42
|
+
!Array.isArray(field.default) &&
|
|
43
|
+
Object.keys(field.default).length === 0
|
|
44
|
+
) {
|
|
45
|
+
return `${indent}${name}: {}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Complex object/array: dump as YAML block
|
|
35
49
|
if (typeof field.default === 'object') {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Indent each line of rawYaml by (indentLevel + 2) spaces:
|
|
40
|
-
const indentedYaml = rawYaml
|
|
50
|
+
try {
|
|
51
|
+
const rawYaml = yaml.stringify(field.default).trim();
|
|
52
|
+
const indentedYaml = rawYaml
|
|
41
53
|
.split('\n')
|
|
42
54
|
.map(line => ' '.repeat(indentLevel + 2) + line)
|
|
43
55
|
.join('\n');
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
return `${indent}${name}:\n${indentedYaml}`;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.warn(`Failed to serialize default for ${field.name}:`, error);
|
|
59
|
+
return `${indent}${name}: {} # Error serializing default`;
|
|
60
|
+
}
|
|
49
61
|
}
|
|
50
62
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
// Primitive default: string, number, boolean
|
|
64
|
+
let value;
|
|
65
|
+
if (typeof field.default === 'string') {
|
|
66
|
+
// Preserve existing quotes
|
|
67
|
+
if (field.default.startsWith('"') && field.default.endsWith('"')) {
|
|
68
|
+
value = field.default;
|
|
69
|
+
} else if (field.default === '') {
|
|
70
|
+
value = '""';
|
|
71
|
+
} else {
|
|
72
|
+
value = field.default;
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
value = String(field.default);
|
|
54
76
|
}
|
|
55
|
-
|
|
77
|
+
|
|
78
|
+
return `${indent}${name}: ${value}`;
|
|
56
79
|
}
|
|
57
80
|
|
|
58
|
-
// No default → choose representation
|
|
81
|
+
// No default → choose representation
|
|
59
82
|
if (field.kind === 'array') {
|
|
60
83
|
return `${indent}${name}: [] ${comment}`;
|
|
61
84
|
} else {
|
|
62
85
|
return `${indent}${name}: "" ${comment}`;
|
|
63
86
|
}
|
|
64
|
-
}
|
|
87
|
+
};
|
|
@@ -12,13 +12,27 @@ module.exports = function renderYamlList(name, exampleGroups) {
|
|
|
12
12
|
exampleGroups.forEach(group => {
|
|
13
13
|
const items = Array.isArray(group) ? group : [group];
|
|
14
14
|
items.forEach(item => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
// Scalars
|
|
16
|
+
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
|
17
|
+
let value = String(item);
|
|
18
|
+
// Quote when needed: already-quoted scalars stay as-is; otherwise quote `*`
|
|
19
|
+
// and any value containing YAML-special characters.
|
|
20
|
+
if (!(value.startsWith('"') && value.endsWith('"'))) {
|
|
21
|
+
if (value === '*' || /[:\[\]\{\},&>|%@`]/.test(value)) {
|
|
22
|
+
value = `"${value}"`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
out += ` - ${value}\n`;
|
|
26
|
+
} else {
|
|
27
|
+
// Objects/arrays: stringify with indentation
|
|
28
|
+
const snippet = yaml.stringify(item).trim();
|
|
29
|
+
const lines = snippet.split('\n');
|
|
30
|
+
out += lines
|
|
31
|
+
.map((line, idx) => (idx === 0 ? ` - ${line}` : ` ${line}`))
|
|
32
|
+
.join('\n') + '\n';
|
|
33
|
+
}
|
|
20
34
|
});
|
|
21
35
|
out += '\n';
|
|
22
36
|
});
|
|
23
37
|
return out;
|
|
24
|
-
}
|
|
38
|
+
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
module.exports.register = function (registry) {
|
|
4
|
-
registry.inlineMacro(function () {
|
|
5
|
-
const self = this;
|
|
6
|
-
self.named('enterprise-label');
|
|
7
|
-
self.process((parent, target, attrs) => {
|
|
8
|
-
return `<span class="inline-enterprise-label">Enterprise</span>`;
|
|
9
|
-
});
|
|
10
|
-
});
|
|
11
|
-
};
|