Skip to content

docs: bare #NNN citations do not resolve in Sphinx — add an extlinks role instead of auto-linking #989

Description

@JarryShaw

A bare #NNN in a docstring or an .rst page renders as literal text — Sphinx has nothing configured to
resolve it. docs/source/conf.py's extensions list has no sphinx.ext.extlinks, no sphinx-issues, and no
custom issue role; it is viewcode, intersphinx, autodoc, napoleon, todo, sphinx_autodoc_typehints,
sphinxext.opengraph, sphinx_copybutton, sphinxcontrib.mermaid. So every citation added by the #719 work is
unclickable in the published docs, while the same text in a plain # comment is fine — GitHub's code view
linkifies it there, and those need no change.

Measured scale (AST over docstrings, so #: attribute comments that autodoc renders are included; plain
comments excluded):

bare #NNN in docstrings                    1858   across 222 files
already hyperlinked in docstrings            22
bare #NNN in docs/**.rst                    492
already hyperlinked in docs/**.rst           53
bare #NNN in plain comments (no action)      627

A blind regex transform is the wrong instrument, and the digit range is why. Counting #\d+ rather than
#\d{3} turns up 46 one-digit matches that are not citations at all — every one is an RFC packet-diagram
label, DH GROUP ID #1 through #4, in HIP and MH docstrings. Today there are 0 two-digit and 0 four-digit
matches, so a #\d{3} pattern happens to be clean — but that is luck, and it expires twice: numbering crosses
#1000 shortly, and the diagram labels stay one-digit forever. A transform keyed on digit count will either
miss the new four-digit citations or linkify the packet diagrams.

Two further forms already excluded from the counts above, both of which a naive pattern would also catch: hex
format specifiers like {spi:#010x}, and RFC section anchors like :rfc:`8684#3.1` .

Recommended: an explicit opt-in role via sphinx.ext.extlinks, not an automatic rule.

extlinks = {'issue': ('https://github.com/JarryShaw/PyPCAPKit/issues/%s', '#%s')}

Then a citation is written :issue:`719` and renders as #719, linked. Being opt-in per site is the whole
point: DH GROUP ID #1 is left alone because nobody marks it up, so the packet diagrams cannot be corrupted by
a future numbering change.

One role covers both issues and pull requests, verified rather than assumed — GitHub redirects between the
two forms, so the URL need not know which it is:

/issues/986  -> 302 -> /pull/986     (986 is a PR)
/pull/985    -> 302 -> /issues/985   (985 is an issue)

That matters here because #719's ruling turns on the issue-versus-pull-request distinction, and a single
:issue: role would quietly flatten it in the markup even though the link still resolves. Worth deciding
whether to add a separate :pr: role purely to keep the distinction visible in source — the rendered text is
#NNN either way.

Sequencing. This should land after #987's paraphrase sweep rather than before: #987 is already rewriting
the prose around most of these citations, and doing the markup conversion first would mean touching the same
1,858 sites twice. Also note tests/project/test_conventions_doc_claims.py already checks that a displayed
number matches the number in its own URL for the hyperlinked cases — that test is the natural place to extend
coverage once a role exists.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsPull requests that change documentation only (docs: subject prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions