Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Contributors
* Justus Magin -- napoleon improvements
* Kazuya Take -- ``sphinx.testing.path`` bug fix
* Kevin Dunn -- MathJax extension
* Kilian Paul -- Docutils compatibility, intl tests, and viewcode fixes
* KINEBUCHI Tomohiko -- typing Sphinx as well as docutils
* Kurt McKee -- documentation updates
* Lars Hupfeldt Nielsen - OpenSSL FIPS mode md5 bug fix
Expand Down
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Release 9.1.1 (in development)
Bugs fixed
----------

* #14659: Use the canonical ``https://www.rfc-editor.org/info/`` base URL for
the :rst:role:`rfc` role and make generated RFC URLs independent of
Docutils' URL template.
Patch by Kilian Paul

* #14465: LaTeX: PDF build crash since LaTeX June 2026 release if tables are
styled with ``'colorrows'`` (which is the default).
Patch by Jean-François B.
Expand Down
4 changes: 2 additions & 2 deletions sphinx/environment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
'cloak_email_addresses': True,
'pep_base_url': 'https://peps.python.org/',
'pep_references': None,
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
'rfc_base_url': 'https://www.rfc-editor.org/info/',
'rfc_references': None,
'input_encoding': 'utf-8-sig',
'doctitle_xform': False,
Expand All @@ -76,7 +76,7 @@

# This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files.
ENV_VERSION = 66
ENV_VERSION = 67

# config status
CONFIG_UNSET = -1
Expand Down
10 changes: 5 additions & 5 deletions sphinx/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,11 @@ def run(self) -> tuple[list[Node], list[system_message]]:

def build_uri(self) -> str:
base_url = self.inliner.document.settings.rfc_base_url
ret = self.target.partition('#')
if ret[1]:
return base_url + self.inliner.rfc_url % int(ret[0]) + '#' + ret[2]
else:
return base_url + self.inliner.rfc_url % int(ret[0])
number, separator, anchor = self.target.partition('#')
uri = f'{base_url}rfc{int(number)}/'
if separator:
uri += f'#{anchor}'
return uri


def _format_rfc_target(target: str, /) -> str:
Expand Down
2 changes: 1 addition & 1 deletion tests/js/fixtures/cpp/searchindex.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/js/fixtures/multiterm/searchindex.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/js/fixtures/partial/searchindex.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/js/fixtures/titles/searchindex.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions tests/test_builders/test_build_html_5_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,13 @@ def checker(nodes: Iterable[Element]) -> Literal[True]:
),
(
'markup.html',
".//a[@href='https://datatracker.ietf.org/doc/html/rfc1.html']"
".//a[@href='https://www.rfc-editor.org/info/rfc1/']"
"[@class='rfc reference external']/strong",
'RFC 1',
),
(
'markup.html',
".//a[@href='https://datatracker.ietf.org/doc/html/rfc1.html']"
".//a[@href='https://www.rfc-editor.org/info/rfc1/']"
"[@class='rfc reference external']/strong",
'Request for Comments #1',
),
Expand Down
8 changes: 4 additions & 4 deletions tests/test_markup/test_markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,12 @@ def rst_to_latex(rst: str, *, app: SphinxTestApp) -> str:
':rfc:`2324`',
(
'<p><span class="target" id="index-0"></span><a class="rfc reference external" '
'href="https://datatracker.ietf.org/doc/html/rfc2324.html"><strong>RFC 2324</strong></a></p>'
'href="https://www.rfc-editor.org/info/rfc2324/"><strong>RFC 2324</strong></a></p>'
),
(
'\\sphinxAtStartPar\n'
'\\index{RFC@\\spxentry{RFC}!RFC 2324@\\spxentry{RFC 2324}}'
'\\sphinxhref{https://datatracker.ietf.org/doc/html/rfc2324.html}'
'\\sphinxhref{https://www.rfc-editor.org/info/rfc2324/}'
'{\\sphinxstylestrong{RFC 2324}}'
),
),
Expand All @@ -226,13 +226,13 @@ def rst_to_latex(rst: str, *, app: SphinxTestApp) -> str:
':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#section-1">'
'href="https://www.rfc-editor.org/info/rfc2324/#section-1">'
'<strong>RFC 2324 Section 1</strong></a></p>'
),
(
'\\sphinxAtStartPar\n'
'\\index{RFC@\\spxentry{RFC}!RFC 2324 Section 1@\\spxentry{RFC 2324 Section 1}}'
'\\sphinxhref{https://datatracker.ietf.org/doc/html/rfc2324.html\\#section-1}'
'\\sphinxhref{https://www.rfc-editor.org/info/rfc2324/\\#section-1}'
'{\\sphinxstylestrong{RFC 2324 Section 1}}'
),
),
Expand Down
26 changes: 25 additions & 1 deletion tests/test_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

from __future__ import annotations

from types import SimpleNamespace
from typing import TYPE_CHECKING, cast
from unittest.mock import Mock

import pytest
from docutils import nodes

from sphinx.roles import EmphasizedLiteral, _format_rfc_target
from sphinx.roles import RFC, EmphasizedLiteral, _format_rfc_target
from sphinx.testing.util import assert_node

if TYPE_CHECKING:
from docutils.parsers.rst.states import Inliner


def test_samp() -> None:
emph_literal_role = EmphasizedLiteral()
Expand Down Expand Up @@ -137,3 +142,22 @@ def test_samp() -> None:
)
def test_format_rfc_target(target: str, expected_output: str) -> None:
assert _format_rfc_target(target) == expected_output


@pytest.mark.parametrize(
('target', 'expected_uri'),
[
('2324', 'https://example.com/rfc/rfc2324/'),
('2324#section-1', 'https://example.com/rfc/rfc2324/#section-1'),
('2324#', 'https://example.com/rfc/rfc2324/#'),
],
)
def test_rfc_build_uri(target: str, expected_uri: str) -> None:
role = RFC()
settings = SimpleNamespace(rfc_base_url='https://example.com/rfc/')
role.inliner = cast(
'Inliner', SimpleNamespace(document=SimpleNamespace(settings=settings))
)
role.target = target

assert role.build_uri() == expected_uri
Loading