1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
import docutils
import re
from sphinx.builders.dirhtml import DirectoryHTMLBuilder
def replace_uris(app, doctree, nodetype, nodeattr):
"""
Replace ``nodetype`` URIs from ``doctree`` to the proper one.
If ``nodetype`` is an image (``docutils.nodes.image``), the URL is prefixed
with ``Builder.imagedir`` and the original image path is added to
``Builder.images`` so it's copied using Sphinx's internals before
finalizing the building.
:param app: Sphinx Application
:type app: sphinx.application.Sphinx
:param doctree: doctree representing the document
:type doctree: docutils.nodes.document
:param nodetype: type of node to replace URIs
:type nodetype: docutils.nodes.Node
:param nodeattr: node attribute to be replaced
:type nodeattr: str
"""
# https://github.com/sphinx-doc/sphinx/blob/2adeb68af1763be46359d5e808dae59d708661b1/sphinx/environment/adapters/toctree.py#L260-L266
for node in doctree.findall(nodetype):
uri = olduri = node.attributes.get(nodeattr) # somepage.html (or ../sompage.html)
if isinstance(app.builder, DirectoryHTMLBuilder):
# When the builder is ``DirectoryHTMLBuilder``, refuri will be
# ``../somepage.html``. In that case, we want to remove the
# initial ``../`` to make valid links
if uri.startswith('../'):
uri = uri.replace('../', '')
if re.match('^https?://', uri):
# allow non-local URLs for resources
continue
imagedir = ''
if nodetype is docutils.nodes.image:
# Prefix the URL with ``Builder.imagedir`` to use the internal's
# Sphinx image handling if the node is an image
imagedir = '{imagedir}/'.format(
imagedir=app.builder.imagedir,
)
# The image is copied into ``app.builder.imagedir`` without keeping
# the directory structure, so we need only the filename for the
# correct link
uri = olduri.split('/')[-1]
uri = '{prefix}{imagedir}{filename}'.format(
prefix=app.config.notfound_urls_prefix or '/',
imagedir=imagedir,
filename=uri,
)
node.replace_attr(nodeattr, uri)
# Force adding the image to the builder so it's copied at ``Builder.copy_image_files``
# https://github.com/sphinx-doc/sphinx/blob/5ce5c2c3156c53c1f1b758c38150e48080138b15/sphinx/builders/html.py#L721
# We need to do this at this point because ``Builder.post_process_images``
# does not add it automatically as the path does not match.
# https://github.com/sphinx-doc/sphinx/blob/5ce5c2c3156c53c1f1b758c38150e48080138b15/sphinx/builders/__init__.py#L189
if nodetype is docutils.nodes.image:
if all([
not olduri.startswith('data:'),
'://' not in olduri,
]):
app.builder.images[olduri] = olduri.split('/')[-1]
|