Skip to content

Commit 9717712

Browse files
authored
Fix Pygments whitespace (#152)
1 parent 76ea0c0 commit 9717712

File tree

3 files changed

+18
-16
lines changed

3 files changed

+18
-16
lines changed

docs/src/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Unreleased
1212
----------
1313
- Declare support for Python 3.12 and 3.13 (:issue:`150`)
1414
- Remove support for Python 3.7 and 3.8 (:issue:`150`)
15+
- Fix changed whitespace handling in Pygments 2.19 (:issue:`152`)
1516

1617
0.15.2 (2024-06-03)
1718
-------------------

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ requires-python = ">=3.9"
1313
dependencies = [
1414
"sphinx>=3.2.0",
1515
"beautifulsoup4>=4.8.1",
16-
"pygments<2.19",
1716
]
1817
# Keep extras in sync with requirements manually
1918
optional-dependencies = {ipython = ["ipython!=8.7.0"]}

src/sphinx_codeautolink/extension/block.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -371,20 +371,22 @@ def link_html(
371371

372372
# The builtin re doesn't support variable-width lookbehind,
373373
# so instead we use a match groups in all pre patterns to remove the non-content.
374-
no_dot_prere = r'(?<!<span class="o">\.</span>)()'
374+
no_dot_pre = r'(?<!<span class="o">\.</span>)()'
375375
# Potentially instead assert an initial closing parenthesis followed by a dot.
376-
call_dot_prere = r'(\)</span>\s*<span class="o">\.</span>\s*)'
377-
import_prere = (
378-
r'((<span class="kn">import</span>\s+(<span class="p">\(</span>\s*)?)'
379-
r'|(<span class="[op]">,</span>\s*))'
376+
call_dot_pre = r'(\)</span>\s*<span class="o">\.</span>\s*)'
377+
no_dot_post = r'(?!(<span class="o">\.)|(</a>))'
378+
379+
# Pygments 2.19 changed import whitespace highlighting so we need to support both
380+
# with "w" class and raw whitespace for now (see #152)
381+
whitespace = r'(<span class="w">\s*</span>)|(\s*)'
382+
import_pre = (
383+
rf'((<span class="kn">import</span>{whitespace}(<span class="p">\(</span>\s*)?)'
384+
rf'|(<span class="[op]">,</span>{whitespace}))'
380385
)
381-
from_prere = r'(<span class="kn">from</span>\s+)'
386+
import_post = r'(?=($)|(\s+)|(<span class="[opw]">))(?!</a>)'
382387

383-
no_dot_postre = r'(?!(<span class="o">\.)|(</a>))'
384-
import_postre = (
385-
r'(?=($)|(\s+)|(<span class="[op]">,</span>)|(<span class="p">\)))(?!</a>)'
386-
)
387-
from_postre = r'(?=\s*<span class="kn">import</span>)'
388+
from_pre = rf'(<span class="kn">from</span>{whitespace})'
389+
from_post = rf'(?={whitespace}<span class="kn">import</span>)'
388390

389391

390392
def construct_name_pattern(name: Name) -> str:
@@ -395,17 +397,17 @@ def construct_name_pattern(name: Name) -> str:
395397
[first_name_pattern.format(name=parts[0])]
396398
+ [name_pattern.format(name=p) for p in parts[1:]]
397399
)
398-
return no_dot_prere + pattern + no_dot_postre
400+
return no_dot_pre + pattern + no_dot_post
399401
elif name.context == LinkContext.after_call:
400402
parts = name.code_str.split(".")
401403
pattern = period.join(
402404
[first_name_pattern.format(name=parts[0])]
403405
+ [name_pattern.format(name=p) for p in parts[1:]]
404406
)
405-
return call_dot_prere + pattern + no_dot_postre
407+
return call_dot_pre + pattern + no_dot_post
406408
elif name.context == LinkContext.import_from:
407409
pattern = import_from_pattern.format(name=name.code_str)
408-
return from_prere + pattern + from_postre
410+
return from_pre + pattern + from_post
409411
elif name.context == LinkContext.import_target:
410412
pattern = import_target_pattern.format(name=name.code_str)
411-
return import_prere + pattern + import_postre
413+
return import_pre + pattern + import_post

0 commit comments

Comments
 (0)