To add target="_blank"
but also rel="noopener noreferrer"
to external links, it is necessary to copy Sphinx' entire visit_reference()
method to patch this in:
atts['target'] = '_blank'
atts['rel'] = 'noopener noreferrer'
Sphinx' original code does not process a rel
attribute that one might set like node['rel'] = 'noopener noreferrer'
, whereas it does apply a target
attribute (atts['target'] = node['target']
).
Below you find my solution. The base code is from Sphinx 3.0.3 (sphinx/writers/html.py):
from sphinx.writers.html import HTMLTranslator
from docutils import nodes
from docutils.nodes import Element
class PatchedHTMLTranslator(HTMLTranslator):
def visit_reference(self, node: Element) -> None:
atts = {'class': 'reference'}
if node.get('internal') or 'refuri' not in node:
atts['class'] += ' internal'
else:
atts['class'] += ' external'
# ---------------------------------------------------------
# Customize behavior (open in new tab, secure linking site)
atts['target'] = '_blank'
atts['rel'] = 'noopener noreferrer'
# ---------------------------------------------------------
if 'refuri' in node:
atts['href'] = node['refuri'] or '#'
if self.settings.cloak_email_addresses and atts['href'].startswith('mailto:'):
atts['href'] = self.cloak_mailto(atts['href'])
self.in_mailto = True
else:
assert 'refid' in node, \
'References must have "refuri" or "refid" attribute.'
atts['href'] = '#' + node['refid']
if not isinstance(node.parent, nodes.TextElement):
assert len(node) == 1 and isinstance(node[0], nodes.image)
atts['class'] += ' image-reference'
if 'reftitle' in node:
atts['title'] = node['reftitle']
if 'target' in node:
atts['target'] = node['target']
self.body.append(self.starttag(node, 'a', '', **atts))
if node.get('secnumber'):
self.body.append(('%s' + self.secnumber_suffix) %
'.'.join(map(str, node['secnumber'])))
def setup(app):
app.set_translator('html', PatchedHTMLTranslator)
You may paste this directly into your conf.py
at the bottom.
Note that this patches the HTMLTranslator. If you use HTML 5 output then you need a modified HTML5Translator (sphinx/writers/html5.py).