From f5a637c96020797f68c568107cd294cc24f25fd6 Mon Sep 17 00:00:00 2001 From: facelessuser Date: Sat, 3 Oct 2026 07:19:37 -0600 Subject: [PATCH 1/2] Fix inline HTML case HTML handling is inconsistent. In some places it allows `<` and `>` in attributes, and in other places rejects it. The HTML spec allows for these in attributes, and browsers will escape them. While it is generally recommended that users escape `<` and `>`, it is not explicitly required. If the attribute is quoted, it should allow `<` and `>`. Update regex pattern to allow attributes with angled brackets and use possessive quantifiers to performance as we are now only supporting Python 3.10+. Fixes #1647 --- docs/changelog.md | 1 + markdown/inlinepatterns.py | 12 ++++++++---- tests/test_syntax/inline/test_raw_html.py | 7 +++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index f20687c0a..a6939f91f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -16,6 +16,7 @@ See the [Contributing Guide](contributing.md) for details. * Update serializer to be non-recursive (#1644). * Improve ancestor handling in the inline `Treeprocessor` (#1646). +* Fix issue where inline HTML attributes were rejected if they had `<` or `>` in the attribute (#1647). ## [3.11.0] - 2026-09-25 diff --git a/markdown/inlinepatterns.py b/markdown/inlinepatterns.py index 1908625a5..811559f6c 100644 --- a/markdown/inlinepatterns.py +++ b/markdown/inlinepatterns.py @@ -159,10 +159,14 @@ def build_inlinepatterns(md: Markdown, **kwargs: Any) -> util.Registry[InlinePro """ Match an automatic email link (``). """ HTML_RE = ( - r'(<(\/?[a-zA-Z][^<>@ ]*( [^<>]*)?|' # Tag - r'!--(?:(?!).)*--|' # Comment - r'[?](?:(?!<[?]|[?]>).)*[?]|' # Processing instruction - r'!\[CDATA\[(?:(?!).)*\]\]' # `CDATA` + # Tag + r'''(<(\/?+[a-zA-Z][^\s"'<>@]*+(?:\s+[^\s"'=<>]++(?:\s*+=\s*+(?:"[^"]*+"|'[^']*+'|[^\s"'=<>]++))?+)*+\s*+/?|''' + # Comment + r'!--(?:(?!).)*--|' + # Processing instruction + r'[?](?:(?!<[?]|[?]>).)*[?]|' + # `CDATA` + r'!\[CDATA\[(?:(?!).)*\]\]' ')>)' ) """ Match an HTML tag (`<...>`). """ diff --git a/tests/test_syntax/inline/test_raw_html.py b/tests/test_syntax/inline/test_raw_html.py index 79d49a507..83bb9f479 100644 --- a/tests/test_syntax/inline/test_raw_html.py +++ b/tests/test_syntax/inline/test_raw_html.py @@ -40,3 +40,10 @@ def test_markdown_nested_in_inline_comment(self): 'Example: ', '

Example:

' ) + + def test_angle_brackets_in_attributes(self): + # https://github.com/Python-Markdown/markdown/issues/1647 + self.assertMarkdownRenders( + 'Anything', + '

Anything

' + ) From dcc4efbc4ff8172e61f6f452a889d73c583e3b7f Mon Sep 17 00:00:00 2001 From: facelessuser Date: Sat, 3 Oct 2026 07:25:08 -0600 Subject: [PATCH 2/2] Lint fix --- markdown/inlinepatterns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown/inlinepatterns.py b/markdown/inlinepatterns.py index 811559f6c..d3c3bef26 100644 --- a/markdown/inlinepatterns.py +++ b/markdown/inlinepatterns.py @@ -165,7 +165,7 @@ def build_inlinepatterns(md: Markdown, **kwargs: Any) -> util.Registry[InlinePro r'!--(?:(?!).)*--|' # Processing instruction r'[?](?:(?!<[?]|[?]>).)*[?]|' - # `CDATA` + # `CDATA` r'!\[CDATA\[(?:(?!).)*\]\]' ')>)' )