mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Improve the formatting for RFC section anchors (#11809)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
@@ -64,6 +64,8 @@ Features added
|
||||
* #11781: Add roles for referencing CVEs (:rst:role:`:cve: <cve>`)
|
||||
and CWEs (:rst:role:`:cwe: <cwe>`).
|
||||
Patch by Hugo van Kemenade.
|
||||
* #11809: Improve the formatting for RFC section anchors.
|
||||
Patch by Jakub Stasiak and Adam Turner.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
@@ -332,7 +332,8 @@ class PEP(ReferenceRole):
|
||||
class RFC(ReferenceRole):
|
||||
def run(self) -> tuple[list[Node], list[system_message]]:
|
||||
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||
entries = [('single', 'RFC; RFC %s' % self.target, target_id, '', None)]
|
||||
formatted_target = _format_rfc_target(self.target)
|
||||
entries = [('single', f'RFC; {formatted_target}', target_id, '', None)]
|
||||
|
||||
index = addnodes.index(entries=entries)
|
||||
target = nodes.target('', '', ids=[target_id])
|
||||
@@ -346,7 +347,7 @@ class RFC(ReferenceRole):
|
||||
if self.has_explicit_title:
|
||||
reference += nodes.strong(self.title, self.title)
|
||||
else:
|
||||
title = 'RFC ' + self.title
|
||||
title = formatted_target
|
||||
reference += nodes.strong(title, title)
|
||||
except ValueError:
|
||||
msg = self.inliner.reporter.error(
|
||||
@@ -366,6 +367,24 @@ class RFC(ReferenceRole):
|
||||
return base_url + self.inliner.rfc_url % int(ret[0])
|
||||
|
||||
|
||||
def _format_rfc_target(target: str, /) -> str:
|
||||
"""
|
||||
Takes an RFC number with an optional anchor (like ``123#section-2.5.3``)
|
||||
and attempts to produce a human-friendly title for it.
|
||||
|
||||
We have a set of known anchors that we format nicely,
|
||||
everything else we leave alone.
|
||||
"""
|
||||
number, _, anchor = target.partition('#')
|
||||
if anchor:
|
||||
first, _, remaining = anchor.partition('-')
|
||||
if first in {'appendix', 'page', 'section'}:
|
||||
if remaining:
|
||||
return f'RFC {number} {first.title()} {remaining}'
|
||||
return f'RFC {number} {first.title()}'
|
||||
return f'RFC {target}'
|
||||
|
||||
|
||||
class GUILabel(SphinxRole):
|
||||
amp_re = re.compile(r'(?<!&)&(?![&\s])')
|
||||
|
||||
|
||||
@@ -278,17 +278,17 @@ def get_verifier(verify, verify_re):
|
||||
(
|
||||
# rfc role with anchor
|
||||
'verify',
|
||||
':rfc:`2324#id1`',
|
||||
':rfc:`2324#section-1`',
|
||||
(
|
||||
'<p><span class="target" id="index-0"></span><a class="rfc reference external" '
|
||||
'href="https://datatracker.ietf.org/doc/html/rfc2324.html#id1">'
|
||||
'<strong>RFC 2324#id1</strong></a></p>'
|
||||
'href="https://datatracker.ietf.org/doc/html/rfc2324.html#section-1">'
|
||||
'<strong>RFC 2324 Section 1</strong></a></p>'
|
||||
),
|
||||
(
|
||||
'\\sphinxAtStartPar\n'
|
||||
'\\index{RFC@\\spxentry{RFC}!RFC 2324\\#id1@\\spxentry{RFC 2324\\#id1}}'
|
||||
'\\sphinxhref{https://datatracker.ietf.org/doc/html/rfc2324.html\\#id1}'
|
||||
'{\\sphinxstylestrong{RFC 2324\\#id1}}'
|
||||
'\\index{RFC@\\spxentry{RFC}!RFC 2324 Section 1@\\spxentry{RFC 2324 Section 1}}'
|
||||
'\\sphinxhref{https://datatracker.ietf.org/doc/html/rfc2324.html\\#section-1}'
|
||||
'{\\sphinxstylestrong{RFC 2324 Section 1}}'
|
||||
),
|
||||
),
|
||||
(
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.roles import EmphasizedLiteral
|
||||
from sphinx.roles import EmphasizedLiteral, _format_rfc_target
|
||||
from sphinx.testing.util import assert_node
|
||||
|
||||
|
||||
@@ -113,3 +114,24 @@ def test_samp():
|
||||
],
|
||||
)
|
||||
assert msg == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('target', 'expected_output'),
|
||||
[
|
||||
('123', 'RFC 123'),
|
||||
('123#', 'RFC 123#'),
|
||||
('123#id1', 'RFC 123#id1'),
|
||||
('123#section', 'RFC 123 Section'),
|
||||
('123#section-1', 'RFC 123 Section 1'),
|
||||
('123#section-2.5.3', 'RFC 123 Section 2.5.3'),
|
||||
('123#page-13', 'RFC 123 Page 13'),
|
||||
('123#appendix-B', 'RFC 123 Appendix B'),
|
||||
# Section names are also present in some RFC anchors. Until we come up with a reliable way
|
||||
# to reconstruct the section names from the corresponding anchors with the correct
|
||||
# capitalization it's probably better to leave them alone.
|
||||
('9076#name-risks-in-the-dns-data', 'RFC 9076#name-risks-in-the-dns-data'),
|
||||
],
|
||||
)
|
||||
def test_format_rfc_target(target: str, expected_output: str) -> None:
|
||||
assert _format_rfc_target(target) == expected_output
|
||||
|
||||
Reference in New Issue
Block a user