@redpanda-data/docs-extensions-and-macros 5.2.3 → 5.2.5
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/package.json
CHANGED
|
@@ -31,14 +31,26 @@ module.exports = function renderConnectFields(children, prefix = '') {
|
|
|
31
31
|
const isArrayTitle = typeof child.name === 'string' && child.name.endsWith('[]');
|
|
32
32
|
if (isArrayTitle) {
|
|
33
33
|
displayType = 'array<object>';
|
|
34
|
-
} else if (child.
|
|
35
|
-
|
|
36
|
-
} else if (child.type === 'unknown' && child.kind === 'map') {
|
|
34
|
+
} else if (child.kind === 'map') {
|
|
35
|
+
// Maps always render as `object`, regardless of value type.
|
|
37
36
|
displayType = 'object';
|
|
38
|
-
} else if (child.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
} else if (child.kind === 'array' || child.kind === 'list' || child.kind === '2darray') {
|
|
38
|
+
// Arrays render as `array<element>` when the element type is known,
|
|
39
|
+
// for example `array<string>`. 2D arrays nest the element type, for
|
|
40
|
+
// example `array<array<string>>`. Unknown element types render as
|
|
41
|
+
// plain `array`. A `type` of `array` (used by some overrides to force
|
|
42
|
+
// the old plain-array display) is treated as unknown so the field
|
|
43
|
+
// renders as `array` rather than the degenerate `array<array>`.
|
|
44
|
+
const elementType = (typeof child.type === 'string' && child.type !== '' && child.type !== 'unknown' && child.type !== 'array')
|
|
45
|
+
? child.type
|
|
46
|
+
: null;
|
|
47
|
+
if (elementType) {
|
|
48
|
+
displayType = child.kind === '2darray'
|
|
49
|
+
? `array<array<${elementType}>>`
|
|
50
|
+
: `array<${elementType}>`;
|
|
51
|
+
} else {
|
|
52
|
+
displayType = 'array';
|
|
53
|
+
}
|
|
42
54
|
} else {
|
|
43
55
|
displayType = child.type;
|
|
44
56
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { extractMetadata } = require('../metadata-utils.js');
|
|
4
|
+
const { normalizeMetadataBlock } = require('../normalize-metadata.js');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Handlebars helper: return the `== Metadata` block extracted from a connector
|
|
7
|
-
* description, or '' when there is none.
|
|
8
|
+
* description with consistent field-list formatting, or '' when there is none.
|
|
9
|
+
* Used by the metadata partial template.
|
|
8
10
|
* @param {string} description
|
|
9
11
|
* @returns {string}
|
|
10
12
|
*/
|
|
11
13
|
module.exports = function renderConnectMetadata (description) {
|
|
12
|
-
return extractMetadata(description);
|
|
14
|
+
return normalizeMetadataBlock(extractMetadata(description));
|
|
13
15
|
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalize the formatting of an extracted `== Metadata` block so the generated
|
|
5
|
+
* metadata partials are consistent regardless of how each connector authored
|
|
6
|
+
* its metadata section upstream.
|
|
7
|
+
*
|
|
8
|
+
* Two inconsistencies are normalized:
|
|
9
|
+
* 1. Some connectors wrap their field list in a fenced code block
|
|
10
|
+
* (```text ... ``` or ``` ... ```) of bare names; others use an AsciiDoc
|
|
11
|
+
* bullet list with the field name in inline code. We strip the fences
|
|
12
|
+
* around a field list and render the fields as a plain bullet list.
|
|
13
|
+
* 2. Within a field bullet, the field name (a lowercase snake_case
|
|
14
|
+
* identifier) is wrapped in inline code. Descriptive bullets such as
|
|
15
|
+
* "All headers (only first values are taken)" are left as prose, and
|
|
16
|
+
* bullets that already contain inline code are left untouched.
|
|
17
|
+
*
|
|
18
|
+
* Everything else (intro sentences, notes, `===` subheadings that legitimately
|
|
19
|
+
* group metadata by operation, non-field-list fenced blocks, and AsciiDoc
|
|
20
|
+
* `----` literal blocks) is preserved verbatim.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const FENCE_OPEN = /^(\s*)(```|~~~)(.*)$/;
|
|
24
|
+
const BULLET = /^(\s*[-*]\s+)(.*)$/;
|
|
25
|
+
// AsciiDoc literal/listing block delimiter. Content inside `----` blocks is
|
|
26
|
+
// rendered verbatim, so backticks would show up literally — such regions must
|
|
27
|
+
// pass through untouched (no field-name inline-coding).
|
|
28
|
+
const BLOCK_DELIMITER = /^-{4,}$/;
|
|
29
|
+
// A metadata field bullet: the leading token is a lowercase snake_case
|
|
30
|
+
// identifier (gcs_key, http_server_verb, header), optionally followed by a
|
|
31
|
+
// parenthetical annotation (for example "(RFC3339)"), and optionally a
|
|
32
|
+
// description separated by ":" or " - ". This distinguishes real field bullets
|
|
33
|
+
// from descriptive ones like "All headers ..." (which start with a capital).
|
|
34
|
+
// The description may itself contain inline code, so it is matched loosely.
|
|
35
|
+
const FIELD_BULLET = /^([a-z][a-z0-9_]*)((?:\s*\([^)]*\))?(?:\s*(?::|-)\s.*)?)$/s;
|
|
36
|
+
|
|
37
|
+
function normalizeBullet (prefix, content) {
|
|
38
|
+
// Skip only when the field name itself is already inline-coded; a backtick
|
|
39
|
+
// later in the description must not prevent coding the field name.
|
|
40
|
+
if (content.startsWith('`')) return prefix + content;
|
|
41
|
+
const m = content.match(FIELD_BULLET);
|
|
42
|
+
if (!m) return prefix + content; // descriptive, leave as prose
|
|
43
|
+
return `${prefix}\`${m[1]}\`${m[2]}`; // inline-code the field name
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** True when a fenced block's info string and content are a bare field list. */
|
|
47
|
+
function isFieldListFence (infoString, contentLines) {
|
|
48
|
+
const info = infoString.trim();
|
|
49
|
+
if (info !== '' && info !== 'text') return false;
|
|
50
|
+
const nonBlank = contentLines.filter((l) => l.trim() !== '');
|
|
51
|
+
if (nonBlank.length === 0 || !nonBlank.every((l) => BULLET.test(l))) return false;
|
|
52
|
+
// Require at least one real field-name bullet. A fenced block of purely
|
|
53
|
+
// descriptive bullets (no snake_case field name) is not a field list, so its
|
|
54
|
+
// fences must be preserved rather than stripped.
|
|
55
|
+
return nonBlank.some((l) => {
|
|
56
|
+
const b = l.match(BULLET);
|
|
57
|
+
return b && FIELD_BULLET.test(b[2]);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {string} block the extracted `== Metadata` block
|
|
63
|
+
* @returns {string} the block with consistent field-list formatting
|
|
64
|
+
*/
|
|
65
|
+
function normalizeMetadataBlock (block) {
|
|
66
|
+
if (!block || typeof block !== 'string') return block;
|
|
67
|
+
const lines = block.split('\n');
|
|
68
|
+
const out = [];
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < lines.length; i++) {
|
|
71
|
+
// AsciiDoc literal/listing block: pass the whole `----` … `----` region
|
|
72
|
+
// through verbatim. Field-name lines inside are rendered literally, so they
|
|
73
|
+
// must not be inline-coded (backticks would appear as visible characters).
|
|
74
|
+
if (BLOCK_DELIMITER.test(lines[i].trim())) {
|
|
75
|
+
out.push(lines[i]);
|
|
76
|
+
let j = i + 1;
|
|
77
|
+
for (; j < lines.length; j++) {
|
|
78
|
+
out.push(lines[j]);
|
|
79
|
+
if (BLOCK_DELIMITER.test(lines[j].trim())) break;
|
|
80
|
+
}
|
|
81
|
+
i = j;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const fence = lines[i].match(FENCE_OPEN);
|
|
86
|
+
if (fence) {
|
|
87
|
+
// Collect the fenced content up to a closing fence of the SAME marker
|
|
88
|
+
// (a ```-opened block is not closed by ~~~, and vice versa).
|
|
89
|
+
const marker = fence[2];
|
|
90
|
+
const content = [];
|
|
91
|
+
let j = i + 1;
|
|
92
|
+
let closed = false;
|
|
93
|
+
for (; j < lines.length; j++) {
|
|
94
|
+
if (lines[j].trim() === marker) { closed = true; break; }
|
|
95
|
+
content.push(lines[j]);
|
|
96
|
+
}
|
|
97
|
+
if (closed && isFieldListFence(fence[3], content)) {
|
|
98
|
+
// Drop the fences and render the fields as a normal bullet list.
|
|
99
|
+
for (const c of content) {
|
|
100
|
+
const b = c.match(BULLET);
|
|
101
|
+
out.push(b ? normalizeBullet(b[1], b[2]) : c);
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// Not a field list (e.g. a YAML example) — keep verbatim.
|
|
105
|
+
out.push(lines[i]);
|
|
106
|
+
for (const c of content) out.push(c);
|
|
107
|
+
if (closed) out.push(lines[j]);
|
|
108
|
+
}
|
|
109
|
+
i = closed ? j : lines.length;
|
|
110
|
+
} else {
|
|
111
|
+
// Bare bullet outside a fence: normalize the field name too.
|
|
112
|
+
const b = lines[i].match(BULLET);
|
|
113
|
+
out.push(b ? normalizeBullet(b[1], b[2]) : lines[i]);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return out.join('\n');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = { normalizeMetadataBlock };
|