From c0bedbce9660b49cba1c2f94bfeaf52184894242 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:15:16 +0000 Subject: [PATCH 1/2] fix: handle triple-backtick code fences in sanitizeChangelogEntry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sanitizer only split on single-backtick inline code spans, so triple-backtick fenced code blocks (common in Java changelog entries) threw off backtick parity. This caused later inline code spans like `onMessage(Consumer)` to be treated as plain text, and Consumer got double-wrapped in backticks — breaking MDX parsing in the docs repo. Fix: split on fenced code blocks first (preserving them verbatim), then process each remaining segment with the existing inline-backtick logic. Co-Authored-By: unknown <> --- .../__tests__/sanitizeChangelogEntry.test.ts | 19 +++++++++++++++ .../core-utils/src/sanitizeChangelogEntry.ts | 23 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/commons/core-utils/src/__tests__/sanitizeChangelogEntry.test.ts b/packages/commons/core-utils/src/__tests__/sanitizeChangelogEntry.test.ts index 96bb50bc8f9e..f17cce2f4c5a 100644 --- a/packages/commons/core-utils/src/__tests__/sanitizeChangelogEntry.test.ts +++ b/packages/commons/core-utils/src/__tests__/sanitizeChangelogEntry.test.ts @@ -74,4 +74,23 @@ describe("sanitizeChangelogEntry", () => { const expected = "Added `Optional` support.\nAlso changed `Map` handling."; expect(sanitizeChangelogEntry(input)).toBe(expected); }); + + it("does not double-wrap types inside backtick spans after a fenced code block", () => { + const input = + "Intro text.\n\n```java\nws.connect();\n```\n\n**Generic `onMessage(Consumer)` handler** fires."; + const expected = + "Intro text.\n\n```java\nws.connect();\n```\n\n**Generic `onMessage(Consumer)` handler** fires."; + expect(sanitizeChangelogEntry(input)).toBe(expected); + }); + + it("preserves fenced code blocks verbatim", () => { + const input = "Before.\n\n```java\nList items = new ArrayList();\n```\n\nAfter."; + expect(sanitizeChangelogEntry(input)).toBe(input); + }); + + it("wraps types outside a code fence but not inside", () => { + const input = "Use Optional.\n\n```java\nOptional x;\n```\n\nAlso Map."; + const expected = "Use `Optional`.\n\n```java\nOptional x;\n```\n\nAlso `Map`."; + expect(sanitizeChangelogEntry(input)).toBe(expected); + }); }); diff --git a/packages/commons/core-utils/src/sanitizeChangelogEntry.ts b/packages/commons/core-utils/src/sanitizeChangelogEntry.ts index 0dc424b59751..2c5c5b21f5f4 100644 --- a/packages/commons/core-utils/src/sanitizeChangelogEntry.ts +++ b/packages/commons/core-utils/src/sanitizeChangelogEntry.ts @@ -9,9 +9,30 @@ * Already-backticked spans are left untouched. */ export function sanitizeChangelogEntry(entry: string): string { + // First, split on triple-backtick fenced code blocks so they are never + // processed by the inline-backtick logic (which only understands single + // backtick pairs and gets confused by the three-backtick delimiters). + const fenceParts = entry.split(/(```[\s\S]*?```)/g); + return fenceParts + .map((part) => { + // Fenced code blocks are preserved verbatim. + if (part.startsWith("```") && part.endsWith("```")) { + return part; + } + return sanitizeInlinePart(part); + }) + .join(""); +} + +/** + * Processes a text segment that is outside any fenced code block. + * Splits on single-backtick inline code spans and only applies + * angle-bracket wrapping to plain-text segments. + */ +function sanitizeInlinePart(text: string): string { // Split the text into alternating segments: plain text and backtick-delimited code spans. // Odd-indexed segments are inside backticks and must be preserved as-is. - const parts = entry.split(/(`[^`]+`)/g); + const parts = text.split(/(`[^`]+`)/g); return parts .map((part) => { // If this part is a code span, leave it as-is From c432cd16e7744b4945001f192cf0746c22084326 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:22:06 +0000 Subject: [PATCH 2/2] fix(changelog): use stricter regex for fenced code blocks Address Graphite review: require newlines around fence content so that triple backticks inside code (e.g. a string literal containing ```) do not prematurely terminate the match. Co-Authored-By: unknown <> --- packages/commons/core-utils/src/sanitizeChangelogEntry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/commons/core-utils/src/sanitizeChangelogEntry.ts b/packages/commons/core-utils/src/sanitizeChangelogEntry.ts index 2c5c5b21f5f4..5f7e0b33d6e8 100644 --- a/packages/commons/core-utils/src/sanitizeChangelogEntry.ts +++ b/packages/commons/core-utils/src/sanitizeChangelogEntry.ts @@ -12,7 +12,7 @@ export function sanitizeChangelogEntry(entry: string): string { // First, split on triple-backtick fenced code blocks so they are never // processed by the inline-backtick logic (which only understands single // backtick pairs and gets confused by the three-backtick delimiters). - const fenceParts = entry.split(/(```[\s\S]*?```)/g); + const fenceParts = entry.split(/(```[^\n]*\n[\s\S]*?\n```)/g); return fenceParts .map((part) => { // Fenced code blocks are preserved verbatim.