diff --git a/generator/_scripts/cfdoc_references_resolver.py b/generator/_scripts/cfdoc_references_resolver.py index 7f6fd9cb1..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() @@ -54,13 +58,12 @@ 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: - 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) @@ -75,13 +78,12 @@ 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: - 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) @@ -91,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)