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(