I was successfully able to generate targets conditionally based on the buildername
by using a simple python sphinx extension.
Preface
First, it's worth noting that the buildername
(html
for html or rinoh
for pdf) is not made available to conf.py
or extensions as the builder is setup after the extensions when the Sphinx class is initialized.
To overcome this, I choose to parse sys.argv
, but this might not work if you build sphinx from python rather than calling sphinx-build
from bash as I do.
A more robust solution might be to use a tag.
conf.py
First, add the following block somewhere the sphinx conf.py
file, which will make an environment variable named 'buildername' available from extensions:
def setup(app):
argv = ' '.join(sys.argv)
if '-b html' in argv:
app.add_config_value('buildername', 'html', 'env')
else:
app.add_config_value('buildername', 'not-html', 'env')
Then update your extensions
list to include conditionaltarget
:
sys.path.insert(0, os.path.abspath('_extensions'))
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.viewcode',
'conditionaltarget',
]
_extensions/conditionaltarget.py
Create the example "Conditional Target" extension at docs/_extensions/conditionaltarget.py
with the following contents:
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx.locale import _
from sphinx.util.docutils import SphinxDirective
class ConditionalTarget(SphinxDirective):
def run(self):
target_node = nodes.target( '', '' )
target_node['names'] = ['targetname1']
if self.env.config.buildername == 'html':
target_node['refuri'] = 'https://example.com/a'
else:
target_node['refuri'] = 'https://example.com/b'
return [target_node]
def setup(app):
app.add_directive("conditionaltarget", ConditionalTarget)
return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
index.rst
Finally, adding the following to the source .rst
file:
test link to targetname1_
.. conditionaltarget::
Now the link should point to example.com/a
when built using sphinx-build -b html . _build/html/
and example.com/b
when built using with any other command that doesn't include -b html
(eg sphinx-build -b rinoh . _build/html/
)
Of course, this is just a very crude proof-of-concept, and a better extension would take inputs from its directive by parsing the newline-delimited self.content
list for target names and URIs.