Skip to content

Commit 212dd3d

Browse files
authored
Improve hyperlink checker to flag unnecessary underscores (#151)
* fix: improve url checks and regex for download roles * Add test case
1 parent e24bb0e commit 212dd3d

File tree

3 files changed

+24
-18
lines changed

3 files changed

+24
-18
lines changed

sphinxlint/checkers.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -246,17 +246,22 @@ def check_missing_space_in_hyperlink(file, lines, options=None):
246246
if "`" not in line:
247247
continue
248248
for match in rst.SEEMS_HYPERLINK_RE.finditer(line):
249-
if not match.group(1):
249+
if not match.group(2):
250250
yield lno, "missing space before < in hyperlink"
251251

252252

253253
@checker(".rst", ".po")
254254
def check_missing_underscore_after_hyperlink(file, lines, options=None):
255-
"""Search for hyperlinks missing underscore after their closing backtick.
255+
"""Search for hyperlinks with incorrect underscore usage after closing backtick.
256256
257+
For regular hyperlinks:
257258
Bad: `Link text <https://example.com>`
258259
Good: `Link text <https://example.com>`_
259260
261+
For hyperlinks within download directives:
262+
Bad: :download:`file <https://example.com>`_
263+
Good: :download:`file <https://example.com>`
264+
260265
Note:
261266
URLs within download directives don't need trailing underscores.
262267
https://www.sphinx-doc.org/en/master/usage/referencing.html#role-download
@@ -265,19 +270,15 @@ def check_missing_underscore_after_hyperlink(file, lines, options=None):
265270
if "`" not in line:
266271
continue
267272
for match in rst.SEEMS_HYPERLINK_RE.finditer(line):
268-
if not match.group(2):
269-
# Check if this is within any download directive on the line
270-
# Include optional underscore in pattern to handle both cases
271-
is_in_download = False
272-
for download_match in rst.HYPERLINK_WITHIN_DOWNLOAD_RE.finditer(line):
273-
if (
274-
match.start() >= download_match.start()
275-
and match.end() <= download_match.end()
276-
):
277-
is_in_download = True
278-
break
279-
if not is_in_download:
280-
yield lno, "missing underscore after closing backtick in hyperlink"
273+
is_in_download = bool(match.group(1))
274+
has_underscore = bool(match.group(3))
275+
276+
if is_in_download and has_underscore:
277+
yield lno, "unnecessary underscore after closing backtick in hyperlink"
278+
elif not is_in_download and not has_underscore:
279+
yield lno, "missing underscore after closing backtick in hyperlink"
280+
else:
281+
continue
281282

282283

283284
@checker(".rst", ".po")

sphinxlint/rst.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,7 @@ def inline_markup_gen(start_string, end_string, extra_allowed_before=""):
280280
# The :issue`123` is ...
281281
ROLE_MISSING_RIGHT_COLON_RE = re.compile(rf"(^|\s):{SIMPLENAME}`(?!`)")
282282

283-
SEEMS_HYPERLINK_RE = re.compile(r"`[^`]+?(\s?)<https?://[^`]+>`(_?)")
284-
285-
HYPERLINK_WITHIN_DOWNLOAD_RE = re.compile(r":download:`[^`]*`_?")
283+
SEEMS_HYPERLINK_RE = re.compile(r"(:download:)?`[^`]+?(\s?)<https?://[^`]+>`(_?)")
286284

287285
LEAKED_MARKUP_RE = re.compile(r"[a-z]::\s|`|\.\.\s*\w+:")
288286

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.. expect: unnecessary underscore after closing backtick in hyperlink
2+
3+
Download directives should not have trailing underscores after hyperlinks.
4+
5+
:download:`Download this file <https://example.com/file.pdf>`_
6+
7+
This is wrong because download directives don't need trailing underscores.

0 commit comments

Comments
 (0)