1# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD 2# 3# SPDX-License-Identifier: Apache-2.0 4 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18 19# Mechanism to generate static HTML redirect pages in the output 20# 21# Uses redirect_template.html and the list of pages given in 22# conf.html_redirect_pages 23# 24# Adapted from ideas in https://tech.signavio.com/2017/managing-sphinx-redirects 25import os.path 26 27from sphinx.builders.html import StandaloneHTMLBuilder 28from sphinx.util import logging 29 30logger = logging.getLogger(__name__) 31 32REDIRECT_TEMPLATE = r""" 33<html> 34 <head> 35 <meta http-equiv="refresh" content="0; url=$NEWURL" /> 36 <script> 37 var id=window.location.href.split("#")[1]; 38 39 if (id && (/^[a-zA-Z\:\/0-9\_\-\.]+$/.test(id))) { 40 window.location.href = "$NEWURL"+"#"+id; 41 } 42 else { 43 window.location.href = "$NEWURL"; 44 }; 45 </script> 46 </head> 47 <body> 48 <p>Page has moved <a href="$NEWURL">here</a>.</p> 49 </body> 50</html> 51""" 52 53 54def setup(app): 55 app.add_config_value('html_redirect_pages', [], 'html') 56 app.connect('build-finished', create_redirect_pages) 57 58 # Since we're just setting up a build-finished hook, which runs 59 # after both reading and writing, this extension is safe for both. 60 return { 61 'parallel_read_safe': True, 62 'parallel_write_safe': True, 63 } 64 65 66def create_redirect_pages(app, exception): 67 if not isinstance(app.builder, StandaloneHTMLBuilder): 68 return # only relevant for standalone HTML output 69 70 for (old_url, new_url) in app.config.html_redirect_pages: 71 if old_url.startswith('/'): 72 old_url = old_url[1:] 73 74 # check that new_url is a valid docname, or if not that it is at least 75 # covered as the "old" part of another redirect rule 76 if new_url not in app.env.all_docs and not any( 77 old == new_url for (old, _) in app.config.html_redirect_pages 78 ): 79 logger.warning( 80 f"{new_url} is not a valid destination for a redirect." 81 "Check that both the source and destination are complete docnames." 82 ) 83 84 new_url = app.builder.get_relative_uri(old_url, new_url) 85 out_file = app.builder.get_outfilename(old_url) 86 87 out_dir = os.path.dirname(out_file) 88 if not os.path.exists(out_dir): 89 os.makedirs(out_dir) 90 91 content = REDIRECT_TEMPLATE.replace("$NEWURL", new_url) 92 93 if not os.path.exists(out_file): 94 with open(out_file, "w") as rp: 95 rp.write(content) 96