@redpanda-data/docs-extensions-and-macros 5.8.0 → 5.10.0

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,121 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Scans AsciiDoc content for http(s) URLs that appear in prose, skipping
5
+ * URLs inside code contexts where rewriting or checking them would be wrong:
6
+ *
7
+ * - delimited listing (----), literal (....), fenced (```), and passthrough
8
+ * (++++) blocks
9
+ * - inline code spans (`...`)
10
+ *
11
+ * Each match records enough position information for a caller to splice a
12
+ * replacement into the original content.
13
+ *
14
+ * Match shape:
15
+ * - url: the URL with any trailing sentence punctuation trimmed
16
+ * - label: text of a directly attached AsciiDoc link label ([...]), or null.
17
+ * A label may span line breaks, which is common in generated content where
18
+ * long lines are wrapped; its newlines are collapsed to single spaces
19
+ * - start/end: absolute offsets in content covering the whole replaceable
20
+ * span (including a leading link: macro prefix and the label, if present)
21
+ * - hasLinkPrefix: true when the URL was written as link:https://...[...]
22
+ * - inAttributeEntry: true when the URL appears in an attribute entry line
23
+ * (for example ":url-docs: https://..."), where a caller may want to leave
24
+ * the value untouched
25
+ * - inAttributeValue: true when the URL is a macro attribute value (for
26
+ * example image:d.png[alt,link=https://...]); rewriting one of these to an
27
+ * xref macro would corrupt the surrounding macro, but the URL is still a
28
+ * real link target worth checking
29
+ */
30
+
31
+ const URL_RX = /(link:)?(https?:\/\/[^\s\][)"'<>]+)(\[[^\]]*\])?/g
32
+ // Sentence punctuation, and the AsciiDoc formatting markup that closes around a
33
+ // URL written as *emphasis* or **bold** (`**https://example.com/page**`), which
34
+ // is not part of the URL.
35
+ const TRAILING_PUNCT_RX = /[.,;:!?*_]+$/
36
+ const ATTRIBUTE_ENTRY_RX = /^:!?[a-zA-Z0-9_][a-zA-Z0-9_-]*!?:(?:\s|$)/
37
+ // Cap on how far a wrapped label may run, so an unmatched bracket somewhere in
38
+ // prose cannot swallow the rest of the document.
39
+ const MAX_WRAPPED_LABEL_LENGTH = 500
40
+
41
+ function blockDelimiter (line) {
42
+ if (/^-{4,}$/.test(line)) return '-'
43
+ if (/^\.{4,}$/.test(line)) return '.'
44
+ if (/^`{3,}$/.test(line)) return '`'
45
+ if (/^\+{4,}$/.test(line)) return '+'
46
+ return null
47
+ }
48
+
49
+ function scanContentUrls (content) {
50
+ const matches = []
51
+ const lines = content.split('\n')
52
+ let offset = 0
53
+ let openDelimiter = null
54
+ for (const rawLine of lines) {
55
+ const line = rawLine.endsWith('\r') ? rawLine.slice(0, -1) : rawLine
56
+ const delimiter = blockDelimiter(line)
57
+ if (delimiter) {
58
+ if (openDelimiter === delimiter) openDelimiter = null
59
+ else if (!openDelimiter) openDelimiter = delimiter
60
+ } else if (!openDelimiter) {
61
+ scanLine(line, offset, matches, content)
62
+ }
63
+ offset += rawLine.length + 1
64
+ }
65
+ return matches
66
+ }
67
+
68
+ /**
69
+ * Reads a link label that opens on this line but closes on a later one, which
70
+ * happens whenever a generator wraps long lines. Returns the label text with
71
+ * its line breaks collapsed, plus the offset just past the closing bracket.
72
+ * A blank line ends the search: that is a paragraph break, so the bracket
73
+ * belongs to something else.
74
+ */
75
+ function readWrappedLabel (content, openIndex) {
76
+ if (content[openIndex] !== '[') return
77
+ const limit = Math.min(content.length, openIndex + MAX_WRAPPED_LABEL_LENGTH)
78
+ const closeIndex = content.indexOf(']', openIndex + 1)
79
+ if (closeIndex === -1 || closeIndex > limit) return
80
+ const raw = content.slice(openIndex + 1, closeIndex)
81
+ if (/\n[ \t]*\n/.test(raw)) return
82
+ return { label: raw.replace(/\s*\n\s*/g, ' '), end: closeIndex + 1 }
83
+ }
84
+
85
+ function scanLine (line, offset, matches, content) {
86
+ const inAttributeEntry = ATTRIBUTE_ENTRY_RX.test(line)
87
+ for (const match of line.matchAll(URL_RX)) {
88
+ const [, linkPrefix, rawUrl, rawLabel] = match
89
+ const backticksBefore = (line.slice(0, match.index).match(/`/g) || []).length
90
+ if (backticksBefore % 2 === 1) continue
91
+ const prefixLength = linkPrefix ? linkPrefix.length : 0
92
+ const start = offset + match.index
93
+ let url = rawUrl
94
+ let label = rawLabel ? rawLabel.slice(1, -1) : null
95
+ let end = start + prefixLength + url.length + (rawLabel ? rawLabel.length : 0)
96
+ if (!rawLabel) {
97
+ const wrapped = readWrappedLabel(content, start + prefixLength + url.length)
98
+ if (wrapped) {
99
+ label = wrapped.label
100
+ end = wrapped.end
101
+ } else {
102
+ url = url.replace(TRAILING_PUNCT_RX, '')
103
+ end = start + prefixLength + url.length
104
+ }
105
+ }
106
+ // A URL directly after an attribute assignment (link=, window=, ...) is a
107
+ // macro attribute value, not a standalone link.
108
+ const before = line.slice(0, match.index)
109
+ matches.push({
110
+ url,
111
+ label,
112
+ start,
113
+ end,
114
+ hasLinkPrefix: Boolean(linkPrefix),
115
+ inAttributeEntry,
116
+ inAttributeValue: /[\w-]=["']?$/.test(before),
117
+ })
118
+ }
119
+ }
120
+
121
+ module.exports = { scanContentUrls }
@@ -68,7 +68,7 @@ function validateCategories(pageCategoryList, pageInfo, categoryMap, logger) {
68
68
  });
69
69
 
70
70
  if (!isValid) {
71
- logger.warn(`Invalid categories detected. For a list of valid categories, see https://github.com/redpanda-data/docs/tree/shared/modules/ROOT/partials/valid-categories.yml`);
71
+ logger.warn(`Invalid categories detected. For a list of valid categories, see https://github.com/redpanda-data/docs/blob/main/shared/modules/ROOT/partials/valid-categories.yml`);
72
72
  }
73
73
  return Array.from(adjustedCategories).join(', ');
74
74
  }
@@ -0,0 +1,90 @@
1
+ = How property and enterprise references work
2
+ :toc:
3
+ :toclevels: 2
4
+
5
+ A plain-English explanation of how the docs mark configuration properties and enterprise features, why it works this way, and what the tooling does for you. For attribute-by-attribute details, see link:REFERENCE.adoc[the macros reference].
6
+
7
+ == The problem this solves
8
+
9
+ The docs used to *guess*. Property tooltips decorated every piece of inline code whose text happened to match a property name. That works fine for a name like `cloud_storage_enabled`, but five real property names are ordinary words: `admin`, `brokers`, `rack`, `retries`, and `superusers`. On a Helm chart page, `admin` usually means an audit-logging setting or a listener name -- and readers still got a tooltip describing the Admin API broker property. Wrong information, delivered confidently.
10
+
11
+ Enterprise feature mentions had the opposite problem: nothing checked them at all. Any writer could mark any feature as enterprise, under any name, and nothing would ever notice a typo, a made-up name, or a feature that isn't actually enterprise.
12
+
13
+ The fix for both is the same idea: *marking is explicit, and every mark is checked against a source of truth at build time.*
14
+
15
+ == Property references: the prop macro
16
+
17
+ To reference a configuration property in prose, write:
18
+
19
+ [,asciidoc]
20
+ ----
21
+ prop:cloud_storage_enabled[]
22
+ ----
23
+
24
+ That's it. Here's what happens for you:
25
+
26
+ *It's checked.* The name is looked up in the published property data -- the same JSON, generated from Redpanda's source code, that powers the reference pages and tooltips. A typo gets a build warning with the file name and a "did you mean" suggestion. Nothing unverified ships. (A site can turn this up to a hard build failure with the `property-validate` attribute.)
27
+
28
+ *It gets a tooltip.* The docs UI decorates only elements the macro marked. A plain backticked word never gets a tooltip anymore, so `admin` in a Helm example stays plain text unless a writer deliberately writes `prop:admin[]`.
29
+
30
+ *It can link itself.* Add `link=true` and the property links to its reference page. You don't say which page -- the build works that out by looking at which reference page actually documents that property (details below). If our property reference is ever reorganized into different pages, every link follows automatically.
31
+
32
+ *It adapts to Kubernetes pages.* Add `helm-path=auto` and, on pages rendered for Kubernetes, the property displays as the Helm values path readers actually type -- `config.cluster.log_segment_size`, `config.node.fips_mode`, or `storage.tiered.config.cloud_storage_enabled` for tiered storage settings. On Linux pages the same call shows the plain name. One sentence, correct for both audiences.
33
+
34
+ *Once per paragraph is enough.* Mark the first mention of a property in a paragraph and leave later mentions as plain backticks -- a paragraph doesn't need three identical tooltips. The migration tool follows this rule, and the UI enforces it as a backstop: even if every mention is marked, only the first one per paragraph gets the tooltip.
35
+
36
+ === How "the build works out the page" (dynamic discovery)
37
+
38
+ Rather than hardcoding "cluster properties live on the cluster-properties page," the macro reads the actual docs during the build. Every documented property appears as a heading in the generated property files, and each reference page pulls in one or more of those files. The macro follows that chain -- which pages exist, what they include, which property headings end up where -- and builds a lookup table per doc set.
39
+
40
+ Because the lookup is done separately for each part of the site, a Cloud page links to Cloud's own property pages and a streaming page to streaming's. Cloud reuses streaming's property files with a filter ("only the cloud-relevant parts"), and the macro applies that same filter, so it never links to a property that a given page doesn't actually document. If a doc set doesn't cover a property at all -- Cloud publishes no topic-properties page, Connect publishes none -- the link borrows the streaming docs instead of pointing nowhere.
41
+
42
+ Think phone book, not memory: if a property moves, the next build's phone book is already right.
43
+
44
+ === What happened to config_ref
45
+
46
+ The old `config_ref` macro did a smaller version of this job with three problems: you had to tell it which page to link to by hand, it never checked the property name, and on Kubernetes pages it prefixed *every* property with `storage.tiered.config.` -- which is only correct for tiered storage settings. The live docs really did render `storage.tiered.config.log_segment_size`, a path that mislabels where that setting belongs.
47
+
48
+ `config_ref` is deprecated. Every hand-written call site has been converted, the property extractor now emits `prop` in generated content, and the published JSON was cleaned up (it had been leaking raw macro text into tooltips). The macro stays registered only because older versioned docs, which are frozen, still contain it. Don't write it in new content.
49
+
50
+ === Migrating existing content
51
+
52
+ One command converts a repo's prose:
53
+
54
+ [,bash]
55
+ ----
56
+ npx doc-tools generate migrate-property-refs \
57
+ --properties modules/reference/attachments/redpanda-properties-<tag>.json \
58
+ --config-refs
59
+ ----
60
+
61
+ It's a dry run by default; add `--write` to apply. It only converts names it can verify in the published JSON, never touches the five ambiguous word-like names, and skips code blocks, headings, generated content, and anything already inside another macro.
62
+
63
+ One thing no tool can check: *meaning*. Marking a name asserts "this mention refers to the Redpanda property" -- and even distinctive names collide in foreign-vocabulary contexts. A Terraform provider table's `replication.factor` argument, a SQL statement's `cluster_id` parameter, or an infrastructure checklist's `cloud_storage_bucket` are other systems' identifiers that happen to share a spelling. When reviewing a migration, unmark those. When writing, only reach for `prop:` when a tooltip describing the Redpanda property would help the reader in that sentence.
64
+
65
+ == Enterprise feature references: the enterprise macro
66
+
67
+ The same explicit-and-checked idea, for licensing:
68
+
69
+ [,asciidoc]
70
+ ----
71
+ enterprise:Tiered Storage[]
72
+ ----
73
+
74
+ The name is validated against the *enterprise features registry* -- a single YAML file in the shared component (`shared/modules/ROOT/partials/enterprise-features.yml` in the docs repo) that is the canonical list of what is enterprise and what each feature is called externally. Writers can't misname a feature (aliases and case differences resolve to the canonical name, and internal engineering names like `cloud_storage` render as their proper external name) and can't mark something enterprise that isn't in the registry. Adding a feature to the registry is a reviewed docs change, and each entry records *why* it's enterprise by pointing at the internal source of truth (a license-gate in Redpanda's source, the Connect plugin catalog, or a written justification).
75
+
76
+ Two more things come from the same registry:
77
+
78
+ * The licensing feature tables on the licensing pages are *generated* from it (`enterprise_features::redpanda[]` and friends), so the tables can never disagree with the registry.
79
+ * `doc-tools validate enterprise-features` compares the registry against the actual license gates in Redpanda's source code and Connect's plugin list. When engineering ships a new license-gated feature, CI fails until someone decides its documented name -- naming stays a human decision, but forgetting is no longer possible.
80
+
81
+ Like properties, feature links adapt to context: registry entries can carry Kubernetes- and Cloud-specific pages, chosen by the page's environment attributes.
82
+
83
+ == Where to see all of this working
84
+
85
+ * The extensions preview site's test page demonstrates every form of both macros, including intentional failure cases, and a Kubernetes-environment page shows the environment-specific behavior side by side.
86
+ * The docs-ui preview's `property-tooltips-test` and `enterprise-macro-test` pages show every output shape the UI styles, including the negative cases (unmarked names must get nothing).
87
+
88
+ == The one-sentence version
89
+
90
+ Nothing in the docs claims a name is a property or a feature is enterprise unless a writer said so explicitly *and* the build verified it against the source of truth.
@@ -10,6 +10,8 @@ AsciiDoc macros are custom inline and block elements that extend AsciiDoc syntax
10
10
 
11
11
  == Documentation
12
12
 
13
+ link:PROPERTY_AND_ENTERPRISE_REFERENCES.adoc[**How property and enterprise references work**]:: Plain-English explanation of the prop and enterprise macros: explicit marking, build-time validation against sources of truth, dynamic link discovery, and why config_ref was deprecated
14
+
13
15
  link:USER_GUIDE.adoc[**User guide**]:: How to use AsciiDoc macros in your documentation
14
16
  +
15
17
  * Installation and setup
@@ -20,6 +20,8 @@ antora:
20
20
 
21
21
  == config_ref
22
22
 
23
+ IMPORTANT: `config_ref` is deprecated. The <<prop>> macro supersedes all of its functionality: it validates names against the published property reference, discovers the target page dynamically instead of taking a manual path, powers hover tooltips, and its `helm-path=auto` attribute replaces `config_ref`'s Kubernetes prefixing with a per-property correct Helm values path (`config_ref` prefixed every property with `storage.tiered.config.`, mislabeling non-tiered properties). Migrate call sites with `doc-tools generate migrate-property-refs --config-refs`. The macro stays registered only because the generated property partials still emit it.
24
+
23
25
  This inline macro is used to generate a reference to a configuration value in the Redpanda documentation. The macro's parameters allow for control over the generated reference's format and the type of output produced.
24
26
 
25
27
  === Usage
@@ -62,6 +64,171 @@ asciidoc:
62
64
  - '@redpanda-data/docs-extensions-and-macros/macros/config-ref'
63
65
  ----
64
66
 
67
+ == enterprise
68
+
69
+ This inline macro marks a feature as an enterprise feature in prose. The feature name renders as a uniquely styled term with a tooltip explaining that the feature requires an Enterprise Edition license, and links to the feature's documentation or to the licensing page.
70
+
71
+ The macro validates its target against the enterprise features registry: `modules/ROOT/partials/enterprise-features.yml` in the `shared` component (the `shared/` folder of the docs repository). The registry is the canonical list of enterprise features and their approved external names. Targets are matched case-insensitively, including aliases, and the canonical name, feature page link, and tooltip come from the matching entry. A target that matches no entry is reported according to `enterprise-validate`. To mark a new feature as enterprise, add it to the registry first.
72
+
73
+ === Usage
74
+
75
+ [,asciidoc]
76
+ ----
77
+ enterprise:Continuous Data Balancing[]
78
+ enterprise:Tiered Storage[xref=manage:tiered-storage.adoc]
79
+ enterprise:Audit Logging[text=audit logging]
80
+ enterprise:Iceberg Topics[tooltip=Iceberg Topics requires an Enterprise Edition license and object storage.]
81
+ ----
82
+
83
+ The macro target is the feature name, which can contain spaces. Named attributes:
84
+
85
+ xref::
86
+ Optional Antora resource ID of the feature's documentation page. Overrides the registry entry's link. When neither is set, the term links to the licensing page.
87
+ +
88
+ Registry entries can carry environment-specific pages: on pages with the `env-cloud` attribute the entry's `xref-cloud` is used, on pages with `env-kubernetes` the entry's `xref-kubernetes` is used, and otherwise the entry's default `xref` (the Linux or generic self-managed page). This mirrors the `config_ref` macro's environment awareness.
89
+
90
+ text::
91
+ Optional display text override. Use it when the sentence needs different casing or phrasing than the feature name.
92
+
93
+ tooltip::
94
+ Optional tooltip text override. Overrides the registry entry's `tooltip`. The default is `<feature> requires an Enterprise Edition license.`
95
+
96
+ === Configuration options
97
+
98
+ enterprise-validate::
99
+ How to report a target that does not match any registry entry: `warn` (default) logs a build warning with the file path and close-match suggestions, `error` fails the build, and `off` disables validation. When no registry is available in the build, the macro renders without validation and logs a single warning.
100
+
101
+ enterprise-licensing-page::
102
+ Resource ID of the licensing page used when no `xref` attribute is given. The default is `get-started:licensing/overview.adoc`.
103
+
104
+ enterprise-feature-role::
105
+ CSS class applied to the wrapping span. The default is `enterprise-feature`. Style this class in the UI bundle to give enterprise terms a consistent visual treatment.
106
+
107
+ enterprise-tooltip::
108
+ Controls the tooltip attribute: `title` (default), `true` (renders `data-enterprise-tooltip` for UI-driven tooltips), any attribute name starting with `data-`, or `false` to disable tooltips.
109
+
110
+ enterprise-links::
111
+ Set to `false` to render the term without a link.
112
+
113
+ enterprise-beta-badge::
114
+ Set to `false` to suppress the beta badge in prose. Generated tables always show it. See <<beta-features>>.
115
+
116
+ [[beta-features]]
117
+ === Beta features
118
+
119
+ Add `beta: true` to a registry entry to mark the feature as beta. The macro then renders a beta badge after the feature name, both in prose and in the generated `enterprise_features` tables, so one registry field keeps every reference consistent:
120
+
121
+ [,yaml]
122
+ ----
123
+ - name: Stretch Clusters
124
+ scope: operator
125
+ beta: true
126
+ feature-suffix: (StretchCluster resource)
127
+ ----
128
+
129
+ Add `beta-tooltip` to give the badge hover text.
130
+
131
+ Do not write a `badge:` macro call into `feature-suffix` to achieve this. The badge is emitted as an inline passthrough, so it renders whether or not the consuming playbook registers the `badge` macro, and it degrades to the text `(beta)` in Markdown. A hand-written macro call renders as literal source text in any build that does not register that macro.
132
+
133
+ === Markdown output
134
+
135
+ In HTML, the enterprise signal is carried by the span's CSS class and its tooltip attribute. Both are attributes, so an HTML-to-Markdown conversion drops them and the term arrives as an ordinary feature name. To keep the signal for readers of the Markdown pages, including AI agents, the `convert-to-markdown` extension appends an explicit `(enterprise)` marker and preserves any link:
136
+
137
+ [,markdown]
138
+ ----
139
+ Enable [Tiered Storage](../manage/tiered-storage.md) (enterprise) today.
140
+ ----
141
+
142
+ A feature that is also marked `beta: true` gets one combined marker rather than two adjacent parentheticals:
143
+
144
+ [,markdown]
145
+ ----
146
+ Enable [Stretch Clusters](../deploy/stretch-clusters.md) (enterprise, beta) today.
147
+ ----
148
+
149
+ This applies to the inline macro. The tables from `enterprise_features` need no enterprise marker, because their expiration column already states the licensing behavior as text. A beta badge in a table converts to `(beta)` on its own.
150
+
151
+ === Registration
152
+
153
+ [,yaml]
154
+ ----
155
+ asciidoc:
156
+ extensions:
157
+ - '@redpanda-data/docs-extensions-and-macros/macros/enterprise'
158
+ ----
159
+
160
+ == enterprise_features
161
+
162
+ This block macro renders the licensing feature table for one scope from the enterprise features registry (see <<enterprise>>). Because the table is generated, it can never drift from the registry.
163
+
164
+ === Usage
165
+
166
+ [,asciidoc]
167
+ ----
168
+ enterprise_features::redpanda[]
169
+ enterprise_features::connect[]
170
+ enterprise_features::operator[title=Operator features,heading=What stops working]
171
+ ----
172
+
173
+ The target is the scope: `redpanda`, `console`, `connect`, `operator`, or `cloud`. Rows render alphabetically by feature name with three columns: the feature name (linked to its documentation page when the entry has an `xref` or `url`), the description, and the expiration or restriction behavior. Named attributes:
174
+
175
+ title::
176
+ Optional table title override. The default is scope-specific, for example `Enterprise features in Redpanda`.
177
+
178
+ heading::
179
+ Optional third-column heading override. The default is `Behavior Upon Expiration` for the `redpanda` scope and `Restrictions Without Valid License` for the other scopes.
180
+
181
+ === Registration
182
+
183
+ Registered together with the `enterprise` inline macro (see <<enterprise>>).
184
+
185
+ == prop
186
+
187
+ This inline macro references a Redpanda configuration property in prose. The property renders as a marked `<code>` element (`property-ref` class plus a `data-property-name` attribute) that the docs UI decorates with a hover-documentation tooltip. Marking is opt-in: only properties referenced through this macro get tooltips, so ambiguous words such as `admin` or `rack` in unrelated contexts (Helm values, feature settings) are never decorated by mistake.
188
+
189
+ The macro validates its target against the published property reference: the newest `redpanda-properties-<tag>.json` attachment in the `reference` module of the build, the same data the tooltips fetch at runtime. To migrate existing plain-backtick property mentions, use `doc-tools generate migrate-property-refs`.
190
+
191
+ === Usage
192
+
193
+ [,asciidoc]
194
+ ----
195
+ prop:cloud_storage_enabled[]
196
+ prop:iceberg_enabled[link=true]
197
+ prop:retention_ms[link=true,page=properties/topic-properties]
198
+ prop:write_caching_default[text=write caching]
199
+ ----
200
+
201
+ The macro target is the property name. Named attributes:
202
+
203
+ link::
204
+ Set to `true` to also link the property to its reference page. The page is discovered dynamically: the macro indexes which reference-module page in the current component documents each property, by scanning property headings in the partials each page includes (respecting include tag filters such as `tags=redpanda-cloud`). Links are component-relative, so a Cloud page links to the Cloud component's own property pages, and they keep working if properties are split across different pages in the future. When discovery finds nothing, the page falls back deterministically to the property's `config_scope` (`cluster`, `broker`, or `topic`). This supersedes the `config_ref` macro's linking for most uses.
205
+
206
+ page::
207
+ Optional reference-page override (module-relative, without `.adoc`), for example `properties/object-storage-properties`. Overrides discovery entirely.
208
+
209
+ helm-path::
210
+ Set to `auto` to display the property as its Helm values path on pages rendered with the `env-kubernetes` attribute, so single-sourced content reads correctly for both Linux and Kubernetes audiences. The path is derived per property: `storage.tiered.config.<name>` for tiered storage properties, `config.node.<name>` for broker properties, and `config.cluster.<name>` for other cluster properties. On pages without `env-kubernetes`, the plain property name renders. This supersedes the deprecated `config_ref` macro's prefixing.
211
+
212
+ text::
213
+ Optional display text override. Wins over the Helm path display.
214
+
215
+ === Configuration options
216
+
217
+ property-validate::
218
+ How to report a target that does not match any published property: `warn` (default) logs a build warning with the file path and close-match suggestions, `error` fails the build, and `off` disables validation. When no property JSON is available in the build, the macro renders without validation and logs a single warning.
219
+
220
+ property-ref-role::
221
+ CSS class applied to the code element. The default is `property-ref`.
222
+
223
+ === Registration
224
+
225
+ [,yaml]
226
+ ----
227
+ asciidoc:
228
+ extensions:
229
+ - '@redpanda-data/docs-extensions-and-macros/macros/prop'
230
+ ----
231
+
65
232
  == glossterm
66
233
 
67
234
  The `glossterm` inline macro provides a way to define and reference glossary terms in your AsciiDoc documents.
package/macros/badge.js CHANGED
@@ -1,21 +1,43 @@
1
1
  'use strict';
2
2
 
3
+ /**
4
+ * Build the HTML for a badge.
5
+ *
6
+ * Extracted from the macro body so other macros can render an identical badge
7
+ * without depending on the badge macro being registered in the consuming
8
+ * playbook. The enterprise macro uses it to render the beta badge for registry
9
+ * entries marked `beta: true`, which keeps one definition of the markup and
10
+ * the CSS class names.
11
+ *
12
+ * @param {object} opts
13
+ * @param {string} [opts.label] - Badge text.
14
+ * @param {string} [opts.size] - `large` renders without surrounding brackets.
15
+ * @param {string} [opts.tooltip] - Tooltip text, rendered as `data-tooltip`.
16
+ * @returns {string} Badge HTML.
17
+ */
18
+ function buildBadgeHtml ({ label, size, tooltip } = {}) {
19
+ const text = label || 'label';
20
+ const className = `badge--${text.toLowerCase().replace(/\s+/g, '-')}`;
21
+ const isLarge = size === 'large';
22
+ const sizeClass = isLarge ? 'badge--large' : '';
23
+ const tooltipAttr = tooltip ? ` data-tooltip="${tooltip}"` : '';
24
+
25
+ // Add brackets if not large. The brackets matter beyond styling: they are
26
+ // real text content, so the label survives an HTML-to-Markdown conversion as
27
+ // "(beta)" rather than vanishing with the CSS class.
28
+ const renderedLabel = isLarge ? text : `(${text})`;
29
+
30
+ return `<span class="badge ${className} ${sizeClass}"${tooltipAttr}>${renderedLabel}</span>`;
31
+ }
32
+
33
+ module.exports.buildBadgeHtml = buildBadgeHtml;
34
+
3
35
  module.exports.register = function (registry) {
4
36
  registry.inlineMacro(function () {
5
37
  const self = this;
6
38
  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
- });
39
+ self.process((parent, target, attrs) =>
40
+ buildBadgeHtml({ label: attrs.label, size: attrs.size, tooltip: attrs.tooltip })
41
+ );
20
42
  });
21
43
  };