@redpanda-data/docs-extensions-and-macros 5.1.2 → 5.2.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.js CHANGED
@@ -770,6 +770,7 @@ automation
770
770
  .option('--template-intro <path>', 'Intro section partial template', path.resolve(__dirname, '../tools/redpanda-connect/templates/intro.hbs'))
771
771
  .option('--template-fields <path>', 'Fields section partial template', path.resolve(__dirname, '../tools/redpanda-connect/templates/fields-partials.hbs'))
772
772
  .option('--template-examples <path>', 'Examples section partial template', path.resolve(__dirname, '../tools/redpanda-connect/templates/examples-partials.hbs'))
773
+ .option('--template-metadata <path>', 'Metadata section partial template', path.resolve(__dirname, '../tools/redpanda-connect/templates/metadata-partials.hbs'))
773
774
  .option('--template-bloblang <path>', 'Custom Handlebars template for bloblang function/method partials')
774
775
  .option('--overrides <path>', 'Optional JSON file with overrides', 'docs-data/overrides.json')
775
776
  .option('--include-bloblang', 'Include Bloblang functions and methods in generation')
@@ -792,6 +793,38 @@ automation
792
793
  await handleRpcnConnectorDocs(options)
793
794
  })
794
795
 
796
+ /**
797
+ * generate migrate-rpcn-metadata
798
+ *
799
+ * @description
800
+ * One-time migration that moves inline `== Metadata` blocks out of connector
801
+ * reference pages (modules/components/pages/<type>/<name>.adoc) and into
802
+ * regenerated partials (modules/components/partials/metadata/<type>/<name>.adoc),
803
+ * replacing the inline block in the page with an include directive. Afterwards
804
+ * `generate rpcn-connector-docs` keeps the partial in sync with the connector's
805
+ * upstream description on every run.
806
+ *
807
+ * @why
808
+ * Metadata documented inline in the main page is never refreshed by normal
809
+ * regeneration, so it drifts from the source. Extracting it into a partial makes
810
+ * it flow through automatically, matching the fields and examples partials.
811
+ *
812
+ * @example
813
+ * # Dry run (default): report the pages that would change
814
+ * npx doc-tools generate migrate-rpcn-metadata
815
+ *
816
+ * # Apply the migration
817
+ * npx doc-tools generate migrate-rpcn-metadata --write
818
+ */
819
+ automation
820
+ .command('migrate-rpcn-metadata')
821
+ .description('One-time migration of inline connector == Metadata blocks into regenerated partials. Dry run unless --write is given.')
822
+ .option('--write', 'Apply changes (default is a dry run that only reports)')
823
+ .action((options) => {
824
+ const { migrateMetadataToPartials } = require('../tools/redpanda-connect/migrate-metadata-to-partials.js')
825
+ migrateMetadataToPartials({ write: Boolean(options.write) })
826
+ })
827
+
795
828
  /**
796
829
  * generate property-docs
797
830
  *
@@ -133,6 +133,9 @@ function generateMetricsDocs(args) {
133
133
  return {
134
134
  success: false,
135
135
  error: err.message,
136
+ // Report the resolved ref even on failure so callers can confirm
137
+ // parameter defaulting worked independently of the build outcome.
138
+ [refType]: version,
136
139
  stdout: err.stdout || '',
137
140
  stderr: err.stderr || '',
138
141
  exitCode: err.status,
@@ -162,6 +162,9 @@ function generatePropertyDocs(args) {
162
162
  return {
163
163
  success: false,
164
164
  error: err.message,
165
+ // Report the resolved ref even on failure so callers can confirm
166
+ // parameter defaulting worked independently of the build outcome.
167
+ [refType]: version,
165
168
  stdout: err.stdout || '',
166
169
  stderr: err.stderr || '',
167
170
  exitCode: err.status,
@@ -188,6 +188,12 @@ function generateRpkDocs(args) {
188
188
  const response = {
189
189
  success: false,
190
190
  error: err.message,
191
+ // Report the ref that was resolved and attempted, even on failure, so
192
+ // callers can confirm parameter defaulting worked independently of the
193
+ // (environment-dependent) build outcome.
194
+ ref: version,
195
+ version: version,
196
+ ref_type: refType,
191
197
  stdout: err.stdout || '',
192
198
  stderr: err.stderr || '',
193
199
  exitCode: err.status
@@ -104,7 +104,11 @@ install_buf() {
104
104
  # Download and install buf for Linux
105
105
  BIN="/usr/local/bin/buf"
106
106
  VERSION="1.28.1"
107
- curl -sSL "https://github.com/bufbuild/buf/releases/download/v${VERSION}/buf-$(uname -s)-$(uname -m)" -o "${BIN}" || { log_error "Failed to download buf"; exit 1; }
107
+ # Same download hardening as install_rpk: fail on HTTP errors and
108
+ # retry transient GitHub/CDN failures with exponential backoff.
109
+ curl -fsSL --retry 5 --retry-all-errors \
110
+ --connect-timeout 30 --max-time 300 --retry-max-time 600 \
111
+ "https://github.com/bufbuild/buf/releases/download/v${VERSION}/buf-$(uname -s)-$(uname -m)" -o "${BIN}" || { log_error "Failed to download buf"; rm -f "${BIN}" 2>/dev/null; exit 1; }
108
112
  chmod +x "${BIN}" || { log_error "Failed to make buf executable"; exit 1; }
109
113
  ;;
110
114
  Darwin)
@@ -464,8 +468,15 @@ install_rpk() {
464
468
 
465
469
  log_info "Detected ${os_name} ${arch_name}, downloading ${rpk_filename}..."
466
470
 
467
- # Try to download and install rpk
468
- if curl -LO "$rpk_url"; then
471
+ # Try to download and install rpk.
472
+ # Use -f so HTTP errors (e.g. 403/404/429/503) fail instead of writing an
473
+ # error page into the zip, and retry with curl's default exponential
474
+ # backoff (1s, 2s, 4s, ...) to ride out transient GitHub/CDN and network
475
+ # errors, including rate limits that need time to clear. --retry-max-time
476
+ # caps the whole retry window so CI fails fast on persistent errors.
477
+ if curl -fL --retry 5 --retry-all-errors \
478
+ --connect-timeout 30 --max-time 300 --retry-max-time 600 \
479
+ -o "$rpk_filename" "$rpk_url"; then
469
480
  if unzip "$rpk_filename" 2>/dev/null; then
470
481
  mkdir -p ~/.local/bin
471
482
  if mv rpk ~/.local/bin/ 2>/dev/null; then
@@ -505,6 +516,8 @@ install_rpk() {
505
516
  fi
506
517
  else
507
518
  log_warn "Failed to download $rpk_url"
519
+ # A mid-transfer failure can leave a partial file behind even with -f.
520
+ rm -f "$rpk_filename" 2>/dev/null
508
521
  log_warn "Please install rpk manually:"
509
522
  log_warn "https://docs.redpanda.com/current/get-started/rpk-install/"
510
523
  return 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "5.1.2",
3
+ "version": "5.2.0",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -304,7 +304,8 @@ IMPORTANT: This documentation is auto-generated. Do not edit manually. Run \`npm
304
304
  'cloud-regions',
305
305
  'crd-spec',
306
306
  'bundle-openapi',
307
- 'update-connect-version'
307
+ 'update-connect-version',
308
+ 'migrate-rpcn-metadata'
308
309
  ];
309
310
 
310
311
  generateSubcommands.forEach(subcmd => {
@@ -18,6 +18,17 @@ Object.entries(helpers).forEach(([name, fn]) => {
18
18
  // Default “main” template (connector.hbs) which invokes partials {{> intro}}, {{> fields}}, {{> examples}}
19
19
  const DEFAULT_TEMPLATE = path.resolve(__dirname, './templates/connector.hbs');
20
20
 
21
+ // Default template for the regenerated per-connector metadata partial.
22
+ const DEFAULT_METADATA_TEMPLATE = path.resolve(__dirname, './templates/metadata-partials.hbs');
23
+
24
+ // Banner-only content written to a metadata partial when its `== Metadata`
25
+ // section is removed upstream. Kept as an AsciiDoc comment so the file renders
26
+ // nothing while any lingering include directive still resolves cleanly.
27
+ const STALE_METADATA_PARTIAL =
28
+ '// This content is autogenerated. Do not edit manually. ' +
29
+ 'The connector description no longer contains a `== Metadata` section, so this partial is intentionally empty. ' +
30
+ 'You can remove the include directive that points at this file from the connector page.\n';
31
+
21
32
  /**
22
33
  * Reads a file at `filePath` and registers it as a Handlebars partial called `name`.
23
34
  * Throws if the file cannot be read.
@@ -241,6 +252,7 @@ async function generateRpcnConnectorDocs(options) {
241
252
  templateIntro,
242
253
  templateFields,
243
254
  templateExamples,
255
+ templateMetadata,
244
256
  templateBloblang,
245
257
  writeFullDrafts,
246
258
  cgoOnly = [], // Array of cgo-only connectors from cgo binary inspection
@@ -336,6 +348,12 @@ async function generateRpcnConnectorDocs(options) {
336
348
  registerPartial('examples', examplesTemplatePath);
337
349
  }
338
350
 
351
+ // Always register the metadata partial. Like fields and examples, it is
352
+ // regenerated on every run so that metadata fields added to a connector's
353
+ // upstream description flow into the docs automatically.
354
+ const metadataTemplatePath = templateMetadata || DEFAULT_METADATA_TEMPLATE;
355
+ registerPartial('metadata', metadataTemplatePath);
356
+
339
357
  // In draft mode, also register the intro partial
340
358
  if (writeFullDrafts && templateIntro) {
341
359
  registerPartial('intro', templateIntro);
@@ -344,6 +362,7 @@ async function generateRpcnConnectorDocs(options) {
344
362
  const outputRoot = path.resolve(process.cwd(), 'modules/components/partials');
345
363
  const fieldsOutRoot = path.join(outputRoot, 'fields');
346
364
  const examplesOutRoot = path.join(outputRoot, 'examples');
365
+ const metadataOutRoot = path.join(outputRoot, 'metadata');
347
366
  // Drafts go to pages/, not partials/
348
367
  const componentsRoot = writeFullDrafts
349
368
  ? path.resolve(process.cwd(), 'modules/components/pages')
@@ -353,6 +372,7 @@ async function generateRpcnConnectorDocs(options) {
353
372
  if (!writeFullDrafts) {
354
373
  fs.mkdirSync(fieldsOutRoot, { recursive: true });
355
374
  fs.mkdirSync(examplesOutRoot, { recursive: true });
375
+ fs.mkdirSync(metadataOutRoot, { recursive: true });
356
376
  }
357
377
 
358
378
  let partialsWritten = 0;
@@ -403,6 +423,37 @@ async function generateRpcnConnectorDocs(options) {
403
423
  }
404
424
  }
405
425
 
426
+ // Render the metadata partial from the connector's description. Only
427
+ // written when the description contains a `== Metadata` section.
428
+ const metadataOut = handlebars
429
+ .compile('{{> metadata description=description type=type typeDir=typeDir name=name}}')(item);
430
+
431
+ if (type !== 'bloblang-functions' && type !== 'bloblang-methods') {
432
+ // Write under typeDir (not the raw data key) so the file path always
433
+ // matches the include directive built by metadataIncludeLine().
434
+ const mPath = path.join(metadataOutRoot, typeDir, `${name}.adoc`);
435
+ if (metadataOut.trim()) {
436
+ fs.mkdirSync(path.dirname(mPath), { recursive: true });
437
+ fs.writeFileSync(mPath, metadataOut);
438
+ if (!writeFullDrafts) {
439
+ partialsWritten++;
440
+ partialFiles.push(path.relative(process.cwd(), mPath));
441
+ }
442
+ } else if (fs.existsSync(mPath)) {
443
+ // The upstream description dropped its `== Metadata` section, but a
444
+ // previously generated partial is still on disk and an already
445
+ // published page may include it. Deleting the file would break that
446
+ // include (unresolved include directive + build warning), so blank it
447
+ // to a banner-only file: the include still resolves and renders
448
+ // nothing. Log it so a human knows to remove the include line.
449
+ fs.writeFileSync(mPath, STALE_METADATA_PARTIAL);
450
+ console.log(
451
+ `Metadata section removed upstream; emptied stale partial ${path.relative(process.cwd(), mPath)} ` +
452
+ `(remove its include directive from the ${type}/${name} page)`
453
+ );
454
+ }
455
+ }
456
+
406
457
  if (writeFullDrafts) {
407
458
  if (String(item.status || '').toLowerCase() === 'deprecated') {
408
459
  console.log(`Skipping draft for deprecated component: ${type}/${name}`);
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const { descriptionWithMetadataInclude } = require('../metadata-utils.js');
4
+
5
+ /**
6
+ * Handlebars helper: render a connector description with its inline
7
+ * `== Metadata` block replaced by an include of the regenerated metadata
8
+ * partial, so newly drafted pages pick up metadata changes automatically.
9
+ * Falls back to the unchanged description when no metadata section exists.
10
+ * @param {object} item connector data (needs description, type/typeDir, name)
11
+ * @returns {string}
12
+ */
13
+ module.exports = function descriptionWithMetadataIncludeHelper (item) {
14
+ return descriptionWithMetadataInclude(item);
15
+ };
@@ -11,6 +11,8 @@ module.exports = {
11
11
  renderYamlList: require('./renderYamlList.js'),
12
12
  renderConnectFields: require('./renderConnectFields.js'),
13
13
  renderConnectExamples: require('./renderConnectExamples.js'),
14
+ renderConnectMetadata: require('./renderConnectMetadata.js'),
15
+ descriptionWithMetadataInclude: require('./descriptionWithMetadataInclude.js'),
14
16
  renderLeafField: require('./renderLeafField.js'),
15
17
  renderObjectField: require('./renderObjectField.js'),
16
18
  buildConfigYaml: require('./buildConfigYaml.js'),
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ const { extractMetadata } = require('../metadata-utils.js');
4
+
5
+ /**
6
+ * Handlebars helper: return the `== Metadata` block extracted from a connector
7
+ * description, or '' when there is none. Used by the metadata partial template.
8
+ * @param {string} description
9
+ * @returns {string}
10
+ */
11
+ module.exports = function renderConnectMetadata (description) {
12
+ return extractMetadata(description);
13
+ };
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Utilities for extracting the "== Metadata" section out of a connector's
5
+ * `description` prose so it can be emitted as a regenerated partial (like the
6
+ * fields and examples partials) instead of being frozen into a hand-maintained
7
+ * main page.
8
+ *
9
+ * Convention: the connector `.Description()` in the Connect source contains a
10
+ * level-2 AsciiDoc heading `== Metadata` followed by a bullet list, terminated
11
+ * by the next level-2 heading (for example `== Permissions`) or end of string.
12
+ * As of Connect 4.99.0, 52 of the 65 metadata-documenting components already
13
+ * follow this exact heading convention.
14
+ */
15
+
16
+ const METADATA_HEADING = /^==\s+Metadata\s*$/;
17
+ const LEVEL2_HEADING = /^==\s+\S/;
18
+ // AsciiDoc listing/literal block delimiter (`----`, possibly longer). Lines
19
+ // inside such blocks must not be treated as headings.
20
+ const BLOCK_DELIMITER = /^-{4,}$/;
21
+
22
+ /**
23
+ * Locate the `== Metadata` section within a description.
24
+ * @param {string} description
25
+ * @returns {{start:number, end:number, block:string}|null} character offsets of
26
+ * the section (heading through the last content line, trailing blank lines
27
+ * excluded) and the extracted block text, or null when no section is present.
28
+ */
29
+ function locateMetadata (description) {
30
+ if (!description || typeof description !== 'string') return null;
31
+
32
+ const lines = description.split('\n');
33
+ let headingLine = -1;
34
+ let inBlock = false;
35
+ for (let i = 0; i < lines.length; i++) {
36
+ if (BLOCK_DELIMITER.test(lines[i])) { inBlock = !inBlock; continue; }
37
+ if (!inBlock && METADATA_HEADING.test(lines[i])) { headingLine = i; break; }
38
+ }
39
+ if (headingLine === -1) return null;
40
+
41
+ // Find the terminating heading (next level-2 heading after the metadata one).
42
+ let endLine = lines.length;
43
+ inBlock = false;
44
+ for (let i = headingLine + 1; i < lines.length; i++) {
45
+ if (BLOCK_DELIMITER.test(lines[i])) { inBlock = !inBlock; continue; }
46
+ if (!inBlock && LEVEL2_HEADING.test(lines[i])) { endLine = i; break; }
47
+ }
48
+
49
+ // Trim trailing blank lines inside the section so the block ends cleanly.
50
+ let lastContent = endLine - 1;
51
+ while (lastContent > headingLine && lines[lastContent].trim() === '') lastContent--;
52
+
53
+ const startOffset = lines.slice(0, headingLine).join('\n').length + (headingLine > 0 ? 1 : 0);
54
+ const block = lines.slice(headingLine, lastContent + 1).join('\n');
55
+ const endOffset = startOffset + block.length;
56
+
57
+ return { start: startOffset, end: endOffset, block };
58
+ }
59
+
60
+ /**
61
+ * Return the extracted `== Metadata` block, or '' when there is none.
62
+ * @param {string} description
63
+ * @returns {string}
64
+ */
65
+ function extractMetadata (description) {
66
+ const found = locateMetadata(description);
67
+ return found ? found.block : '';
68
+ }
69
+
70
+ /**
71
+ * Derive the plural type directory (for example `input` -> `inputs`).
72
+ * @param {object} item connector data with `type` and/or `typeDir`
73
+ * @returns {string}
74
+ */
75
+ function typeDirFor (item) {
76
+ if (item && item.typeDir) return item.typeDir;
77
+ const type = item && item.type;
78
+ if (!type) return '';
79
+ return type.endsWith('s') ? type : `${type}s`;
80
+ }
81
+
82
+ /**
83
+ * Build the Antora include directive for a connector's metadata partial.
84
+ * @param {object} item connector data with `type`/`typeDir` and `name`
85
+ * @returns {string}
86
+ */
87
+ function metadataIncludeLine (item) {
88
+ return `include::connect:components:partial$metadata/${typeDirFor(item)}/${item.name}.adoc[]`;
89
+ }
90
+
91
+ /**
92
+ * Replace the inline `== Metadata` block in a description with an include
93
+ * directive pointing at the regenerated metadata partial, preserving position
94
+ * relative to surrounding sections (such as `== Permissions`). Returns the
95
+ * description unchanged when no metadata section is present.
96
+ * @param {object} item connector data (needs `description`, `type`/`typeDir`, `name`)
97
+ * @returns {string}
98
+ */
99
+ function descriptionWithMetadataInclude (item) {
100
+ const description = (item && item.description) || '';
101
+ const found = locateMetadata(description);
102
+ if (!found) return description;
103
+ return description.slice(0, found.start) + metadataIncludeLine(item) + description.slice(found.end);
104
+ }
105
+
106
+ module.exports = {
107
+ locateMetadata,
108
+ extractMetadata,
109
+ typeDirFor,
110
+ metadataIncludeLine,
111
+ descriptionWithMetadataInclude,
112
+ };
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * One-time migration for the metadata-partial change.
5
+ *
6
+ * Existing connector reference pages carry their `== Metadata` block inline in
7
+ * the main page (`modules/components/pages/<type>/<name>.adoc`), where normal
8
+ * regeneration never refreshes it. This script moves that block into a
9
+ * regenerated partial (`modules/components/partials/metadata/<type>/<name>.adoc`)
10
+ * and replaces the inline block in the page with an include directive, matching
11
+ * the pattern already used for the fields and examples partials.
12
+ *
13
+ * After migration, `doc-tools generate rpcn-connector-docs` keeps the partial in
14
+ * sync with the connector's upstream description on every run.
15
+ *
16
+ * Usage (run from the docs repo root):
17
+ * npx doc-tools generate migrate-rpcn-metadata # dry run, reports changes
18
+ * npx doc-tools generate migrate-rpcn-metadata --write # apply changes
19
+ */
20
+
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+ const { globSync } = require('glob');
24
+ const { locateMetadata, metadataIncludeLine } = require('./metadata-utils.js');
25
+
26
+ const PARTIAL_BANNER =
27
+ '// This content is autogenerated. Do not edit manually. Metadata fields come from the connector\'s description in the Connect source. To change them, update the connector description upstream, or use the doc-tools CLI with the --overrides option: https://redpandadata.atlassian.net/wiki/spaces/DOC/pages/1247543314/Generate+reference+docs+for+Redpanda+Connect';
28
+
29
+ const PAGES_ROOT = path.resolve(process.cwd(), 'modules/components/pages');
30
+ const PARTIALS_ROOT = path.resolve(process.cwd(), 'modules/components/partials/metadata');
31
+
32
+ /** Recursively collect .adoc files under a directory (minimatch glob). */
33
+ function collectAdocFiles (dir) {
34
+ if (!fs.existsSync(dir)) return [];
35
+ return globSync('**/*.adoc', { cwd: dir, absolute: true, nodir: true });
36
+ }
37
+
38
+ /**
39
+ * Migrate inline `== Metadata` blocks in connector pages to regenerated
40
+ * partials plus include directives.
41
+ * @param {object} [options]
42
+ * @param {boolean} [options.write=false] Apply changes (otherwise dry run).
43
+ * @returns {{migrated:number, skipped:number}}
44
+ */
45
+ function migrateMetadataToPartials ({ write = false } = {}) {
46
+ const pages = collectAdocFiles(PAGES_ROOT);
47
+
48
+ let migrated = 0;
49
+ let skipped = 0;
50
+
51
+ for (const page of pages) {
52
+ // Connector pages live in a <type> subdirectory (pages/<type>/<name>.adoc).
53
+ // Skip pages directly under pages/ — they are not connector pages, and the
54
+ // parent-directory name would be a bogus type.
55
+ if (path.dirname(page) === PAGES_ROOT) { skipped++; continue; }
56
+
57
+ const content = fs.readFileSync(page, 'utf8');
58
+ const found = locateMetadata(content);
59
+ if (!found) { skipped++; continue; }
60
+
61
+ // Derive type directory and connector name from the page path.
62
+ const typeDir = path.basename(path.dirname(page));
63
+ const name = path.basename(page, '.adoc');
64
+ const item = { typeDir, name };
65
+
66
+ // If the block is already an include, nothing to do.
67
+ if (/include::connect:components:partial\$metadata\//.test(found.block)) { skipped++; continue; }
68
+
69
+ const partialPath = path.join(PARTIALS_ROOT, typeDir, `${name}.adoc`);
70
+ const partialContent = `${PARTIAL_BANNER}\n\n${found.block}\n`;
71
+ const newPage = content.slice(0, found.start) + metadataIncludeLine(item) + content.slice(found.end);
72
+
73
+ // Prefer a partial already produced by the generator (source of truth).
74
+ // Only seed one from the page's inline block when none exists yet, so the
75
+ // migration works standalone but never clobbers generated content.
76
+ const partialExists = fs.existsSync(partialPath);
77
+
78
+ console.log(`${write ? 'MIGRATE' : 'WOULD MIGRATE'}: ${typeDir}/${name}`);
79
+ console.log(` -> partial: ${path.relative(process.cwd(), partialPath)}${partialExists ? ' (exists, kept)' : ' (seeded from page)'}`);
80
+
81
+ if (write) {
82
+ if (!partialExists) {
83
+ fs.mkdirSync(path.dirname(partialPath), { recursive: true });
84
+ fs.writeFileSync(partialPath, partialContent);
85
+ }
86
+ fs.writeFileSync(page, newPage);
87
+ }
88
+ migrated++;
89
+ }
90
+
91
+ console.log(`\n${write ? 'Migrated' : 'Would migrate'} ${migrated} page(s); ${skipped} without an inline metadata section.`);
92
+ if (!write) console.log('Dry run only. Re-run with --write to apply.');
93
+
94
+ return { migrated, skipped };
95
+ }
96
+
97
+ module.exports = { migrateMetadataToPartials };
98
+
99
+ // Allow direct execution for local development; the supported entry point is
100
+ // `npx doc-tools generate migrate-rpcn-metadata`.
101
+ if (require.main === module) {
102
+ migrateMetadataToPartials({ write: process.argv.includes('--write') });
103
+ }
@@ -1093,6 +1093,7 @@ async function handleRpcnConnectorDocs (options) {
1093
1093
  templateIntro: options.templateIntro,
1094
1094
  templateFields: options.templateFields,
1095
1095
  templateExamples: options.templateExamples,
1096
+ templateMetadata: options.templateMetadata,
1096
1097
  templateBloblang: options.templateBloblang,
1097
1098
  writeFullDrafts: false,
1098
1099
  includeBloblang: !!options.includeBloblang,
@@ -1882,6 +1883,7 @@ async function handleRpcnConnectorDocs (options) {
1882
1883
  template: options.templateMain,
1883
1884
  templateFields: options.templateFields,
1884
1885
  templateExamples: options.templateExamples,
1886
+ templateMetadata: options.templateMetadata,
1885
1887
  templateIntro: options.templateIntro,
1886
1888
  writeFullDrafts: true,
1887
1889
  cgoOnly: binaryAnalysis?.cgoOnly || [],
@@ -7,7 +7,7 @@ endif::[]
7
7
  {{/if}}
8
8
 
9
9
  {{#if description}}
10
- {{{description}}}
10
+ {{{descriptionWithMetadataInclude this}}}
11
11
  {{else}}
12
12
  // TODO: Missing description. Add a description in the overrides file or source data.
13
13
  {{/if}}
@@ -0,0 +1,5 @@
1
+ {{#if (renderConnectMetadata description)}}
2
+ // This content is autogenerated. Do not edit manually. Metadata fields come from the connector's description in the Connect source. To change them, update the connector description upstream, or use the doc-tools CLI with the --overrides option: https://redpandadata.atlassian.net/wiki/spaces/DOC/pages/1247543314/Generate+reference+docs+for+Redpanda+Connect
3
+
4
+ {{{renderConnectMetadata description}}}
5
+ {{/if}}