@redpanda-data/docs-extensions-and-macros 5.38.0 → 5.38.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.
@@ -0,0 +1,135 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://redpanda.com/schemas/property-overrides.schema.json",
4
+ "title": "Property overrides",
5
+ "description": "Hand-authored corrections and additions applied on top of properties extracted from Redpanda's C++ source. See tools/property-extractor/README.adoc.",
6
+ "type": "object",
7
+ "properties": {
8
+ "properties": {
9
+ "type": "object",
10
+ "description": "Keyed by property key or name (see property_extractor.py's name-fallback lookup). An override key that matches neither creates a phantom stub property — see property_extractor.py's report_phantom_stubs().",
11
+ "additionalProperties": { "$ref": "#/$defs/propertyOverride" }
12
+ }
13
+ },
14
+ "additionalProperties": false,
15
+ "$defs": {
16
+ "propertyOverride": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "_comment": {
21
+ "type": "string",
22
+ "description": "Free-text note to whoever edits this entry next. Never read by the generator."
23
+ },
24
+ "description": { "type": "string" },
25
+ "upstream_ref": {
26
+ "type": "string",
27
+ "description": "The upstream issue or PR (against the engineering repo whose defective string this description patches, either the short form 'redpanda-data/streaming-enterprise#12345' or the full URL) that will make this description override redundant once merged and released. A description override is a stopgap, not a fix: set this so the override is born with a retirement path, and remove both the override and this field once the fix ships. Only meaningful alongside 'description' — has no effect on generation or rendering."
28
+ },
29
+ "version": {
30
+ "type": "string",
31
+ "description": "Version the property was introduced in (e.g. 'v23.1.0')."
32
+ },
33
+ "example": {
34
+ "description": "Literal example content, or an example_file/example_yaml reference resolved relative to this overrides file."
35
+ },
36
+ "example_file": { "type": "string" },
37
+ "example_yaml": { "type": "string" },
38
+ "default": {
39
+ "description": "Replaces the extracted default. Prefer leaving this unset — it silently pins a value the extractor would otherwise keep in sync with the C++ source on every release."
40
+ },
41
+ "type": { "type": "string" },
42
+ "config_scope": {
43
+ "enum": ["cluster", "broker", "topic", null],
44
+ "description": "Almost always inferred automatically from defined_in — see property_extractor.py's add_config_scope(). Only set this for an override-created property (defined_in: 'override'), which has no source file to infer from."
45
+ },
46
+ "exclude_from_docs": { "type": "boolean" },
47
+ "category": {
48
+ "type": "string",
49
+ "description": "Documentation grouping. Not inferable for cluster/broker properties; topic properties get a mechanical default from infer_category() that this can still override."
50
+ },
51
+ "accepted_values": {
52
+ "type": "array",
53
+ "description": "Replaces the enum field to filter displayed values (e.g. hiding an internal-only mode).",
54
+ "items": {}
55
+ },
56
+ "is_deprecated": { "type": "boolean" },
57
+ "visibility": { "type": "string" },
58
+ "related_topics": {
59
+ "type": "array",
60
+ "deprecated": true,
61
+ "description": "Deprecated — use see_also. A plain string, or one prefixed 'cloud-only:'/'self-managed-only:' for conditional display. The prefix is free text with no validation; still read for existing entries, normalized alongside see_also by seeAlsoView.js.",
62
+ "items": { "type": "string" }
63
+ },
64
+ "see_also": {
65
+ "type": "array",
66
+ "description": "Related commands or documentation pages, in the docs-data/rpk-overrides.json 'seeAlso' shape. Each item is a plain string (shown everywhere) or an object naming exactly one of cloud_only/self_hosted_only (shown only in that build).",
67
+ "items": {
68
+ "oneOf": [
69
+ {
70
+ "type": "string",
71
+ "description": "xref link or related-topic text, shown in every build."
72
+ },
73
+ {
74
+ "type": "object",
75
+ "description": "Conditional see-also item shown only in the named build.",
76
+ "properties": {
77
+ "content": {
78
+ "type": "string",
79
+ "description": "The xref link or related-topic text."
80
+ },
81
+ "cloud_only": {
82
+ "type": "boolean",
83
+ "description": "If true, only shown in Cloud docs (wrapped with ifdef::env-cloud[])."
84
+ },
85
+ "self_hosted_only": {
86
+ "type": "boolean",
87
+ "description": "If true, only shown in self-hosted docs (wrapped with ifndef::env-cloud[])."
88
+ }
89
+ },
90
+ "required": ["content"],
91
+ "additionalProperties": false,
92
+ "oneOf": [
93
+ {
94
+ "required": ["cloud_only"],
95
+ "not": { "required": ["self_hosted_only"] }
96
+ },
97
+ {
98
+ "required": ["self_hosted_only"],
99
+ "not": { "required": ["cloud_only"] }
100
+ }
101
+ ]
102
+ }
103
+ ]
104
+ }
105
+ },
106
+ "admonitions": {
107
+ "type": "array",
108
+ "description": "Structured NOTE/TIP/IMPORTANT/WARNING/CAUTION callouts, rendered as Asciidoctor admonition blocks instead of hand-written markup in description. Each entry needs type and text; title is optional. See property_extractor.py's _normalize_admonitions() -- an entry that doesn't match this shape is dropped with a warning, not rejected here, so the schema stays permissive on casing/whitespace that the generator itself normalizes.",
109
+ "items": {
110
+ "type": "object",
111
+ "required": ["type", "text"],
112
+ "properties": {
113
+ "type": {
114
+ "type": "string",
115
+ "description": "Case-insensitive; normalized to uppercase. One of note, tip, important, warning, caution.",
116
+ "enum": ["note", "tip", "important", "warning", "caution",
117
+ "NOTE", "TIP", "IMPORTANT", "WARNING", "CAUTION",
118
+ "Note", "Tip", "Important", "Warning", "Caution"]
119
+ },
120
+ "text": {
121
+ "type": "string",
122
+ "description": "Admonition body. May itself contain AsciiDoc markup."
123
+ },
124
+ "title": {
125
+ "type": "string",
126
+ "description": "Optional admonition title, shown in place of the default type label."
127
+ }
128
+ },
129
+ "additionalProperties": false
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "5.38.0",
3
+ "version": "5.38.2",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -106,9 +106,8 @@
106
106
  "tools",
107
107
  "docker-compose",
108
108
  "mcp",
109
- "docs-data/rpk-overrides.schema.json",
110
- "docs-data/kapa-source-groups.json",
111
- "docs-data/kapa-source-groups.schema.json"
109
+ "docs-data/*.schema.json",
110
+ "docs-data/kapa-source-groups.json"
112
111
  ],
113
112
  "license": "ISC",
114
113
  "engines": {
@@ -33,7 +33,11 @@ const CONVENTION = {
33
33
  case: 'sentence',
34
34
  terminal_period: true,
35
35
  verbatim_asciidoc: true,
36
- state_default: true
36
+ // Not state_default. The rendered page builds a "Default:" row from the
37
+ // extractor's own field, so prose restating a concrete default duplicates
38
+ // structured data. Only a sentinel default (null, 0, -1, "") carries
39
+ // behavior that row cannot express.
40
+ state_sentinel_default: true
37
41
  }
38
42
 
39
43
  function run (cmd, args, options = {}) {
@@ -133,8 +137,9 @@ function mapExtractorJson (json, repo, options = {}) {
133
137
 
134
138
  const lineStart = prop.line_start != null ? prop.line_start : null
135
139
  const lineEnd = prop.line_end != null ? prop.line_end : lineStart
136
- const hasDefault = Object.prototype.hasOwnProperty.call(prop, 'default') &&
137
- prop.default !== null && prop.default !== ''
140
+ // null and "" are defaults too: the extractor emits null for every
141
+ // std::nullopt, and those are exactly the sentinels the rule below is for.
142
+ const hasDefault = Object.prototype.hasOwnProperty.call(prop, 'default')
138
143
 
139
144
  declarations.push({
140
145
  surface: 'properties',
@@ -148,6 +153,7 @@ function mapExtractorJson (json, repo, options = {}) {
148
153
  meta: {
149
154
  has_default: hasDefault,
150
155
  default: hasDefault ? prop.default : null,
156
+ type: typeof prop.type === 'string' ? prop.type : null,
151
157
  is_enum: Boolean(prop.is_enum),
152
158
  nullable: Boolean(prop.nullable)
153
159
  }
@@ -184,16 +190,52 @@ const RULES = [
184
190
  }
185
191
  },
186
192
  {
187
- name: 'default-not-stated',
188
- description: 'Property has a default the description never mentions',
193
+ name: 'sentinel-default-unexplained',
194
+ description: 'Property defaults to a sentinel whose meaning the description never explains',
189
195
  severity: 'info',
196
+ // The rendered page already carries a "Default:" row built from the
197
+ // extractor's own `default` field, so asking the prose to restate a
198
+ // concrete default duplicates structured data -- and duplicated facts go
199
+ // stale. A real example: tombstone_retention_ms's description claimed "a
200
+ // typical default setting is 86400000" while the actual default was null.
201
+ //
202
+ // A SENTINEL default is the exception. null, 0, -1 and "" usually mean
203
+ // disabled, unlimited or unset, and which one is not inferable from the
204
+ // value, so "Default: null" leaves the reader guessing. That meaning is
205
+ // information the structured field cannot carry, which is the only case
206
+ // worth a finding.
190
207
  check: (decl) => {
191
- const text = decl.string || ''
208
+ const text = (decl.string || '').trim()
192
209
  if (!text || !decl.meta || !decl.meta.has_default) return []
193
- const defaultText = String(decl.meta.default)
194
- if (/\bdefaults?\b/i.test(text)) return []
195
- if (defaultText.length > 0 && text.includes(defaultText)) return []
196
- return [{ message: `Property has a default (${JSON.stringify(decl.meta.default)}) that the description does not state.` }]
210
+ const value = decl.meta.default
211
+ // Booleans are never sentinels: `false` is a real setting, not a
212
+ // stand-in for "off".
213
+ if (typeof value === 'boolean') return []
214
+ // A string-typed property defaulting to null or "" is plainly "not
215
+ // configured" (credentials, bucket names, endpoints); the "Default:" row
216
+ // says that on its own, so only non-string sentinels are ambiguous.
217
+ if (decl.meta.type === 'string' && (value === null || value === '')) return []
218
+ const sentinels = [
219
+ { match: (v) => v === null || v === 'null', token: /\bnull\b/i, label: 'null' },
220
+ { match: (v) => v === '' , token: /\b(empty|blank)\b/i, label: 'an empty string' },
221
+ { match: (v) => v === 0 || v === '0', token: /\b(0|zero)\b/i, label: '0' },
222
+ { match: (v) => v === -1 || v === '-1', token: /-1\b/, label: '-1' }
223
+ ]
224
+ const sentinel = sentinels.find((s) => s.match(value))
225
+ if (!sentinel) return []
226
+ // Either name the sentinel, or say what it does. Both forms explain it;
227
+ // neither is satisfied by an unrelated digit elsewhere in the sentence.
228
+ // "default"/"falls back"/"inherits"/"omitted" cover descriptions that
229
+ // explain the null case by naming what is used instead, which is the
230
+ // explanation being asked for.
231
+ const MEANING = /\b(disabl\w*|unlimited|no limit|unbounded|infinite|unset|not set|never|off|ignored|no maximum|no minimum|defaults?|inherit\w*|blank|omitted|not specified|falls? back)\b/i
232
+ if (sentinel.token.test(text) || MEANING.test(text)) return []
233
+ return [{
234
+ message: `Property defaults to ${sentinel.label}, and the description does not say what that means. `
235
+ + 'A sentinel default carries behavior the rendered "Default:" row cannot: say whether it disables '
236
+ + 'the property, means unlimited, or leaves it unset. There is no need to restate a concrete '
237
+ + 'default value; the page already renders it from structured data.'
238
+ }]
197
239
  }
198
240
  }
199
241
  ]