From dbfcbe038441d31b7e90a893062549c13ea296a8 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Wed, 20 May 2026 23:53:55 +0200 Subject: [PATCH 1/2] Fixed autolinking issue with double quotes Co-authored-by: Claude Opus 4.7 (1M context) Ticket: ENT-14111 Signed-off-by: Ole Herman Schumacher Elgesem --- generator/_scripts/cfdoc_references_resolver.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/generator/_scripts/cfdoc_references_resolver.py b/generator/_scripts/cfdoc_references_resolver.py index 7f6fd9cb1..4f6071936 100644 --- a/generator/_scripts/cfdoc_references_resolver.py +++ b/generator/_scripts/cfdoc_references_resolver.py @@ -54,7 +54,8 @@ def replace_link(match): if ref_lower in references: url, title = references[ref_lower] if title: - return f'[{text}]({url} "{title}")' + escaped_title = title.replace('"', '\\"') + return f'[{text}]({url} "{escaped_title}")' else: return f"[{text}]({url})" else: @@ -75,7 +76,8 @@ def replace_function_link(match): if ref_lower in references: url, title = references[ref_lower] if title: - return f'[{text}]({url} "{title}")' + escaped_title = title.replace('"', '\\"') + return f'[{text}]({url} "{escaped_title}")' else: return f"[{text}]({url})" else: From 320d8fcfc01566b533b5f107b6a910af8a1c0008 Mon Sep 17 00:00:00 2001 From: Ole Herman Schumacher Elgesem Date: Thu, 21 May 2026 00:34:00 +0200 Subject: [PATCH 2/2] Made autolinking fail loudly so broken links are exposed Co-authored-by: Claude Opus 4.7 (1M context) Signed-off-by: Ole Herman Schumacher Elgesem --- .../_scripts/cfdoc_references_resolver.py | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/generator/_scripts/cfdoc_references_resolver.py b/generator/_scripts/cfdoc_references_resolver.py index 4f6071936..64a36810d 100644 --- a/generator/_scripts/cfdoc_references_resolver.py +++ b/generator/_scripts/cfdoc_references_resolver.py @@ -35,8 +35,12 @@ def load_references(references_file): return references -def process(file_path, references): - """Process a markdown file and replace reference links with direct links.""" +def process(file_path, references, missing): + """Process a markdown file and replace reference links with direct links. + + Any reference that cannot be resolved is appended to `missing` as a + (file_path, ref) tuple so the caller can fail the build. + """ with open(file_path, "r", encoding="utf-8") as f: content = f.read() @@ -59,9 +63,7 @@ def replace_link(match): else: return f"[{text}]({url})" else: - sys.stderr.write( - f"References {ref} is not found in the _references.md. File: {file_path}\n" - ) + missing.append((file_path, ref)) return match.group(0) new_content = re.sub(pattern, replace_link, content) @@ -81,9 +83,7 @@ def replace_function_link(match): else: return f"[{text}]({url})" else: - sys.stderr.write( - f"References {ref} is not found in the _references.md. File: {file_path}\n" - ) + missing.append((file_path, f"{ref}()")) return match.group(0) new_content = re.sub(functions_pattern, replace_function_link, new_content) @@ -93,9 +93,27 @@ def replace_function_link(match): def run(config): - """Replaces [text][reference] with markdown links retrieved from _references.md""" + """Replaces [text][reference] with markdown links retrieved from _references.md. + + Exits non-zero if any reference cannot be resolved, so broken autolinks + fail the build loudly instead of silently shipping unresolved markdown. + """ markdown_files = config["markdown_files"] references = load_references("documentation/generator/_references.md") + missing = [] for file in markdown_files: - process(file, references) + process(file, references, missing) + + if missing: + sys.stderr.write( + "ERROR: %d unresolved reference link(s) found in _references.md:\n" + % len(missing) + ) + for file_path, ref in missing: + sys.stderr.write(f" [{ref}] in {file_path}\n") + sys.stderr.write( + "Add the missing entries to documentation/generator/_references.md " + "or fix the links in the listed files.\n" + ) + sys.exit(1)