Sam Hooke

Sphinx: Link to HTML from MyST Markdown

TL;DR: If you try to create a link in Sphinx from MyST Markdown to an HTML file in the _static directory, Sphinx seems to only include the individual file you link to, and places it in the _downloads directory. If you want to include a group of HTML files, use {.external} as shown below.

If you are using Sphinx, and want to both:

  1. Write your documentation in MyST Markdown (*.md)…
  2. …and, include some pre-built HTML (*.html) alongside the HTML generated from your Sphinx documentation.

Then read on!

The static directory §

To include some pre-built HTML with your Sphinx documentation, a good place to put it is in the _static directory. Ensure you have html_static_path defined in your conf.py as follows:

conf.py §
html_static_path = ['_static']

Then you can place your pre-built HTML inside the source/_static directory. For example, here we have a directory named my_html_pages, which includes a bunch of pre-built HTML, complete with multiple pages and sub-directories:

.
└── my_package/
    ├── public
    └── source/
        ├── _static/
        │   └── my_html_pages/
        │       ├── index.html
        │       └── foo/
        │           ├── page_1.html
        │           └── page_2.html
        ├── a_section/
        │   └── introduction.md
        └── index.md

Building §

At build time, everything in the source/_static directory is copied to a public/_static directory, so then we end upp with:

.
└── my_package/
    ├── public/
    │   ├── _static/
    │   │   └── my_html_pages/
    │   │       ├── index.html
    │   │       └── foo/
    │   │           ├── page_1.html
    │   │           └── page_2.html
    │   ├── index.html
    │   └── a_section/
    │       └── introduction.html
    └── source/
        ├── _static/
        │   └── my_html_pages/
        │       ├── index.html
        │       └── foo/
        │           ├── page_1.html
        │           └── page_2.html
        ├── a_section/
        │   └── introduction.md
        └── index.md

Linking from MyST Markdown to HTML (the problem) §

If we want to link from a_section/introduction.md to _static/my_html_pages/index.html, at first we might try this:

# Introduction

Click [here](../_static/my_html_pages/index.html) to open the HTML page.

However, Sphinx treats this type of link as a download, which it handles by placing a copy of just the linked file in the _downloads directory, and uses that for the link target.

This type of linking is fine for individual files, e.g. a PDF for download, but does not work for linking to a collection of HTML files.

For example, in our case, it copies source/_static/my_html_pages/index.html to public/_downloads/6c3d04a91d0a2d2f7f774041e8670d2d/index.html, but does not copy source/_static/my_html_pages/foo/!

So how do we link to the entire collection of pre-built HTML files?

Linking from MyST Markdown to HTML (the solution) §

The solution is to append {.external} to the link1, which tell Sphinx MyST Markdown this is an external link:

# Introduction

Click [here](../_static/my_html_pages/index.html){.external} to open the HTML page.

The link will then point to _static/my_html_pages/index.html, where all the pre-built HTML files are, rather than _downloads/<hash>/index.html. The relative links from _static/my_html_pages/index.html to foo/page_1.html and foo/page_2.html will then also work.


  1. Thanks to this PR (found via this PR), which introduced me to myst_url_schemes, which subsequently lead me to find {.external}↩︎

These are rough notes that vary greatly in quality and length, but prove useful to me, and hopefully to you too!

← Previous: Append to .bashrc using Ansible
Next: Using gprof with POSIX FreeRTOS →