diff --git a/docs/changelog.md b/docs/changelog.md index 94b4a2f5..6f27060e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -16,6 +16,8 @@ See the [Contributing Guide](contributing.md) for details. ### Fixed +* Strip complete HTML tags with quoted `>` characters from `toc` labels and + generated heading IDs. * Fix quadratic-time regex backtracking in `attr_list` when a block ends with an unclosed attribute list followed by a long run of spaces, e.g. a line consisting only of `{` and some text with many trailing spaces (#1656). diff --git a/markdown/extensions/toc.py b/markdown/extensions/toc.py index 06812549..e0c4c74e 100644 --- a/markdown/extensions/toc.py +++ b/markdown/extensions/toc.py @@ -24,6 +24,7 @@ from ..util import parseBoolValue, AMP_SUBSTITUTE, deprecated, HTML_PLACEHOLDER_RE, AtomicString from ..treeprocessors import UnescapeTreeprocessor from ..serializers import RE_AMP +from ..inlinepatterns import HTML_RE import re import html import unicodedata @@ -108,8 +109,8 @@ def strip_tags(text: str) -> str: while (start := text.find('', start)) != -1: text = f'{text[:start]}{text[end + 3:]}' - while (start := text.find('<')) != -1 and (end := text.find('>', start)) != -1: - text = f'{text[:start]}{text[end + 1:]}' + # Use the inline HTML pattern to respect quoted attribute values. + text = re.sub(HTML_RE, '', text, flags=re.DOTALL) # Collapse whitespace text = ' '.join(text.split()) diff --git a/tests/test_syntax/extensions/test_toc.py b/tests/test_syntax/extensions/test_toc.py index 372ba09c..07df442b 100644 --- a/tests/test_syntax/extensions/test_toc.py +++ b/tests/test_syntax/extensions/test_toc.py @@ -155,6 +155,53 @@ def testTOCReset(self): self.assertEqual(md.toc, '') self.assertEqual(md.toc_tokens, []) + def testHTMLAttributeWithAngleBracket(self): + for quote in ['"', "'"]: + with self.subTest(quote=quote): + heading = f' 3{quote}>Python support' + self.assertMarkdownRenders( + f'# {heading}', + f'