Skip to content

Commit 4cebc79

Browse files
committed
Redirect when building site with JSON.
It turns out that the site generator code at https://github.com/ros-infrastructure/rosindex uses the JSON builder to generate pages, so using sphinx-reredirects doesn't really work. Instead, add in our own custom version that supports both HTML redirects and adding 'canonical_url' to the JSON, which should make redirects in rosindex work. Signed-off-by: Chris Lalancette <[email protected]>
1 parent 60d388c commit 4cebc79

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

conf.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@
1818
#
1919
import os
2020
import itertools
21+
import json
22+
from pathlib import Path
2123
from docutils.parsers.rst import Directive
2224

25+
from fnmatch import fnmatch
26+
from string import Template
27+
2328
# The suffix(es) of source filenames.
2429
# You can specify multiple suffix as a list of string:
2530
#
@@ -66,7 +71,7 @@
6671

6772
# Add any Sphinx extension module names here, as strings. They can be
6873
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
69-
extensions = ['sphinx.ext.intersphinx', 'sphinx_tabs.tabs', 'sphinx_reredirects']
74+
extensions = ['sphinx.ext.intersphinx', 'sphinx_tabs.tabs']
7075

7176
# Intersphinx mapping
7277

@@ -404,8 +409,61 @@ def _missing_reference(app, env, node, contnode):
404409
return _missing_reference
405410

406411

412+
def apply_redirects(app, exception):
413+
redirects = app.config['redirects']
414+
415+
if not redirects:
416+
return
417+
418+
from sphinx.builders.html import StandaloneHTMLBuilder
419+
from sphinxcontrib.serializinghtml import JSONHTMLBuilder
420+
421+
if isinstance(app.builder, JSONHTMLBuilder):
422+
# If the builder is the JSONHTMLBuilder, then to support redirects from
423+
# the https://github.com/ros-infrastructure/rosindex site, we need to
424+
# add a 'canonical_url' portion to the JSON. When that is in place, the
425+
# site generator will automatically use that as a redirect.
426+
427+
for source, target in redirects.items():
428+
# examine if it matches to some doc
429+
for doc in app.env.found_docs:
430+
if fnmatch(doc, source):
431+
file_path = Path(app.outdir).joinpath(doc).with_suffix('.fjson')
432+
with open(file_path, 'r') as infp:
433+
data = json.load(infp)
434+
data['canonical_url'] = target
435+
with open(file_path, 'w') as outfp:
436+
json.dump(data, outfp)
437+
elif isinstance(app.builder, StandaloneHTMLBuilder):
438+
# If the builder is the StandaloneHTMLBuilder, we just assume that the
439+
# user meant to generate an HTML file and do that here.
440+
441+
# The below code is a lightly-modified version of the code at
442+
# https://gitlab.com/documatt/sphinx-reredirects . It is licensed as BSD.
443+
444+
# HTML used as redirect file content
445+
redirect_template = '<html><head><meta http-equiv="refresh" content="0; url=${to_uri}"></head></html>'
446+
# For each entry
447+
for source, target in redirects.items():
448+
# examine if it matches to some doc
449+
for doc in app.env.found_docs:
450+
if fnmatch(doc, source):
451+
# if so, apply $source placeholder
452+
new_target = Template(target).substitute({'source': doc})
453+
# create redirect file
454+
redirect_file_path = Path(app.outdir).joinpath(doc).with_suffix('.html')
455+
content = Template(redirect_template).substitute({'to_uri': new_target})
456+
redirect_file_path.write_text(content)
457+
else:
458+
print('Only JSON and HTML builders support redirects')
459+
460+
407461
def setup(app):
408462
RedirectFrom.register(app)
463+
464+
app.connect('build-finished', apply_redirects)
465+
app.add_config_value('redirects', {}, 'env')
466+
409467
app.connect('missing-reference', make_router(
410468
'Installation', 'Installation/Eloquent'
411469
))

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
pip
22
sphinx
3-
sphinx-reredirects
43
sphinx-tabs

0 commit comments

Comments
 (0)