Is it possible to reuse hyperlink defined in anoth

2020-05-01 05:12发布

问题:

Suppose I have two files a.rst and b.rst in the same folder, and a.rst looks like this

.. _foo: http://stackoverflow.com

`foo`_ is a website

It seems using foo in b.rst is not allowed. Is there a way to define hyperlinks and use them in multiple files?

Followup

I used the extlinks extension as Steve Piercy suggested. Its implementation and docstring can be seen here on github.

In my case, I define wikipedia link in my conf.py

extlinks = {'wiki': ('https://en.wikipedia.org/wiki/%s', '')}

and in the .rst files, use them like

:wiki:`Einstein <Albert_Einstein>`

where Einstein will be displayed as a link to https://en.wikipedia.org/wiki/Albert_Einstein

回答1:

There are at least four possible solutions.

repeat yourself

Put your complete reST in each file. You probably don't want that.

combined rst_epilog and substitution

This one is clever. Configure the rst_epilog value, in your conf.py along with a substition with the replace directive:

rst_epilog = """
.. |foo| replace:: foo
.. _foo: http://stackoverflow.com
"""

and reST:

|foo|_ is a website

yields:

<a class="reference external" href="http://stackoverflow.com">foo</a>

extlinks

For links to external websites where you want to have a base URL and append path segments or arguments, you can use extlinks in your conf.py:

extensions = [
...
    'sphinx.ext.extlinks',
...
]
...
extlinks = {'so': ('https://stackoverflow.com/%s', None)}

Then in your reST:

:so:`questions/49016433`

Yields:

<a class="reference external"
 href="https://stackoverflow.com/questions/49016433">
 https://stackoverflow.com/questions/49016433
</a>

intersphinx

For external websites that are documentation generated by Sphinx, then you can use intersphinx, in your conf.py:

extensions = [
...
    'sphinx.ext.intersphinx',
...
]
...
intersphinx_mapping = {
    'python': ('https://docs.python.org/3', None),
}

Then in your reST:

:py:mod:`doctest`

Yields:

<a class="reference external"
 href="https://docs.python.org/3/library/doctest.html#module-doctest"
 title="(in Python v3.6)">
    <code class="xref py py-mod docutils literal">
        <span class="pre">doctest</span>
    </code>
</a>


回答2:

This is another solution: it is a bit hacky and a little bit different respect to the officially supported way to share external links.

First complete the Setup then:

  1. in conf.py add the commonlinks entry in extensions
  2. in conf.py configure the map of common links:

For example:

extensions = [
    ...,
    'sphinx.ext.commonlinks'
]

commonlinks = {
                'issues': 'https://github.com/sphinx-doc/sphinx/issues',
                'github': 'https://github.com'
              }

Then in .rst files you can do these:

The :github:`_url_` url is aliased to :github:`GitHub` and also to :github:`this`

Setup

All that is needed is to copy into sphinx/ext directory the file commonlinks.py:

# -*- coding: utf-8 -*-
"""
    sphinx.ext.commonlinks
    ~~~~~~~~~~~~~~~~~~~~~~

    Extension to save typing and prevent hard-coding of common URLs in the reST
    files.

    This adds a new config value called ``commonlinks`` that is created like this::

       commonlinks = {'exmpl': 'http://example.com/mypage.html', ...}

    Now you can use e.g. :exmpl:`foo` in your documents.  This will create a
    link to ``http://example.com/mypage.html``.  The link caption depends on the
    role content:

    - If it is ``_url_``, the caption will be the full URL.
    - If it is a string, the caption will be the role content.

"""

from six import iteritems
from docutils import nodes, utils

import sphinx
from sphinx.util.nodes import split_explicit_title


def make_link_role(base_url):
    def role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
        text = utils.unescape(text)
        if text == '_url_':
            title = base_url
        else:
            title = text
        pnode = nodes.reference(title, title, internal=False, refuri=base_url)
        return [pnode], []
    return role


def setup_link_roles(app):
    for name, base_url in iteritems(app.config.commonlinks):
        app.add_role(name, make_link_role(base_url))


def setup(app):
    app.add_config_value('commonlinks', {}, 'env')
    app.connect('builder-inited', setup_link_roles)
    return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

To locate the sphinx installation directory one way is:

$ python 3
> import sphinx
> sphinx
<module 'sphinx' from '/usr/local/lib/python3.5/dist-packages/sphinx/__init__.py'>

then:

% cp commonlinks.py /usr/local/lib/python3.5/dist-packages/sphinx/ext