From 1f10853f242871b0d50f3d24c65e708e3fbbbe56 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Fri, 11 Nov 2016 18:14:50 +0000 Subject: [PATCH] Support GitHub cross references using source files Allow links to be specified to the source files, which will be converted correctly by GitHub, by ensuring the sphinx generation then transforms the link from the source file to the correct output file depending on the builder used. Change-Id: I18ac055fc6d44982048365cad819f891786484a8 --- doc/source/conf.py | 4 +- doc/source/transform_github_links.py | 90 ++++++++++++++++++++++++++++ doc/source/workflows.rst | 2 +- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 doc/source/transform_github_links.py diff --git a/doc/source/conf.py b/doc/source/conf.py index b4aa293..607eaab 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -30,7 +30,9 @@ sys.path.insert(0, os.path.abspath('../../git_upstream')) # for indices # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', - 'sphinxcontrib.fulltoc'] + 'sphinxcontrib.fulltoc', + 'transform_github_links', + ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/doc/source/transform_github_links.py b/doc/source/transform_github_links.py new file mode 100644 index 0000000..695d51d --- /dev/null +++ b/doc/source/transform_github_links.py @@ -0,0 +1,90 @@ +# based on the idea from +# https://github.com/andsens/bootstrap-vz/blob/5250f8233215f6f2e3a571be2f5cf3e09accd4b6/docs/transform_github_links.py +# +# Copyright 2013-2014 Anders Ingemann +# Copyright 2016 Darragh Bailey + + +from docutils import nodes +import os.path + + +def transform_github_links(app, doctree, fromdocname): + """Convert file references for github to correct target + + Scans the doctree for links directly referencing ReSTructured + text documents within this repository. It converts these links + to a suitable target for sphinx generated docs. + + Such references as .rst are used by source code hosting + sites such as GitHub when rendering documents directly from + individual source files without parsing the entire doctree. + + However referencing the original .rst is not useful for + sphinx generated documentation as .rst will not exist in + the resulting documentation as it will also have been converted + to the chosen format e.g. .html + + Supporting automatic conversion ensures that GitHub/BitBucket + and any other git hosting site performing rendering on a file + by file basis allowing users to navigate through the documentation, + while still ensuring the output from fully generated sphinx docs + will point to the correct target. + """ + + try: + target_format = app.builder.link_suffix + except AttributeError: + # if the builder has no link_suffix, then no need to modify + # the current links. + return + + source_suffix = app.config.source_suffix + # Links are either absolute against the repository or relative to + # the current document's directory. Note that this is not + # necessarily app.srcdir, which is the documentation root + # directory. Instead rely on 'source' attribute of doctree to + # identify the path of the file providing the current doctree + try: + doc_path = doctree.attributes['source'] + doc_dir = os.path.dirname(doc_path) + except KeyError: + # some doctrees added by other libraries through dynamic + # generation do not have a source file. Assume paths are + # relative to the repo. + doc_dir = "" + + for node in doctree.traverse(nodes.reference): + if 'refuri' not in node: + continue + if node['refuri'].startswith('http'): + continue + + try: + link, anchor = node['refuri'].split('#', 1) + anchor = '#' + anchor + except ValueError: + link = node['refuri'] + anchor = '' + + if link is None: + continue + + # Replace the suffix with the correct target format file ending, + # but only if the link ends with both the correct source suffix + # and refers to a local file. + if link.endswith(source_suffix): + # absolute paths are considered relative to repo + if link.startswith("/"): + basepath = "" + # relative paths are against the current doctree source path + else: + basepath = doc_dir + if os.path.exists(os.path.join(basepath, link)): + node['refuri'] = (link[:-len(source_suffix)] + target_format + + anchor) + + +def setup(app): + app.connect('doctree-resolved', transform_github_links) + return {'version': '0.1'} diff --git a/doc/source/workflows.rst b/doc/source/workflows.rst index c2317a7..40f3e17 100644 --- a/doc/source/workflows.rst +++ b/doc/source/workflows.rst @@ -14,7 +14,7 @@ Workflows Importing from upstream: using git-upstream ------------------------------------------- -See :doc:`installation instructions ` for details on +See `installation instructions `_ for details on installing. Initial import of an upstream project