7. Hyperlinks in General
One of the primary methods of web navigation in a web browser allows the user, by clicking something, to cause the browser to
“navigate somewhere else”.
The mechanism underlying this change is called a “hyperlink” or just “link”. Think of a hyperlink as a sort of “line” having a source and destination anchor at each end. HTML provdes the source anchor by way of an Anchor element with an HREF attribute.
<A HREF=”some_destination”>…</A>
The HREF attribute provides the URI for the destination.
Destinations can be many things, but if they are whole HTML web pages, the content within the HREF string will look something like this:
Destinations can also be specific (internal) points within a web page, such as a specific definition on a web page containing a glossary. When this is the case, the anchor element has an ID attribute instead of an HREF element:
<A ID=”identifier”>…</A>
ID attribute identifiers are expected to be unique within a web page. (Web browsers still work with putting this identifier in a NAME attribute, but this practice has been deprecated.) When this is the case, the “source” Anchor’s URI gets the destination’s identifier appended to it like this:
7.1. ReST Hyperlinks
7.1.1. Anchor Nomenclature
In reStructuredText context (and its documentation), there are 3 important terms from above that are different:
- source anchor:
is called “link reference” in ReST context
- destination anchor:
is called “link target” in ReST context
- anchor identifier:
is called “reference name” in ReST context
ReStructuredText uses the underscore character (‘_’) for both hyperlink references and hyperlink targets, but in different ways: think of the underscore as a right-facing arrow. When it is on the left side of a “link” it produces a link TARGET. When it is on the right side of a “link” it produces a link REFERENCE.
7.1.2. Reference Names
With reference to Hyperlinks in General, reference names serve as reStructuredText anchor identifiers. Like anchor identifiers, they are used both in hyperlink references and hyperlink targets to tie the two together to form the source and destination of a hyperlink, respectively.
In Docutils documentation on reStructuredText, the author is careful not to use the term “identifier” when referring to “reference names” because “identifier” has more meaning in the intermediate files generaterated by the Docutils reStructuredText parser. So from here forward, we will refrain from using the term “identifier” and stick to the term “reference name”.
7.1.3. —> Hyperlink Targets
There are five types of hyperlink targets:
explicit internal,
implicit internal,
explicit external,
inline, and
indirect.
7.1.3.1. Explicit Internal Hyperlink Targets
Explicit internal link targets are location-based: they point to the first document element following them, and behave like the glossary example mentioned above. The link reference names are case insensitive for both hyperlink references and hyperlink targets, giving the author flexibility with capitalization when those reference names are displayed in the final output document. When this occurs is entirely under the author’s control. Read on to find out how.
Explicit internal-hyperlink targets provide link destinations within a document (like the glossary example above) and are created by using reStructuredText explicit markup (“..”) like this:
.. _referencename:
.. _multi word reference name:
These targets are recognized by the parser by:
leading “.. “
1 colon,
nothing after it,
a blank line (or other explicit markup) following it, and
no quoting.
Note
Explicit internal link targets are not needed over section titles because section titles generate their own implicit internal link targets, and those link targets can be used to link to document sections. See Linking to Section Titles for how to do this.
However! With the above in mind, there is still a good use case for using them to link to section titles, and that is if the section title itself is subject to change, if the links are done using implicit internal link targets, changing the section title will invalidate all the links to it, whereas if explicit internal hyperlink targets are used instead, the writer can change the section title all he wants and the links will not be invalidated!
If 2 or more explicit internal hyperlink targets are placed together, they will all refer to the first document element that comes after them. In reStructuredText parlance, these 2 link targets are “chained”:
.. _target1:
.. _target2:
Both of the above (target1 and target2) refer to this paragraph.
The following document element can be an explicit external link target, in which case the URI from the external hyperlink target will be propagated to the internal hyperlink targets; they will all “point to” the same URI. Thus, there is no need to duplicate a URI. For example, the first 2 hyperlink targets below are both explicit internal hyperlink targets. And in the generated output document, they will both point to https://mail.python.org/pipermail/doc-sig/ .
.. _Python DOC-SIG mailing list archive:
.. _archive:
.. _Doc-SIG: https://mail.python.org/pipermail/doc-sig/
If you want to make an internal hyperlink target refer to a list item other than the first list item, place it in its own indeneded line below the list item above it, like this:
* item 1
* item 2
.. _third item:
* item 3
* item 4
Link to `third item`_ in another part of the document.
7.1.3.2. Implicit Internal Link Targets
Implicit link targets are those that the reStructuredText WRITER (as opposed to reader) generates by itself, without the author having to code it himself. The are generated by section titles, footnotes, and citations, and may also be generated by constructs built into reStructureText extension software. Implicit hyperlink targets otherwise behave identically to explicit hyperlink targets.
Reference names generated by section titles are simply the section names themselves (case insensitive). If a section name contains spaces, it can be back-quoted with an underscore (‘_’) placed after it. For an example of how simple and convenient this is, this link: Implicit Internal Link Targets links to this section’s title using this syntax:
`Implicit Internal Link Targets`_
See Hyperlink References for more information.
Footnotes and citations have their own syntax. See links for syntax specifics.
Authors should strive to avoid using explicit link reference names that conflict with implicit hyperlink target reference names, but if they do, problems of ambiguity due to conflicting implicit and explicit reference names are handled as follows:
Explicit hyperlink targets override any implicit targets having the same reference name. The implicit hyperlink targets are removed, and level-1 (info) system messages are inserted into the generated output (e.g. HTML).
Duplicate implicit hyperlink targets (e.g. 2 subsections named “Introductcion”) are removed, and level-1 (info) system messages inserted into the generated output (e.g. HTML).
Duplicate explicit internal hyperlink targets are removed, and level-2 (warning) system messages are inserted into the generated output (e.g. HTML).
Having duplicate external hyperlink targets is not considered an error so they are not removed.
During HTML (or other output) generation, system messages are inserted where target links have been removed.
7.1.3.3. Explicit External Link Targets
Explicit external links lead to destinations (normally) outside the current document.
.. _ext_referencename: link-block
.. _external multi word reference name: link-block
These syntax for these is identical to explicit internal link targets except for the addition of the “link-block” after the colon.
Example:
See the Python_ home page for info.
`Write to me`_ with your questions.
.. _Python: https://www.python.org
.. _another topic: other_topics.html
.. _Write to me: jdoe@example.com
After processing into HTML, these hyperlinks might be expressed as:
See the <a href="https://www.python.org">Python</a> home page for info.
See the <a href="other_topics.html">Other Topic</a> in this multi-page document.
<a href="mailto:jdoe@example.com">Write to me</a> with your questions.
7.1.3.3.1. Link Block Syntax
Link blocks contain absolute or relative URIs to external documents. They can even include URIs relative to the current document if you know the anchor identifier (the string after the ‘#’ in the URI). While such a use technically works, in practice it is not used, because internal hyperlink references can be made so much more easily as described in Hyperlink References.
If a URI is very long, it can be wrapped onto multiple lines. Surrounding whitespace is removed before the link is generated. Examples:
.. _one-liner: https://docutils.sourceforge.io/rst.html
.. _starts-on-this-line: https://
docutils.sourceforge.net/rst.html
.. _entirely-below:
https://docutils.
sourceforge.net/rst.html
The URI can refer to an .HTML file on the local hard drive. If the path has spaces in it, escape the sapces with a backslash.
.. _reference: ../local\ path\ with\ spaces.html
If an external hyperlink target’s URI contains an underscore as its last character, it must be escaped to avoid being mistaken for an indirect hyperlink target:
This link_ refers to a file called ``underscore_``.
.. _link: underscore\_
It is possible (although not generally recommended) to include URIs directly within hyperlink references. See Embedded URIs and Aliases below.
7.1.3.4. Inline Link Targets
Inline internal targets are the equivalent of explicit internal hyperlink targets, but may appear within running text. The syntax begins with an underscore and a back-quote, is followed by a hyperlink name or phrase, and ends with a back-quote.
For example, the following paragraph contains a hyperlink target named “Norwegian Blue”:
Oh yes, the _`Norwegian Blue`. What's, um, what's wrong with it?
7.1.3.5. Indirect Link Taregets
Indirect hyperlink targets have a hyperlink reference in their link blocks. In the following example, target “one” indirectly references whatever target “two” references, and target “two” references target “three”, an internal hyperlink target. In effect, all three reference the same thing:
.. _one: `multi word ref two`_
.. _multi word ref two: three_
.. _three:
Like URIs in link blocks, the hyperlink references to the right of the colon may occur on the following line or be split across multiple lines. Unlike wrapped URIs (which are re-assembled removing whitespace), split hyperlink references are joined with whitespace before being normalized.
It is possible to include an alias directly within hyperlink references. See Embedded URIs and Aliases below.
If the reference name contains any colons, either the phrase must be enclosed in back-quotes, or the colon(s) must be backslash-escaped in the link target.
7.1.4. Hyperlink References —>
7.1.4.1. Standalone Hyperlinks
A URI or standalone email address within a text block is treated as a general external hyperlink with the URI address itself as the link’s text. For example:
See https://www.python.org.
would be marked up in HTML as:
See <a href="https://www.python.org">https://www.python.org</a>.
and
someone@somewhere.com
would be marked up in HTML as:
See <a href="mailto:someone@somewhere.com">someone@somewhere.com</a>.
If your documentation project is complex, however, use of this method of providing link references is not condoned, since the same URL is often used in multiple places and when it changes, will you remember to change it in all the different places where it exists?
Instead, use the methods below so that your URLs are contained in, at most, one place so maintenance is easier.
7.1.4.2. Linking to Explicit Internal Link Targets
Linking to explicit link targets is as easy as using the link name followed by an underscore (‘_’). If it is a multi-word name, back-quote it (the under score goes after the closing back quote). If
.. _interesting paragraph:
Interesting paragraph being linked to... yada yada yada yada yada yada yada yada
yada yada yada yada yada yada yada yada yada yada yada yada yada yada yada yada
yada yada yada yada yada yada yada.
is an explicit internal link target, then it can be linked to like this:
Some text that wants to link to the `interesting paragraph`_.
7.1.4.3. Embedded Link References
If the reference name of a link target has different wording than the wording you want to display in a link’s text, you can handle it as follows. Let us say you want to use the text “interesting paragraphs” (plural) to refer to the above paragraph with an explicit internal link, you can do so in 2 ways:
This is where we discuss `interesting paragraphs <interesting paragraph_>`_
and wish to provide a link to it herein.
or you can simply provide an alternate (chained) explicit internal link like this:
.. _interesting paragraph:
.. _interesting paragraphs:
Interesting paragraph being linked to... yada yada yada yada yada yada yada yada
yada yada yada yada yada yada yada yada yada yada yada yada yada yada yada yada
yada yada yada yada yada yada yada.
and then link to the paragraph with simpler syntax, like this:
This is where we discuss `interesting paragraphs`_ and wish to provide a link to
it herein.
7.1.4.4. Linking to Section Titles
7.1.4.4.1. Within the Same Document
Linking to section titles is probably the easiest link reference to create. You simple state the name in your paragraph or list and follow it with an underscore. If the title contains spaces, you will need to back-quote it in your text. In the generated documents, the link is generated using that text. For example, the following syntax will generate a link to this section title. Remember, the reference name is case insensitive, so it need not be capitalized if it is not a proper noun within the referencing text. (If it is being referred to as a section title, of course it is a proper noun—the name of a section title.)
`Within the same document`_
thus
See `Linking to Section Titles`_ for more information.
remains very readable in the .RST
file while at the same time embedding a
convenient link to that section title in the generated output document.
7.1.4.4.2. Linking to List Items
See Explicit Internal Hyperlink Targets for how to do this.
7.1.4.4.3. Linking From Another Web Page
To link to a section title from another web page outside of the reStructuredText project, simply hover your mouse over the icon to the right of the section title in its final output form, right click in your browser and select “Copy Link”, and then use that string as the HREF attribute in the source web page.
Hint
The anchor identifier will be the lower-case form of the section title with adjacent whitespace replaced by a single space, which is then replaced by a single hyphen. For example, the reference name for this section in this document is:
linking-from-another-web-page
thus
http://sample.com/destination_document.html#linking-from-another-web-page
as an HREF value would link to this section from an another web page.
7.1.4.5. Linking to Footnotes and Citations
7.1.4.6. Embedded URIs and Aliases
A hyperlink reference may directly embed a target URI or an “alias” hyperlink reference within angle brackets as follows:
See the `Python home page <https://www.python.org>`_ for info.
This `link <Python home page_>`_ is an alias to the link above.
This is exactly equivalent to:
See the `Python home page`_ for info.
This link_ is an alias to the link above.
.. _Python home page: https://www.python.org
.. _link: `Python home page`_
Use of this feature is not particularly recommended, however, because it is hard to maintain when the URI changes. What IS recommended is keeping a set of explicit external link targets all in one place in a document (e.g. at the bottom or top) so that each URI is only listed once, and they are in a known location so they are easy to find when URIs change.
Even better: have them all in a single file and include the file with an
.. include::
directive wherever any of the URIs are needed.
Example: at the end of this document is this block of explicit external link targets:
.. _section titles: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#section-titles
.. _footnotes: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#footnotes
.. _citations: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#citations
.. _explicit_hyperlink_targets: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#explicit-hyperlink-targets
.. _reStructuredText: https://docutils.sourceforge.io/rst.html
.. _sphinx ref role: https://www.sphinx-doc.org/en/master/usage/referencing.html#role-ref
.. _comments: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#comments
.. _sphinx_cross_referencing: https://docs.readthedocs.io/en/stable/guides/cross-referencing-with-sphinx.html
7.2. Sphinx Hyperlinks
7.2.1. The Problem
reStructuredText syntax for cross-referencing to other .RST
files leaves a few
things to be desired. With reStructuredText syntax alone you are limited to using
external links to HTML files, which requires the writer to know the URL. When the
URL is in the same documents project as the referencing .RST
file, it is hard not
to think of this as being a little weak. Further, this type of linking can result in
HTML links not working in the HTML files on the local workstation where testing might
be needed, since they would typically use relative URLs that are either relative to
the on-line HTML file (without a leading /
) or that are relative to the BASE URL
(with a leading /
), and of course that HTML syntax applied to the local file
system will generate a FILE NOT FOUND error when loading local files into a browser
for testing.
7.2.2. The Solution
Sphinx has a beautiful solution to this: Sphinx hyperlink syntax.
This syntax is slightly different than reStructuredText hyperlink syntax, and is
equally applicable to linking to link targets in the same .RST
file as well
as to locations in other .RST
files with the following improvements over
reStructuredText hyperlink syntax:
it does NOT require the writer to know the final URL — only a unique link target label (“anchor identifier” in HTML terms);
the links are robust (moving
.RST
files around within the docs project does not break the links); andthe links do work on the local workstation when testing locally-generated HTML files!
7.2.3. How it Works
First a link target must exist. Note that the “link target label” must:
be preceded by a single underscore,
be followed by exactly one colon (making it different than other ReST or Sphinx directives),
be unique among all the documents in the project, and
be followed by at least one blank line
for the doc-generation logic to process it correctly. Note that this is reStructuredText link target syntax shared by both reStructuredText and Sphinx.
Example:
.. _unique_link_target_label:
Some Heading
------------
Once this is in place, then Sphinx hyperlink syntax to link to it can be one of these two formats.
7.2.3.1. When “link text” should be a title or section heading from the target document:
:ref:`unique_link_target_label`
This syntax causes the link text to be the heading just below the link target (“Some
Heading” in this example). For this reason, when using this syntax,
unique_link_target_label
must reference link targets that are just above a
title or section heading.
7.2.3.2. When “link text” should be something else:
:ref:`different link text <unique_link_target_label>`
This syntax will cause the link text to be “different link text” in the above example.
This latter syntax enables you to put a link target anywhere in an .RST
file (not
just above a heading) and link to it using this syntax.
This is similar to the <a id=”unique-anchor-id”/> HTML tag. The difference is that
the HTML “unique-anchor-id” only has to be unique in that HTML page, but for
“unique_link_target_label”, it has to be unique among all .RST
files in the
document project.
See Also
ReadTheDocs write-up on Cross-Referencing with Sphinx
7.3. Sphinx Hyperlink Policy (for WGA Crystal Research, Inc.)
As covered above, words in link targets can be separated by:
spaces,
hyphens, or
underscores
and Sphinx is just as happy with any of these, as long as the link-reference and link-target strings match (not case sensitive).
However, there is one policy that this author finds that it helps: when a link
target is placed at the head of a file (e.g. chapter), that it reduces confused if
the string of the link target matches the stem of the .rst
file name.
Example:
Given the source file getting_started.rst
, if a hyperlink target appears at the
top of this file it should look like this:
.. _getting_started:
Reason: when later writing and adding link references to this target, it is most common in this author’s experience to think of it as a reference to that file — thus matching the file name stem makes sense in this context.