diff --git a/.pyspelling.yml b/.pyspelling.yml index bede9711..62ad0266 100644 --- a/.pyspelling.yml +++ b/.pyspelling.yml @@ -20,6 +20,7 @@ matrix: - alt ignores: - 'code, pre' + - '.autorefs-internal[title]' captures: - '[role=main] *|*:not(script,style)' - pyspelling.filters.context: diff --git a/docs/changelog.md b/docs/changelog.md index 34817bdd..29ff8d31 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `md_in_html` handle tags within inline code blocks better (#1075). * `md_in_html` fix handling of one-liner block HTML handling (#1074). * Ensure `
` is treated like a block-level element (#1481). +* Ensure that `abbr` extension respects `AtomicString` and does not process + perceived abbreviations in these strings (#1512). ## [3.7] -- 2024-08-16 diff --git a/markdown/extensions/abbr.py b/markdown/extensions/abbr.py index 36c1d91c..ab7c3743 100644 --- a/markdown/extensions/abbr.py +++ b/markdown/extensions/abbr.py @@ -98,20 +98,22 @@ def iter_element(self, el: etree.Element, parent: etree.Element | None = None) - for child in reversed(el): self.iter_element(child, el) if text := el.text: - for m in reversed(list(self.RE.finditer(text))): - if self.abbrs[m.group(0)]: - abbr = self.create_element(self.abbrs[m.group(0)], m.group(0), text[m.end():]) - el.insert(0, abbr) - text = text[:m.start()] - el.text = text + if not isinstance(text, AtomicString): + for m in reversed(list(self.RE.finditer(text))): + if self.abbrs[m.group(0)]: + abbr = self.create_element(self.abbrs[m.group(0)], m.group(0), text[m.end():]) + el.insert(0, abbr) + text = text[:m.start()] + el.text = text if parent is not None and el.tail: tail = el.tail index = list(parent).index(el) + 1 - for m in reversed(list(self.RE.finditer(tail))): - abbr = self.create_element(self.abbrs[m.group(0)], m.group(0), tail[m.end():]) - parent.insert(index, abbr) - tail = tail[:m.start()] - el.tail = tail + if not isinstance(tail, AtomicString): + for m in reversed(list(self.RE.finditer(tail))): + abbr = self.create_element(self.abbrs[m.group(0)], m.group(0), tail[m.end():]) + parent.insert(index, abbr) + tail = tail[:m.start()] + el.tail = tail def run(self, root: etree.Element) -> etree.Element | None: ''' Step through tree to find known abbreviations. ''' diff --git a/tests/test_syntax/extensions/test_abbr.py b/tests/test_syntax/extensions/test_abbr.py index 9d3ebb27..32016e1c 100644 --- a/tests/test_syntax/extensions/test_abbr.py +++ b/tests/test_syntax/extensions/test_abbr.py @@ -30,6 +30,18 @@ class TestAbbr(TestCase): default_kwargs = {'extensions': ['abbr']} + def test_ignore_atomic(self): + self.assertMarkdownRenders( + self.dedent( + """ + This + + *[YAFR]: Yet Another Feature Request + """ + ), + '

This https://example.com/{YAFR}

' + ) + def test_abbr_upper(self): self.assertMarkdownRenders( self.dedent(