@redpanda-data/docs-extensions-and-macros 5.54.0 → 5.56.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.
- package/bin/doc-tools-mcp.js +4 -5
- package/bin/doc-tools.js +354 -9
- package/bin/mcp-tools/generated-docs-review.js +26 -9
- package/bin/mcp-tools/overrides-audit.js +1 -1
- package/bin/mcp-tools/rpcn-docs.js +4 -14
- package/cli-utils/docs-links-to-xrefs.js +174 -0
- package/cli-utils/format-helm-spec.js +4 -3
- package/cli-utils/generated-marker.js +43 -0
- package/cli-utils/helm-commented-values.js +125 -21
- package/cli-utils/self-managed-docs-branch.js +36 -30
- package/extension-utils/html-utils.js +27 -0
- package/extension-utils/llms-utils.js +6 -2
- package/extension-utils/metadata-candidates.js +304 -0
- package/extension-utils/metadata-check.js +174 -0
- package/extension-utils/metadata-suggest.js +573 -0
- package/extension-utils/taxonomy-categories.js +106 -0
- package/extension-utils/taxonomy.js +566 -0
- package/extensions/REFERENCE.adoc +110 -8
- package/extensions/add-git-dates.js +13 -1
- package/extensions/aggregate-terms.js +34 -20
- package/extensions/algolia-indexer/generate-index.js +13 -1
- package/extensions/algolia-indexer/index.js +4 -2
- package/extensions/convert-sitemap-to-markdown.js +47 -12
- package/extensions/convert-to-markdown.js +176 -0
- package/extensions/generate-fields-only-pages.js +14 -0
- package/extensions/modify-connect-tag-playbook.js +181 -3
- package/extensions/resolve-xrefs-in-attachments.js +1 -12
- package/extensions/url-to-xref.js +92 -22
- package/extensions/util/connect-docs-asset.js +6 -5
- package/extensions/validate-attributes.js +10 -1
- package/extensions/version-fetcher/fetch-latest-docker-tag.js +35 -13
- package/extensions/version-fetcher/get-latest-redpanda-helm-version-from-operator.js +64 -40
- package/extensions/version-fetcher/list-connect-releases.js +3 -3
- package/extensions/version-fetcher/release-lines.js +64 -0
- package/extensions/version-fetcher/set-latest-version.js +73 -3
- package/macros/README.adoc +1 -0
- package/macros/REFERENCE.adoc +99 -0
- package/macros/badge.js +5 -8
- package/macros/enterprise.js +2 -5
- package/macros/glossary.js +4 -14
- package/macros/iceberg-explorer.js +242 -0
- package/macros/prop.js +3 -13
- package/mcp/USER_GUIDE.adoc +25 -135
- package/package.json +5 -2
- package/tools/check-metadata/index.js +523 -0
- package/tools/cloud-regions/cloud-regions-table-adoc.hbs +1 -2
- package/tools/cloud-regions/cloud-regions-table-md.hbs +2 -2
- package/tools/cloud-regions/render-cloud-regions.js +3 -0
- package/tools/dispatch-graph/check-dispatch-graph.js +790 -0
- package/tools/dispatch-graph/classify-runs.js +128 -0
- package/tools/dispatch-graph/parse-workflows.js +499 -0
- package/tools/doc-impact-recording/index.js +190 -0
- package/tools/enterprise-features/detect-gating-changes.js +393 -0
- package/tools/enterprise-features/verify.js +2 -1
- package/tools/gen-rpk-ascii.py +7 -1
- package/tools/lint-strings/fixtures/connect/lint_connect.go +8 -0
- package/tools/lint-strings/fixtures/crd/lint_types.go +4 -1
- package/tools/lint-strings/fixtures/rpk-pr461/delete.base.go +42 -0
- package/tools/lint-strings/fixtures/rpk-pr461/delete.head.go +45 -0
- package/tools/lint-strings/fixtures/rpk-pr461/reviewer-comments.json +1 -0
- package/tools/lint-strings/index.js +133 -3
- package/tools/lint-strings/rules/verbatim-asciidoc.js +166 -1
- package/tools/lint-strings/surfaces/connect.js +72 -12
- package/tools/lint-strings/surfaces/crd.js +10 -6
- package/tools/metrics/metrics.py +11 -0
- package/tools/overrides-audit/README.adoc +1 -2
- package/tools/overrides-audit/adapters/properties.js +1 -1
- package/tools/overrides-audit/index.js +3 -4
- package/tools/property-extractor/generate-handlebars-docs.js +9 -1
- package/tools/property-extractor/helpers/applyPropertyLinks.js +35 -0
- package/tools/redpanda-connect/AUTOMATION.md +3 -36
- package/tools/redpanda-connect/README.adoc +5 -33
- package/tools/redpanda-connect/generate-rpcn-connector-docs.js +32 -11
- package/tools/redpanda-connect/pr-summary-formatter.js +6 -4
- package/tools/redpanda-connect/report-delta.js +6 -3
- package/tools/redpanda-connect/rpcn-connector-docs-handler.js +42 -25
- package/tools/redpanda-connect/templates/bloblang-function.hbs +1 -1
- package/tools/redpanda-connect/templates/descriptions-partials.hbs +1 -1
- package/tools/redpanda-connect/templates/examples-partials.hbs +1 -1
- package/tools/redpanda-connect/templates/fields-partials.hbs +2 -2
- package/tools/redpanda-connect/templates/metadata-partials.hbs +1 -1
- package/tools/redpanda-release-notes/generate-release-notes.js +116 -1
- package/tools/rpk-docs/generate-rpk-docs.js +2 -0
- package/tools/rpk-docs/generate-x-env-partial.js +7 -4
- package/tools/rpk-docs/helpers/index.js +4 -1
- package/tools/rpk-docs/templates/command.hbs +2 -2
- package/tools/overrides-audit/adapters/connect.js +0 -144
package/tools/metrics/metrics.py
CHANGED
|
@@ -23,6 +23,16 @@ These output files are stored in a versioned folder under `docs/autogenerated/<v
|
|
|
23
23
|
|
|
24
24
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
|
25
25
|
|
|
26
|
+
|
|
27
|
+
def generated_marker(generator, source, hint=""):
|
|
28
|
+
"""Same marker shape as cli-utils/generated-marker.js (no version, so a
|
|
29
|
+
release does not rewrite every file); convert-to-markdown reads it."""
|
|
30
|
+
marker = (
|
|
31
|
+
"// This content is autogenerated. Do not edit manually. "
|
|
32
|
+
f"Generated by doc-tools ({generator}) from {source.rstrip('.')}."
|
|
33
|
+
)
|
|
34
|
+
return marker + (f" {hint.strip()}" if hint.strip() else "")
|
|
35
|
+
|
|
26
36
|
def fetch_metrics(url):
|
|
27
37
|
"""Fetch metrics from the given URL."""
|
|
28
38
|
try:
|
|
@@ -123,6 +133,7 @@ def parse_metrics(metrics_text):
|
|
|
123
133
|
def output_asciidoc(metrics, adoc_file):
|
|
124
134
|
"""Output metrics as AsciiDoc."""
|
|
125
135
|
with open(adoc_file, "w") as f:
|
|
136
|
+
f.write(generated_marker("metrics-docs", "the metrics Redpanda exposes, defined in redpanda-data/streaming-enterprise") + "\n\n")
|
|
126
137
|
for name, data in metrics.items():
|
|
127
138
|
f.write(f"=== {name}\n\n")
|
|
128
139
|
f.write(f"{data['description']}\n\n")
|
|
@@ -22,7 +22,7 @@ npx doc-tools overrides audit \
|
|
|
22
22
|
--format human
|
|
23
23
|
|
|
24
24
|
# Standalone
|
|
25
|
-
node tools/overrides-audit/index.js --overrides <path> --extracted <path> [--surface properties|rpk
|
|
25
|
+
node tools/overrides-audit/index.js --overrides <path> --extracted <path> [--surface properties|rpk] [--format json|human] [--output <file>]
|
|
26
26
|
----
|
|
27
27
|
|
|
28
28
|
IMPORTANT: `--extracted` must be the property extractor's *raw* output (the `--output` file), never the enhanced output (`--enhanced-output`) or the versioned `redpanda-properties-<tag>.json` attachments: those already have overrides applied, so every override would classify as REDUNDANT. The same trap exists for rpk: the versioned `rpk-v<version>.json` files in docs repos are post-override snapshots.
|
|
@@ -133,7 +133,6 @@ JSON (default): `{ surface, overrides_file, extracted_file, manifest, summary, c
|
|
|
133
133
|
|
|
134
134
|
* `properties` (complete): `property-overrides.json` vs the property extractor's raw JSON.
|
|
135
135
|
* `rpk` (structural): enumerates `rpk-overrides.json` (see `docs-data/rpk-overrides.schema.json`) -- command/flag `description` fields are the upstreamable prose (classified `REVIEW` with a TODO note until source comparison lands; it needs a raw pre-override `--print-tree` snapshot plus the `formatDescription()` pipeline from `tools/rpk-docs`), everything else (`seeAlso`, `pageAliases`, `content`, platform scoping, ...) is `KEEP` by design.
|
|
136
|
-
* `connect` (structural): enumerates the rp-connect-docs `overrides.json` (`definitions` + per-component arrays with nested `config.children`); prose fields classify `REVIEW` with a TODO note until `$ref` resolution and plugin-JSON comparison land.
|
|
137
136
|
|
|
138
137
|
== Golden run (local checkouts required)
|
|
139
138
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Reads docs-data/property-overrides.json and an extracted-properties JSON
|
|
5
5
|
* (the property extractor's raw --output, WITHOUT overrides applied) and
|
|
6
6
|
* classifies every override field. This is the complete reference adapter;
|
|
7
|
-
* rpk
|
|
7
|
+
* The rpk adapter follows the same shape.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict'
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* node tools/overrides-audit/index.js \
|
|
13
13
|
* --overrides docs-data/property-overrides.json \
|
|
14
14
|
* --extracted tools/property-extractor/gen/properties-output.json \
|
|
15
|
-
* [--surface properties|rpk
|
|
15
|
+
* [--surface properties|rpk] [--format json|human] [--output <file>]
|
|
16
16
|
*
|
|
17
17
|
* Also exposed as `doc-tools overrides audit` and the `audit_overrides`
|
|
18
18
|
* MCP tool. See README.adoc in this directory for the classification rules
|
|
@@ -26,8 +26,7 @@ const path = require('path')
|
|
|
26
26
|
|
|
27
27
|
const ADAPTERS = {
|
|
28
28
|
properties: () => require('./adapters/properties'),
|
|
29
|
-
rpk: () => require('./adapters/rpk')
|
|
30
|
-
connect: () => require('./adapters/connect')
|
|
29
|
+
rpk: () => require('./adapters/rpk')
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
/**
|
|
@@ -153,7 +152,7 @@ function main (argv) {
|
|
|
153
152
|
.description('Classify docs-side override fields against extracted source strings')
|
|
154
153
|
.requiredOption('--overrides <path>', 'Path to the overrides JSON file (for example docs-data/property-overrides.json)')
|
|
155
154
|
.option('--extracted <path>', 'Path to the extracted source JSON (property extractor raw output; required for the properties surface)')
|
|
156
|
-
.option('--surface <surface>', 'Override surface: properties
|
|
155
|
+
.option('--surface <surface>', 'Override surface: properties or rpk', 'properties')
|
|
157
156
|
.option('--format <format>', 'Output format: json or human', 'json')
|
|
158
157
|
.option('--output <path>', 'Also write the JSON result to this file')
|
|
159
158
|
.action((options) => {
|
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
// writer already has open. The previous pointer was a Confluence page, and
|
|
3
3
|
// Confluence is retired, so it sent every writer who read this line to a dead
|
|
4
4
|
// end. A repo-relative path cannot rot the same way.
|
|
5
|
-
const AUTOGEN_NOTICE = '// This content is autogenerated. Do not edit manually. To change a description, add a link, or scope text to one docs build, edit docs-data/property-overrides.json (fields are documented in docs-data/property-overrides.schema.json and docs-data/README.adoc) and regenerate.\n';
|
|
6
5
|
'use strict';
|
|
7
6
|
|
|
8
7
|
const fs = require('fs');
|
|
8
|
+
const { generatedMarker } = require('../../cli-utils/generated-marker');
|
|
9
|
+
|
|
10
|
+
// The marker's shape is shared by every generator and read by the
|
|
11
|
+
// convert-to-markdown extension, which exports it to the Markdown twins.
|
|
12
|
+
const AUTOGEN_NOTICE = generatedMarker(
|
|
13
|
+
'property-docs',
|
|
14
|
+
'the configuration property definitions in redpanda-data/streaming-enterprise',
|
|
15
|
+
'To change a description, add a link, or scope text to one docs build, edit docs-data/property-overrides.json (fields are documented in docs-data/property-overrides.schema.json and docs-data/README.adoc) and regenerate.'
|
|
16
|
+
) + '\n';
|
|
9
17
|
const bigIntJson = require('../../cli-utils/big-int-json');
|
|
10
18
|
const path = require('path');
|
|
11
19
|
const handlebars = require('handlebars');
|
|
@@ -419,6 +419,39 @@ function normalizeIncludes(propName, raw, warnings) {
|
|
|
419
419
|
return out;
|
|
420
420
|
}
|
|
421
421
|
|
|
422
|
+
/**
|
|
423
|
+
* Remove the inline copies of `includes` that the attachment write-back appended.
|
|
424
|
+
*
|
|
425
|
+
* generate-handlebars-docs.js writes each include back into the description
|
|
426
|
+
* on disk, so the attachment's tooltip still renders it, and leaves `includes`
|
|
427
|
+
* in place. A run that reads that file again (a reused gen/<tag>-properties.json,
|
|
428
|
+
* or generate-docs run twice without re-extraction) sees the directive in the
|
|
429
|
+
* description and in `includes`, and the template rendered it twice. Only the
|
|
430
|
+
* exact shapes the write-back produces are
|
|
431
|
+
* removed, so an include a human put in the prose is left alone.
|
|
432
|
+
*
|
|
433
|
+
* @param {string|undefined} description - Flattened description.
|
|
434
|
+
* @param {Array<{target: string, cloud_only?: boolean, self_managed_only?: boolean}>} items - Normalized includes.
|
|
435
|
+
* @returns {string|undefined}
|
|
436
|
+
*/
|
|
437
|
+
function stripInlineIncludes(description, items) {
|
|
438
|
+
if (typeof description !== 'string' || !description.includes('include::')) return description;
|
|
439
|
+
let text = description;
|
|
440
|
+
// The write-back appends in order, so peel from the end.
|
|
441
|
+
for (const item of [...items].reverse()) {
|
|
442
|
+
const directive = `include::${item.target}`;
|
|
443
|
+
let block = directive;
|
|
444
|
+
if (item.cloud_only) block = `ifdef::env-cloud[]\n${directive}\nendif::[]`;
|
|
445
|
+
else if (item.self_managed_only) block = `ifndef::env-cloud[]\n${directive}\nendif::[]`;
|
|
446
|
+
if (text.endsWith(`\n\n${block}`)) {
|
|
447
|
+
text = text.slice(0, -(block.length + 2));
|
|
448
|
+
} else if (text === block) {
|
|
449
|
+
text = '';
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return text;
|
|
453
|
+
}
|
|
454
|
+
|
|
422
455
|
/**
|
|
423
456
|
* Why the Cloud build cannot reach a link target, or null when it can.
|
|
424
457
|
*
|
|
@@ -471,6 +504,7 @@ function applyPropertyLinks(properties) {
|
|
|
471
504
|
}
|
|
472
505
|
if (prop.includes !== undefined) {
|
|
473
506
|
prop.includes = normalizeIncludes(propName, prop.includes, warnings);
|
|
507
|
+
prop.description = stripInlineIncludes(prop.description, prop.includes);
|
|
474
508
|
}
|
|
475
509
|
if (Array.isArray(prop.admonitions)) {
|
|
476
510
|
prop.admonitions = prop.admonitions.filter((item) => {
|
|
@@ -589,3 +623,4 @@ module.exports.applyLinksToText = applyLinksToText;
|
|
|
589
623
|
module.exports.renderLink = renderLink;
|
|
590
624
|
module.exports.cloudUnreachable = cloudUnreachable;
|
|
591
625
|
module.exports.normalizeIncludes = normalizeIncludes;
|
|
626
|
+
module.exports.stripInlineIncludes = stripInlineIncludes;
|
|
@@ -581,7 +581,7 @@ npx doc-tools generate rpcn-connector-docs \
|
|
|
581
581
|
| `--draft-missing` | Generate full page drafts for new connectors | false |
|
|
582
582
|
| `--update-whats-new` | Update whats-new.adoc with changes | false |
|
|
583
583
|
| `--include-bloblang` | Include Bloblang functions/methods | false |
|
|
584
|
-
| `--overrides <path>` | JSON file with description overrides |
|
|
584
|
+
| `--overrides <path>` | Optional JSON file with description overrides | None |
|
|
585
585
|
|
|
586
586
|
### Examples
|
|
587
587
|
|
|
@@ -766,41 +766,8 @@ Templates are in `tools/redpanda-connect/templates/`:
|
|
|
766
766
|
- `connector-examples.hbs` - Examples template
|
|
767
767
|
- `connector-full.hbs` - Full page draft template
|
|
768
768
|
|
|
769
|
-
###
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
```json
|
|
773
|
-
{
|
|
774
|
-
"inputs": {
|
|
775
|
-
"kafka": {
|
|
776
|
-
"fields": {
|
|
777
|
-
"addresses": {
|
|
778
|
-
"description": "Custom description override",
|
|
779
|
-
"examples": ["localhost:9092"]
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
```
|
|
786
|
-
|
|
787
|
-
Supports `$ref` syntax for deduplication:
|
|
788
|
-
```json
|
|
789
|
-
{
|
|
790
|
-
"inputs": {
|
|
791
|
-
"kafka": {
|
|
792
|
-
"fields": {
|
|
793
|
-
"tls": { "$ref": "#/common/tls" }
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
},
|
|
797
|
-
"common": {
|
|
798
|
-
"tls": {
|
|
799
|
-
"description": "TLS configuration (reused across components)"
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
```
|
|
769
|
+
### Fixing connector descriptions
|
|
770
|
+
Field, component, and Bloblang descriptions come from the component specs in `redpanda-data/connect` and `redpanda-data/benthos`. To fix wrong or missing text, open a PR against the spec. The fix ships in the next Connect release.
|
|
804
771
|
|
|
805
772
|
## Troubleshooting
|
|
806
773
|
|
|
@@ -46,11 +46,6 @@ npm install @redpanda-data/docs-extensions-and-macros
|
|
|
46
46
|
# Generate connector documentation with latest data
|
|
47
47
|
npx doc-tools generate rpcn-connector-docs --fetch-connectors
|
|
48
48
|
|
|
49
|
-
# Generate with custom overrides
|
|
50
|
-
npx doc-tools generate rpcn-connector-docs \
|
|
51
|
-
--fetch-connectors \
|
|
52
|
-
--overrides path/to/overrides.json
|
|
53
|
-
|
|
54
49
|
# Generate and draft missing connectors
|
|
55
50
|
npx doc-tools generate rpcn-connector-docs \
|
|
56
51
|
--fetch-connectors \
|
|
@@ -176,11 +171,6 @@ You can generate connector documentation with various options:
|
|
|
176
171
|
# Basic generation with fetching latest data
|
|
177
172
|
npx doc-tools generate rpcn-connector-docs --fetch-connectors
|
|
178
173
|
|
|
179
|
-
# Generate with custom overrides for descriptions/examples
|
|
180
|
-
npx doc-tools generate rpcn-connector-docs \
|
|
181
|
-
--fetch-connectors \
|
|
182
|
-
--overrides overrides.json
|
|
183
|
-
|
|
184
174
|
# Draft full pages for connectors missing documentation
|
|
185
175
|
npx doc-tools generate rpcn-connector-docs \
|
|
186
176
|
--fetch-connectors \
|
|
@@ -202,7 +192,7 @@ npx doc-tools generate rpcn-connector-docs \
|
|
|
202
192
|
* `--fetch-connectors` - Fetch latest data using `rpk connect list`
|
|
203
193
|
* `--connect-version <version>` - Specific Connect version to install and fetch (requires `--fetch-connectors`)
|
|
204
194
|
* `--draft-missing` - Generate full draft pages for undocumented connectors
|
|
205
|
-
* `--overrides <path>` -
|
|
195
|
+
* `--overrides <path>` - Merge descriptions and examples from an optional JSON file. Nothing is merged unless you pass it
|
|
206
196
|
* `--data-dir <path>` - Directory containing versioned connect JSON files
|
|
207
197
|
* `--old-data <path>` - Specific old version file for diff comparison
|
|
208
198
|
* `--include-bloblang` - Include Bloblang functions/methods
|
|
@@ -791,7 +781,9 @@ console.log('<!-- PR_SUMMARY_END -->');
|
|
|
791
781
|
|
|
792
782
|
=== Override system
|
|
793
783
|
|
|
794
|
-
|
|
784
|
+
Connector field, component, and Bloblang descriptions come from the component specs in https://github.com/redpanda-data/connect[redpanda-data/connect^] and https://github.com/redpanda-data/benthos[redpanda-data/benthos^]. To fix wrong or missing text, open a PR against the spec. The fix ships in the next Connect release.
|
|
785
|
+
|
|
786
|
+
The generator can also merge an optional JSON file passed with `--overrides` into the extracted data. Nothing is merged unless you pass the flag:
|
|
795
787
|
|
|
796
788
|
[,json]
|
|
797
789
|
----
|
|
@@ -840,11 +832,9 @@ Overrides support:
|
|
|
840
832
|
* Connector catalog enrichment
|
|
841
833
|
* Version tracking and change detection
|
|
842
834
|
* Handlebars template rendering
|
|
843
|
-
* Override system for custom documentation
|
|
844
835
|
|
|
845
836
|
=== Current limitations
|
|
846
837
|
|
|
847
|
-
* *Manual override maintenance*: Custom descriptions must be maintained in overrides.json
|
|
848
838
|
* *Example quality*: Auto-generated examples may not represent best practices
|
|
849
839
|
* *Duplicate YAML keys*: Some examples contain multiple configurations in one block, creating invalid YAML with duplicate top-level keys (for example, multiple `processors:` keys)
|
|
850
840
|
* *CSV catalog dependency*: Relies on manually maintained CSV in Connect repository
|
|
@@ -876,25 +866,7 @@ This occurs when multiple separate configurations are concatenated into a single
|
|
|
876
866
|
|
|
877
867
|
=== Workarounds
|
|
878
868
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
[,json]
|
|
882
|
-
----
|
|
883
|
-
{
|
|
884
|
-
"inputs": [
|
|
885
|
-
{
|
|
886
|
-
"name": "problematic_connector",
|
|
887
|
-
"description": "Custom description overriding auto-extracted text",
|
|
888
|
-
"examples": [
|
|
889
|
-
{
|
|
890
|
-
"title": "Corrected example",
|
|
891
|
-
"config": "input:\n problematic_connector:\n field: value"
|
|
892
|
-
}
|
|
893
|
-
]
|
|
894
|
-
}
|
|
895
|
-
]
|
|
896
|
-
}
|
|
897
|
-
----
|
|
869
|
+
To fix an unsupported pattern, a wrong description, or a broken example, edit the component spec in redpanda-data/connect or redpanda-data/benthos. The fix ships in the next Connect release.
|
|
898
870
|
|
|
899
871
|
== Contributing
|
|
900
872
|
|
|
@@ -17,6 +17,9 @@ Object.entries(helpers).forEach(([name, fn]) => {
|
|
|
17
17
|
}
|
|
18
18
|
handlebars.registerHelper(name, fn);
|
|
19
19
|
});
|
|
20
|
+
// The provenance marker the partial templates write on their first line
|
|
21
|
+
const { generatedMarker } = require('../../cli-utils/generated-marker');
|
|
22
|
+
handlebars.registerHelper('generatedMarker', generatedMarker);
|
|
20
23
|
|
|
21
24
|
// Default “main” template (connector.hbs) which invokes partials {{> intro}}, {{> fields}}, {{> examples}}
|
|
22
25
|
const DEFAULT_TEMPLATE = path.resolve(__dirname, './templates/connector.hbs');
|
|
@@ -34,9 +37,12 @@ const { hasStructuralHeadings, hasMarkdownHeadings, firstHeadingDepth, escapePla
|
|
|
34
37
|
// section is removed upstream. Kept as an AsciiDoc comment so the file renders
|
|
35
38
|
// nothing while any lingering include directive still resolves cleanly.
|
|
36
39
|
const STALE_METADATA_PARTIAL =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
generatedMarker(
|
|
41
|
+
'rpcn-connector-docs',
|
|
42
|
+
'the component spec in redpanda-data/connect',
|
|
43
|
+
'The connector description no longer contains a `== Metadata` section, so this partial is intentionally empty. ' +
|
|
44
|
+
'You can remove the include directive that points at this file from the connector page.'
|
|
45
|
+
) + '\n';
|
|
40
46
|
|
|
41
47
|
// Banner-only content written to a description partial when the connector's
|
|
42
48
|
// description is removed upstream. Same rationale as STALE_METADATA_PARTIAL:
|
|
@@ -50,12 +56,27 @@ const STALE_METADATA_PARTIAL =
|
|
|
50
56
|
// every page that includes it, on every build, which is a build failure
|
|
51
57
|
// wherever Asciidoctor warnings are treated as errors. An empty region
|
|
52
58
|
// resolves to nothing and says nothing.
|
|
53
|
-
const
|
|
54
|
-
'// This content is autogenerated. Do not edit manually. ' +
|
|
55
|
-
'The connector no longer has a description, so this partial is intentionally empty. ' +
|
|
56
|
-
'You can remove the include directive that points at this file from the connector page.\n' +
|
|
59
|
+
const STALE_DESCRIPTION_REGIONS =
|
|
57
60
|
'\n// tag::meta[]\n// end::meta[]\n' +
|
|
58
61
|
'\n// tag::body[]\n// end::body[]\n';
|
|
62
|
+
const STALE_DESCRIPTION_PARTIAL =
|
|
63
|
+
generatedMarker(
|
|
64
|
+
'rpcn-connector-docs',
|
|
65
|
+
'the component spec in redpanda-data/connect',
|
|
66
|
+
'The connector no longer has a description, so this partial is intentionally empty. ' +
|
|
67
|
+
'You can remove the include directive that points at this file from the connector page.'
|
|
68
|
+
) + '\n' + STALE_DESCRIPTION_REGIONS;
|
|
69
|
+
// What earlier releases wrote for the same blanked partial. The orphan sweep
|
|
70
|
+
// treats either as already blanked, so a partial emptied before the marker
|
|
71
|
+
// changed is not re-blanked and re-reported. The marker carries no version,
|
|
72
|
+
// so this list grows only when the wording does.
|
|
73
|
+
const STALE_DESCRIPTION_PARTIALS = new Set([
|
|
74
|
+
STALE_DESCRIPTION_PARTIAL,
|
|
75
|
+
'// This content is autogenerated. Do not edit manually. ' +
|
|
76
|
+
'The connector no longer has a description, so this partial is intentionally empty. ' +
|
|
77
|
+
'You can remove the include directive that points at this file from the connector page.\n' +
|
|
78
|
+
STALE_DESCRIPTION_REGIONS,
|
|
79
|
+
]);
|
|
59
80
|
|
|
60
81
|
// Component families with their own reference pages, keyed by the canonical
|
|
61
82
|
// type directory from typeDirFor(). Other data keys -- `config`, the bloblang
|
|
@@ -101,9 +122,9 @@ function mergeOverrides(target, overrides) {
|
|
|
101
122
|
throw new Error('Target must be a valid object');
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
125
|
+
// Scalar keys are replaced outright. 'summary' must be listed: a key that
|
|
126
|
+
// falls through every branch below is silently dropped, and summaries feed
|
|
127
|
+
// page meta descriptions.
|
|
107
128
|
const scalarKeys = ['description', 'summary', 'type', 'annotated_field', 'version'];
|
|
108
129
|
|
|
109
130
|
for (const key in overrides) {
|
|
@@ -932,7 +953,7 @@ async function generateRpcnConnectorDocs(options) {
|
|
|
932
953
|
const orphanPath = path.join(typeDirPath, file);
|
|
933
954
|
// Already blanked on an earlier run: leave it alone so it is not
|
|
934
955
|
// re-reported forever.
|
|
935
|
-
if (fs.readFileSync(orphanPath, 'utf8')
|
|
956
|
+
if (STALE_DESCRIPTION_PARTIALS.has(fs.readFileSync(orphanPath, 'utf8'))) continue;
|
|
936
957
|
orphans.push({ key, orphanPath });
|
|
937
958
|
}
|
|
938
959
|
}
|
|
@@ -179,7 +179,7 @@ function renderStyleRegressionWarnings(warnings) {
|
|
|
179
179
|
if (!Array.isArray(warnings) || warnings.length === 0) return [];
|
|
180
180
|
const lines = [];
|
|
181
181
|
lines.push('> [!WARNING]');
|
|
182
|
-
lines.push('> **This update reintroduces house-style issues that the published docs do not have.** The fix belongs upstream in the
|
|
182
|
+
lines.push('> **This update reintroduces house-style issues that the published docs do not have.** The fix belongs upstream in the connect or benthos component spec: correcting the generated partial is undone by the next regeneration.');
|
|
183
183
|
for (const w of warnings) {
|
|
184
184
|
lines.push(`> - \`${w.partial}\` adds: ${w.issues.join(', ')}`);
|
|
185
185
|
}
|
|
@@ -323,7 +323,8 @@ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, drafte
|
|
|
323
323
|
lines.push('|-----------|-------|-------------|');
|
|
324
324
|
|
|
325
325
|
newFields.forEach(field => {
|
|
326
|
-
const
|
|
326
|
+
const text = field.shortDescription || field.description;
|
|
327
|
+
const desc = text ? truncateToSentence(text, 1).replace(/\|/g, '\\|') : '_No description_';
|
|
327
328
|
lines.push(`| \`${field.component}\` | \`${field.field}\` | ${desc} |`);
|
|
328
329
|
});
|
|
329
330
|
lines.push('');
|
|
@@ -359,7 +360,8 @@ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, drafte
|
|
|
359
360
|
lines.push(`**Deprecated Fields (${summary.deprecatedFields}):**`);
|
|
360
361
|
lines.push('');
|
|
361
362
|
deprecatedFields.forEach(field => {
|
|
362
|
-
const
|
|
363
|
+
const text = field.shortDescription || field.description;
|
|
364
|
+
const guidance = text ? ` — ${truncateToSentence(text, 1)}` : '';
|
|
363
365
|
lines.push(`- \`${field.component}.${field.field}\`${guidance}`);
|
|
364
366
|
});
|
|
365
367
|
lines.push('');
|
|
@@ -436,7 +438,7 @@ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, drafte
|
|
|
436
438
|
allDeprecatedFields.push({
|
|
437
439
|
component: field.component,
|
|
438
440
|
field: field.field,
|
|
439
|
-
description: field.description,
|
|
441
|
+
description: field.shortDescription || field.description,
|
|
440
442
|
version: release.toVersion
|
|
441
443
|
});
|
|
442
444
|
});
|
|
@@ -77,7 +77,8 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
|
|
|
77
77
|
// span being compared: inputs:oracledb_cdc/snapshot_mode reports
|
|
78
78
|
// 4.99.0 in the 4.98.0 to 4.103.1 diff.
|
|
79
79
|
introducedIn: (rawFieldObj && (rawFieldObj.introducedInVersion || rawFieldObj.version)) || opts.newVersion || null,
|
|
80
|
-
description: rawFieldObj && rawFieldObj.description
|
|
80
|
+
description: rawFieldObj && rawFieldObj.description,
|
|
81
|
+
shortDescription: rawFieldObj && rawFieldObj.short_description
|
|
81
82
|
});
|
|
82
83
|
});
|
|
83
84
|
});
|
|
@@ -193,7 +194,8 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
|
|
|
193
194
|
deprecatedFields.push({
|
|
194
195
|
component: cKey,
|
|
195
196
|
field: fName,
|
|
196
|
-
description: newFieldObj && newFieldObj.description
|
|
197
|
+
description: newFieldObj && newFieldObj.description,
|
|
198
|
+
shortDescription: newFieldObj && newFieldObj.short_description
|
|
197
199
|
});
|
|
198
200
|
}
|
|
199
201
|
|
|
@@ -212,7 +214,8 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
|
|
|
212
214
|
field: fName,
|
|
213
215
|
oldDefault: oldDefault,
|
|
214
216
|
newDefault: newDefault,
|
|
215
|
-
description: newFieldObj && newFieldObj.description
|
|
217
|
+
description: newFieldObj && newFieldObj.description,
|
|
218
|
+
shortDescription: newFieldObj && newFieldObj.short_description
|
|
216
219
|
});
|
|
217
220
|
}
|
|
218
221
|
}
|
|
@@ -30,11 +30,9 @@ function capToTwoSentences (description) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const abbreviations = [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/\bv\d+\.\d+(?:\.\d+)?/gi,
|
|
37
|
-
/\d+\.\d+/g,
|
|
33
|
+
// A period inside a token (a URL, an xref target, a filename, a version
|
|
34
|
+
// or a decimal) has no whitespace after it, so it never ends a sentence.
|
|
35
|
+
// Only abbreviations that are followed by a space need protecting.
|
|
38
36
|
/\be\.g\./gi,
|
|
39
37
|
/\bi\.e\./gi,
|
|
40
38
|
/\betc\./gi,
|
|
@@ -47,6 +45,21 @@ function capToTwoSentences (description) {
|
|
|
47
45
|
/\bNo\./gi
|
|
48
46
|
]
|
|
49
47
|
|
|
48
|
+
// A table cell takes one paragraph of plain text. Keep only the text before
|
|
49
|
+
// the first blank line or list item, so a description such as
|
|
50
|
+
// "Controls how X is sized:\n\n- `a`: ...\n- `b`: ..." does not leak half a
|
|
51
|
+
// list into the cell. A lead-in that ends with a colon is left unterminated
|
|
52
|
+
// so the sentence match below drops it whenever a complete sentence comes
|
|
53
|
+
// before it ("Configure TCP settings. These controls are useful for:" keeps
|
|
54
|
+
// only the first sentence). Only a lead-in with nothing before it is kept,
|
|
55
|
+
// with the colon turned into a period.
|
|
56
|
+
let colonLeadIn = false
|
|
57
|
+
const firstBlock = description.split(/\n\s*\n|\n(?=\s*(?:[-*]|\d+\.)\s)/)[0].trim()
|
|
58
|
+
if (firstBlock && firstBlock !== description.trim() && !/^(?:[=#]|```|----)/.test(firstBlock)) {
|
|
59
|
+
description = firstBlock
|
|
60
|
+
colonLeadIn = firstBlock.endsWith(':')
|
|
61
|
+
}
|
|
62
|
+
|
|
50
63
|
let normalized = description
|
|
51
64
|
const placeholders = []
|
|
52
65
|
|
|
@@ -64,25 +77,19 @@ function capToTwoSentences (description) {
|
|
|
64
77
|
return placeholder
|
|
65
78
|
})
|
|
66
79
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
if (sentences && sentences.length > 0) {
|
|
74
|
-
const firstIndex = normalized.indexOf(sentences[0])
|
|
75
|
-
if (firstIndex > 0) {
|
|
76
|
-
sentences[0] = normalized.slice(0, firstIndex) + sentences[0]
|
|
77
|
-
}
|
|
78
|
-
}
|
|
80
|
+
// A sentence ends at punctuation, optionally followed by a closing quote,
|
|
81
|
+
// parenthesis or bracket, then whitespace or the end of the text. Matching
|
|
82
|
+
// lazily up to that boundary keeps a period inside a token, such as the
|
|
83
|
+
// dotted name partition.assignment.strategy, in its sentence. Text after the
|
|
84
|
+
// last match (an unterminated colon lead-in, for example) is dropped.
|
|
85
|
+
const sentences = normalized.match(/[\s\S]+?[.!?]+["')\]`]*(?:\s|$)/g)
|
|
79
86
|
|
|
80
87
|
if (!sentences || sentences.length === 0) {
|
|
81
88
|
let result = normalized
|
|
82
89
|
placeholders.forEach(({ placeholder, original }) => {
|
|
83
90
|
result = result.replace(placeholder, original)
|
|
84
91
|
})
|
|
85
|
-
return result
|
|
92
|
+
return colonLeadIn ? result.replace(/:$/, '.') : result
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
let maxSentences = 2
|
|
@@ -592,7 +599,7 @@ function buildFieldsTable (fields, capFn, opts = {}) {
|
|
|
592
599
|
if (!byField[key]) {
|
|
593
600
|
byField[key] = {
|
|
594
601
|
field: field.field,
|
|
595
|
-
description: field.description,
|
|
602
|
+
description: field.shortDescription || field.description,
|
|
596
603
|
introducedIn: field.introducedIn,
|
|
597
604
|
components: []
|
|
598
605
|
}
|
|
@@ -626,7 +633,8 @@ function buildFieldsTable (fields, capFn, opts = {}) {
|
|
|
626
633
|
})
|
|
627
634
|
}
|
|
628
635
|
|
|
629
|
-
|
|
636
|
+
// A | in the description would end the cell and shift the row.
|
|
637
|
+
const desc = info.description ? capFn(info.description).replace(/\|/g, '\\|') : '// TODO: Add description'
|
|
630
638
|
|
|
631
639
|
section += `|${fieldName}\n`
|
|
632
640
|
section += `|${desc}\n`
|
|
@@ -655,7 +663,7 @@ function buildChangedDefaultsTable (changedDefaults, capFn) {
|
|
|
655
663
|
field: change.field,
|
|
656
664
|
oldDefault: change.oldDefault,
|
|
657
665
|
newDefault: change.newDefault,
|
|
658
|
-
description: change.description,
|
|
666
|
+
description: change.shortDescription || change.description,
|
|
659
667
|
components: []
|
|
660
668
|
}
|
|
661
669
|
}
|
|
@@ -667,16 +675,25 @@ function buildChangedDefaultsTable (changedDefaults, capFn) {
|
|
|
667
675
|
section += '|Field |Old default |New default |Description |Affected components\n\n'
|
|
668
676
|
|
|
669
677
|
for (const [, info] of Object.entries(byFieldAndDefaults)) {
|
|
678
|
+
// Values render as literal inline code, so interpolations like
|
|
679
|
+
// ${!uuid_v4()} and characters like * or _ show as typed.
|
|
680
|
+
// Values render as literal inline code through pass:c, which, unlike
|
|
681
|
+
// `+...+`, also keeps values with ++ or with spaces at either end. Strings
|
|
682
|
+
// that are empty, start or end with whitespace, or contain a newline show
|
|
683
|
+
// as JSON, so " " and "\n" read as the values they are.
|
|
670
684
|
const formatDefault = (val) => {
|
|
671
685
|
if (val === undefined || val === null) return 'none'
|
|
672
|
-
|
|
673
|
-
if (typeof val === '
|
|
674
|
-
|
|
686
|
+
let text
|
|
687
|
+
if (typeof val === 'string') text = (val === '' || /^\s|\s$|\n/.test(val)) ? JSON.stringify(val) : val
|
|
688
|
+
else if (typeof val === 'number' || typeof val === 'boolean') text = String(val)
|
|
689
|
+
else text = JSON.stringify(val)
|
|
690
|
+
return `\`pass:c[${text.replace(/\]/g, '\\]').replace(/\|/g, '\\|')}]\``
|
|
675
691
|
}
|
|
676
692
|
|
|
677
693
|
const oldVal = formatDefault(info.oldDefault)
|
|
678
694
|
const newVal = formatDefault(info.newDefault)
|
|
679
|
-
|
|
695
|
+
// A | in the description would end the cell and shift the row.
|
|
696
|
+
const desc = info.description ? capFn(info.description).replace(/\|/g, '\\|') : '// TODO: Add description'
|
|
680
697
|
|
|
681
698
|
const byType = {}
|
|
682
699
|
for (const comp of info.components) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
{{{generatedMarker "rpcn-connector-docs" "the Bloblang spec in redpanda-data/connect or redpanda-data/benthos" "This file is a doc-tools preview. The published partials are generated in redpanda-data/connect by `task docs`, and their first line names the file that registers the function or method. To change the text, edit the spec in that file."}}}
|
|
2
2
|
|
|
3
3
|
= {{name}}
|
|
4
4
|
{{#if signature}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{{#if (or summary description version)}}
|
|
2
|
-
|
|
2
|
+
{{{generatedMarker "rpcn-connector-docs" "the component spec in redpanda-data/connect or redpanda-data/benthos" "The summary and description come from the component spec. This file is a doc-tools preview. The published partials are generated in redpanda-data/connect by `task docs`, and their first line names the file that registers the component. To change the text, edit the component spec in that file."}}}
|
|
3
3
|
//
|
|
4
4
|
// Pages consume this partial in two places so both stay fresh:
|
|
5
5
|
// header: include::...[tag=meta] (sets :description: for search snippets and meta tags)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{{#with examples}}
|
|
2
|
-
|
|
2
|
+
{{{generatedMarker "rpcn-connector-docs" "the component spec in redpanda-data/connect or redpanda-data/benthos" "This file is a doc-tools preview. The published partials are generated in redpanda-data/connect by `task docs`, and their first line names the file that registers the component. To change the text, edit the component spec in that file."}}}
|
|
3
3
|
|
|
4
4
|
== Examples
|
|
5
5
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{{#if this.config.children}}
|
|
2
|
-
|
|
2
|
+
{{{generatedMarker "rpcn-connector-docs" "the component spec in redpanda-data/connect or redpanda-data/benthos" "This file is a doc-tools preview. The published partials are generated in redpanda-data/connect by `task docs`, and their first line names the file that registers the component. To change the text, edit the component spec in that file."}}}
|
|
3
3
|
|
|
4
4
|
== Fields
|
|
5
5
|
|
|
6
6
|
{{{renderConnectFields this.config.children}}}
|
|
7
7
|
{{else if this.children}}
|
|
8
|
-
|
|
8
|
+
{{{generatedMarker "rpcn-connector-docs" "the component spec in redpanda-data/connect or redpanda-data/benthos" "This file is a doc-tools preview. The published partials are generated in redpanda-data/connect by `task docs`, and their first line names the file that registers the component. To change the text, edit the component spec in that file."}}}
|
|
9
9
|
|
|
10
10
|
== Fields
|
|
11
11
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{{#if (renderConnectMetadata description)}}
|
|
2
|
-
|
|
2
|
+
{{{generatedMarker "rpcn-connector-docs" "the component spec in redpanda-data/connect or redpanda-data/benthos" "Metadata fields come from the `== Metadata` section of the component description. This file is a doc-tools preview. The published partials are generated in redpanda-data/connect by `task docs`, and their first line names the file that registers the component. To change the text, edit the component spec in that file."}}}
|
|
3
3
|
|
|
4
4
|
{{{renderConnectMetadata description}}}
|
|
5
5
|
{{/if}}
|