Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8087a9d

Browse files
jklymakAntony Lee
and
Antony Lee
committed
ENH: add redirect_from sphinx extension
Co-authored-by: Antony Lee <[email protected]>
1 parent de7d791 commit 8087a9d

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""
2+
Redirecting old docs to new location
3+
====================================
4+
5+
If an rst file is moved or its content subsumed in a different file, it
6+
is desireable to redirect the old file to the new or existing file. This
7+
extension enables this with a simple html refresh.
8+
9+
For example suppose ``doc/topic/old-page.rst`` is removed and its content
10+
included in ``doc/topic/new-page.rst``. We use the ``redirect_from``
11+
directive in ``doc/topic/new-page.rst``::
12+
13+
.. redirect-from:: /topic/old-page
14+
15+
This creates in the build directory a file ``build/html/topic/old-page.html``
16+
that contains a relative refresh::
17+
18+
<html>
19+
<head>
20+
<meta http-equiv="refresh" content="0; url=new-page.html">
21+
<link rel="canonical" href="new-page.html">
22+
</head>
23+
</html>
24+
25+
If you need to redirect across subdirectory trees, that works as well. For
26+
instance if ``doc/topic/subdir1/old-page.rst`` is now found at
27+
``doc/topic/subdir2/new-page.rst`` then ``new-page.rst`` just lists the
28+
full path::
29+
30+
.. redirect-from:: /topic/subdir1/old-page.rst
31+
32+
"""
33+
34+
from pathlib import Path
35+
from docutils.parsers.rst import Directive
36+
from sphinx.util import logging
37+
38+
logger = logging.getLogger(__name__)
39+
40+
41+
HTML_TEMPLATE = """<html>
42+
<head>
43+
<meta http-equiv="refresh" content="0; url={v}">
44+
<link rel="canonical" href="{v}">
45+
</head>
46+
</html>
47+
"""
48+
49+
def setup(app):
50+
RedirectFrom.app = app
51+
app.add_directive("redirect-from", RedirectFrom)
52+
app.connect("build-finished", _generate_redirects)
53+
54+
55+
class RedirectFrom(Directive):
56+
required_arguments = 1
57+
redirects = {}
58+
59+
def run(self):
60+
redirected_doc, = self.arguments
61+
env = self.app.env
62+
builder = self.app.builder
63+
current_doc = env.path2doc(self.state.document.current_source)
64+
redirected_reldoc, _ = env.relfn2path(redirected_doc, current_doc)
65+
if redirected_reldoc in self.redirects:
66+
raise ValueError(
67+
f"{redirected_reldoc} is already noted as redirecting to "
68+
f"{self.redirects[redirected_reldoc]}")
69+
self.redirects[redirected_reldoc] = builder.get_relative_uri(
70+
redirected_reldoc, current_doc)
71+
return []
72+
73+
74+
def _generate_redirects(app, exception):
75+
builder = app.builder
76+
if builder.name != "html" or exception:
77+
return
78+
for k, v in RedirectFrom.redirects.items():
79+
with Path(app.outdir, k + builder.out_suffix).open("w") as file:
80+
logger.info('making refresh html file: ' + k + ' redirect to ' + v)
81+
file.write(HTML_TEMPLATE.format(v=v))

0 commit comments

Comments
 (0)