From 7176b04a2e1273de72aeaeb72241db808b74d60a Mon Sep 17 00:00:00 2001 From: agu2347 <94227848+agu2347@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:54:44 +0530 Subject: [PATCH] Escape `"` in image titles (#586) image() in src/mdformat/renderer/_context.py rendered node.attrs['title'] directly into the parenthesized `(uri "title")` form without escaping embedded double quotes, unlike link() a few lines below which already does `title.replace('"', '\\\\"')`. An unescaped quote in an image title terminates the title early, producing malformed Markdown, and made mdformat.text() non-idempotent on such input (a second format pass reparsed the corrupted output differently, even escaping the image brackets themselves). Mirror link()'s escaping in image() so titles round-trip correctly. Adds a `link and image titles with embedded quotes` case to tests/data/default_style.md covering both link and image titles. --- src/mdformat/renderer/_context.py | 2 ++ tests/data/default_style.md | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/mdformat/renderer/_context.py b/src/mdformat/renderer/_context.py index 238dd07d..73150c3d 100644 --- a/src/mdformat/renderer/_context.py +++ b/src/mdformat/renderer/_context.py @@ -218,6 +218,8 @@ def image(node: RenderTreeNode, context: RenderContext) -> str: uri = maybe_add_link_brackets(uri) title = node.attrs.get("title") if title is not None: + assert isinstance(title, str) + title = title.replace('"', '\\"') return f'![{description}]({uri} "{title}")' return f"![{description}]({uri})" diff --git a/tests/data/default_style.md b/tests/data/default_style.md index 7f1d4538..eed8b3ed 100644 --- a/tests/data/default_style.md +++ b/tests/data/default_style.md @@ -130,6 +130,17 @@ references: [ref2]: link3 "title" . +link and image titles with embedded quotes +. +[text](link1 "a \"quoted\" title") + +![text](img.png "a \"quoted\" title") +. +[text](link1 "a \"quoted\" title") + +![text](img.png "a \"quoted\" title") +. + thematic breaks . something something