From 7aad67ccf8c4df4dd11dc4f20cc347a8987ab299 Mon Sep 17 00:00:00 2001 From: Rahul Ranjan Date: Mon, 9 Nov 2026 12:04:52 +0000 Subject: [PATCH] fix: don't linkify inside inline HTML markup tokens (#752) The link-patterns extra checked only markdown link syntax and auto-links before replacing a match. A match inside any other inline HTML markup token that markdown2's own tokenizer recognizes - a tag (), a comment, a processing instruction, or a style auto-link - was replaced anyway, inserting an anchor into an attribute value (invalid HTML) and destroying the email auto-link before _do_auto_links could see it. Exclude matches that fall inside _sorta_html_tokenize_re tokens, so prose is still linkified while markup and auto-links are left intact and _do_auto_links can produce the mailto link afterwards. Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com> --- CHANGES.md | 2 ++ lib/markdown2.py | 12 ++++++++++++ .../link_patterns_in_html_tags_issue752.html | 7 +++++++ .../link_patterns_in_html_tags_issue752.opts | 5 +++++ .../link_patterns_in_html_tags_issue752.text | 7 +++++++ 5 files changed, 33 insertions(+) create mode 100644 test/tm-cases/link_patterns_in_html_tags_issue752.html create mode 100644 test/tm-cases/link_patterns_in_html_tags_issue752.opts create mode 100644 test/tm-cases/link_patterns_in_html_tags_issue752.text diff --git a/CHANGES.md b/CHANGES.md index 10aabd33..35a547f4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ## python-markdown2 2.5.6 (not yet released) +- Fix the `link-patterns` extra replacing matches inside inline HTML markup tokens (tag attributes, HTML comments, processing instructions, and `` style auto-links) (#752) + - [pull #762] Speed up documents with many links by skipping the backslash-escape scan for text without a backslash - [pull #748] Speed up `_unescape_special_chars` by skipping text with no hashes and dropping the full-text comparison per pass (#635) - [pull #749] URL-encode destinations generated by the `link-patterns` extra (#55) diff --git a/lib/markdown2.py b/lib/markdown2.py index d6285404..34928b51 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -3918,6 +3918,18 @@ def run(self, text: str): continue break + if not is_inside_link: + # Also exclude markdown2's own inline HTML markup tokens + # (tags, comments, processing instructions, and + # style auto-links): a match inside + # one of them would corrupt the markup or destroy the + # auto-link (e.g. linkifying an attribute value). + for match in self.md._sorta_html_tokenize_re.finditer(text): + m_start, m_end = match.span(1) + if m_start <= start and end <= m_end: + is_inside_link = True + break + if is_inside_link: continue diff --git a/test/tm-cases/link_patterns_in_html_tags_issue752.html b/test/tm-cases/link_patterns_in_html_tags_issue752.html new file mode 100644 index 00000000..f339cef9 --- /dev/null +++ b/test/tm-cases/link_patterns_in_html_tags_issue752.html @@ -0,0 +1,7 @@ +

See word here.

+ +

word@example.com

+ +

word

+ +

A word in prose.

diff --git a/test/tm-cases/link_patterns_in_html_tags_issue752.opts b/test/tm-cases/link_patterns_in_html_tags_issue752.opts new file mode 100644 index 00000000..31c85880 --- /dev/null +++ b/test/tm-cases/link_patterns_in_html_tags_issue752.opts @@ -0,0 +1,5 @@ +{"extras": ["link-patterns"], + "link_patterns": [ + (re.compile(r"\b(word)\b"), r"/w/\1"), + ], +} diff --git a/test/tm-cases/link_patterns_in_html_tags_issue752.text b/test/tm-cases/link_patterns_in_html_tags_issue752.text new file mode 100644 index 00000000..66a798e2 --- /dev/null +++ b/test/tm-cases/link_patterns_in_html_tags_issue752.text @@ -0,0 +1,7 @@ +See word here. + + + +word + +A word in prose.