Skip to content

Commit 37922a7

Browse files
committed
AbbrTreeprocessor now sorts the abbreviation
list by length before processing the element tree This ensures that multi-word abbreviations are implemented even if an abbreviation exists for one of those component words. To test this, added `test_abbr_superset_vs_subset()` to `tests.test_syntax.extensions.test_abbr`.
1 parent ec8c305 commit 37922a7

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

docs/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ better reflects what it is. `AbbrPreprocessor` has been deprecated.
2323

2424
A call to `Markdown.reset()` now clears all previously defined abbreviations.
2525

26+
Abbreviations are now sorted by length before executing `AbbrTreeprocessor`
27+
to ensure that multi-word abbreviations are implemented even if an abbreviation
28+
exists for one of those component words.
29+
2630
### Fixed
2731

2832
* Fixed links to source code on GitHub from the documentation (#1453).

markdown/extensions/abbr.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ def run(self, root: etree.Element) -> etree.Element | None:
9292
# No abbreviations defined. Skip running processor.
9393
return
9494
# Build and compile regex
95-
self.RE = re.compile(f"\\b(?:{ '|'.join(re.escape(key) for key in self.abbrs) })\\b")
95+
abbr_list = list(self.abbrs.keys())
96+
abbr_list.sort(key=len, reverse=True)
97+
self.RE = re.compile(f"\\b(?:{ '|'.join(re.escape(key) for key in abbr_list) })\\b")
9698
# Step through tree and modify on matches
9799
self.iter_element(root)
98100

tests/test_syntax/extensions/test_abbr.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,24 @@ def test_abbr_with_attr_list(self):
383383
extensions=['abbr', 'attr_list']
384384
)
385385

386+
def test_abbr_superset_vs_subset(self):
387+
self.assertMarkdownRenders(
388+
self.dedent(
389+
"""
390+
abbr, SS, and abbr-SS should have different definitions.
391+
392+
*[abbr]: Abbreviation Definition
393+
*[abbr-SS]: Abbreviation Superset Definition
394+
*[SS]: Superset Definition
395+
"""
396+
),
397+
self.dedent(
398+
"""
399+
<p><abbr title="Abbreviation Definition">abbr</abbr>, <abbr title="Superset Definition">SS</abbr>, and <abbr title="Abbreviation Superset Definition">abbr-SS</abbr> should have different definitions.</p>
400+
"""
401+
)
402+
)
403+
386404
def test_abbr_reset(self):
387405
ext = AbbrExtension()
388406
md = Markdown(extensions=[ext])

0 commit comments

Comments
 (0)