diff --git a/_extensions/redirects.py b/_extensions/redirects.py new file mode 100644 index 000000000..2022d3d04 --- /dev/null +++ b/_extensions/redirects.py @@ -0,0 +1,64 @@ +# Adapted from https://github.com/sphinx-contrib/redirects + +import os +import re +from pathlib import Path + +from sphinx.builders import html as builders +from sphinx.util import logging as logging + +TEMPLATE = '
' + +logger = logging.getLogger(__name__) + +def generate_redirects(app): + path = os.path.join(app.srcdir, app.config.redirects_file) + if not os.path.exists(path): + logger.debug("Could not find redirects file at '%s'", path) + return + + source_suffix = next(iter(app.config.source_suffix)) + + if not type(app.builder) == builders.StandaloneHTMLBuilder: + logger.info("Redirects are only supported by the 'html' builder. Skipping...") + return + + with open(path) as redirects: + escaped_source_suffix = source_suffix.replace('.', '\.') + pattern = re.compile( + r'^[ \t]*([\w\-/]+{0})[ \t]+([\w\-/]+{0})[ \t]*(#.*)?$'.format(escaped_source_suffix) + ) + for line in redirects.readlines(): + # Exclude comment or empty lines + if not line.rstrip() or line.startswith('#'): + continue + + match_result = pattern.match(line) + + # Log malformed rules + if not match_result: + logger.error( + "Ignoring malformed redirection: {0}" + "Please use this format: old_page{1} new_page{1} # optional comment".format( + line, source_suffix) + ) + continue + + # Parse the rule + from_file, to_file, _ = match_result.groups() + logger.debug("Redirecting '%s' to '%s'", from_file, to_file) + + # Prepare source and destination paths + to_path_prefix = '../' * from_file.count('/') + from_html_file = from_file.replace(source_suffix, '.html') + to_html_file = to_path_prefix + to_file.replace(source_suffix, '.html') + absolute_from_path = Path(app.builder.outdir) / from_html_file + + # Create the redirection + absolute_from_path.parent.mkdir(parents=True, exist_ok=True) + absolute_from_path.write_text(TEMPLATE % to_html_file) + + +def setup(app): + app.add_config_value('redirects_file', 'redirects', 'env') + app.connect('builder-inited', generate_redirects) diff --git a/conf.py b/conf.py index 85c6198ca..26402358d 100644 --- a/conf.py +++ b/conf.py @@ -31,10 +31,11 @@ extensions = [ 'sphinx.ext.ifconfig', 'sphinx.ext.todo', 'odoo', - 'html_domain', 'demo_link', - 'github_link', 'embedded_video', + 'github_link', + 'html_domain', + 'redirects', ] # Add any paths that contain templates here, relative to this directory. @@ -81,6 +82,9 @@ exclude_patterns = [ 'bin', 'include', 'lib', ] +# The specifications of redirect rules used by the redirects extension. +redirects_file = 'redirects.txt' + # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None diff --git a/redirects.txt b/redirects.txt new file mode 100644 index 000000000..e937d27b7 --- /dev/null +++ b/redirects.txt @@ -0,0 +1,39 @@ +# REDIRECT RULES # + +# Each line in this file specifies a redirect rule that redirects users from one URL to another. +# +# Redirect rules must follow this pattern: old_file.rst new_file.rst # optional comment +# Both parts are file paths and must thus include the full path of the file starting from the root +# of the documentation to the file name, including the .rst extension. +# If you consider it necessary, add a comment after the symbol '#' to explain why the redirection is +# needed. +# +# A redirect rule must be added to this file in the following cases: +# +# 1. An RST file is moved from one location to another. +# Example: The TOC of the Sales app is moved into a file index.rst located in sales/ . +# Rule: sales.rst sales/index.rst +# +# 2. An RST file is renamed. +# Example: The file create_quotations.rst in sales/ is renamed to quotations.rst. +# Rule: sales/create_quotations.rst sales/quotations.rst # no longer limited to creating quotes +# +# 3. Another pertinent case. +# Example: The file open_order_line_popup.rst is removed from sales/ in 13.0. +# Rule (13.0 only): sales/open_order_line_popup.rst sales/orders.rst # feature replaced in 13.0 +# +# Note that if the old file was already present in previous versions, the rule needs to be added +# from the branch of the lowest of those versions (usually 11.0) to allow the version switcher to +# land on the correct page (the redirection will be duplicated in other branches). + + +# Redirections taking effect as of 11.0 : + + + +# Redirections taking effect as of 12.0 : + + + +# Redirections taking effect as of 13.0 : +