@redpanda-data/docs-extensions-and-macros 5.47.0 → 5.47.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "5.47.0",
3
+ "version": "5.47.2",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -183,9 +183,16 @@ class ConstexprCache:
183
183
  for search_dir in search_dirs:
184
184
  if not os.path.exists(search_dir):
185
185
  continue
186
-
186
+
187
187
  for root, dirs, files in os.walk(search_dir):
188
- for file in files:
188
+ # Deterministic traversal, same reasoning as get_file_pairs:
189
+ # constexpr_cache and function_cache below are plain dict
190
+ # assignment, last-write-wins, and an identifier redefined in
191
+ # more than one file would otherwise resolve to whichever
192
+ # file the filesystem's own directory order happened to
193
+ # visit last.
194
+ dirs.sort()
195
+ for file in sorted(files):
189
196
  if file.endswith(('.h', '.cc', '.hpp', '.cpp')):
190
197
  file_path = os.path.join(root, file)
191
198
  try:
@@ -616,9 +623,13 @@ def resolve_constexpr_identifier(identifier):
616
623
  if not os.path.exists(search_dir):
617
624
  continue
618
625
 
619
- # Walk through the directory recursively
626
+ # Walk through the directory recursively. Deterministic order, same
627
+ # reasoning as the ConstantResolver scan above: this feeds a
628
+ # last-write-wins dict, so an identifier defined in more than one
629
+ # file would otherwise resolve non-deterministically.
620
630
  for root, dirs, files in os.walk(search_dir):
621
- for file in files:
631
+ dirs.sort()
632
+ for file in sorted(files):
622
633
  # Check both .h and .cc files since definitions can be in either
623
634
  if file.endswith(('.h', '.cc', '.hpp', '.cpp')):
624
635
  file_path = os.path.join(root, file)
@@ -686,7 +697,17 @@ def get_file_pairs(options):
686
697
 
687
698
  file_pairs = []
688
699
 
689
- for i in file_iter:
700
+ # Sorted, not raw rglob/glob order: iteration order reflects the
701
+ # filesystem's own directory-entry order, which is not guaranteed stable
702
+ # across clones or machines. A property name registered in more than one
703
+ # file (api_doc_dir, in both pandaproxy/rest/ and
704
+ # pandaproxy/schema_registry/) hits the "different defined_in" branch in
705
+ # transform_files_with_properties below, which keeps whichever file was
706
+ # processed last -- non-deterministically, without the sort, since that
707
+ # depends on this exact order. Confirmed live: two regenerations of the
708
+ # same overrides-unchanged tag six minutes apart produced different
709
+ # defined_in values for api_doc_dir.
710
+ for i in sorted(file_iter):
690
711
  if os.path.exists(i.with_suffix(".cc")):
691
712
  file_pairs.append(FilePair(i.resolve(), i.with_suffix(".cc").resolve()))
692
713
 
@@ -93,10 +93,16 @@ function ensureHeadingSeparation (body) {
93
93
  * Single-backtick spans still apply attribute substitution, so spans are
94
94
  * escaped too; `----` listing blocks and ```/~~~ fences are verbatim and stay
95
95
  * untouched (a `\{` inside a fence would render as a literal backslash).
96
+ *
97
+ * The name may start uppercase or with an underscore, because environment
98
+ * variable placeholders are the common case in prose: Asciidoctor downcases
99
+ * a reference before looking it up, so ${SALESFORCE_CLIENT_SECRET} outside a
100
+ * fence is consumed exactly like a lowercase one and logs the missing
101
+ * attribute as salesforce_client_secret.
96
102
  */
97
103
  function escapePlaceholderBraces (body) {
98
104
  return annotateVerbatimLines(body).map(({ line, verbatim }) => (
99
- verbatim ? line : line.replace(/(?<![\\{])\{([a-z][\w.-]{1,30})\}/g, '\\{$1}')
105
+ verbatim ? line : line.replace(/(?<![\\{])\{([A-Za-z_][\w.-]{1,30})\}/g, '\\{$1}')
100
106
  )).join('\n');
101
107
  }
102
108
 
@@ -2,6 +2,7 @@ const yaml = require('yaml');
2
2
  const renderYamlList = require('./renderYamlList');
3
3
  const handlebars = require('handlebars');
4
4
  const { connectFieldName } = require('./flattenConnectFields');
5
+ const { escapePlaceholderBraces } = require('./renderConnectDescription');
5
6
 
6
7
  /**
7
8
  * Renders the children of a configuration object into AsciiDoc.
@@ -68,7 +69,9 @@ module.exports = function renderConnectFields(children, prefix = '') {
68
69
  block += `=== \`${currentPath}\`\n\n`;
69
70
 
70
71
  // --- Beta badge logic (now uses is_beta) ---
71
- let desc = child.description || '';
72
+ // Escaped before the badge is prepended, not after: the badge's own
73
+ // tooltip={page-beta-text} is a real attribute reference and must survive.
74
+ let desc = escapePlaceholderBraces(child.description || '');
72
75
  if (child.is_beta) {
73
76
  // Remove any leading "BETA:" label (case-insensitive, trims leading whitespace)
74
77
  desc = 'badge::[label=Beta, size=large, tooltip={page-beta-text}]\n\n' + desc.replace(/^\s*BETA:\s*/i, '');